UNPKG

vue-router

Version:

> - This is the repository for Vue Router 4 (for Vue 3) > - For Vue Router 3 (for Vue 2) see [vuejs/vue-router](https://github.com/vuejs/vue-router). > To see what versions are currently supported, please refer to the [Security Policy](./packages/router

2,438 lines 95 kB
/*!
 * vue-router v5.0.3
 * (c) 2026 Eduardo San Martin Morote
 * @license MIT
 */
var VueRouter = (function(exports, vue) {


//#region src/utils/env.ts
	const isBrowser = typeof document !== "undefined";

//#endregion
//#region src/utils/index.ts
/**
	* Allows differentiating lazy components from functional components and vue-class-component
	* @internal
	*
	* @param component
	*/
	function isRouteComponent(component) {
		return typeof component === "object" || "displayName" in component || "props" in component || "__vccOpts" in component;
	}
	function isESModule(obj) {
		return obj.__esModule || obj[Symbol.toStringTag] === "Module" || obj.default && isRouteComponent(obj.default);
	}
	const assign = Object.assign;
	function applyToParams(fn, params) {
		const newParams = {};
		for (const key in params) {
			const value = params[key];
			newParams[key] = isArray(value) ? value.map(fn) : fn(value);
		}
		return newParams;
	}
	const noop = () => {};
	/**
	* Typesafe alternative to Array.isArray
	* https://github.com/microsoft/TypeScript/pull/48228
	*
	* @internal
	*/
	const isArray = Array.isArray;
	function mergeOptions(defaults, partialOptions) {
		const options = {};
		for (const key in defaults) options[key] = key in partialOptions ? partialOptions[key] : defaults[key];
		return options;
	}

//#endregion
//#region src/warning.ts
	function warn(msg) {
		const args = Array.from(arguments).slice(1);
		console.warn.apply(console, ["[Vue Router warn]: " + msg].concat(args));
	}

//#endregion
//#region src/encoding.ts
/**
	* Encoding Rules (␣ = Space)
	* - Path: ␣ " < > # ? { }
	* - Query: ␣ " < > # & =
	* - Hash: ␣ " < > `
	*
	* On top of that, the RFC3986 (https://tools.ietf.org/html/rfc3986#section-2.2)
	* defines some extra characters to be encoded. Most browsers do not encode them
	* in encodeURI https://github.com/whatwg/url/issues/369, so it may be safer to
	* also encode `!'()*`. Leaving un-encoded only ASCII alphanumeric(`a-zA-Z0-9`)
	* plus `-._~`. This extra safety should be applied to query by patching the
	* string returned by encodeURIComponent encodeURI also encodes `[\]^`. `\`
	* should be encoded to avoid ambiguity. Browsers (IE, FF, C) transform a `\`
	* into a `/` if directly typed in. The _backtick_ (`````) should also be
	* encoded everywhere because some browsers like FF encode it when directly
	* written while others don't. Safari and IE don't encode ``"<>{}``` in hash.
	*/
	const HASH_RE = /#/g;
	const AMPERSAND_RE = /&/g;
	const SLASH_RE = /\//g;
	const EQUAL_RE = /=/g;
	const IM_RE = /\?/g;
	const PLUS_RE = /\+/g;
	/**
	* NOTE: It's not clear to me if we should encode the + symbol in queries, it
	* seems to be less flexible than not doing so and I can't find out the legacy
	* systems requiring this for regular requests like text/html. In the standard,
	* the encoding of the plus character is only mentioned for
	* application/x-www-form-urlencoded
	* (https://url.spec.whatwg.org/#urlencoded-parsing) and most browsers seems lo
	* leave the plus character as is in queries. To be more flexible, we allow the
	* plus character on the query, but it can also be manually encoded by the user.
	*
	* Resources:
	* - https://url.spec.whatwg.org/#urlencoded-parsing
	* - https://stackoverflow.com/questions/1634271/url-encoding-the-space-character-or-20
	*/
	const ENC_BRACKET_OPEN_RE = /%5B/g;
	const ENC_BRACKET_CLOSE_RE = /%5D/g;
	const ENC_CARET_RE = /%5E/g;
	const ENC_BACKTICK_RE = /%60/g;
	const ENC_CURLY_OPEN_RE = /%7B/g;
	const ENC_PIPE_RE = /%7C/g;
	const ENC_CURLY_CLOSE_RE = /%7D/g;
	const ENC_SPACE_RE = /%20/g;
	/**
	* Encode characters that need to be encoded on the path, search and hash
	* sections of the URL.
	*
	* @internal
	* @param text - string to encode
	* @returns encoded string
	*/
	function commonEncode(text) {
		return text == null ? "" : encodeURI("" + text).replace(ENC_PIPE_RE, "|").replace(ENC_BRACKET_OPEN_RE, "[").replace(ENC_BRACKET_CLOSE_RE, "]");
	}
	/**
	* Encode characters that need to be encoded on the hash section of the URL.
	*
	* @param text - string to encode
	* @returns encoded string
	*/
	function encodeHash(text) {
		return commonEncode(text).replace(ENC_CURLY_OPEN_RE, "{").replace(ENC_CURLY_CLOSE_RE, "}").replace(ENC_CARET_RE, "^");
	}
	/**
	* Encode characters that need to be encoded query values on the query
	* section of the URL.
	*
	* @param text - string to encode
	* @returns encoded string
	*/
	function encodeQueryValue(text) {
		return commonEncode(text).replace(PLUS_RE, "%2B").replace(ENC_SPACE_RE, "+").replace(HASH_RE, "%23").replace(AMPERSAND_RE, "%26").replace(ENC_BACKTICK_RE, "`").replace(ENC_CURLY_OPEN_RE, "{").replace(ENC_CURLY_CLOSE_RE, "}").replace(ENC_CARET_RE, "^");
	}
	/**
	* Like `encodeQueryValue` but also encodes the `=` character.
	*
	* @param text - string to encode
	*/
	function encodeQueryKey(text) {
		return encodeQueryValue(text).replace(EQUAL_RE, "%3D");
	}
	/**
	* Encode characters that need to be encoded on the path section of the URL.
	*
	* @param text - string to encode
	* @returns encoded string
	*/
	function encodePath(text) {
		return commonEncode(text).replace(HASH_RE, "%23").replace(IM_RE, "%3F");
	}
	/**
	* Encode characters that need to be encoded on the path section of the URL as a
	* param. This function encodes everything {@link encodePath} does plus the
	* slash (`/`) character. If `text` is `null` or `undefined`, returns an empty
	* string instead.
	*
	* @param text - string to encode
	* @returns encoded string
	*/
	function encodeParam(text) {
		return encodePath(text).replace(SLASH_RE, "%2F");
	}
	function decode(text) {
		if (text == null) return null;
		try {
			return decodeURIComponent("" + text);
		} catch (err) {
			warn(`Error decoding "${text}". Using original value`);
		}
		return "" + text;
	}

//#endregion
//#region src/location.ts
	const TRAILING_SLASH_RE = /\/$/;
	const removeTrailingSlash = (path) => path.replace(TRAILING_SLASH_RE, "");
	/**
	* Transforms a URI into a normalized history location
	*
	* @param parseQuery
	* @param location - URI to normalize
	* @param currentLocation - current absolute location. Allows resolving relative
	* paths. Must start with `/`. Defaults to `/`
	* @returns a normalized history location
	*/
	function parseURL(parseQuery, location, currentLocation = "/") {
		let path, query = {}, searchString = "", hash = "";
		const hashPos = location.indexOf("#");
		let searchPos = location.indexOf("?");
		searchPos = hashPos >= 0 && searchPos > hashPos ? -1 : searchPos;
		if (searchPos >= 0) {
			path = location.slice(0, searchPos);
			searchString = location.slice(searchPos, hashPos > 0 ? hashPos : location.length);
			query = parseQuery(searchString.slice(1));
		}
		if (hashPos >= 0) {
			path = path || location.slice(0, hashPos);
			hash = location.slice(hashPos, location.length);
		}
		path = resolveRelativePath(path != null ? path : location, currentLocation);
		return {
			fullPath: path + searchString + hash,
			path,
			query,
			hash: decode(hash)
		};
	}
	/**
	* Stringifies a URL object
	*
	* @param stringifyQuery
	* @param location
	*/
	function stringifyURL(stringifyQuery, location) {
		const query = location.query ? stringifyQuery(location.query) : "";
		return location.path + (query && "?") + query + (location.hash || "");
	}
	/**
	* Strips off the base from the beginning of a location.pathname in a non-case-sensitive way.
	*
	* @param pathname - location.pathname
	* @param base - base to strip off
	*/
	function stripBase(pathname, base) {
		if (!base || !pathname.toLowerCase().startsWith(base.toLowerCase())) return pathname;
		return pathname.slice(base.length) || "/";
	}
	/**
	* Checks if two RouteLocation are equal. This means that both locations are
	* pointing towards the same {@link RouteRecord} and that all `params`, `query`
	* parameters and `hash` are the same
	*
	* @param stringifyQuery - A function that takes a query object of type LocationQueryRaw and returns a string representation of it.
	* @param a - first {@link RouteLocation}
	* @param b - second {@link RouteLocation}
	*/
	function isSameRouteLocation(stringifyQuery, a, b) {
		const aLastIndex = a.matched.length - 1;
		const bLastIndex = b.matched.length - 1;
		return aLastIndex > -1 && aLastIndex === bLastIndex && isSameRouteRecord(a.matched[aLastIndex], b.matched[bLastIndex]) && isSameRouteLocationParams(a.params, b.params) && stringifyQuery(a.query) === stringifyQuery(b.query) && a.hash === b.hash;
	}
	/**
	* Check if two `RouteRecords` are equal. Takes into account aliases: they are
	* considered equal to the `RouteRecord` they are aliasing.
	*
	* @param a - first {@link RouteRecord}
	* @param b - second {@link RouteRecord}
	*/
	function isSameRouteRecord(a, b) {
		return (a.aliasOf || a) === (b.aliasOf || b);
	}
	function isSameRouteLocationParams(a, b) {
		if (Object.keys(a).length !== Object.keys(b).length) return false;
		for (var key in a) if (!isSameRouteLocationParamsValue(a[key], b[key])) return false;
		return true;
	}
	function isSameRouteLocationParamsValue(a, b) {
		return isArray(a) ? isEquivalentArray(a, b) : isArray(b) ? isEquivalentArray(b, a) : (a && a.valueOf()) === (b && b.valueOf());
	}
	/**
	* Check if two arrays are the same or if an array with one single entry is the
	* same as another primitive value. Used to check query and parameters
	*
	* @param a - array of values
	* @param b - array of values or a single value
	*/
	function isEquivalentArray(a, b) {
		return isArray(b) ? a.length === b.length && a.every((value, i) => value === b[i]) : a.length === 1 && a[0] === b;
	}
	/**
	* Resolves a relative path that starts with `.`.
	*
	* @param to - path location we are resolving
	* @param from - currentLocation.path, should start with `/`
	*/
	function resolveRelativePath(to, from) {
		if (to.startsWith("/")) return to;
		if (!from.startsWith("/")) {
			warn(`Cannot resolve a relative location without an absolute path. Trying to resolve "${to}" from "${from}". It should look like "/${from}".`);
			return to;
		}
		if (!to) return from;
		const fromSegments = from.split("/");
		const toSegments = to.split("/");
		const lastToSegment = toSegments[toSegments.length - 1];
		if (lastToSegment === ".." || lastToSegment === ".") toSegments.push("");
		let position = fromSegments.length - 1;
		let toPosition;
		let segment;
		for (toPosition = 0; toPosition < toSegments.length; toPosition++) {
			segment = toSegments[toPosition];
			if (segment === ".") continue;
			if (segment === "..") {
				if (position > 1) position--;
			} else break;
		}
		return fromSegments.slice(0, position).join("/") + "/" + toSegments.slice(toPosition).join("/");
	}
	/**
	* Initial route location where the router is. Can be used in navigation guards
	* to differentiate the initial navigation.
	*
	* @example
	* ```js
	* import { START_LOCATION } from 'vue-router'
	*
	* router.beforeEach((to, from) => {
	*   if (from === START_LOCATION) {
	*     // initial navigation
	*   }
	* })
	* ```
	*/
	const START_LOCATION_NORMALIZED = {
		path: "/",
		name: void 0,
		params: {},
		query: {},
		hash: "",
		fullPath: "/",
		matched: [],
		meta: {},
		redirectedFrom: void 0
	};

//#endregion
//#region src/history/common.ts
	let NavigationType = /* @__PURE__ */ function(NavigationType) {
		NavigationType["pop"] = "pop";
		NavigationType["push"] = "push";
		return NavigationType;
	}({});
	let NavigationDirection = /* @__PURE__ */ function(NavigationDirection) {
		NavigationDirection["back"] = "back";
		NavigationDirection["forward"] = "forward";
		NavigationDirection["unknown"] = "";
		return NavigationDirection;
	}({});
	/**
	* Starting location for Histories
	*/
	const START = "";
	/**
	* Normalizes a base by removing any trailing slash and reading the base tag if
	* present.
	*
	* @param base - base to normalize
	*/
	function normalizeBase(base) {
		if (!base) if (isBrowser) {
			const baseEl = document.querySelector("base");
			base = baseEl && baseEl.getAttribute("href") || "/";
			base = base.replace(/^\w+:\/\/[^\/]+/, "");
		} else base = "/";
		if (base[0] !== "/" && base[0] !== "#") base = "/" + base;
		return removeTrailingSlash(base);
	}
	const BEFORE_HASH_RE = /^[^#]+#/;
	function createHref(base, location) {
		return base.replace(BEFORE_HASH_RE, "#") + location;
	}

//#endregion
//#region src/scrollBehavior.ts
	function getElementPosition(el, offset) {
		const docRect = document.documentElement.getBoundingClientRect();
		const elRect = el.getBoundingClientRect();
		return {
			behavior: offset.behavior,
			left: elRect.left - docRect.left - (offset.left || 0),
			top: elRect.top - docRect.top - (offset.top || 0)
		};
	}
	const computeScrollPosition = () => ({
		left: window.scrollX,
		top: window.scrollY
	});
	function scrollToPosition(position) {
		let scrollToOptions;
		if ("el" in position) {
			const positionEl = position.el;
			const isIdSelector = typeof positionEl === "string" && positionEl.startsWith("#");
			/**
			* `id`s can accept pretty much any characters, including CSS combinators
			* like `>` or `~`. It's still possible to retrieve elements using
			* `document.getElementById('~')` but it needs to be escaped when using
			* `document.querySelector('#\\~')` for it to be valid. The only
			* requirements for `id`s are them to be unique on the page and to not be
			* empty (`id=""`). Because of that, when passing an id selector, it should
			* be properly escaped for it to work with `querySelector`. We could check
			* for the id selector to be simple (no CSS combinators `+ >~`) but that
			* would make things inconsistent since they are valid characters for an
			* `id` but would need to be escaped when using `querySelector`, breaking
			* their usage and ending up in no selector returned. Selectors need to be
			* escaped:
			*
			* - `#1-thing` becomes `#\31 -thing`
			* - `#with~symbols` becomes `#with\\~symbols`
			*
			* - More information about  the topic can be found at
			*   https://mathiasbynens.be/notes/html5-id-class.
			* - Practical example: https://mathiasbynens.be/demo/html5-id
			*/
			if (typeof position.el === "string") {
				if (!isIdSelector || !document.getElementById(position.el.slice(1))) try {
					const foundEl = document.querySelector(position.el);
					if (isIdSelector && foundEl) {
						warn(`The selector "${position.el}" should be passed as "el: document.querySelector('${position.el}')" because it starts with "#".`);
						return;
					}
				} catch (err) {
					warn(`The selector "${position.el}" is invalid. If you are using an id selector, make sure to escape it. You can find more information about escaping characters in selectors at https://mathiasbynens.be/notes/css-escapes or use CSS.escape (https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape).`);
					return;
				}
			}
			const el = typeof positionEl === "string" ? isIdSelector ? document.getElementById(positionEl.slice(1)) : document.querySelector(positionEl) : positionEl;
			if (!el) {
				warn(`Couldn't find element using selector "${position.el}" returned by scrollBehavior.`);
				return;
			}
			scrollToOptions = getElementPosition(el, position);
		} else scrollToOptions = position;
		if ("scrollBehavior" in document.documentElement.style) window.scrollTo(scrollToOptions);
		else window.scrollTo(scrollToOptions.left != null ? scrollToOptions.left : window.scrollX, scrollToOptions.top != null ? scrollToOptions.top : window.scrollY);
	}
	function getScrollKey(path, delta) {
		return (history.state ? history.state.position - delta : -1) + path;
	}
	const scrollPositions = /* @__PURE__ */ new Map();
	function saveScrollPosition(key, scrollPosition) {
		scrollPositions.set(key, scrollPosition);
	}
	function getSavedScrollPosition(key) {
		const scroll = scrollPositions.get(key);
		scrollPositions.delete(key);
		return scroll;
	}
	/**
	* ScrollBehavior instance used by the router to compute and restore the scroll
	* position when navigating.
	*/

//#endregion
//#region src/history/html5.ts
	let createBaseLocation = () => location.protocol + "//" + location.host;
	/**
	* Creates a normalized history location from a window.location object
	* @param base - The base path
	* @param location - The window.location object
	*/
	function createCurrentLocation(base, location) {
		const { pathname, search, hash } = location;
		const hashPos = base.indexOf("#");
		if (hashPos > -1) {
			let slicePos = hash.includes(base.slice(hashPos)) ? base.slice(hashPos).length : 1;
			let pathFromHash = hash.slice(slicePos);
			if (pathFromHash[0] !== "/") pathFromHash = "/" + pathFromHash;
			return stripBase(pathFromHash, "");
		}
		return stripBase(pathname, base) + search + hash;
	}
	function useHistoryListeners(base, historyState, currentLocation, replace) {
		let listeners = [];
		let teardowns = [];
		let pauseState = null;
		const popStateHandler = ({ state }) => {
			const to = createCurrentLocation(base, location);
			const from = currentLocation.value;
			const fromState = historyState.value;
			let delta = 0;
			if (state) {
				currentLocation.value = to;
				historyState.value = state;
				if (pauseState && pauseState === from) {
					pauseState = null;
					return;
				}
				delta = fromState ? state.position - fromState.position : 0;
			} else replace(to);
			listeners.forEach((listener) => {
				listener(currentLocation.value, from, {
					delta,
					type: NavigationType.pop,
					direction: delta ? delta > 0 ? NavigationDirection.forward : NavigationDirection.back : NavigationDirection.unknown
				});
			});
		};
		function pauseListeners() {
			pauseState = currentLocation.value;
		}
		function listen(callback) {
			listeners.push(callback);
			const teardown = () => {
				const index = listeners.indexOf(callback);
				if (index > -1) listeners.splice(index, 1);
			};
			teardowns.push(teardown);
			return teardown;
		}
		function beforeUnloadListener() {
			if (document.visibilityState === "hidden") {
				const { history } = window;
				if (!history.state) return;
				history.replaceState(assign({}, history.state, { scroll: computeScrollPosition() }), "");
			}
		}
		function destroy() {
			for (const teardown of teardowns) teardown();
			teardowns = [];
			window.removeEventListener("popstate", popStateHandler);
			window.removeEventListener("pagehide", beforeUnloadListener);
			document.removeEventListener("visibilitychange", beforeUnloadListener);
		}
		window.addEventListener("popstate", popStateHandler);
		window.addEventListener("pagehide", beforeUnloadListener);
		document.addEventListener("visibilitychange", beforeUnloadListener);
		return {
			pauseListeners,
			listen,
			destroy
		};
	}
	/**
	* Creates a state object
	*/
	function buildState(back, current, forward, replaced = false, computeScroll = false) {
		return {
			back,
			current,
			forward,
			replaced,
			position: window.history.length,
			scroll: computeScroll ? computeScrollPosition() : null
		};
	}
	function useHistoryStateNavigation(base) {
		const { history, location } = window;
		const currentLocation = { value: createCurrentLocation(base, location) };
		const historyState = { value: history.state };
		if (!historyState.value) changeLocation(currentLocation.value, {
			back: null,
			current: currentLocation.value,
			forward: null,
			position: history.length - 1,
			replaced: true,
			scroll: null
		}, true);
		function changeLocation(to, state, replace) {
			/**
			* if a base tag is provided, and we are on a normal domain, we have to
			* respect the provided `base` attribute because pushState() will use it and
			* potentially erase anything before the `#` like at
			* https://github.com/vuejs/router/issues/685 where a base of
			* `/folder/#` but a base of `/` would erase the `/folder/` section. If
			* there is no host, the `<base>` tag makes no sense and if there isn't a
			* base tag we can just use everything after the `#`.
			*/
			const hashIndex = base.indexOf("#");
			const url = hashIndex > -1 ? (location.host && document.querySelector("base") ? base : base.slice(hashIndex)) + to : createBaseLocation() + base + to;
			try {
				history[replace ? "replaceState" : "pushState"](state, "", url);
				historyState.value = state;
			} catch (err) {
				warn("Error with push/replace State", err);
				location[replace ? "replace" : "assign"](url);
			}
		}
		function replace(to, data) {
			changeLocation(to, assign({}, history.state, buildState(historyState.value.back, to, historyState.value.forward, true), data, { position: historyState.value.position }), true);
			currentLocation.value = to;
		}
		function push(to, data) {
			const currentState = assign({}, historyState.value, history.state, {
				forward: to,
				scroll: computeScrollPosition()
			});
			if (!history.state) warn("history.state seems to have been manually replaced without preserving the necessary values. Make sure to preserve existing history state if you are manually calling history.replaceState:\n\nhistory.replaceState(history.state, '', url)\n\nYou can find more information at https://router.vuejs.org/guide/migration/#Usage-of-history-state");
			changeLocation(currentState.current, currentState, true);
			changeLocation(to, assign({}, buildState(currentLocation.value, to, null), { position: currentState.position + 1 }, data), false);
			currentLocation.value = to;
		}
		return {
			location: currentLocation,
			state: historyState,
			push,
			replace
		};
	}
	/**
	* Creates an HTML5 history. Most common history for single page applications.
	*
	* @param base -
	*/
	function createWebHistory(base) {
		base = normalizeBase(base);
		const historyNavigation = useHistoryStateNavigation(base);
		const historyListeners = useHistoryListeners(base, historyNavigation.state, historyNavigation.location, historyNavigation.replace);
		function go(delta, triggerListeners = true) {
			if (!triggerListeners) historyListeners.pauseListeners();
			history.go(delta);
		}
		const routerHistory = assign({
			location: "",
			base,
			go,
			createHref: createHref.bind(null, base)
		}, historyNavigation, historyListeners);
		Object.defineProperty(routerHistory, "location", {
			enumerable: true,
			get: () => historyNavigation.location.value
		});
		Object.defineProperty(routerHistory, "state", {
			enumerable: true,
			get: () => historyNavigation.state.value
		});
		return routerHistory;
	}

//#endregion
//#region src/history/memory.ts
/**
	* Creates an in-memory based history. The main purpose of this history is to handle SSR. It starts in a special location that is nowhere.
	* It's up to the user to replace that location with the starter location by either calling `router.push` or `router.replace`.
	*
	* @param base - Base applied to all urls, defaults to '/'
	* @returns a history object that can be passed to the router constructor
	*/
	function createMemoryHistory(base = "") {
		let listeners = [];
		let queue = [[START, {}]];
		let position = 0;
		base = normalizeBase(base);
		function setLocation(location, state = {}) {
			position++;
			if (position !== queue.length) queue.splice(position);
			queue.push([location, state]);
		}
		function triggerListeners(to, from, { direction, delta }) {
			const info = {
				direction,
				delta,
				type: NavigationType.pop
			};
			for (const callback of listeners) callback(to, from, info);
		}
		const routerHistory = {
			location: START,
			state: {},
			base,
			createHref: createHref.bind(null, base),
			replace(to, state) {
				queue.splice(position--, 1);
				setLocation(to, state);
			},
			push(to, state) {
				setLocation(to, state);
			},
			listen(callback) {
				listeners.push(callback);
				return () => {
					const index = listeners.indexOf(callback);
					if (index > -1) listeners.splice(index, 1);
				};
			},
			destroy() {
				listeners = [];
				queue = [[START, {}]];
				position = 0;
			},
			go(delta, shouldTrigger = true) {
				const from = this.location;
				const direction = delta < 0 ? NavigationDirection.back : NavigationDirection.forward;
				position = Math.max(0, Math.min(position + delta, queue.length - 1));
				if (shouldTrigger) triggerListeners(this.location, from, {
					direction,
					delta
				});
			}
		};
		Object.defineProperty(routerHistory, "location", {
			enumerable: true,
			get: () => queue[position][0]
		});
		Object.defineProperty(routerHistory, "state", {
			enumerable: true,
			get: () => queue[position][1]
		});
		return routerHistory;
	}

//#endregion
//#region src/history/hash.ts
/**
	* Creates a hash history. Useful for web applications with no host (e.g. `file://`) or when configuring a server to
	* handle any URL is not possible.
	*
	* @param base - optional base to provide. Defaults to `location.pathname + location.search` If there is a `<base>` tag
	* in the `head`, its value will be ignored in favor of this parameter **but note it affects all the history.pushState()
	* calls**, meaning that if you use a `<base>` tag, it's `href` value **has to match this parameter** (ignoring anything
	* after the `#`).
	*
	* @example
	* ```js
	* // at https://example.com/folder
	* createWebHashHistory() // gives a url of `https://example.com/folder#`
	* createWebHashHistory('/folder/') // gives a url of `https://example.com/folder/#`
	* // if the `#` is provided in the base, it won't be added by `createWebHashHistory`
	* createWebHashHistory('/folder/#/app/') // gives a url of `https://example.com/folder/#/app/`
	* // you should avoid doing this because it changes the original url and breaks copying urls
	* createWebHashHistory('/other-folder/') // gives a url of `https://example.com/other-folder/#`
	*
	* // at file:///usr/etc/folder/index.html
	* // for locations with no `host`, the base is ignored
	* createWebHashHistory('/iAmIgnored') // gives a url of `file:///usr/etc/folder/index.html#`
	* ```
	*/
	function createWebHashHistory(base) {
		base = location.host ? base || location.pathname + location.search : "";
		if (!base.includes("#")) base += "#";
		if (!base.endsWith("#/") && !base.endsWith("#")) warn(`A hash base must end with a "#":\n"${base}" should be "${base.replace(/#.*$/, "#")}".`);
		return createWebHistory(base);
	}

//#endregion
//#region src/types/typeGuards.ts
	function isRouteLocation(route) {
		return typeof route === "string" || route && typeof route === "object";
	}
	function isRouteName(name) {
		return typeof name === "string" || typeof name === "symbol";
	}

//#endregion
//#region src/errors.ts
/**
	* Flags so we can combine them when checking for multiple errors. This is the internal version of
	* {@link NavigationFailureType}.
	*
	* @internal
	*/
	let ErrorTypes = /* @__PURE__ */ function(ErrorTypes) {
		ErrorTypes[ErrorTypes["MATCHER_NOT_FOUND"] = 1] = "MATCHER_NOT_FOUND";
		ErrorTypes[ErrorTypes["NAVIGATION_GUARD_REDIRECT"] = 2] = "NAVIGATION_GUARD_REDIRECT";
		ErrorTypes[ErrorTypes["NAVIGATION_ABORTED"] = 4] = "NAVIGATION_ABORTED";
		ErrorTypes[ErrorTypes["NAVIGATION_CANCELLED"] = 8] = "NAVIGATION_CANCELLED";
		ErrorTypes[ErrorTypes["NAVIGATION_DUPLICATED"] = 16] = "NAVIGATION_DUPLICATED";
		return ErrorTypes;
	}({});
	const NavigationFailureSymbol = Symbol("navigation failure");
	/**
	* Enumeration with all possible types for navigation failures. Can be passed to
	* {@link isNavigationFailure} to check for specific failures.
	*/
	let NavigationFailureType = /* @__PURE__ */ function(NavigationFailureType) {
		/**
		* An aborted navigation is a navigation that failed because a navigation
		* guard returned `false` or called `next(false)`
		*/
		NavigationFailureType[NavigationFailureType["aborted"] = 4] = "aborted";
		/**
		* A cancelled navigation is a navigation that failed because a more recent
		* navigation finished started (not necessarily finished).
		*/
		NavigationFailureType[NavigationFailureType["cancelled"] = 8] = "cancelled";
		/**
		* A duplicated navigation is a navigation that failed because it was
		* initiated while already being at the exact same location.
		*/
		NavigationFailureType[NavigationFailureType["duplicated"] = 16] = "duplicated";
		return NavigationFailureType;
	}({});
	const ErrorTypeMessages = {
		[ErrorTypes.MATCHER_NOT_FOUND]({ location, currentLocation }) {
			return `No match for\n ${JSON.stringify(location)}${currentLocation ? "\nwhile being at\n" + JSON.stringify(currentLocation) : ""}`;
		},
		[ErrorTypes.NAVIGATION_GUARD_REDIRECT]({ from, to }) {
			return `Redirected from "${from.fullPath}" to "${stringifyRoute(to)}" via a navigation guard.`;
		},
		[ErrorTypes.NAVIGATION_ABORTED]({ from, to }) {
			return `Navigation aborted from "${from.fullPath}" to "${to.fullPath}" via a navigation guard.`;
		},
		[ErrorTypes.NAVIGATION_CANCELLED]({ from, to }) {
			return `Navigation cancelled from "${from.fullPath}" to "${to.fullPath}" with a new navigation.`;
		},
		[ErrorTypes.NAVIGATION_DUPLICATED]({ from, to }) {
			return `Avoided redundant navigation to current location: "${from.fullPath}".`;
		}
	};
	/**
	* Creates a typed NavigationFailure object.
	* @internal
	* @param type - NavigationFailureType
	* @param params - { from, to }
	*/
	function createRouterError(type, params) {
		return assign(new Error(ErrorTypeMessages[type](params)), {
			type,
			[NavigationFailureSymbol]: true
		}, params);
	}
	function isNavigationFailure(error, type) {
		return error instanceof Error && NavigationFailureSymbol in error && (type == null || !!(error.type & type));
	}
	const propertiesToLog = [
		"params",
		"query",
		"hash"
	];
	function stringifyRoute(to) {
		if (typeof to === "string") return to;
		if (to.path != null) return to.path;
		const location = {};
		for (const key of propertiesToLog) if (key in to) location[key] = to[key];
		return JSON.stringify(location, null, 2);
	}

//#endregion
//#region src/matcher/pathTokenizer.ts
	let TokenType = /* @__PURE__ */ function(TokenType) {
		TokenType[TokenType["Static"] = 0] = "Static";
		TokenType[TokenType["Param"] = 1] = "Param";
		TokenType[TokenType["Group"] = 2] = "Group";
		return TokenType;
	}({});
	var TokenizerState = /* @__PURE__ */ function(TokenizerState) {
		TokenizerState[TokenizerState["Static"] = 0] = "Static";
		TokenizerState[TokenizerState["Param"] = 1] = "Param";
		TokenizerState[TokenizerState["ParamRegExp"] = 2] = "ParamRegExp";
		TokenizerState[TokenizerState["ParamRegExpEnd"] = 3] = "ParamRegExpEnd";
		TokenizerState[TokenizerState["EscapeNext"] = 4] = "EscapeNext";
		return TokenizerState;
	}(TokenizerState || {});
	const ROOT_TOKEN = {
		type: TokenType.Static,
		value: ""
	};
	const VALID_PARAM_RE = /[a-zA-Z0-9_]/;
	function tokenizePath(path) {
		if (!path) return [[]];
		if (path === "/") return [[ROOT_TOKEN]];
		if (!path.startsWith("/")) throw new Error(`Route paths should start with a "/": "${path}" should be "/${path}".`);
		function crash(message) {
			throw new Error(`ERR (${state})/"${buffer}": ${message}`);
		}
		let state = TokenizerState.Static;
		let previousState = state;
		const tokens = [];
		let segment;
		function finalizeSegment() {
			if (segment) tokens.push(segment);
			segment = [];
		}
		let i = 0;
		let char;
		let buffer = "";
		let customRe = "";
		function consumeBuffer() {
			if (!buffer) return;
			if (state === TokenizerState.Static) segment.push({
				type: TokenType.Static,
				value: buffer
			});
			else if (state === TokenizerState.Param || state === TokenizerState.ParamRegExp || state === TokenizerState.ParamRegExpEnd) {
				if (segment.length > 1 && (char === "*" || char === "+")) crash(`A repeatable param (${buffer}) must be alone in its segment. eg: '/:ids+.`);
				segment.push({
					type: TokenType.Param,
					value: buffer,
					regexp: customRe,
					repeatable: char === "*" || char === "+",
					optional: char === "*" || char === "?"
				});
			} else crash("Invalid state to consume buffer");
			buffer = "";
		}
		function addCharToBuffer() {
			buffer += char;
		}
		while (i < path.length) {
			char = path[i++];
			if (char === "\\" && state !== TokenizerState.ParamRegExp) {
				previousState = state;
				state = TokenizerState.EscapeNext;
				continue;
			}
			switch (state) {
				case TokenizerState.Static:
					if (char === "/") {
						if (buffer) consumeBuffer();
						finalizeSegment();
					} else if (char === ":") {
						consumeBuffer();
						state = TokenizerState.Param;
					} else addCharToBuffer();
					break;
				case TokenizerState.EscapeNext:
					addCharToBuffer();
					state = previousState;
					break;
				case TokenizerState.Param:
					if (char === "(") state = TokenizerState.ParamRegExp;
					else if (VALID_PARAM_RE.test(char)) addCharToBuffer();
					else {
						consumeBuffer();
						state = TokenizerState.Static;
						if (char !== "*" && char !== "?" && char !== "+") i--;
					}
					break;
				case TokenizerState.ParamRegExp:
					if (char === ")") if (customRe[customRe.length - 1] == "\\") customRe = customRe.slice(0, -1) + char;
					else state = TokenizerState.ParamRegExpEnd;
					else customRe += char;
					break;
				case TokenizerState.ParamRegExpEnd:
					consumeBuffer();
					state = TokenizerState.Static;
					if (char !== "*" && char !== "?" && char !== "+") i--;
					customRe = "";
					break;
				default:
					crash("Unknown state");
					break;
			}
		}
		if (state === TokenizerState.ParamRegExp) crash(`Unfinished custom RegExp for param "${buffer}"`);
		consumeBuffer();
		finalizeSegment();
		return tokens;
	}

//#endregion
//#region src/matcher/pathParserRanker.ts
	const BASE_PARAM_PATTERN = "[^/]+?";
	const BASE_PATH_PARSER_OPTIONS = {
		sensitive: false,
		strict: false,
		start: true,
		end: true
	};
	var PathScore = /* @__PURE__ */ function(PathScore) {
		PathScore[PathScore["_multiplier"] = 10] = "_multiplier";
		PathScore[PathScore["Root"] = 90] = "Root";
		PathScore[PathScore["Segment"] = 40] = "Segment";
		PathScore[PathScore["SubSegment"] = 30] = "SubSegment";
		PathScore[PathScore["Static"] = 40] = "Static";
		PathScore[PathScore["Dynamic"] = 20] = "Dynamic";
		PathScore[PathScore["BonusCustomRegExp"] = 10] = "BonusCustomRegExp";
		PathScore[PathScore["BonusWildcard"] = -50] = "BonusWildcard";
		PathScore[PathScore["BonusRepeatable"] = -20] = "BonusRepeatable";
		PathScore[PathScore["BonusOptional"] = -8] = "BonusOptional";
		PathScore[PathScore["BonusStrict"] = .7000000000000001] = "BonusStrict";
		PathScore[PathScore["BonusCaseSensitive"] = .25] = "BonusCaseSensitive";
		return PathScore;
	}(PathScore || {});
	const REGEX_CHARS_RE = /[.+*?^${}()[\]/\\]/g;
	/**
	* Creates a path parser from an array of Segments (a segment is an array of Tokens)
	*
	* @param segments - array of segments returned by tokenizePath
	* @param extraOptions - optional options for the regexp
	* @returns a PathParser
	*/
	function tokensToParser(segments, extraOptions) {
		const options = assign({}, BASE_PATH_PARSER_OPTIONS, extraOptions);
		const score = [];
		let pattern = options.start ? "^" : "";
		const keys = [];
		for (const segment of segments) {
			const segmentScores = segment.length ? [] : [PathScore.Root];
			if (options.strict && !segment.length) pattern += "/";
			for (let tokenIndex = 0; tokenIndex < segment.length; tokenIndex++) {
				const token = segment[tokenIndex];
				let subSegmentScore = PathScore.Segment + (options.sensitive ? PathScore.BonusCaseSensitive : 0);
				if (token.type === TokenType.Static) {
					if (!tokenIndex) pattern += "/";
					pattern += token.value.replace(REGEX_CHARS_RE, "\\$&");
					subSegmentScore += PathScore.Static;
				} else if (token.type === TokenType.Param) {
					const { value, repeatable, optional, regexp } = token;
					keys.push({
						name: value,
						repeatable,
						optional
					});
					const re = regexp ? regexp : BASE_PARAM_PATTERN;
					if (re !== BASE_PARAM_PATTERN) {
						subSegmentScore += PathScore.BonusCustomRegExp;
						try {
							new RegExp(`(${re})`);
						} catch (err) {
							throw new Error(`Invalid custom RegExp for param "${value}" (${re}): ` + err.message);
						}
					}
					let subPattern = repeatable ? `((?:${re})(?:/(?:${re}))*)` : `(${re})`;
					if (!tokenIndex) subPattern = optional && segment.length < 2 ? `(?:/${subPattern})` : "/" + subPattern;
					if (optional) subPattern += "?";
					pattern += subPattern;
					subSegmentScore += PathScore.Dynamic;
					if (optional) subSegmentScore += PathScore.BonusOptional;
					if (repeatable) subSegmentScore += PathScore.BonusRepeatable;
					if (re === ".*") subSegmentScore += PathScore.BonusWildcard;
				}
				segmentScores.push(subSegmentScore);
			}
			score.push(segmentScores);
		}
		if (options.strict && options.end) {
			const i = score.length - 1;
			score[i][score[i].length - 1] += PathScore.BonusStrict;
		}
		if (!options.strict) pattern += "/?";
		if (options.end) pattern += "$";
		else if (options.strict && !pattern.endsWith("/")) pattern += "(?:/|$)";
		const re = new RegExp(pattern, options.sensitive ? "" : "i");
		function parse(path) {
			const match = path.match(re);
			const params = {};
			if (!match) return null;
			for (let i = 1; i < match.length; i++) {
				const value = match[i] || "";
				const key = keys[i - 1];
				params[key.name] = value && key.repeatable ? value.split("/") : value;
			}
			return params;
		}
		function stringify(params) {
			let path = "";
			let avoidDuplicatedSlash = false;
			for (const segment of segments) {
				if (!avoidDuplicatedSlash || !path.endsWith("/")) path += "/";
				avoidDuplicatedSlash = false;
				for (const token of segment) if (token.type === TokenType.Static) path += token.value;
				else if (token.type === TokenType.Param) {
					const { value, repeatable, optional } = token;
					const param = value in params ? params[value] : "";
					if (isArray(param) && !repeatable) throw new Error(`Provided param "${value}" is an array but it is not repeatable (* or + modifiers)`);
					const text = isArray(param) ? param.join("/") : param;
					if (!text) if (optional) {
						if (segment.length < 2) if (path.endsWith("/")) path = path.slice(0, -1);
						else avoidDuplicatedSlash = true;
					} else throw new Error(`Missing required param "${value}"`);
					path += text;
				}
			}
			return path || "/";
		}
		return {
			re,
			score,
			keys,
			parse,
			stringify
		};
	}
	/**
	* Compares an array of numbers as used in PathParser.score and returns a
	* number. This function can be used to `sort` an array
	*
	* @param a - first array of numbers
	* @param b - second array of numbers
	* @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b
	* should be sorted first
	*/
	function compareScoreArray(a, b) {
		let i = 0;
		while (i < a.length && i < b.length) {
			const diff = b[i] - a[i];
			if (diff) return diff;
			i++;
		}
		if (a.length < b.length) return a.length === 1 && a[0] === PathScore.Static + PathScore.Segment ? -1 : 1;
		else if (a.length > b.length) return b.length === 1 && b[0] === PathScore.Static + PathScore.Segment ? 1 : -1;
		return 0;
	}
	/**
	* Compare function that can be used with `sort` to sort an array of PathParser
	*
	* @param a - first PathParser
	* @param b - second PathParser
	* @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b
	*/
	function comparePathParserScore(a, b) {
		let i = 0;
		const aScore = a.score;
		const bScore = b.score;
		while (i < aScore.length && i < bScore.length) {
			const comp = compareScoreArray(aScore[i], bScore[i]);
			if (comp) return comp;
			i++;
		}
		if (Math.abs(bScore.length - aScore.length) === 1) {
			if (isLastScoreNegative(aScore)) return 1;
			if (isLastScoreNegative(bScore)) return -1;
		}
		return bScore.length - aScore.length;
	}
	/**
	* This allows detecting splats at the end of a path: /home/:id(.*)*
	*
	* @param score - score to check
	* @returns true if the last entry is negative
	*/
	function isLastScoreNegative(score) {
		const last = score[score.length - 1];
		return score.length > 0 && last[last.length - 1] < 0;
	}
	const PATH_PARSER_OPTIONS_DEFAULTS = {
		strict: false,
		end: true,
		sensitive: false
	};

//#endregion
//#region src/matcher/pathMatcher.ts
	function createRouteRecordMatcher(record, parent, options) {
		const parser = tokensToParser(tokenizePath(record.path), options);
		{
			const existingKeys = /* @__PURE__ */ new Set();
			for (const key of parser.keys) {
				if (existingKeys.has(key.name)) warn(`Found duplicated params with name "${key.name}" for path "${record.path}". Only the last one will be available on "$route.params".`);
				existingKeys.add(key.name);
			}
		}
		const matcher = assign(parser, {
			record,
			parent,
			children: [],
			alias: []
		});
		if (parent) {
			if (!matcher.record.aliasOf === !parent.record.aliasOf) parent.children.push(matcher);
		}
		return matcher;
	}

//#endregion
//#region src/matcher/index.ts
/**
	* Creates a Router Matcher.
	*
	* @internal
	* @param routes - array of initial routes
	* @param globalOptions - global route options
	*/
	function createRouterMatcher(routes, globalOptions) {
		const matchers = [];
		const matcherMap = /* @__PURE__ */ new Map();
		globalOptions = mergeOptions(PATH_PARSER_OPTIONS_DEFAULTS, globalOptions);
		function getRecordMatcher(name) {
			return matcherMap.get(name);
		}
		function addRoute(record, parent, originalRecord) {
			const isRootAdd = !originalRecord;
			const mainNormalizedRecord = normalizeRouteRecord(record);
			checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent);
			mainNormalizedRecord.aliasOf = originalRecord && originalRecord.record;
			const options = mergeOptions(globalOptions, record);
			const normalizedRecords = [mainNormalizedRecord];
			if ("alias" in record) {
				const aliases = typeof record.alias === "string" ? [record.alias] : record.alias;
				for (const alias of aliases) normalizedRecords.push(normalizeRouteRecord(assign({}, mainNormalizedRecord, {
					components: originalRecord ? originalRecord.record.components : mainNormalizedRecord.components,
					path: alias,
					aliasOf: originalRecord ? originalRecord.record : mainNormalizedRecord
				})));
			}
			let matcher;
			let originalMatcher;
			for (const normalizedRecord of normalizedRecords) {
				const { path } = normalizedRecord;
				if (parent && path[0] !== "/") {
					const parentPath = parent.record.path;
					const connectingSlash = parentPath[parentPath.length - 1] === "/" ? "" : "/";
					normalizedRecord.path = parent.record.path + (path && connectingSlash + path);
				}
				if (normalizedRecord.path === "*") throw new Error("Catch all routes (\"*\") must now be defined using a param with a custom regexp.\nSee more at https://router.vuejs.org/guide/migration/#Removed-star-or-catch-all-routes.");
				matcher = createRouteRecordMatcher(normalizedRecord, parent, options);
				if (parent && path[0] === "/") checkMissingParamsInAbsolutePath(matcher, parent);
				if (originalRecord) {
					originalRecord.alias.push(matcher);
					checkSameParams(originalRecord, matcher);
				} else {
					originalMatcher = originalMatcher || matcher;
					if (originalMatcher !== matcher) originalMatcher.alias.push(matcher);
					if (isRootAdd && record.name && !isAliasRecord(matcher)) {
						checkSameNameAsAncestor(record, parent);
						removeRoute(record.name);
					}
				}
				if (isMatchable(matcher)) insertMatcher(matcher);
				if (mainNormalizedRecord.children) {
					const children = mainNormalizedRecord.children;
					for (let i = 0; i < children.length; i++) addRoute(children[i], matcher, originalRecord && originalRecord.children[i]);
				}
				originalRecord = originalRecord || matcher;
			}
			return originalMatcher ? () => {
				removeRoute(originalMatcher);
			} : noop;
		}
		function removeRoute(matcherRef) {
			if (isRouteName(matcherRef)) {
				const matcher = matcherMap.get(matcherRef);
				if (matcher) {
					matcherMap.delete(matcherRef);
					matchers.splice(matchers.indexOf(matcher), 1);
					matcher.children.forEach(removeRoute);
					matcher.alias.forEach(removeRoute);
				}
			} else {
				const index = matchers.indexOf(matcherRef);
				if (index > -1) {
					matchers.splice(index, 1);
					if (matcherRef.record.name) matcherMap.delete(matcherRef.record.name);
					matcherRef.children.forEach(removeRoute);
					matcherRef.alias.forEach(removeRoute);
				}
			}
		}
		function getRoutes() {
			return matchers;
		}
		function insertMatcher(matcher) {
			const index = findInsertionIndex(matcher, matchers);
			matchers.splice(index, 0, matcher);
			if (matcher.record.name && !isAliasRecord(matcher)) matcherMap.set(matcher.record.name, matcher);
		}
		function resolve(location, currentLocation) {
			let matcher;
			let params = {};
			let path;
			let name;
			if ("name" in location && location.name) {
				matcher = matcherMap.get(location.name);
				if (!matcher) throw createRouterError(ErrorTypes.MATCHER_NOT_FOUND, { location });
				{
					const invalidParams = Object.keys(location.params || {}).filter((paramName) => !matcher.keys.find((k) => k.name === paramName));
					if (invalidParams.length) warn(`Discarded invalid param(s) "${invalidParams.join("\", \"")}" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.`);
				}
				name = matcher.record.name;
				params = assign(pickParams(currentLocation.params, matcher.keys.filter((k) => !k.optional).concat(matcher.parent ? matcher.parent.keys.filter((k) => k.optional) : []).map((k) => k.name)), location.params && pickParams(location.params, matcher.keys.map((k) => k.name)));
				path = matcher.stringify(params);
			} else if (location.path != null) {
				path = location.path;
				if (!path.startsWith("/")) warn(`The Matcher cannot resolve relative paths but received "${path}". Unless you directly called \`matcher.resolve("${path}")\`, this is probably a bug in vue-router. Please open an issue at https://github.com/vuejs/router/issues/new/choose.`);
				matcher = matchers.find((m) => m.re.test(path));
				if (matcher) {
					params = matcher.parse(path);
					name = matcher.record.name;
				}
			} else {
				matcher = currentLocation.name ? matcherMap.get(currentLocation.name) : matchers.find((m) => m.re.test(currentLocation.path));
				if (!matcher) throw createRouterError(ErrorTypes.MATCHER_NOT_FOUND, {
					location,
					currentLocation
				});
				name = matcher.record.name;
				params = assign({}, currentLocation.params, location.params);
				path = matcher.stringify(params);
			}
			const matched = [];
			let parentMatcher = matcher;
			while (parentMatcher) {
				matched.unshift(parentMatcher.record);
				parentMatcher = parentMatcher.parent;
			}
			return {
				name,
				path,
				params,
				matched,
				meta: mergeMetaFields(matched)
			};
		}
		routes.forEach((route) => addRoute(route));
		function clearRoutes() {
			matchers.length = 0;
			matcherMap.clear();
		}
		return {
			addRoute,
			resolve,
			removeRoute,
			clearRoutes,
			getRoutes,
			getRecordMatcher
		};
	}
	/**
	* Picks an object param to contain only specified keys.
	*
	* @param params - params object to pick from
	* @param keys - keys to pick
	*/
	function pickParams(params, keys) {
		const newParams = {};
		for (const key of keys) if (key in params) newParams[key] = params[key];
		return newParams;
	}
	/**
	* Normalizes a RouteRecordRaw. Creates a copy
	*
	* @param record
	* @returns the normalized version
	*/
	function normalizeRouteRecord(record) {
		const normalized = {
			path: record.path,
			redirect: record.redirect,
			name: record.name,
			meta: record.meta || {},
			aliasOf: record.aliasOf,
			beforeEnter: record.beforeEnter,
			props: normalizeRecordProps(record),
			children: record.children || [],
			instances: {},
			leaveGuards: /* @__PURE__ */ new Set(),
			updateGuards: /* @__PURE__ */ new Set(),
			enterCallbacks: {},
			components: "components" in record ? record.components || null : record.component && { default: record.component }
		};
		Object.defineProperty(normalized, "mods", { value: {} });
		return normalized;
	}
	/**
	* Normalize the optional `props` in a record to always be an object similar to
	* components. Also accept a boolean for components.
	* @param record
	*/
	function normalizeRecordProps(record) {
		const propsObject = {};
		const props = record.props || false;
		if ("component" in record) propsObject.default = props;
		else for (const name in record.components) propsObject[name] = typeof props === "object" ? props[name] : props;
		return propsObject;
	}
	/**
	* Checks if a record or any of its parent is an alias
	* @param record
	*/
	function isAliasRecord(record) {
		while (record) {
			if (record.record.aliasOf) return true;
			record = record.parent;
		}
		return false;
	}
	/**
	* Merge meta fields of an array of records
	*
	* @param matched - array of matched records
	*/
	function mergeMetaFields(matched) {
		return matched.reduce((meta, record) => assign(meta, record.meta), {});
	}
	function isSameParam(a, b) {
		return a.name === b.name && a.optional === b.optional && a.repeatable === b.repeatable;
	}
	/**
	* Check if a path and its alias have the same required params
	*
	* @param a - original record
	* @param b - alias record
	*/
	function checkSameParams(a, b) {
		for (const key of a.keys) if (!key.optional && !b.keys.find(isSameParam.bind(null, key))) return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`);
		for (const key of b.keys) if (!key.optional && !a.keys.find(isSameParam.bind(null, key))) return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`);
	}
	/**
	* A route with a name and a child with an empty path without a name should warn when adding the route
	*
	* @param mainNormalizedRecord - RouteRecordNormalized
	* @param parent - RouteRecordMatcher
	*/
	function checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent) {
		if (parent && parent.record.name && !mainNormalizedRecord.name && !mainNormalizedRecord.path && mainNormalizedRecord.children.length === 0) warn(`The route named "${String(parent.record.name)}" has a child without a name, an empty path, and no children. This is probably a mistake: using that name won't render the empty path child so you probably want to move the name to the child instead. If this is intentional, add a name to the child route to silence the warning.`);
	}
	function checkSameNameAsAncestor(record, parent) {
		for (let ancestor = parent; ancestor; ancestor = ancestor.parent) if (ancestor.record.name === record.name) throw new Error(`A route named "${String(record.name)}" has been added as a ${parent === ancestor ? "child" : "descendant"} of a route with the same name. Route names must be unique and a nested route cannot use the same name as an ancestor.`);
	}
	function checkMissingParamsInAbsolutePath(record, parent) {
		for (const key of parent.keys) if (!record.keys.find(isSameParam.bind(null, key))) return warn(`Absolute path "${record.record.path}" must have the exact same param named "${key.name}" as its parent "${parent.record.path}".`);
	}
	/**
	* Performs a binary search to find the correct insertion index for a new matcher.
	*
	* Matchers are primarily sorted by their score. If scores are tied then we also consider parent/child relationships,
	* with descendants coming before ancestors. If there's still a tie, new routes are inserted after existing routes.
	*
	* @param matcher - new matcher to be inserted
	* @param matchers - existing matchers
	*/
	function findInsertionIndex(matcher, matchers) {
		let lower = 0;
		let upper = matchers.length;
		while (lower !== upper) {
			const mid = lower + upper >> 1;
			if (comparePathParserScore(matcher, matchers[mid]) < 0) upper = mid;
			else lower = mid + 1;
		}
		const insertionAncestor = getInsertionAncestor(matcher);
		if (insertionAncestor) {
			upper = matchers.lastIndexOf(insertionAncestor, upper - 1);
			if (upper < 0) warn(`Finding ancestor route "${insertionAncestor.record.path}" failed for "${matcher.record.path}"`);
		}
		return upper;
	}
	function getInsertionAncestor(matcher) {
		let ancestor = matcher;
		while (ancestor = ancestor.parent) if (isMatchable(ancestor) && comparePathParserScore(matcher, ancestor) === 0) return ancestor;
	}
	/**
	* Checks if a matcher can be reachable. This means if it's possible to reach it as a route. For example, routes without
	* a component, or name, or redirect, are just used to group other routes.
	* @param matcher
	* @param matcher.record record of the matcher
	* @returns
	*/
	function isMatchable({ record }) {
		return !!(record.name || record.components && Object.keys(record.components).length || record.redirect);
	}

//#endregion
//#region src/query.ts
/**
	* Transforms a queryString into a {@link LocationQuery} object. Accept both, a
	* version with the leading `?` and without Should work as URLSearchParams
	
	* @internal
	*
	* @param search - search string to parse
	* @returns a query object
	*/
	function parseQuery(search) {
		const query = {};
		if (search === "" || search === "?") return query;
		const searchParams = (search[0] === "?" ? search.slice(1) : search).split("&");
		for (let i = 0; i < searchParams.length; ++i) {
			const searchParam = searchParams[i].replace(PLUS_RE, " ");
			const eqPos = searchParam.indexOf("=");
			const key = decode(eqPos < 0 ? searchParam : searchParam.slice(0, eqPos));
			const value = eqPos < 0 ? null : decode(searchParam.slice(eqPos + 1));
			if (key in query) {
				let currentValue = query[key];
				if (!isArray(currentValue)) currentValue = query[key] = [currentValue];
				currentValue.push(value);
			} else query[key] = value;
		}
		return query;
	}
	/**
	* Stringifies a {@link LocationQueryRaw} object. Like `URLSearchParams`, it
	* doesn't prepend a `?`
	*
	* @internal
	*
	* @param query - query object to stringify
	* @returns string version of the query without the leading `?`
	*/
	function stringifyQuery(query) {
		let search = "";
		for (let key in query) {
			const value = query[key];
			key = encodeQueryKey(key);
			if (value == null) {
				if (value !== void 0) search += (search.length ? "&" : "") + key;
				continue;
			}
			(isArray(value) ? value.map((v) => v && encodeQueryValue(v)) : [value && encodeQueryValue(value)]).forEach((value) => {
				if (value !== void 0) {
					search += (search.length ? "&" : "") + key;
					if (value != null) search += "=" + value;
				}
			});
		}
		return search;
	}
	/**
	* Transforms a {@link LocationQueryRaw} into a {@link LocationQuery} by casting
	* numbers into strings, removing keys with an undefined value and replacing
	* undefined with null in arrays
	*
	* @param query - query object to normalize
	* @returns a normalized query object
	*/
	function normalizeQuery(query) {
		const normalizedQuery = {};
		for (const key in query) {
			const value = query[key];
			if (value !== void 0) normalizedQuery[key] = isArray(value) ? value.map((v) => v == null ? null : "" + v) : value == null ? value : "" + value;
		}
		return normalizedQuery;
	}

//#endregion
//#region src/injectionSymbols.ts
/**
	* RouteRecord being rendered by the closest ancestor Router View. Used for
	* `onBeforeRouteUpdate` and `onBeforeRouteLeave`. rvlm stands for Router View
	* Location Matched
	*
	* @internal
	*/
	const matchedRouteKey = Symbol("router view location matched");
	/**
	* Allows overriding the router view depth to control which component in
	* `matched` is rendered. rvd stands for Router View Depth
	*
	* @internal
	*/
	const viewDepthKey = Symbol("router view depth");
	/**
	* Allows overriding the router instance returned by `useRouter` in tests. r
	* stands for router
	*
	* @internal
	*/
	const routerKey = Symbol("router");
	/**
	* Allows overriding the current route returned by `useRoute` in tests. rl
	* stands for route location
	*
	* @internal
	*/
	const routeLocationKey = Symbol("route location");
	/**
	* Allows overriding the current route used by router-view. Internally this is
	* used when the `route` prop is passed.
	*
	* @internal
	*/
	const routerViewLocationKey = Symbol("router view location");

//#endregion
//#region src/utils/callbacks.ts
/**
	* Create a list of callbacks that can be reset. Used to create before and after navigation guards list
	*/
	function useCallbacks() {
		let handlers = [];
		function add(handler) {
			handlers.push(handler);
			return () => {
				const i = handlers.indexOf(handler);
				if (i > -1) handlers.splice(i, 1);
			};
		}
		function reset() {
			handlers = [];
		}
		return {
			add,
			list: () => handlers.slice(),
			reset
		};
	}

//#endregion
//#region src/navigationGuards.ts
	function registerGuard(activeRecordRef, name, guard) {
		const record = activeRecordRef.value;
		if (!record) {
			warn(`No active route record was found when calling \`${name === "updateGuards" ? "onBeforeRouteUpdate" : "onBeforeRouteLeave"}()\`. Make sure you call this function inside a component child of <router-view>. Maybe you called it inside of App.vue?`);
			return;
		}
		let currentRecord = record;
		const removeFromList = () => {
			currentRecord[name].delete(guard);
		};
		(0, vue.onUnmounted)(removeFromList);
		(0, vue.onDeactivated)(removeFromList);
		(0, vue.onActivated)(() => {
			const newRecord = activeRecordRef.value;
			if (!newRecord) warn("No active route record was found when reactivating component with navigation guard. This is likely a bug in vue-router. Please report it.");
			if (newRecord) currentRecord = newRecord;
			currentRecord[name].add(guard);
		});
		currentRecord[name].add(guard);
	}
	/**
	* Add a navigation guard that triggers whenever the component for the current
	* location is about to be left. Similar to {@link beforeRouteLeave} but can be
	* used in any component. The guard is removed when the component is unmounted.
	*
	* @param leaveGuard - {@link NavigationGuard}
	*/
	function onBeforeRouteLeave(leaveGuard) {
		if (!(0, vue.getCurrentInstance)()) {
			warn("getCurrentInstance() returned null. onBeforeRouteLeave() must be called at the top of a setup function");
			return;
		}
		registerGuard((0, vue.inject)(matchedRouteKey, {}), "leaveGuards", leaveGuard);
	}
	/**
	* Add a navigation guard that triggers whenever the current location is about
	* to be updated. Similar to {@link beforeRouteUpdate} but can be used in any
	* component. The guard is removed when the component is unmounted.
	*
	* @param updateGuard - {@link NavigationGuard}
	*/
	function onBeforeRouteUpdate(updateGuard) {
		if (!(0, vue.getCurrentInstance)()) {
			warn("getCurrentInstance() returned null. onBeforeRouteUpdate() must be called at the top of a setup function");
			return;
		}
		registerGuard((0, vue.inject)(matchedRouteKey, {}), "updateGuards", updateGuard);
	}
	function guardToPromiseFn(guard, to, from, record, name, runWithContext = (fn) => fn()) {
		const enterCallbackArray = record && (record.enterCallbacks[name] = record.enterCallbacks[name] || []);
		return () => new Promise((resolve, reject) => {
			const next = (valid) => {
				if (valid === false) reject(createRouterError(ErrorTypes.NAVIGATION_ABORTED, {
					from,
					to
				}));
				else if (valid instanceof Error) reject(valid);
				else if (isRouteLocation(valid)) reject(createRouterError(ErrorTypes.NAVIGATION_GUARD_REDIRECT, {
					from: to,
					to: valid
				}));
				else {
					if (enterCallbackArray && record.enterCallbacks[name] === enterCallbackArray && typeof valid === "function") enterCallbackArray.push(valid);
					resolve();
				}
			};
			const guardReturn = runWithContext(() => guard.call(record && record.instances[name], to, from, withDeprecationWarning(canOnlyBeCalledOnce(next, to, from))));
			let guardCall = Promise.resolve(guardReturn);
			if (guard.length < 3) guardCall = guardCall.then(next);
			if (guard.length > 2) {
				const message = `The "next" callback was never called inside of ${guard.name ? "\"" + guard.name + "\"" : ""}:\n${guard.toString()}\n. If you are returning a value instead of calling "next", make sure to remove the "next" parameter from your function.`;
				if (typeof guardReturn === "object" && "then" in guardReturn) guardCall = guardCall.then((resolvedValue) => {
					if (!next._called) {
						warn(message);
						return Promise.reject(/* @__PURE__ */ new Error("Invalid navigation guard"));
					}
					return resolvedValue;
				});
				else if (guardReturn !== void 0) {
					if (!next._called) {
						warn(message);
						reject(/* @__PURE__ */ new Error("Invalid navigation guard"));
						return;
					}
				}
			}
			guardCall.catch((err) => reject(err));
		});
	}
	/**
	* Wraps the next callback to warn when it is used. Dev-only: when __DEV__ is
	* false (production builds), this branch is dead code and is stripped from the
	* bundle.
	*
	* @internal
	*/
	function withDeprecationWarning(next) {
		let warned = false;
		return function() {
			if (!warned) {
				warned = true;
				warn("The `next()` callback in navigation guards is deprecated. Return the value instead of calling `next(value)`.");
			}
			return next.apply(this, arguments);
		};
	}
	function canOnlyBeCalledOnce(next, to, from) {
		let called = 0;
		return function() {
			if (called++ === 1) warn(`The "next" callback was called more than once in one navigation guard when going from "${from.fullPath}" to "${to.fullPath}". It should be called exactly one time in each navigation guard. This will fail in production.`);
			next._called = true;
			if (called === 1) next.apply(null, arguments);
		};
	}
	function extractComponentsGuards(matched, guardType, to, from, runWithContext = (fn) => fn()) {
		const guards = [];
		for (const record of matched) {
			if (!record.components && record.children && !record.children.length) warn(`Record with path "${record.path}" is either missing a "component(s)" or "children" property.`);
			for (const name in record.components) {
				let rawComponent = record.components[name];
				if (!rawComponent || typeof rawComponent !== "object" && typeof rawComponent !== "function") {
					warn(`Component "${name}" in record with path "${record.path}" is not a valid component. Received "${String(rawComponent)}".`);
					throw new Error("Invalid route component");
				} else if ("then" in rawComponent) {
					warn(`Component "${name}" in record with path "${record.path}" is a Promise instead of a function that returns a Promise. Did you write "import('./MyPage.vue')" instead of "() => import('./MyPage.vue')" ? This will break in production if not fixed.`);
					const promise = rawComponent;
					rawComponent = () => promise;
				} else if (rawComponent.__asyncLoader && !rawComponent.__warnedDefineAsync) {
					rawComponent.__warnedDefineAsync = true;
					warn(`Component "${name}" in record with path "${record.path}" is defined using "defineAsyncComponent()". Write "() => import('./MyPage.vue')" instead of "defineAsyncComponent(() => import('./MyPage.vue'))".`);
				}
				if (guardType !== "beforeRouteEnter" && !record.instances[name]) continue;
				if (isRouteComponent(rawComponent)) {
					const guard = (rawComponent.__vccOpts || rawComponent)[guardType];
					guard && guards.push(guardToPromiseFn(guard, to, from, record, name, runWithContext));
				} else {
					let componentPromise = rawComponent();
					if (!("catch" in componentPromise)) {
						warn(`Component "${name}" in record with path "${record.path}" is a function that does not return a Promise. If you were passing a functional component, make sure to add a "displayName" to the component. This will break in production if not fixed.`);
						componentPromise = Promise.resolve(componentPromise);
					}
					guards.push(() => componentPromise.then((resolved) => {
						if (!resolved) throw new Error(`Couldn't resolve component "${name}" at "${record.path}"`);
						const resolvedComponent = isESModule(resolved) ? resolved.default : resolved;
						record.mods[name] = resolved;
						record.components[name] = resolvedComponent;
						const guard = (resolvedComponent.__vccOpts || resolvedComponent)[guardType];
						return guard && guardToPromiseFn(guard, to, from, record, name, runWithContext)();
					}));
				}
			}
		}
		return guards;
	}
	/**
	* Ensures a route is loaded, so it can be passed as o prop to `<RouterView>`.
	*
	* @param route - resolved route to load
	*/
	function loadRouteLocation(route) {
		return route.matched.every((record) => record.redirect) ? Promise.reject(/* @__PURE__ */ new Error("Cannot load a route that redirects.")) : Promise.all(route.matched.map((record) => record.components && Promise.all(Object.keys(record.components).reduce((promises, name) => {
			const rawComponent = record.components[name];
			if (typeof rawComponent === "function" && !("displayName" in rawComponent)) promises.push(rawComponent().then((resolved) => {
				if (!resolved) return Promise.reject(/* @__PURE__ */ new Error(`Couldn't resolve component "${name}" at "${record.path}". Ensure you passed a function that returns a promise.`));
				const resolvedComponent = isESModule(resolved) ? resolved.default : resolved;
				record.mods[name] = resolved;
				record.components[name] = resolvedComponent;
			}));
			return promises;
		}, [])))).then(() => route);
	}
	/**
	* Split the leaving, updating, and entering records.
	* @internal
	*
	* @param  to - Location we are navigating to
	* @param from - Location we are navigating from
	*/
	function extractChangingRecords(to, from) {
		const leavingRecords = [];
		const updatingRecords = [];
		const enteringRecords = [];
		const len = Math.max(from.matched.length, to.matched.length);
		for (let i = 0; i < len; i++) {
			const recordFrom = from.matched[i];
			if (recordFrom) if (to.matched.find((record) => isSameRouteRecord(record, recordFrom))) updatingRecords.push(recordFrom);
			else leavingRecords.push(recordFrom);
			const recordTo = to.matched[i];
			if (recordTo) {
				if (!from.matched.find((record) => isSameRouteRecord(record, recordTo))) enteringRecords.push(recordTo);
			}
		}
		return [
			leavingRecords,
			updatingRecords,
			enteringRecords
		];
	}

//#endregion
//#region src/RouterLink.ts
/**
	* Returns the internal behavior of a {@link RouterLink} without the rendering part.
	*
	* @param props - a `to` location and an optional `replace` flag
	*/
	function useLink(props) {
		const router = (0, vue.inject)(routerKey);
		const currentRoute = (0, vue.inject)(routeLocationKey);
		let hasPrevious = false;
		let previousTo = null;
		const route = (0, vue.computed)(() => {
			const to = (0, vue.unref)(props.to);
			if (!hasPrevious || to !== previousTo) {
				if (!isRouteLocation(to)) if (hasPrevious) warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- previous to:`, previousTo, `\n- props:`, props);
				else warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- props:`, props);
				previousTo = to;
				hasPrevious = true;
			}
			return router.resolve(to);
		});
		const activeRecordIndex = (0, vue.computed)(() => {
			const { matched } = route.value;
			const { length } = matched;
			const routeMatched = matched[length - 1];
			const currentMatched = currentRoute.matched;
			if (!routeMatched || !currentMatched.length) return -1;
			const index = currentMatched.findIndex(isSameRouteRecord.bind(null, routeMatched));
			if (index > -1) return index;
			const parentRecordPath = getOriginalPath(matched[length - 2]);
			return length > 1 && getOriginalPath(routeMatched) === parentRecordPath && currentMatched[currentMatched.length - 1].path !== parentRecordPath ? currentMatched.findIndex(isSameRouteRecord.bind(null, matched[length - 2])) : index;
		});
		const isActive = (0, vue.computed)(() => activeRecordIndex.value > -1 && includesParams(currentRoute.params, route.value.params));
		const isExactActive = (0, vue.computed)(() => activeRecordIndex.value > -1 && activeRecordIndex.value === currentRoute.matched.length - 1 && isSameRouteLocationParams(currentRoute.params, route.value.params));
		function navigate(e = {}) {
			if (guardEvent(e)) {
				const p = router[(0, vue.unref)(props.replace) ? "replace" : "push"]((0, vue.unref)(props.to)).catch(noop);
				if (props.viewTransition && typeof document !== "undefined" && "startViewTransition" in document) document.startViewTransition(() => p);
				return p;
			}
			return Promise.resolve();
		}
		if (isBrowser) {
			const instance = (0, vue.getCurrentInstance)();
			if (instance) {
				const linkContextDevtools = {
					route: route.value,
					isActive: isActive.value,
					isExactActive: isExactActive.value,
					error: null
				};
				instance.__vrl_devtools = instance.__vrl_devtools || [];
				instance.__vrl_devtools.push(linkContextDevtools);
				(0, vue.watchEffect)(() => {
					linkContextDevtools.route = route.value;
					linkContextDevtools.isActive = isActive.value;
					linkContextDevtools.isExactActive = isExactActive.value;
					linkContextDevtools.error = isRouteLocation((0, vue.unref)(props.to)) ? null : "Invalid \"to\" value";
				}, { flush: "post" });
			}
		}
		/**
		* NOTE: update {@link _RouterLinkI}'s `$slots` type when updating this
		*/
		return {
			route,
			href: (0, vue.computed)(() => route.value.href),
			isActive,
			isExactActive,
			navigate
		};
	}
	function preferSingleVNode(vnodes) {
		return vnodes.length === 1 ? vnodes[0] : vnodes;
	}
	const RouterLinkImpl = /* @__PURE__ */ (0, vue.defineComponent)({
		name: "RouterLink",
		compatConfig: { MODE: 3 },
		props: {
			to: {
				type: [String, Object],
				required: true
			},
			replace: Boolean,
			activeClass: String,
			exactActiveClass: String,
			custom: Boolean,
			ariaCurrentValue: {
				type: String,
				default: "page"
			},
			viewTransition: Boolean
		},
		useLink,
		setup(props, { slots }) {
			const link = (0, vue.reactive)(useLink(props));
			const { options } = (0, vue.inject)(routerKey);
			const elClass = (0, vue.computed)(() => ({
				[getLinkClass(props.activeClass, options.linkActiveClass, "router-link-active")]: link.isActive,
				[getLinkClass(props.exactActiveClass, options.linkExactActiveClass, "router-link-exact-active")]: link.isExactActive
			}));
			return () => {
				const children = slots.default && preferSingleVNode(slots.default(link));
				return props.custom ? children : (0, vue.h)("a", {
					"aria-current": link.isExactActive ? props.ariaCurrentValue : null,
					href: link.href,
					onClick: link.navigate,
					class: elClass.value
				}, children);
			};
		}
	});
	/**
	* Component to render a link that triggers a navigation on click.
	*/
	const RouterLink = RouterLinkImpl;
	function guardEvent(e) {
		if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return;
		if (e.defaultPrevented) return;
		if (e.button !== void 0 && e.button !== 0) return;
		if (e.currentTarget && e.currentTarget.getAttribute) {
			const target = e.currentTarget.getAttribute("target");
			if (/\b_blank\b/i.test(target)) return;
		}
		if (e.preventDefault) e.preventDefault();
		return true;
	}
	function includesParams(outer, inner) {
		for (const key in inner) {
			const innerValue = inner[key];
			const outerValue = outer[key];
			if (typeof innerValue === "string") {
				if (innerValue !== outerValue) return false;
			} else if (!isArray(outerValue) || outerValue.length !== innerValue.length || innerValue.some((value, i) => value.valueOf() !== outerValue[i].valueOf())) return false;
		}
		return true;
	}
	/**
	* Get the original path value of a record by following its aliasOf
	* @param record
	*/
	function getOriginalPath(record) {
		return record ? record.aliasOf ? record.aliasOf.path : record.path : "";
	}
	/**
	* Utility class to get the active class based on defaults.
	* @param propClass
	* @param globalClass
	* @param defaultClass
	*/
	const getLinkClass = (propClass, globalClass, defaultClass) => propClass != null ? propClass : globalClass != null ? globalClass : defaultClass;

//#endregion
//#region src/RouterView.ts
	const RouterViewImpl = /* @__PURE__ */ (0, vue.defineComponent)({
		name: "RouterView",
		inheritAttrs: false,
		props: {
			name: {
				type: String,
				default: "default"
			},
			route: Object
		},
		compatConfig: { MODE: 3 },
		setup(props, { attrs, slots }) {
			warnDeprecatedUsage();
			const injectedRoute = (0, vue.inject)(routerViewLocationKey);
			const routeToDisplay = (0, vue.computed)(() => props.route || injectedRoute.value);
			const injectedDepth = (0, vue.inject)(viewDepthKey, 0);
			const depth = (0, vue.computed)(() => {
				let initialDepth = (0, vue.unref)(injectedDepth);
				const { matched } = routeToDisplay.value;
				let matchedRoute;
				while ((matchedRoute = matched[initialDepth]) && !matchedRoute.components) initialDepth++;
				return initialDepth;
			});
			const matchedRouteRef = (0, vue.computed)(() => routeToDisplay.value.matched[depth.value]);
			(0, vue.provide)(viewDepthKey, (0, vue.computed)(() => depth.value + 1));
			(0, vue.provide)(matchedRouteKey, matchedRouteRef);
			(0, vue.provide)(routerViewLocationKey, routeToDisplay);
			const viewRef = (0, vue.ref)();
			(0, vue.watch)(() => [
				viewRef.value,
				matchedRouteRef.value,
				props.name
			], ([instance, to, name], [oldInstance, from, oldName]) => {
				if (to) {
					to.instances[name] = instance;
					if (from && from !== to && instance && instance === oldInstance) {
						if (!to.leaveGuards.size) to.leaveGuards = from.leaveGuards;
						if (!to.updateGuards.size) to.updateGuards = from.updateGuards;
					}
				}
				if (instance && to && (!from || !isSameRouteRecord(to, from) || !oldInstance)) (to.enterCallbacks[name] || []).forEach((callback) => callback(instance));
			}, { flush: "post" });
			return () => {
				const route = routeToDisplay.value;
				const currentName = props.name;
				const matchedRoute = matchedRouteRef.value;
				const ViewComponent = matchedRoute && matchedRoute.components[currentName];
				if (!ViewComponent) return normalizeSlot(slots.default, {
					Component: ViewComponent,
					route
				});
				const routePropsOption = matchedRoute.props[currentName];
				const routeProps = routePropsOption ? routePropsOption === true ? route.params : typeof routePropsOption === "function" ? routePropsOption(route) : routePropsOption : null;
				const onVnodeUnmounted = (vnode) => {
					if (vnode.component.isUnmounted) matchedRoute.instances[currentName] = null;
				};
				const component = (0, vue.h)(ViewComponent, assign({}, routeProps, attrs, {
					onVnodeUnmounted,
					ref: viewRef
				}));
				if (isBrowser && component.ref) {
					const info = {
						depth: depth.value,
						name: matchedRoute.name,
						path: matchedRoute.path,
						meta: matchedRoute.meta
					};
					(isArray(component.ref) ? component.ref.map((r) => r.i) : [component.ref.i]).forEach((instance) => {
						instance.__vrv_devtools = info;
					});
				}
				return normalizeSlot(slots.default, {
					Component: component,
					route
				}) || component;
			};
		}
	});
	function normalizeSlot(slot, data) {
		if (!slot) return null;
		const slotContent = slot(data);
		return slotContent.length === 1 ? slotContent[0] : slotContent;
	}
	/**
	* Component to display the current route the user is at.
	*/
	const RouterView = RouterViewImpl;
	function warnDeprecatedUsage() {
		const instance = (0, vue.getCurrentInstance)();
		const parentName = instance.parent && instance.parent.type.name;
		const parentSubTreeType = instance.parent && instance.parent.subTree && instance.parent.subTree.type;
		if (parentName && (parentName === "KeepAlive" || parentName.includes("Transition")) && typeof parentSubTreeType === "object" && parentSubTreeType.name === "RouterView") {
			const comp = parentName === "KeepAlive" ? "keep-alive" : "transition";
			warn(`<router-view> can no longer be used directly inside <transition> or <keep-alive>.
Use slot props instead:

<router-view v-slot="{ Component }">
  <${comp}>\n    <component :is="Component" />\n  </${comp}>\n</router-view>`);
		}
	}

//#endregion
//#region src/router.ts
/**
	* Creates a Router instance that can be used by a Vue app.
	*
	* @param options - {@link RouterOptions}
	*/
	function createRouter(options) {
		const matcher = createRouterMatcher(options.routes, options);
		const parseQuery$1 = options.parseQuery || parseQuery;
		const stringifyQuery$1 = options.stringifyQuery || stringifyQuery;
		const routerHistory = options.history;
		if (!routerHistory) throw new Error("Provide the \"history\" option when calling \"createRouter()\": https://router.vuejs.org/api/interfaces/RouterOptions.html#history");
		const beforeGuards = useCallbacks();
		const beforeResolveGuards = useCallbacks();
		const afterGuards = useCallbacks();
		const currentRoute = (0, vue.shallowRef)(START_LOCATION_NORMALIZED);
		let pendingLocation = START_LOCATION_NORMALIZED;
		if (isBrowser && options.scrollBehavior && "scrollRestoration" in history) history.scrollRestoration = "manual";
		const normalizeParams = applyToParams.bind(null, (paramValue) => "" + paramValue);
		const encodeParams = applyToParams.bind(null, encodeParam);
		const decodeParams = applyToParams.bind(null, decode);
		function addRoute(parentOrRoute, route) {
			let parent;
			let record;
			if (isRouteName(parentOrRoute)) {
				parent = matcher.getRecordMatcher(parentOrRoute);
				if (!parent) warn(`Parent route "${String(parentOrRoute)}" not found when adding child route`, route);
				record = route;
			} else record = parentOrRoute;
			return matcher.addRoute(record, parent);
		}
		function removeRoute(name) {
			const recordMatcher = matcher.getRecordMatcher(name);
			if (recordMatcher) matcher.removeRoute(recordMatcher);
			else warn(`Cannot remove non-existent route "${String(name)}"`);
		}
		function getRoutes() {
			return matcher.getRoutes().map((routeMatcher) => routeMatcher.record);
		}
		function hasRoute(name) {
			return !!matcher.getRecordMatcher(name);
		}
		function resolve(rawLocation, currentLocation) {
			currentLocation = assign({}, currentLocation || currentRoute.value);
			if (typeof rawLocation === "string") {
				const locationNormalized = parseURL(parseQuery$1, rawLocation, currentLocation.path);
				const matchedRoute = matcher.resolve({ path: locationNormalized.path }, currentLocation);
				const href = routerHistory.createHref(locationNormalized.fullPath);
				if (href.startsWith("//")) warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`);
				else if (!matchedRoute.matched.length) warn(`No match found for location with path "${rawLocation}"`);
				return assign(locationNormalized, matchedRoute, {
					params: decodeParams(matchedRoute.params),
					hash: decode(locationNormalized.hash),
					redirectedFrom: void 0,
					href
				});
			}
			if (!isRouteLocation(rawLocation)) {
				warn(`router.resolve() was passed an invalid location. This will fail in production.\n- Location:`, rawLocation);
				return resolve({});
			}
			let matcherLocation;
			if (rawLocation.path != null) {
				if ("params" in rawLocation && !("name" in rawLocation) && Object.keys(rawLocation.params).length) warn(`Path "${rawLocation.path}" was passed with params but they will be ignored. Use a named route alongside params instead.`);
				matcherLocation = assign({}, rawLocation, { path: parseURL(parseQuery$1, rawLocation.path, currentLocation.path).path });
			} else {
				const targetParams = assign({}, rawLocation.params);
				for (const key in targetParams) if (targetParams[key] == null) delete targetParams[key];
				matcherLocation = assign({}, rawLocation, { params: encodeParams(targetParams) });
				currentLocation.params = encodeParams(currentLocation.params);
			}
			const matchedRoute = matcher.resolve(matcherLocation, currentLocation);
			const hash = rawLocation.hash || "";
			if (hash && !hash.startsWith("#")) warn(`A \`hash\` should always start with the character "#". Replace "${hash}" with "#${hash}".`);
			matchedRoute.params = normalizeParams(decodeParams(matchedRoute.params));
			const fullPath = stringifyURL(stringifyQuery$1, assign({}, rawLocation, {
				hash: encodeHash(hash),
				path: matchedRoute.path
			}));
			const href = routerHistory.createHref(fullPath);
			if (href.startsWith("//")) warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`);
			else if (!matchedRoute.matched.length) warn(`No match found for location with path "${rawLocation.path != null ? rawLocation.path : rawLocation}"`);
			return assign({
				fullPath,
				hash,
				query: stringifyQuery$1 === stringifyQuery ? normalizeQuery(rawLocation.query) : rawLocation.query || {}
			}, matchedRoute, {
				redirectedFrom: void 0,
				href
			});
		}
		function locationAsObject(to) {
			return typeof to === "string" ? parseURL(parseQuery$1, to, currentRoute.value.path) : assign({}, to);
		}
		function checkCanceledNavigation(to, from) {
			if (pendingLocation !== to) return createRouterError(ErrorTypes.NAVIGATION_CANCELLED, {
				from,
				to
			});
		}
		function push(to) {
			return pushWithRedirect(to);
		}
		function replace(to) {
			return push(assign(locationAsObject(to), { replace: true }));
		}
		function handleRedirectRecord(to, from) {
			const lastMatched = to.matched[to.matched.length - 1];
			if (lastMatched && lastMatched.redirect) {
				const { redirect } = lastMatched;
				let newTargetLocation = typeof redirect === "function" ? redirect(to, from) : redirect;
				if (typeof newTargetLocation === "string") {
					newTargetLocation = newTargetLocation.includes("?") || newTargetLocation.includes("#") ? newTargetLocation = locationAsObject(newTargetLocation) : { path: newTargetLocation };
					newTargetLocation.params = {};
				}
				if (newTargetLocation.path == null && !("name" in newTargetLocation)) {
					warn(`Invalid redirect found:\n${JSON.stringify(newTargetLocation, null, 2)}\n when navigating to "${to.fullPath}". A redirect must contain a name or path. This will break in production.`);
					throw new Error("Invalid redirect");
				}
				return assign({
					query: to.query,
					hash: to.hash,
					params: newTargetLocation.path != null ? {} : to.params
				}, newTargetLocation);
			}
		}
		function pushWithRedirect(to, redirectedFrom) {
			const targetLocation = pendingLocation = resolve(to);
			const from = currentRoute.value;
			const data = to.state;
			const force = to.force;
			const replace = to.replace === true;
			const shouldRedirect = handleRedirectRecord(targetLocation, from);
			if (shouldRedirect) return pushWithRedirect(assign(locationAsObject(shouldRedirect), {
				state: typeof shouldRedirect === "object" ? assign({}, data, shouldRedirect.state) : data,
				force,
				replace
			}), redirectedFrom || targetLocation);
			const toLocation = targetLocation;
			toLocation.redirectedFrom = redirectedFrom;
			let failure;
			if (!force && isSameRouteLocation(stringifyQuery$1, from, targetLocation)) {
				failure = createRouterError(ErrorTypes.NAVIGATION_DUPLICATED, {
					to: toLocation,
					from
				});
				handleScroll(from, from, true, false);
			}
			return (failure ? Promise.resolve(failure) : navigate(toLocation, from)).catch((error) => isNavigationFailure(error) ? isNavigationFailure(error, ErrorTypes.NAVIGATION_GUARD_REDIRECT) ? error : markAsReady(error) : triggerError(error, toLocation, from)).then((failure) => {
				if (failure) {
					if (isNavigationFailure(failure, ErrorTypes.NAVIGATION_GUARD_REDIRECT)) {
						if (isSameRouteLocation(stringifyQuery$1, resolve(failure.to), toLocation) && redirectedFrom && (redirectedFrom._count = redirectedFrom._count ? redirectedFrom._count + 1 : 1) > 30) {
							warn(`Detected a possibly infinite redirection in a navigation guard when going from "${from.fullPath}" to "${toLocation.fullPath}". Aborting to avoid a Stack Overflow.\n Are you always returning a new location within a navigation guard? That would lead to this error. Only return when redirecting or aborting, that should fix this. This might break in production if not fixed.`);
							return Promise.reject(/* @__PURE__ */ new Error("Infinite redirect in navigation guard"));
						}
						return pushWithRedirect(assign({ replace }, locationAsObject(failure.to), {
							state: typeof failure.to === "object" ? assign({}, data, failure.to.state) : data,
							force
						}), redirectedFrom || toLocation);
					}
				} else failure = finalizeNavigation(toLocation, from, true, replace, data);
				triggerAfterEach(toLocation, from, failure);
				return failure;
			});
		}
		/**
		* Helper to reject and skip all navigation guards if a new navigation happened
		* @param to
		* @param from
		*/
		function checkCanceledNavigationAndReject(to, from) {
			const error = checkCanceledNavigation(to, from);
			return error ? Promise.reject(error) : Promise.resolve();
		}
		function runWithContext(fn) {
			const app = installedApps.values().next().value;
			return app && typeof app.runWithContext === "function" ? app.runWithContext(fn) : fn();
		}
		function navigate(to, from) {
			let guards;
			const [leavingRecords, updatingRecords, enteringRecords] = extractChangingRecords(to, from);
			guards = extractComponentsGuards(leavingRecords.reverse(), "beforeRouteLeave", to, from);
			for (const record of leavingRecords) record.leaveGuards.forEach((guard) => {
				guards.push(guardToPromiseFn(guard, to, from));
			});
			const canceledNavigationCheck = checkCanceledNavigationAndReject.bind(null, to, from);
			guards.push(canceledNavigationCheck);
			return runGuardQueue(guards).then(() => {
				guards = [];
				for (const guard of beforeGuards.list()) guards.push(guardToPromiseFn(guard, to, from));
				guards.push(canceledNavigationCheck);
				return runGuardQueue(guards);
			}).then(() => {
				guards = extractComponentsGuards(updatingRecords, "beforeRouteUpdate", to, from);
				for (const record of updatingRecords) record.updateGuards.forEach((guard) => {
					guards.push(guardToPromiseFn(guard, to, from));
				});
				guards.push(canceledNavigationCheck);
				return runGuardQueue(guards);
			}).then(() => {
				guards = [];
				for (const record of enteringRecords) if (record.beforeEnter) if (isArray(record.beforeEnter)) for (const beforeEnter of record.beforeEnter) guards.push(guardToPromiseFn(beforeEnter, to, from));
				else guards.push(guardToPromiseFn(record.beforeEnter, to, from));
				guards.push(canceledNavigationCheck);
				return runGuardQueue(guards);
			}).then(() => {
				to.matched.forEach((record) => record.enterCallbacks = {});
				guards = extractComponentsGuards(enteringRecords, "beforeRouteEnter", to, from, runWithContext);
				guards.push(canceledNavigationCheck);
				return runGuardQueue(guards);
			}).then(() => {
				guards = [];
				for (const guard of beforeResolveGuards.list()) guards.push(guardToPromiseFn(guard, to, from));
				guards.push(canceledNavigationCheck);
				return runGuardQueue(guards);
			}).catch((err) => isNavigationFailure(err, ErrorTypes.NAVIGATION_CANCELLED) ? err : Promise.reject(err));
		}
		function triggerAfterEach(to, from, failure) {
			afterGuards.list().forEach((guard) => runWithContext(() => guard(to, from, failure)));
		}
		/**
		* - Cleans up any navigation guards
		* - Changes the url if necessary
		* - Calls the scrollBehavior
		*/
		function finalizeNavigation(toLocation, from, isPush, replace, data) {
			const error = checkCanceledNavigation(toLocation, from);
			if (error) return error;
			const isFirstNavigation = from === START_LOCATION_NORMALIZED;
			const state = !isBrowser ? {} : history.state;
			if (isPush) if (replace || isFirstNavigation) routerHistory.replace(toLocation.fullPath, assign({ scroll: isFirstNavigation && state && state.scroll }, data));
			else routerHistory.push(toLocation.fullPath, data);
			currentRoute.value = toLocation;
			handleScroll(toLocation, from, isPush, isFirstNavigation);
			markAsReady();
		}
		let removeHistoryListener;
		function setupListeners() {
			if (removeHistoryListener) return;
			removeHistoryListener = routerHistory.listen((to, _from, info) => {
				if (!router.listening) return;
				const toLocation = resolve(to);
				const shouldRedirect = handleRedirectRecord(toLocation, router.currentRoute.value);
				if (shouldRedirect) {
					pushWithRedirect(assign(shouldRedirect, {
						replace: true,
						force: true
					}), toLocation).catch(noop);
					return;
				}
				pendingLocation = toLocation;
				const from = currentRoute.value;
				if (isBrowser) saveScrollPosition(getScrollKey(from.fullPath, info.delta), computeScrollPosition());
				navigate(toLocation, from).catch((error) => {
					if (isNavigationFailure(error, ErrorTypes.NAVIGATION_ABORTED | ErrorTypes.NAVIGATION_CANCELLED)) return error;
					if (isNavigationFailure(error, ErrorTypes.NAVIGATION_GUARD_REDIRECT)) {
						pushWithRedirect(assign(locationAsObject(error.to), { force: true }), toLocation).then((failure) => {
							if (isNavigationFailure(failure, ErrorTypes.NAVIGATION_ABORTED | ErrorTypes.NAVIGATION_DUPLICATED) && !info.delta && info.type === NavigationType.pop) routerHistory.go(-1, false);
						}).catch(noop);
						return Promise.reject();
					}
					if (info.delta) routerHistory.go(-info.delta, false);
					return triggerError(error, toLocation, from);
				}).then((failure) => {
					failure = failure || finalizeNavigation(toLocation, from, false);
					if (failure) {
						if (info.delta && !isNavigationFailure(failure, ErrorTypes.NAVIGATION_CANCELLED)) routerHistory.go(-info.delta, false);
						else if (info.type === NavigationType.pop && isNavigationFailure(failure, ErrorTypes.NAVIGATION_ABORTED | ErrorTypes.NAVIGATION_DUPLICATED)) routerHistory.go(-1, false);
					}
					triggerAfterEach(toLocation, from, failure);
				}).catch(noop);
			});
		}
		let readyHandlers = useCallbacks();
		let errorListeners = useCallbacks();
		let ready;
		/**
		* Trigger errorListeners added via onError and throws the error as well
		*
		* @param error - error to throw
		* @param to - location we were navigating to when the error happened
		* @param from - location we were navigating from when the error happened
		* @returns the error as a rejected promise
		*/
		function triggerError(error, to, from) {
			markAsReady(error);
			const list = errorListeners.list();
			if (list.length) list.forEach((handler) => handler(error, to, from));
			else {
				warn("uncaught error during route navigation:");
				console.error(error);
			}
			return Promise.reject(error);
		}
		function isReady() {
			if (ready && currentRoute.value !== START_LOCATION_NORMALIZED) return Promise.resolve();
			return new Promise((resolve, reject) => {
				readyHandlers.add([resolve, reject]);
			});
		}
		function markAsReady(err) {
			if (!ready) {
				ready = !err;
				setupListeners();
				readyHandlers.list().forEach(([resolve, reject]) => err ? reject(err) : resolve());
				readyHandlers.reset();
			}
			return err;
		}
		function handleScroll(to, from, isPush, isFirstNavigation) {
			const { scrollBehavior } = options;
			if (!isBrowser || !scrollBehavior) return Promise.resolve();
			const scrollPosition = !isPush && getSavedScrollPosition(getScrollKey(to.fullPath, 0)) || (isFirstNavigation || !isPush) && history.state && history.state.scroll || null;
			return (0, vue.nextTick)().then(() => scrollBehavior(to, from, scrollPosition)).then((position) => position && scrollToPosition(position)).catch((err) => triggerError(err, to, from));
		}
		const go = (delta) => routerHistory.go(delta);
		let started;
		const installedApps = /* @__PURE__ */ new Set();
		const router = {
			currentRoute,
			listening: true,
			addRoute,
			removeRoute,
			clearRoutes: matcher.clearRoutes,
			hasRoute,
			getRoutes,
			resolve,
			options,
			push,
			replace,
			go,
			back: () => go(-1),
			forward: () => go(1),
			beforeEach: beforeGuards.add,
			beforeResolve: beforeResolveGuards.add,
			afterEach: afterGuards.add,
			onError: errorListeners.add,
			isReady,
			install(app) {
				app.component("RouterLink", RouterLink);
				app.component("RouterView", RouterView);
				app.config.globalProperties.$router = router;
				Object.defineProperty(app.config.globalProperties, "$route", {
					enumerable: true,
					get: () => (0, vue.unref)(currentRoute)
				});
				if (isBrowser && !started && currentRoute.value === START_LOCATION_NORMALIZED) {
					started = true;
					push(routerHistory.location).catch((err) => {
						warn("Unexpected error when starting the router:", err);
					});
				}
				const reactiveRoute = {};
				for (const key in START_LOCATION_NORMALIZED) Object.defineProperty(reactiveRoute, key, {
					get: () => currentRoute.value[key],
					enumerable: true
				});
				app.provide(routerKey, router);
				app.provide(routeLocationKey, (0, vue.shallowReactive)(reactiveRoute));
				app.provide(routerViewLocationKey, currentRoute);
				const unmountApp = app.unmount;
				installedApps.add(app);
				app.unmount = function() {
					installedApps.delete(app);
					if (installedApps.size < 1) {
						pendingLocation = START_LOCATION_NORMALIZED;
						removeHistoryListener && removeHistoryListener();
						removeHistoryListener = null;
						currentRoute.value = START_LOCATION_NORMALIZED;
						started = false;
						ready = false;
					}
					unmountApp();
				};
			}
		};
		function runGuardQueue(guards) {
			return guards.reduce((promise, guard) => promise.then(() => runWithContext(guard)), Promise.resolve());
		}
		return router;
	}

//#endregion
//#region src/useApi.ts
/**
	* Returns the router instance. Equivalent to using `$router` inside
	* templates.
	*/
	function useRouter() {
		return (0, vue.inject)(routerKey);
	}
	/**
	* Returns the current route location. Equivalent to using `$route` inside
	* templates.
	*/
	function useRoute(_name) {
		return (0, vue.inject)(routeLocationKey);
	}

//#endregion
exports.NavigationFailureType = NavigationFailureType;
exports.RouterLink = RouterLink;
exports.RouterView = RouterView;
exports.START_LOCATION = START_LOCATION_NORMALIZED;
exports.createMemoryHistory = createMemoryHistory;
exports.createRouter = createRouter;
exports.createRouterMatcher = createRouterMatcher;
exports.createWebHashHistory = createWebHashHistory;
exports.createWebHistory = createWebHistory;
exports.isNavigationFailure = isNavigationFailure;
exports.loadRouteLocation = loadRouteLocation;
exports.matchedRouteKey = matchedRouteKey;
exports.onBeforeRouteLeave = onBeforeRouteLeave;
exports.onBeforeRouteUpdate = onBeforeRouteUpdate;
exports.parseQuery = parseQuery;
exports.routeLocationKey = routeLocationKey;
exports.routerKey = routerKey;
exports.routerViewLocationKey = routerViewLocationKey;
exports.stringifyQuery = stringifyQuery;
exports.useLink = useLink;
exports.useRoute = useRoute;
exports.useRouter = useRouter;
exports.viewDepthKey = viewDepthKey;
return exports;
})({}, Vue);