@qwik.dev/router 2.0.0-beta.43 → 2.0.0-beta.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/lib/adapters/azure-swa/vite/index.d.ts +2 -2
  2. package/lib/adapters/azure-swa/vite/index.mjs +2 -1
  3. package/lib/adapters/bun-server/vite/index.d.ts +2 -2
  4. package/lib/adapters/bun-server/vite/index.mjs +2 -1
  5. package/lib/adapters/cloud-run/vite/index.d.ts +2 -2
  6. package/lib/adapters/cloud-run/vite/index.mjs +2 -1
  7. package/lib/adapters/cloudflare-pages/vite/index.d.ts +2 -2
  8. package/lib/adapters/cloudflare-pages/vite/index.mjs +2 -1
  9. package/lib/adapters/deno-server/vite/index.d.ts +2 -2
  10. package/lib/adapters/deno-server/vite/index.mjs +2 -1
  11. package/lib/adapters/netlify-edge/vite/index.d.ts +2 -2
  12. package/lib/adapters/netlify-edge/vite/index.mjs +2 -1
  13. package/lib/adapters/node-server/vite/index.d.ts +2 -2
  14. package/lib/adapters/node-server/vite/index.mjs +2 -1
  15. package/lib/adapters/shared/vite/index.d.ts +1 -1
  16. package/lib/adapters/shared/vite/index.mjs +36 -32
  17. package/lib/adapters/ssg/vite/index.d.ts +1 -1
  18. package/lib/adapters/ssg/vite/index.mjs +4 -2
  19. package/lib/adapters/vercel-edge/vite/index.d.ts +2 -2
  20. package/lib/adapters/vercel-edge/vite/index.mjs +18 -15
  21. package/lib/chunks/fs.mjs +28 -25
  22. package/lib/chunks/head.qwik.mjs +731 -448
  23. package/lib/chunks/http-error.qwik.mjs +8 -7
  24. package/lib/chunks/pathname.mjs +9 -8
  25. package/lib/chunks/request-path.mjs +8 -4
  26. package/lib/chunks/route-trie-key.mjs +10 -0
  27. package/lib/chunks/routes.mjs +14 -14
  28. package/lib/chunks/server-error.mjs +28 -6
  29. package/lib/chunks/{url.mjs → static-file.mjs} +12 -2
  30. package/lib/chunks/system.mjs +31 -25
  31. package/lib/chunks/user-response.mjs +455 -348
  32. package/lib/chunks/worker-thread.mjs +90 -88
  33. package/lib/index.d.ts +94 -63
  34. package/lib/index.qwik.mjs +615 -523
  35. package/lib/middleware/aws-lambda/index.mjs +6 -3
  36. package/lib/middleware/azure-swa/index.mjs +4 -2
  37. package/lib/middleware/bun/index.mjs +12 -12
  38. package/lib/middleware/cloudflare-pages/index.mjs +19 -4
  39. package/lib/middleware/deno/index.mjs +12 -12
  40. package/lib/middleware/firebase/index.mjs +4 -2
  41. package/lib/middleware/netlify-edge/index.mjs +4 -2
  42. package/lib/middleware/node/index.mjs +16 -15
  43. package/lib/middleware/request-handler/index.d.ts +102 -2
  44. package/lib/middleware/request-handler/index.mjs +30 -34
  45. package/lib/middleware/vercel-edge/index.mjs +4 -2
  46. package/lib/service-worker/index.mjs +2 -1
  47. package/lib/ssg/index.mjs +23 -18
  48. package/lib/vite/index.d.ts +1 -1
  49. package/lib/vite/index.mjs +669 -604
  50. package/package.json +5 -5
@@ -1,36 +1,13 @@
1
1
  import { t as ensureSlash } from "./chunks/pathname.mjs";
2
- import { A as routeLoader$, B as RouteLoaderCtxContext, E as isImmutableLoader, F as ContentContext, G as QACTION_KEY, H as RouteNavigateContext, I as ContentInternalContext, J as Q_ROUTE, K as QDATA_KEY, L as DocumentHeadContext, M as setLoaderSignalValue, P as updateRouteLoaderPaths, R as HttpStatusContext, T as invalidateNavRouteLoaders, U as RoutePreventNavigateContext, V as RouteLocationContext, W as RouteStateContext, _ as fetchRouteLoaderData, a as isPromise, b as getRequestEvent, c as shouldPreload, d as loadRoute, g as ensureRouteLoaderSignals, i as getClientNavPath, j as routeLoaderQrl, l as toPath, m as clearNavFetchCache, n as resolveHead, o as isSameOrigin, q as QFN_KEY, s as isSamePath, t as createDocumentHead, u as toUrl, y as getModuleRouteLoaders, z as RouteActionContext } from "./chunks/head.qwik.mjs";
3
- import { SkipRender, Slot, _captures, _fnSignal, _getConstProps, _getVarProps, _jsxSorted, _jsxSplit, _qrlSync, _restProps, _wrapProp, componentQrl, createComputedQrl, createElement, eventQrl, getLocale, implicit$FirstArg, inlinedQrl, isBrowser, isDev, isServer, noSerialize, untrack, useContext, useContextProvider, useServerData, useSignal, useStore, useTaskQrl, useVisibleTaskQrl, withLocale } from "@qwik.dev/core";
4
- import * as qwikRouterConfig from "@qwik-router-config";
5
- import { p } from "@qwik.dev/core/preloader";
6
- import { _deserialize, _getContextContainer, _getContextHostElement, _hasStoreEffects, _serialize, _waitUntilRendered, forceStoreEffects } from "@qwik.dev/core/internal";
2
+ import { $ as RoutePreventNavigateContext, B as _setRouterConfig, C as getRequestEvent, F as routeLoader$, G as ContentContext, H as getRouterConfig, I as routeLoaderQrl, J as HttpStatusContext, K as ContentInternalContext, L as setLoaderSignalValue, M as prepareRouteLoaders, P as restoreRouteLoaders, Q as RouteNavigateContext, S as getModuleRouteLoaders, U as getRoutes, V as getBasePathname, W as getTrailingSlash, X as RouteLoaderCtxContext, Y as RouteActionContext, Z as RouteLocationContext, _ as commitRouteLoaders, a as isPromise, b as getClientRouteLoaders, c as shouldPreload, d as loadRoute, et as RouteStateContext, h as clearNavFetchCache, i as getClientNavPath, it as Q_ROUTE, k as isImmutableLoader, l as toPath, m as abortRouteLoaderNavigation, n as resolveHead, nt as QDATA_KEY, o as isSameOrigin, q as DocumentHeadContext, rt as QFN_KEY, s as isSamePath, t as createDocumentHead, tt as QACTION_KEY, u as toUrl, v as ensureRouteLoaderSignals, y as fetchRouteLoaderData, z as _getServiceWorkerUrl } from "./chunks/head.qwik.mjs";
3
+ import { SkipRender, Slot, _capturesObj, _fnSignal, _getConstProps, _getVarProps, _jsxSorted, _jsxSplit, _qrlSync, _restProps, _wrapProp, componentQrl, createComputedQrl, createElement, eventQrl, getLocale, implicit$FirstArg, inlinedQrl, isBrowser, isDev, isServer, noSerialize, untrack, useContext, useContextProvider, useServerData, useSignal, useStore, useTaskQrl, useVisibleTaskQrl, withLocale } from "@qwik.dev/core";
4
+ import { _deserialize, _getContextContainer, _getContextHostElement, _hasStoreEffects, _regInlinedQrl, _requestPreload, _serialize, _waitUntilRendered, forceStoreEffects } from "@qwik.dev/core/internal";
7
5
  import { Fragment } from "@qwik.dev/core/jsx-runtime";
8
6
  import * as v from "valibot";
9
7
  import * as z$1 from "zod";
10
8
  import { z } from "zod";
11
- import swRegister from "@qwik-router-sw-register";
12
9
  import { renderToStream } from "@qwik.dev/core/server";
13
10
  /**
14
- * Prefetch a route's loader data in parallel (fire-and-forget). The per-nav fetch map dedupes
15
- * repeat hovers and shares the promise with the navigation's own fetch; the browser HTTP cache
16
- * handles freshness. Immutable loaders are skipped: they download lazily on first actual read and
17
- * are then browser-cached for the life of the deploy.
18
- */ var prefetchLoaderData = (loadedRoute, url, manifestHash) => {
19
- if (!loadedRoute.$loaders$?.length || !loadedRoute.$loaderPaths$) return;
20
- const immutableIds = new Set(getModuleRouteLoaders(loadedRoute.$mods$).filter((loader) => loader.__cacheControl === "immutable").map((loader) => loader.__id));
21
- const basePath = qwikRouterConfig.basePathname ?? "/";
22
- for (const hash of loadedRoute.$loaders$) {
23
- if (immutableIds.has(hash)) continue;
24
- let loaderPath = loadedRoute.$loaderPaths$[hash];
25
- if (!loaderPath) continue;
26
- if (basePath !== "/" && !loaderPath.startsWith(basePath)) loaderPath = basePath + loaderPath.slice(1);
27
- fetchRouteLoaderData(hash, loaderPath, manifestHash, {
28
- pageUrl: url,
29
- basePath
30
- }).catch(() => {});
31
- }
32
- };
33
- /**
34
11
  * Prefetch a route's JS bundles and optionally its loader data.
35
12
  *
36
13
  * Resolves the route from the trie to get the routeName (for the bundle graph preloader) and
@@ -42,34 +19,63 @@ import { renderToStream } from "@qwik.dev/core/server";
42
19
  * @param probability - Bundle preload probability (0-1, default 0.8)
43
20
  * @param manifestHash - Build manifest hash for loader URLs (from `useDocumentHead().manifestHash`)
44
21
  * @param prefetchBundle - Whether to prefetch route JS bundles
45
- */ async function prefetchRoute(url, prefetchData, probability = .8, manifestHash, prefetchBundle = true) {
22
+ */
23
+ async function prefetchRoute(url, prefetchData, probability = .8, manifestHash, prefetchBundle = true) {
46
24
  if (!isBrowser || isDev) return;
47
25
  try {
48
- const loadedRoute = await loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, url.pathname);
26
+ const { routes, cacheModules } = await getRouterConfig();
27
+ const loadedRoute = await loadRoute(routes, cacheModules, url.pathname);
49
28
  if (!loadedRoute) return;
50
29
  if (prefetchBundle) {
51
30
  let routeName = loadedRoute.$routeName$;
52
31
  routeName = ensureSlash(routeName);
53
32
  if (routeName.length > 1 && routeName.startsWith("/")) routeName = routeName.slice(1);
54
- p(routeName, probability);
33
+ _requestPreload(routeName, probability);
55
34
  }
56
35
  if (!prefetchData || !manifestHash) return;
57
36
  prefetchLoaderData(loadedRoute, url, manifestHash);
58
37
  } catch {}
59
38
  }
60
- /** @public */ var useHttpStatus = () => useContext(HttpStatusContext).value;
61
- /** @public */ var useContent = () => useContext(ContentContext);
39
+ /**
40
+ * Prefetch a route's loader data in parallel (fire-and-forget). The per-nav fetch map dedupes
41
+ * repeat hovers and shares the promise with the navigation's own fetch; the browser HTTP cache
42
+ * handles freshness. Immutable loaders are skipped: they download lazily on first actual read and
43
+ * are then browser-cached for the life of the deploy.
44
+ */
45
+ var prefetchLoaderData = (loadedRoute, url, manifestHash) => {
46
+ if (!loadedRoute.$loaders$?.length || !loadedRoute.$loaderPaths$) return;
47
+ const immutableIds = new Set(getModuleRouteLoaders(loadedRoute.$mods$).filter((loader) => loader.__cacheControl === "immutable").map((loader) => loader.__id));
48
+ const basePath = getBasePathname();
49
+ for (const hash of loadedRoute.$loaders$) {
50
+ if (immutableIds.has(hash)) continue;
51
+ let loaderPath = loadedRoute.$loaderPaths$[hash];
52
+ if (!loaderPath) continue;
53
+ if (basePath !== "/" && !loaderPath.startsWith(basePath)) loaderPath = basePath + loaderPath.slice(1);
54
+ fetchRouteLoaderData(hash, loaderPath, manifestHash, {
55
+ pageUrl: url,
56
+ basePath
57
+ }).catch(() => {});
58
+ }
59
+ };
60
+ /** @public */
61
+ var useHttpStatus = () => useContext(HttpStatusContext).value;
62
+ /** @public */
63
+ var useContent = () => useContext(ContentContext);
62
64
  /**
63
65
  * Returns the document head for the current page. The generic type describes the front matter.
64
66
  *
65
67
  * @public
66
- */ var useDocumentHead = () => useContext(DocumentHeadContext);
67
- /** @public */ var useLocation = () => useContext(RouteLocationContext);
68
- /** @public */ var useNavigate = () => useContext(RouteNavigateContext);
69
- /** @internal Implementation of usePreventNavigate$ */ var usePreventNavigateQrl = (fn) => {
68
+ */
69
+ var useDocumentHead = () => useContext(DocumentHeadContext);
70
+ /** @public */
71
+ var useLocation = () => useContext(RouteLocationContext);
72
+ /** @public */
73
+ var useNavigate = () => useContext(RouteNavigateContext);
74
+ /** @internal Implementation of usePreventNavigate$ */
75
+ var usePreventNavigateQrl = (fn) => {
70
76
  const registerPreventNav = useContext(RoutePreventNavigateContext);
71
77
  useVisibleTaskQrl(/*#__PURE__*/ inlinedQrl(() => {
72
- const fn = _captures[0], registerPreventNav = _captures[1];
78
+ let fn = _capturesObj._[0], registerPreventNav = _capturesObj._[1];
73
79
  return registerPreventNav(fn);
74
80
  }, "usePreventNavigateQrl_useVisibleTask_BsYUaz9XhUs", [fn, registerPreventNav]));
75
81
  };
@@ -106,26 +112,33 @@ import { renderToStream } from "@qwik.dev/core/server";
106
112
  * you can show a dialog or just return `true` to prevent the navigation.
107
113
  *
108
114
  * @public
109
- */ var usePreventNavigate$ = implicit$FirstArg(usePreventNavigateQrl);
115
+ */
116
+ var usePreventNavigate$ = implicit$FirstArg(usePreventNavigateQrl);
110
117
  var useAction = () => useContext(RouteActionContext);
111
118
  var useQwikRouterEnv = () => noSerialize(useServerData("qwikrouter"));
112
- /** @public */ var Link = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
119
+ /** @public */
120
+ var Link = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
113
121
  const nav = useNavigate();
114
122
  const loc = useLocation();
115
123
  const head = useDocumentHead();
116
- const originalHref = props.href;
117
124
  const { onClick$, prefetch: prefetchProp, reload, replaceState, scroll, prefetchBundles: prefetchBundlesProp = "visible", prefetchData: prefetchDataProp = prefetchProp === "js" ? "off" : "intent", ...linkProps } = props;
118
125
  const clientNavPath = untrack(getClientNavPath, {
119
126
  ...linkProps,
120
127
  reload
121
128
  }, loc);
122
- linkProps.href = clientNavPath || originalHref;
129
+ linkProps.href = clientNavPath || props.href;
123
130
  const isDepratedPrefetchDisabled = prefetchProp === false;
124
131
  const shouldPrefetch = untrack(shouldPreload, clientNavPath, loc);
125
132
  const shouldVisiblePrefetchBundles = !!clientNavPath && shouldPrefetch && !isDepratedPrefetchDisabled && (prefetchBundlesProp === "visible" || prefetchProp === "js" || prefetchProp === true);
126
133
  const shouldVisiblePrefetchData = !!clientNavPath && shouldPrefetch && !isDepratedPrefetchDisabled && (prefetchDataProp === "visible" || prefetchProp === true);
127
- const handleDataPrefetch = !!clientNavPath && prefetchDataProp !== "off" && shouldPrefetch && !isDepratedPrefetchDisabled ? /*#__PURE__*/ inlinedQrl((_, elm) => {
128
- const head = _captures[0];
134
+ const shouldPrefetchBundles = !!clientNavPath && prefetchBundlesProp !== "off" && shouldPrefetch && !isDepratedPrefetchDisabled;
135
+ const shouldPrefetchData = !!clientNavPath && prefetchDataProp !== "off" && shouldPrefetch && !isDepratedPrefetchDisabled;
136
+ const handleBundlePrefetch = shouldPrefetchBundles ? /*#__PURE__*/ inlinedQrl((_, elm) => {
137
+ if (navigator.connection?.saveData) return;
138
+ if (elm && elm.href) prefetchRoute(new URL(elm.href), false, .8);
139
+ }, "Link_component_handleBundlePrefetch_ZttUP0kLKj0") : null;
140
+ const handleDataPrefetch = shouldPrefetchData ? /*#__PURE__*/ inlinedQrl((_, elm) => {
141
+ let head = _capturesObj._[0];
129
142
  if (navigator.connection?.saveData) return;
130
143
  if (elm && elm.href) prefetchRoute(new URL(elm.href), true, .8, head.manifestHash, false);
131
144
  }, "Link_component_handleDataPrefetch_lcd4O9LHbbA", [head]) : null;
@@ -133,15 +146,22 @@ var useQwikRouterEnv = () => noSerialize(useServerData("qwikrouter"));
133
146
  if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) event.preventDefault();
134
147
  }, "event=>{if(!(event.metaKey||event.ctrlKey||event.shiftKey||event.altKey)){event.preventDefault();}}") : null;
135
148
  const prefetchData = /*#__PURE__*/ inlinedQrl(async (_, elm) => {
136
- const handleDataPrefetch = _captures[0];
149
+ let handleDataPrefetch = _capturesObj._[0];
137
150
  handleDataPrefetch?.(null, elm);
138
151
  }, "Link_component_prefetchData_UwVx4NhHkSo", [handleDataPrefetch]);
139
152
  const onEnterKeyDown = /*#__PURE__*/ inlinedQrl((event, element) => {
140
- const prefetchData = _captures[0];
141
- if (event.key === "Enter") prefetchData(null, element);
142
- }, "Link_component_onEnterKeyDown_z274ws00irY", [prefetchData]);
153
+ let handleBundlePrefetch = _capturesObj._[0], prefetchBundlesProp = _capturesObj._[1], prefetchData = _capturesObj._[2], prefetchDataProp = _capturesObj._[3];
154
+ if (event.key !== "Enter") return;
155
+ if (prefetchDataProp === "commit") prefetchData(null, element);
156
+ if (prefetchBundlesProp === "commit") handleBundlePrefetch?.(null, element);
157
+ }, "Link_component_onEnterKeyDown_z274ws00irY", [
158
+ handleBundlePrefetch,
159
+ prefetchBundlesProp,
160
+ prefetchData,
161
+ prefetchDataProp
162
+ ]);
143
163
  const handleClientSideNavigation = clientNavPath ? /*#__PURE__*/ inlinedQrl((event, elm) => {
144
- const nav = _captures[0], reload = _captures[1], replaceState = _captures[2], scroll = _captures[3];
164
+ let nav = _capturesObj._[0], reload = _capturesObj._[1], replaceState = _capturesObj._[2], scroll = _capturesObj._[3];
145
165
  if (event.defaultPrevented) {
146
166
  if (elm.href) {
147
167
  elm.setAttribute("aria-pressed", "true");
@@ -160,34 +180,37 @@ var useQwikRouterEnv = () => noSerialize(useServerData("qwikrouter"));
160
180
  replaceState,
161
181
  scroll
162
182
  ]) : null;
163
- const handlePreload = /*#__PURE__*/ inlinedQrl((_, elm) => {
164
- prefetchRoute(new URL(elm.href), false, 1);
165
- }, "Link_component_handlePreload_AAemwtuBjsE");
166
183
  return /*#__PURE__*/ _jsxSplit("a", {
167
- "q:link": !!clientNavPath,
168
- ..._getVarProps(linkProps),
169
- ..._getConstProps(linkProps),
184
+ ..._getVarProps({ "q:link": !!clientNavPath }),
185
+ ..._getConstProps({ "q:link": !!clientNavPath }),
186
+ ...linkProps,
170
187
  "data-q-prefetch": shouldVisiblePrefetchBundles && shouldVisiblePrefetchData ? "bd" : shouldVisiblePrefetchBundles ? "b" : shouldVisiblePrefetchData ? "d" : null,
171
188
  "q-e:click": [
172
189
  preventDefault,
173
- handlePreload,
190
+ /*#__PURE__*/ inlinedQrl((_, elm) => {
191
+ prefetchRoute(new URL(elm.href), false, 1);
192
+ }, "Link_component_handlePreload_AAemwtuBjsE"),
174
193
  onClick$,
175
194
  handleClientSideNavigation
176
195
  ],
177
- "q-e:pointerenter": [linkProps.onMouseOver$, prefetchDataProp === "intent" ? prefetchData : null],
178
- "q-e:focus": [linkProps.onFocus$, prefetchDataProp === "intent" ? prefetchData : null],
179
- "q-e:pointerdown": [linkProps.onPointerDown$, prefetchDataProp === "commit" ? prefetchData : null],
180
- "q-e:keydown": [linkProps.onKeyDown$, prefetchDataProp === "commit" ? onEnterKeyDown : null]
181
- }, null, /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "jO_0"), 0, "jO_1");
196
+ "q-e:pointerenter": [
197
+ linkProps.onPointerEnter$,
198
+ prefetchDataProp === "intent" ? prefetchData : null,
199
+ prefetchBundlesProp === "intent" ? handleBundlePrefetch : null
200
+ ],
201
+ "q-e:focus": [
202
+ linkProps.onFocus$,
203
+ prefetchDataProp === "intent" ? prefetchData : null,
204
+ prefetchBundlesProp === "intent" ? handleBundlePrefetch : null
205
+ ],
206
+ "q-e:pointerdown": [
207
+ linkProps.onPointerDown$,
208
+ prefetchDataProp === "commit" ? prefetchData : null,
209
+ prefetchBundlesProp === "commit" ? handleBundlePrefetch : null
210
+ ],
211
+ "q-e:keydown": [linkProps.onKeyDown$, prefetchDataProp === "commit" || prefetchBundlesProp === "commit" ? onEnterKeyDown : null]
212
+ }, null, /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "xa_0"), 0, "xa_1");
182
213
  }, "Link_component_VPmar9tb3t4"));
183
- var newScrollState = () => {
184
- return {
185
- x: 0,
186
- y: 0,
187
- w: 0,
188
- h: 0
189
- };
190
- };
191
214
  var clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
192
215
  if (navType !== "popstate") {
193
216
  const samePath = isSamePath(fromURL, toURL);
@@ -199,11 +222,19 @@ var clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
199
222
  }
200
223
  }
201
224
  };
225
+ var newScrollState = () => {
226
+ return {
227
+ x: 0,
228
+ y: 0,
229
+ w: 0,
230
+ h: 0
231
+ };
232
+ };
202
233
  var preloadRouteBundles = (path, probability = .8) => {
203
234
  if (isBrowser) {
204
235
  path = ensureSlash(path);
205
236
  path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
206
- p(path, probability);
237
+ _requestPreload(path, probability);
207
238
  }
208
239
  };
209
240
  var prefetchedLinks = /* @__PURE__ */ new WeakSet();
@@ -211,6 +242,14 @@ var cleanupPrefetchObserver;
211
242
  var resetLinkPrefetchState = () => {
212
243
  prefetchedLinks = /* @__PURE__ */ new WeakSet();
213
244
  };
245
+ var refreshLinkPrefetchObserver = (manifestHash) => {
246
+ resetLinkPrefetchState();
247
+ cleanupPrefetchObserver?.();
248
+ cleanupPrefetchObserver = createLinkPrefetchObserver(manifestHash);
249
+ };
250
+ var linkPrefetchInit = eventQrl(/*#__PURE__*/ inlinedQrl((_, element) => {
251
+ refreshLinkPrefetchObserver(element.closest("[q\\:manifest-hash]")?.getAttribute("q:manifest-hash") || void 0);
252
+ }, "linkPrefetchInit_event_hoZr9O26Irg"));
214
253
  var createLinkPrefetchObserver = (manifestHash) => {
215
254
  const anchors = document.querySelectorAll("a[q\\:link][data-q-prefetch]");
216
255
  const prefetchAnchor = (anchor, observer) => {
@@ -242,20 +281,18 @@ var createLinkPrefetchObserver = (manifestHash) => {
242
281
  observer.disconnect();
243
282
  };
244
283
  };
245
- var refreshLinkPrefetchObserver = (manifestHash) => {
246
- resetLinkPrefetchState();
247
- cleanupPrefetchObserver?.();
248
- cleanupPrefetchObserver = createLinkPrefetchObserver(manifestHash);
249
- };
250
- var linkPrefetchInit = eventQrl(/*#__PURE__*/ inlinedQrl((_, element) => {
251
- refreshLinkPrefetchObserver(element.closest("[q\\:manifest-hash]")?.getAttribute("q:manifest-hash") || void 0);
252
- }, "linkPrefetchInit_event_hoZr9O26Irg"));
253
284
  function callRestoreScrollOnDocument() {
254
285
  if (document.__q_scroll_restore__) {
255
286
  document.__q_scroll_restore__();
256
287
  document.__q_scroll_restore__ = void 0;
257
288
  }
258
289
  }
290
+ var restoreScroll = (type, toUrl, fromUrl, scroller, scrollState) => {
291
+ if (type === "popstate" && scrollState) scroller.scrollTo(scrollState.x, scrollState.y);
292
+ else if (type === "link" || type === "form") {
293
+ if (!hashScroll(toUrl, fromUrl)) scroller.scrollTo(0, 0);
294
+ }
295
+ };
259
296
  var hashScroll = (toUrl, fromUrl) => {
260
297
  const elmId = toUrl.hash.slice(1);
261
298
  const elm = elmId && document.getElementById(elmId);
@@ -265,12 +302,6 @@ var hashScroll = (toUrl, fromUrl) => {
265
302
  } else if (!elm && toUrl.hash && isSamePath(toUrl, fromUrl)) return true;
266
303
  return false;
267
304
  };
268
- var restoreScroll = (type, toUrl, fromUrl, scroller, scrollState) => {
269
- if (type === "popstate" && scrollState) scroller.scrollTo(scrollState.x, scrollState.y);
270
- else if (type === "link" || type === "form") {
271
- if (!hashScroll(toUrl, fromUrl)) scroller.scrollTo(0, 0);
272
- }
273
- };
274
305
  var currentScrollState = (elm) => {
275
306
  return {
276
307
  x: elm.scrollLeft,
@@ -411,7 +442,8 @@ var spa_init_default = eventQrl(/*#__PURE__*/ inlinedQrl((_, el) => {
411
442
  * POSTs to the route URL with `qaction={actionId}` appended and `Accept: application/json`. The
412
443
  * server runs the action and returns the action result, optionally with the loader hashes that
413
444
  * should be invalidated.
414
- */ async function submitAction(action, routeUrl) {
445
+ */
446
+ async function submitAction(action, routeUrl) {
415
447
  const pathBase = ensureSlash(routeUrl.pathname);
416
448
  const searchParams = new URLSearchParams(routeUrl.search);
417
449
  searchParams.set(QACTION_KEY, action.id);
@@ -433,15 +465,11 @@ var spa_init_default = eventQrl(/*#__PURE__*/ inlinedQrl((_, el) => {
433
465
  }
434
466
  };
435
467
  const response = await fetch(url, fetchOptions);
436
- if (response.redirected) {
437
- const redirectedURL = new URL(response.url);
438
- if (redirectedURL.origin !== location.origin) {
439
- location.href = redirectedURL.href;
440
- return;
441
- }
442
- location.href = redirectedURL.href;
443
- return;
444
- }
468
+ if (response.redirected) return {
469
+ status: response.status,
470
+ result: void 0,
471
+ redirect: new URL(response.url)
472
+ };
445
473
  if ((response.headers.get("content-type") || "").includes("json")) {
446
474
  const text = await response.text();
447
475
  const data = await _deserialize(text);
@@ -454,9 +482,11 @@ var spa_init_default = eventQrl(/*#__PURE__*/ inlinedQrl((_, el) => {
454
482
  }
455
483
  }
456
484
  var qwik_view_transition_default = "@layer qwik{@supports selector(html:active-view-transition-type(type)){html:active-view-transition-type(qwik-navigation){& :root{view-transition-name:none}}}@supports not selector(html:active-view-transition-type(type)){:root{view-transition-name:none}}}";
457
- /** View transitions are opt-in and require browser support. */ var shouldStartViewTransition = (viewTransition) => viewTransition === true && "startViewTransition" in document;
485
+ /** View transitions are opt-in and require browser support. */
486
+ var shouldStartViewTransition = (viewTransition) => viewTransition === true && "startViewTransition" in document;
458
487
  var VIEW_TRANSITION_STYLE_ID = "qwik-view-transition";
459
- /** Inject the view-transition stylesheet once, only when a transition actually runs. */ var ensureViewTransitionStyles = () => {
488
+ /** Inject the view-transition stylesheet once, only when a transition actually runs. */
489
+ var ensureViewTransitionStyles = () => {
460
490
  if (document.getElementById(VIEW_TRANSITION_STYLE_ID)) return;
461
491
  const style = document.createElement("style");
462
492
  style.id = VIEW_TRANSITION_STYLE_ID;
@@ -481,44 +511,17 @@ var startViewTransition = (params) => {
481
511
  } else return { ready: params.update() };
482
512
  };
483
513
  /**
484
- * Qwik Router Component
485
- *
486
- * This file contains the main Qwik Router component, which initializes the router and provides the
487
- * necessary context for it to work. It also contains the logic for handling navigation, including
488
- * updating the URL, managing scroll restoration, and resolving document head changes.
489
- *
490
- * Note: This component is designed to work both on the server and the client. During server-side
491
- * rendering (SSR), it initializes the router state based on the URL and route data provided by the
492
- * server environment. On the client, it handles navigation events and updates the router state
493
- * accordingly.
494
- *
495
- * SSR is _required_ for the initial load.
496
- *
497
- * The flow of navigation is as follows:
498
- *
499
- * 1. During SSR, the server environment parses the initial URL and collects the route data.
500
- * 2. It runs the middleware hooks (`onRequest`, `onGet`, `onPost`, etc.), and responds to q-loader,
501
- * action$ and server$ requests.
502
- * 3. If SSR is deemed appropriate, the route data is provided via `useServerData` and this component
503
- * uses it to initialize the router contexts, register Tasks, and render the Slot. This component
504
- * will never render again.
505
- * 4. Then, slotted components like `<DocumentHeadTags />` and `<RouterOutlet />` can consume the route
506
- * data to render the page.
507
- * 5. On the client, when a navigation event occurs, this calls `goto()`, which updates the URL in the
508
- * same tick, loads the route data and adjusts the router context.
509
- * 6. The changed contexts trigger the slotted components to re-render with the new route data.
510
- *
511
- * Since the head data can depend on route loaders and they get their data asynchronously and can
512
- * update without navigation, the head is resolved in a separate Task that tracks the relevant
513
- * signals.
514
- */
515
- /**
516
514
  * @deprecated Use `QWIK_ROUTER_SCROLLER` instead (will be removed in V3)
517
515
  * @public
518
- */ var QWIK_CITY_SCROLLER = "_qCityScroller";
519
- /** @public */ var QWIK_ROUTER_SCROLLER = "_qRouterScroller";
516
+ */
517
+ var QWIK_CITY_SCROLLER = "_qCityScroller";
518
+ /** @public */
519
+ var QWIK_ROUTER_SCROLLER = "_qRouterScroller";
520
520
  var preventNav = {};
521
- var internalState = { navCount: 0 };
521
+ var internalState = {
522
+ navCount: 0,
523
+ attemptCount: 0
524
+ };
522
525
  var getScroller = () => {
523
526
  let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
524
527
  if (!scroller) {
@@ -527,154 +530,13 @@ var getScroller = () => {
527
530
  }
528
531
  return scroller ?? document.documentElement;
529
532
  };
530
- /** @public */ var useQwikMockRouter = (props) => {
531
- const urlEnv = props.url ?? "http://localhost/";
532
- const url = new URL(urlEnv);
533
- const routeLocation = useStore({
534
- url,
535
- params: props.params ?? {},
536
- isNavigating: false,
537
- prevUrl: void 0
538
- }, { deep: false });
539
- const loadersData = props.loaders?.reduce((acc, { loader, data }) => {
540
- acc[loader.__id] = data;
541
- return acc;
542
- }, {});
543
- const loadersState = useStore({}, { deep: false });
544
- for (const [loaderId, data] of Object.entries(loadersData ?? {})) loadersState[loaderId] ||= createComputedQrl(/*#__PURE__*/ inlinedQrl(() => {
545
- return _captures[0];
546
- }, "useQwikMockRouter_createComputed_JL6bChMwwyc", [data]));
547
- const goto = props.goto ?? /*#__PURE__*/ inlinedQrl(async () => {
548
- console.warn("QwikRouterMockProvider: goto not provided");
549
- }, "useQwikMockRouter_goto_aViHFxQ1a3s");
550
- const documentHead = useStore(createDocumentHead, { deep: false });
551
- const content = useStore({
552
- headings: void 0,
553
- menu: void 0
554
- }, { deep: false });
555
- const contentInternal = useSignal();
556
- const actionState = useSignal();
557
- const httpStatus = useSignal({
558
- status: 200,
559
- message: ""
560
- });
561
- useContextProvider(ContentContext, content);
562
- useContextProvider(ContentInternalContext, contentInternal);
563
- useContextProvider(DocumentHeadContext, documentHead);
564
- useContextProvider(HttpStatusContext, httpStatus);
565
- useContextProvider(RouteLocationContext, routeLocation);
566
- useContextProvider(RouteNavigateContext, goto);
567
- useContextProvider(RouteStateContext, loadersState);
568
- useContextProvider(RouteActionContext, actionState);
569
- const actionsMocks = props.actions?.reduce((acc, { action, handler }) => {
570
- acc[action.__id] = handler;
571
- return acc;
572
- }, {});
573
- useTaskQrl(/*#__PURE__*/ inlinedQrl(async ({ track }) => {
574
- const actionState = _captures[0], actionsMocks = _captures[1];
575
- const action = track(actionState);
576
- if (!action?.resolve) return;
577
- const mock = actionsMocks?.[action.id];
578
- if (mock) {
579
- const actionResult = await mock(action.data);
580
- action.resolve(actionResult);
581
- }
582
- }, "useQwikMockRouter_useTask_tXTLR4tzCy0", [actionState, actionsMocks]));
583
- };
584
- /** @public */ var QwikRouterMockProvider = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
585
- useQwikMockRouter(props);
586
- return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "5y_1");
587
- }, "QwikRouterMockProvider_component_IN4dVpT0x74"));
588
- /**
589
- * @deprecated Use `useQwikMockRouter()` instead. Will be removed in V3
590
- * @public
591
- */ var QwikCityMockProvider = QwikRouterMockProvider;
592
- function initializeSPA(goto, scroller) {
593
- if (!window._qRouterSPA) {
594
- window._qRouterSPA = true;
595
- history.scrollRestoration = "manual";
596
- window.addEventListener("popstate", () => {
597
- window._qRouterScrollEnabled = false;
598
- clearTimeout(window._qRouterScrollDebounce);
599
- goto(location.href, { type: "popstate" });
600
- });
601
- window.removeEventListener("popstate", window._qRouterInitPopstate);
602
- window._qRouterInitPopstate = void 0;
603
- if (!window._qRouterHistoryPatch) {
604
- window._qRouterHistoryPatch = true;
605
- const pushState = history.pushState;
606
- const replaceState = history.replaceState;
607
- const prepareState = (state) => {
608
- if (state === null || typeof state === "undefined") state = {};
609
- else if (state?.constructor !== Object) {
610
- state = { _data: state };
611
- if (isDev) console.warn("In a Qwik SPA context, `history.state` is used to store scroll state. Direct calls to `pushState()` and `replaceState()` must supply an actual Object type. We need to be able to automatically attach the scroll state to your state object. A new state object has been created, your data has been moved to: `history.state._data`");
612
- }
613
- state._qRouterScroll = state._qRouterScroll || currentScrollState(scroller);
614
- return state;
615
- };
616
- history.pushState = (state, title, url) => {
617
- state = prepareState(state);
618
- return pushState.call(history, state, title, url);
619
- };
620
- history.replaceState = (state, title, url) => {
621
- state = prepareState(state);
622
- return replaceState.call(history, state, title, url);
623
- };
624
- }
625
- document.addEventListener("click", (event) => {
626
- if (event.defaultPrevented) return;
627
- const target = event.target.closest("a[href]");
628
- if (target && !target.hasAttribute("preventdefault:click")) {
629
- const href = target.getAttribute("href");
630
- const prev = new URL(location.href);
631
- const dest = new URL(href, prev);
632
- if (isSameOrigin(dest, prev) && isSamePath(dest, prev)) {
633
- event.preventDefault();
634
- if (!dest.hash && !dest.href.endsWith("#")) {
635
- if (dest.href !== prev.href) history.pushState(null, "", dest);
636
- window._qRouterScrollEnabled = false;
637
- clearTimeout(window._qRouterScrollDebounce);
638
- saveScrollHistory({
639
- ...currentScrollState(scroller),
640
- x: 0,
641
- y: 0
642
- });
643
- location.reload();
644
- return;
645
- }
646
- goto(target.getAttribute("href"));
647
- }
648
- }
649
- });
650
- document.removeEventListener("click", window._qRouterInitAnchors);
651
- window._qRouterInitAnchors = void 0;
652
- if (!window.navigation) {
653
- document.addEventListener("visibilitychange", () => {
654
- if (window._qRouterScrollEnabled && document.visibilityState === "hidden") saveScrollHistory(currentScrollState(scroller));
655
- }, { passive: true });
656
- document.removeEventListener("visibilitychange", window._qRouterInitVisibility);
657
- window._qRouterInitVisibility = void 0;
658
- }
659
- window.addEventListener("scroll", () => {
660
- if (!window._qRouterScrollEnabled) return;
661
- clearTimeout(window._qRouterScrollDebounce);
662
- window._qRouterScrollDebounce = setTimeout(() => {
663
- saveScrollHistory(currentScrollState(scroller));
664
- window._qRouterScrollDebounce = void 0;
665
- }, 200);
666
- }, { passive: true });
667
- removeEventListener("scroll", window._qRouterInitScroll);
668
- window._qRouterInitScroll = void 0;
669
- spa_init_default.resolve();
670
- }
671
- }
672
533
  /**
673
534
  * @public
674
535
  * This hook initializes Qwik Router, providing the necessary context for it to work.
675
536
  *
676
537
  * This hook should be used once, at the root of your application.
677
- */ var useQwikRouter = (props) => {
538
+ */
539
+ var useQwikRouter = (props) => {
678
540
  if (!isServer) throw new Error("useQwikRouter can only run during SSR on the server. If you are seeing this, it means you are re-rendering the root of your application. Fix that or use the <QwikRouterProvider> component around the root of your application.");
679
541
  const env = useQwikRouterEnv();
680
542
  if (!env?.params) throw new Error(`Missing Qwik Router Env Data for help visit https://github.com/QwikDev/qwik/issues/6237`);
@@ -695,7 +557,7 @@ function initializeSPA(goto, scroller) {
695
557
  routeLoaderCtx.manifestHash = manifestHash;
696
558
  const loaderState = {};
697
559
  const contentModulesForInit = env.loadedRoute.$mods$;
698
- const loaders = ensureRouteLoaderSignals(contentModulesForInit, loaderState, routeLoaderCtx);
560
+ const loaders = ensureRouteLoaderSignals(contentModulesForInit, loaderState, routeLoaderCtx, env.ev);
699
561
  for (const loader of loaders) if (loader.__id in env.loaderValues) {
700
562
  const value = env.loaderValues[loader.__id];
701
563
  setLoaderSignalValue(loaderState[loader.__id], value);
@@ -711,9 +573,10 @@ function initializeSPA(goto, scroller) {
711
573
  });
712
574
  const contentInternal = useSignal();
713
575
  /**
714
- * Non-serializable navigation context passed from the nav task to the head+commit task. Only the
576
+ * Non-serializable navigation context passed from the nav task to the navigation task. Only the
715
577
  * data that can't be derived from existing stores/signals.
716
- */ const navContext = useSignal();
578
+ */
579
+ const navContext = useSignal();
717
580
  const httpStatus = useSignal({
718
581
  status: env.response.status,
719
582
  message: env.loadedRoute.$notFound$ ? "Not Found" : env.response.statusMessage ?? ""
@@ -736,7 +599,7 @@ function initializeSPA(goto, scroller) {
736
599
  const registerPreventNav = /*#__PURE__*/ inlinedQrl((fn$) => {
737
600
  if (!isBrowser) return;
738
601
  preventNav.$handler$ ||= (event) => {
739
- internalState.navCount++;
602
+ internalState.attemptCount++;
740
603
  if (!preventNav.$cbs$) return;
741
604
  if ([...preventNav.$cbs$.values()].map((cb) => cb.resolved ? cb.resolved() : cb()).some(Boolean)) {
742
605
  event.preventDefault();
@@ -763,8 +626,9 @@ function initializeSPA(goto, scroller) {
763
626
  * Note: when goto is called, the address bar change must happen in the same tick for Safari to
764
627
  * treat it as a user-initiated navigation and allow scroll restoration to work. For this reason,
765
628
  * make sure to change the address bar before awaiting anything.
766
- */ const goto = /*#__PURE__*/ inlinedQrl(async (path, opt) => {
767
- const actionState = _captures[0], manifestHash = _captures[1], navResolver = _captures[2], routeInternal = _captures[3], routeLocation = _captures[4];
629
+ */
630
+ const goto = /*#__PURE__*/ inlinedQrl(async (path, opt) => {
631
+ let actionState = _capturesObj._[0], manifestHash = _capturesObj._[1], navResolver = _capturesObj._[2], routeInternal = _capturesObj._[3], routeLoaderCtx = _capturesObj._[4], routeLocation = _capturesObj._[5];
768
632
  const { type = "link", forceReload = path === void 0, replaceState = false, scroll = true } = typeof opt === "object" ? opt : { forceReload: opt };
769
633
  if (isBrowser && type === "link" && routeInternal.value.type === "initial") {
770
634
  const url = new URL(window.location.href);
@@ -774,12 +638,11 @@ function initializeSPA(goto, scroller) {
774
638
  const lastDest = routeInternal.value.dest;
775
639
  const dest = path === void 0 ? lastDest : typeof path === "number" ? path : toUrl(path, routeLocation.url);
776
640
  if (navResolver.p && !forceReload && typeof dest !== "number" && isSamePath(dest, lastDest) && dest.href === lastDest.href) return navResolver.p;
777
- const navCount = ++internalState.navCount;
778
- internalState.currentTransition?.skipTransition();
641
+ const attemptCount = ++internalState.attemptCount;
779
642
  if (preventNav.$cbs$ && (forceReload || typeof dest === "number" || !isSamePath(dest, lastDest) || !isSameOrigin(dest, lastDest))) {
780
643
  const prevents = await Promise.all([...preventNav.$cbs$.values()].map((cb) => cb(dest)));
781
- if (navCount !== internalState.navCount || prevents.some(Boolean)) {
782
- if (navCount === internalState.navCount && type === "popstate") history.pushState(null, "", lastDest);
644
+ if (attemptCount !== internalState.attemptCount || prevents.some(Boolean)) {
645
+ if (attemptCount === internalState.attemptCount && type === "popstate") history.pushState(null, "", lastDest);
783
646
  return;
784
647
  }
785
648
  }
@@ -803,9 +666,15 @@ function initializeSPA(goto, scroller) {
803
666
  routeInternal.value.dest = newUrl;
804
667
  routeLocation.url = newUrl;
805
668
  }
806
- return;
669
+ return navResolver.p;
807
670
  }
671
+ const navCount = ++internalState.navCount;
672
+ internalState.currentTransition?.skipTransition();
673
+ navResolver.cancel?.();
674
+ navResolver.cancel = void 0;
675
+ navResolver.r?.();
808
676
  let historyUpdated = false;
677
+ if (isBrowser) getClientRouteLoaders(routeLoaderCtx, routeLocation.url.href);
809
678
  if (isBrowser && type === "link" && !forceReload) {
810
679
  const scroller = getScroller();
811
680
  window._qRouterScrollEnabled = false;
@@ -814,9 +683,10 @@ function initializeSPA(goto, scroller) {
814
683
  clientNavigate(window, type, new URL(location.href), dest, replaceState);
815
684
  historyUpdated = true;
816
685
  }
686
+ const wasNavigating = routeLocation.isNavigating;
817
687
  routeLocation.isNavigating = true;
818
688
  const container = isBrowser ? _getContextContainer() : void 0;
819
- if (container) {
689
+ if (container && !wasNavigating) {
820
690
  await _waitUntilRendered(container);
821
691
  if (navCount !== internalState.navCount) return;
822
692
  }
@@ -829,6 +699,7 @@ function initializeSPA(goto, scroller) {
829
699
  scroll,
830
700
  historyUpdated
831
701
  };
702
+ if (wasNavigating) abortRouteLoaderNavigation(routeLoaderCtx);
832
703
  if (isBrowser) prefetchRoute(dest, false, .8, manifestHash, true);
833
704
  navResolver.p = new Promise((resolve) => {
834
705
  navResolver.r = () => {
@@ -843,6 +714,7 @@ function initializeSPA(goto, scroller) {
843
714
  manifestHash,
844
715
  navResolver,
845
716
  routeInternal,
717
+ routeLoaderCtx,
846
718
  routeLocation
847
719
  ]);
848
720
  useContextProvider(ContentContext, content);
@@ -858,10 +730,13 @@ function initializeSPA(goto, scroller) {
858
730
  /**
859
731
  * This is split in 3 tasks because we need to update the head once we figured out the route, and
860
732
  * before we trigger the render, and we need to subscribe only head to loader signal updates
861
- */ useTaskQrl(/*#__PURE__*/ inlinedQrl(async ({ track }) => {
862
- const actionDataSignal = _captures[0], actionState = _captures[1], content = _captures[2], contentInternal = _captures[3], env = _captures[4], goto = _captures[5], httpStatus = _captures[6], loaderState = _captures[7], navContext = _captures[8], routeInternal = _captures[9], routeLoaderCtx = _captures[10], routeLocation = _captures[11], routeLocationTarget = _captures[12];
733
+ */
734
+ useTaskQrl(/*#__PURE__*/ inlinedQrl(async ({ track }) => {
735
+ let actionDataSignal = _capturesObj._[0], actionState = _capturesObj._[1], content = _capturesObj._[2], contentInternal = _capturesObj._[3], env = _capturesObj._[4], goto = _capturesObj._[5], httpStatus = _capturesObj._[6], loaderState = _capturesObj._[7], navContext = _capturesObj._[8], navResolver = _capturesObj._[9], routeInternal = _capturesObj._[10], routeLoaderCtx = _capturesObj._[11], routeLocation = _capturesObj._[12], routeLocationTarget = _capturesObj._[13];
863
736
  const navigation = track(routeInternal);
864
737
  const action = track(actionState);
738
+ action?.resolveDispatch?.();
739
+ if (action) action.resolveDispatch = void 0;
865
740
  const prevUrl = routeLocation.url;
866
741
  const navType = action ? "form" : navigation.type;
867
742
  const replaceState = navigation.replaceState;
@@ -870,7 +745,6 @@ function initializeSPA(goto, scroller) {
870
745
  let endpointResponse;
871
746
  let actionData;
872
747
  let actionLoaderHashes;
873
- let shouldInvalidateActionLoaders = false;
874
748
  let loadedRoute;
875
749
  if (isServer) {
876
750
  trackUrl = new URL(navigation.dest, routeLocation.url);
@@ -879,20 +753,42 @@ function initializeSPA(goto, scroller) {
879
753
  actionData = endpointResponse;
880
754
  } else {
881
755
  trackUrl = new URL(navigation.dest, location);
756
+ const canceled = new Promise((resolve) => {
757
+ navResolver.cancel = () => resolve(void 0);
758
+ });
882
759
  if (trackUrl.pathname.endsWith("/")) {
883
760
  if (globalThis.__NO_TRAILING_SLASH__) trackUrl.pathname = trackUrl.pathname.slice(0, -1);
884
761
  } else if (!globalThis.__NO_TRAILING_SLASH__) trackUrl.pathname = ensureSlash(trackUrl.pathname);
885
- const loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, trackUrl.pathname);
762
+ const loadRoutePromise = getRouterConfig().then((config) => {
763
+ if (internalState.navCount !== navCountBefore) return;
764
+ return loadRoute(config.routes, config.cacheModules, trackUrl.pathname);
765
+ });
886
766
  try {
887
- loadedRoute = await loadRoutePromise;
767
+ const route = await Promise.race([loadRoutePromise, canceled]);
768
+ if (!route) return;
769
+ loadedRoute = route;
888
770
  } catch (e) {
771
+ if (internalState.navCount !== navCountBefore) return;
772
+ const preparedNavCount = getClientRouteLoaders(routeLoaderCtx).navCount;
773
+ if (preparedNavCount !== void 0) restoreRouteLoaders(loaderState, routeLoaderCtx, preparedNavCount);
889
774
  console.error(`Could not load route ${trackUrl.pathname}, reloading:`, e);
890
775
  window.location.href = trackUrl.href;
891
776
  return;
892
777
  }
893
778
  if (internalState.navCount !== navCountBefore) return;
894
779
  if (action) {
895
- const result = await submitAction(action, trackUrl);
780
+ const result = await Promise.race([submitAction(action, trackUrl).then((result) => {
781
+ if (result && action.resolve) {
782
+ action.resolve({
783
+ status: result.status,
784
+ result: result.result
785
+ });
786
+ action.resolve = void 0;
787
+ }
788
+ return result;
789
+ }), canceled]);
790
+ if (internalState.navCount !== navCountBefore || action !== actionState.untrackedValue) return;
791
+ navResolver.cancel = void 0;
896
792
  if (!result) {
897
793
  routeInternal.untrackedValue = {
898
794
  type: navType,
@@ -900,15 +796,9 @@ function initializeSPA(goto, scroller) {
900
796
  };
901
797
  return;
902
798
  }
903
- if (action.resolve) {
904
- action.resolve({
905
- status: result.status,
906
- result: result.result
907
- });
908
- action.resolve = void 0;
909
- }
910
799
  if (result.redirect) {
911
- goto(result.redirect, { replaceState: true });
800
+ if (result.redirect instanceof URL) location.href = result.redirect.href;
801
+ else goto(result.redirect, { replaceState: true });
912
802
  return;
913
803
  }
914
804
  actionData = {
@@ -917,19 +807,17 @@ function initializeSPA(goto, scroller) {
917
807
  actionResult: result.result
918
808
  };
919
809
  actionLoaderHashes = result.loaderHashes;
920
- shouldInvalidateActionLoaders = true;
921
810
  }
811
+ navResolver.cancel = void 0;
922
812
  }
923
813
  const { $routeName$, $params$, $mods$, $menu$, $notFound$ } = loadedRoute;
924
814
  const contentModules = $mods$;
925
815
  if (!isServer) routeLoaderCtx.goto = noSerialize(goto);
926
- updateRouteLoaderPaths(routeLoaderCtx, loadedRoute.$loaderPaths$, trackUrl);
927
- if (!isServer) invalidateNavRouteLoaders(loaderState);
928
- const routeLoaders = ensureRouteLoaderSignals(contentModules, loaderState, routeLoaderCtx);
929
- if (shouldInvalidateActionLoaders) {
930
- if (actionLoaderHashes !== void 0) for (const hash of actionLoaderHashes) loaderState[hash]?.invalidate(true);
931
- else for (const loader of routeLoaders) loaderState[loader.__id].invalidate(true);
932
- }
816
+ let routeLoaders;
817
+ if (isServer) {
818
+ Object.assign(routeLoaderCtx.loaderPaths, loadedRoute.$loaderPaths$);
819
+ routeLoaders = ensureRouteLoaderSignals(contentModules, loaderState, routeLoaderCtx, env.ev);
820
+ } else routeLoaders = prepareRouteLoaders(contentModules, loaderState, routeLoaderCtx, loadedRoute.$loaderPaths$, trackUrl, prevUrl, navCountBefore, action ? actionLoaderHashes ?? null : void 0, action ?? navigation);
933
821
  if (routeLoaders.length > 0) for (let i = 0; i < routeLoaders.length; i++) {
934
822
  const loader = routeLoaders[i];
935
823
  if (!isImmutableLoader(loader.__id)) loaderState[loader.__id].untrackedPending;
@@ -953,6 +841,7 @@ function initializeSPA(goto, scroller) {
953
841
  message: "OK"
954
842
  };
955
843
  const pageModule = contentModules[contentModules.length - 1];
844
+ if (isSamePath(trackUrl, navigation.dest)) trackUrl.hash = navigation.dest.hash;
956
845
  if (navigation.dest.search && !!isSamePath(trackUrl, prevUrl)) trackUrl.search = navigation.dest.search;
957
846
  let shouldForcePrevUrl = false;
958
847
  let shouldForceUrl = false;
@@ -1002,6 +891,7 @@ function initializeSPA(goto, scroller) {
1002
891
  httpStatus,
1003
892
  loaderState,
1004
893
  navContext,
894
+ navResolver,
1005
895
  routeInternal,
1006
896
  routeLoaderCtx,
1007
897
  routeLocation,
@@ -1012,9 +902,12 @@ function initializeSPA(goto, scroller) {
1012
902
  * without re-running the navigation logic.
1013
903
  *
1014
904
  * Note that on the server these tasks run sequentially.
1015
- */ useTaskQrl(/*#__PURE__*/ inlinedQrl(({ track }) => {
1016
- const actionDataSignal = _captures[0], contentInternal = _captures[1], documentHead = _captures[2], loaderState = _captures[3], routeLocation = _captures[4], serverHead = _captures[5];
905
+ */
906
+ useTaskQrl(/*#__PURE__*/ inlinedQrl(({ track }) => {
907
+ let actionDataSignal = _capturesObj._[0], contentInternal = _capturesObj._[1], documentHead = _capturesObj._[2], loaderState = _capturesObj._[3], navContext = _capturesObj._[4], routeLocation = _capturesObj._[5], serverHead = _capturesObj._[6];
1017
908
  const contentModules = track(contentInternal);
909
+ const nav = navContext.untrackedValue;
910
+ if (!isServer && routeLocation.isNavigating && nav && nav.navCount !== internalState.navCount) return;
1018
911
  if (!contentModules) return;
1019
912
  const actionData = track(actionDataSignal);
1020
913
  let head;
@@ -1036,11 +929,13 @@ function initializeSPA(goto, scroller) {
1036
929
  contentInternal,
1037
930
  documentHead,
1038
931
  loaderState,
932
+ navContext,
1039
933
  routeLocation,
1040
934
  serverHead
1041
935
  ]), { deferUpdates: isServer });
1042
- /** Actual navigation */ useTaskQrl(/*#__PURE__*/ inlinedQrl(({ track }) => {
1043
- const contentInternal = _captures[0], goto = _captures[1], manifestHash = _captures[2], navContext = _captures[3], navResolver = _captures[4], props = _captures[5], routeInternal = _captures[6], routeLocation = _captures[7];
936
+ /** Actual navigation */
937
+ useTaskQrl(/*#__PURE__*/ inlinedQrl(({ track }) => {
938
+ let contentInternal = _capturesObj._[0], goto = _capturesObj._[1], loaderState = _capturesObj._[2], manifestHash = _capturesObj._[3], navContext = _capturesObj._[4], navResolver = _capturesObj._[5], props = _capturesObj._[6], routeInternal = _capturesObj._[7], routeLoaderCtx = _capturesObj._[8], routeLocation = _capturesObj._[9];
1044
939
  const nav = track(navContext);
1045
940
  if (isServer || !nav) return;
1046
941
  if (nav.navCount !== internalState.navCount) return;
@@ -1071,7 +966,12 @@ function initializeSPA(goto, scroller) {
1071
966
  if (currentPath !== nextPath) history.replaceState(history.state, "", nextPath);
1072
967
  } else clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1073
968
  contentInternal.trigger();
1074
- return navigatePromise = _waitUntilRendered(container);
969
+ return navigatePromise = _waitUntilRendered(container).then(() => {
970
+ if (nav.navCount === internalState.navCount) commitRouteLoaders(loaderState, routeLoaderCtx, nav.navCount);
971
+ }, (error) => {
972
+ if (nav.navCount === internalState.navCount) restoreRouteLoaders(loaderState, routeLoaderCtx, nav.navCount);
973
+ throw error;
974
+ });
1075
975
  };
1076
976
  const _waitNextPage = () => {
1077
977
  if (!shouldStartViewTransition(props?.viewTransition)) return navigate().then(() => void 0);
@@ -1104,40 +1004,192 @@ function initializeSPA(goto, scroller) {
1104
1004
  }, "useQwikRouter_useTask_2_yw17chooOac", [
1105
1005
  contentInternal,
1106
1006
  goto,
1007
+ loaderState,
1107
1008
  manifestHash,
1108
1009
  navContext,
1109
1010
  navResolver,
1110
1011
  props,
1111
1012
  routeInternal,
1013
+ routeLoaderCtx,
1112
1014
  routeLocation
1113
1015
  ]), { deferUpdates: false });
1114
1016
  };
1115
- /** @public This is a wrapper around the `useQwikRouter()` hook. We recommend using the hook instead of this component, unless you have a good reason to make your root component reactive. */ var QwikRouterProvider = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
1017
+ /** @public This is a wrapper around the `useQwikRouter()` hook. We recommend using the hook instead of this component, unless you have a good reason to make your root component reactive. */
1018
+ function initializeSPA(goto, scroller) {
1019
+ if (!window._qRouterSPA) {
1020
+ window._qRouterSPA = true;
1021
+ history.scrollRestoration = "manual";
1022
+ window.addEventListener("popstate", () => {
1023
+ window._qRouterScrollEnabled = false;
1024
+ clearTimeout(window._qRouterScrollDebounce);
1025
+ goto(location.href, { type: "popstate" });
1026
+ });
1027
+ window.removeEventListener("popstate", window._qRouterInitPopstate);
1028
+ window._qRouterInitPopstate = void 0;
1029
+ if (!window._qRouterHistoryPatch) {
1030
+ window._qRouterHistoryPatch = true;
1031
+ const pushState = history.pushState;
1032
+ const replaceState = history.replaceState;
1033
+ const prepareState = (state) => {
1034
+ if (state === null || typeof state === "undefined") state = {};
1035
+ else if (state?.constructor !== Object) {
1036
+ state = { _data: state };
1037
+ if (isDev) console.warn("In a Qwik SPA context, `history.state` is used to store scroll state. Direct calls to `pushState()` and `replaceState()` must supply an actual Object type. We need to be able to automatically attach the scroll state to your state object. A new state object has been created, your data has been moved to: `history.state._data`");
1038
+ }
1039
+ state._qRouterScroll = state._qRouterScroll || currentScrollState(scroller);
1040
+ return state;
1041
+ };
1042
+ history.pushState = (state, title, url) => {
1043
+ state = prepareState(state);
1044
+ return pushState.call(history, state, title, url);
1045
+ };
1046
+ history.replaceState = (state, title, url) => {
1047
+ state = prepareState(state);
1048
+ return replaceState.call(history, state, title, url);
1049
+ };
1050
+ }
1051
+ document.addEventListener("click", (event) => {
1052
+ if (event.defaultPrevented) return;
1053
+ const target = event.target.closest("a[href]");
1054
+ if (target && !target.hasAttribute("preventdefault:click")) {
1055
+ const href = target.getAttribute("href");
1056
+ const prev = new URL(location.href);
1057
+ const dest = new URL(href, prev);
1058
+ if (isSameOrigin(dest, prev) && isSamePath(dest, prev)) {
1059
+ event.preventDefault();
1060
+ if (!dest.hash && !dest.href.endsWith("#")) {
1061
+ if (dest.href !== prev.href) history.pushState(null, "", dest);
1062
+ window._qRouterScrollEnabled = false;
1063
+ clearTimeout(window._qRouterScrollDebounce);
1064
+ saveScrollHistory({
1065
+ ...currentScrollState(scroller),
1066
+ x: 0,
1067
+ y: 0
1068
+ });
1069
+ location.reload();
1070
+ return;
1071
+ }
1072
+ goto(target.getAttribute("href"));
1073
+ }
1074
+ }
1075
+ });
1076
+ document.removeEventListener("click", window._qRouterInitAnchors);
1077
+ window._qRouterInitAnchors = void 0;
1078
+ if (!window.navigation) {
1079
+ document.addEventListener("visibilitychange", () => {
1080
+ if (window._qRouterScrollEnabled && document.visibilityState === "hidden") saveScrollHistory(currentScrollState(scroller));
1081
+ }, { passive: true });
1082
+ document.removeEventListener("visibilitychange", window._qRouterInitVisibility);
1083
+ window._qRouterInitVisibility = void 0;
1084
+ }
1085
+ window.addEventListener("scroll", () => {
1086
+ if (!window._qRouterScrollEnabled) return;
1087
+ clearTimeout(window._qRouterScrollDebounce);
1088
+ window._qRouterScrollDebounce = setTimeout(() => {
1089
+ saveScrollHistory(currentScrollState(scroller));
1090
+ window._qRouterScrollDebounce = void 0;
1091
+ }, 200);
1092
+ }, { passive: true });
1093
+ removeEventListener("scroll", window._qRouterInitScroll);
1094
+ window._qRouterInitScroll = void 0;
1095
+ spa_init_default.resolve();
1096
+ }
1097
+ }
1098
+ var QwikRouterMockProvider = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
1099
+ useQwikMockRouter(props);
1100
+ return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "dU_1");
1101
+ }, "QwikRouterMockProvider_component_IN4dVpT0x74"));
1102
+ var useQwikMockRouter = (props) => {
1103
+ const urlEnv = props.url ?? "http://localhost/";
1104
+ const url = new URL(urlEnv);
1105
+ const routeLocation = useStore({
1106
+ url,
1107
+ params: props.params ?? {},
1108
+ isNavigating: false,
1109
+ prevUrl: void 0
1110
+ }, { deep: false });
1111
+ const loadersData = props.loaders?.reduce((acc, { loader, data }) => {
1112
+ acc[loader.__id] = data;
1113
+ return acc;
1114
+ }, {});
1115
+ const loadersState = useStore({}, { deep: false });
1116
+ for (const [loaderId, data] of Object.entries(loadersData ?? {})) loadersState[loaderId] ||= createComputedQrl(/*#__PURE__*/ inlinedQrl(() => {
1117
+ return _capturesObj._[0];
1118
+ }, "useQwikMockRouter_createComputed_JL6bChMwwyc", [data]));
1119
+ const goto = props.goto ?? /*#__PURE__*/ inlinedQrl(async () => {
1120
+ console.warn("QwikRouterMockProvider: goto not provided");
1121
+ }, "useQwikMockRouter_goto_aViHFxQ1a3s");
1122
+ const documentHead = useStore(createDocumentHead, { deep: false });
1123
+ const content = useStore({
1124
+ headings: void 0,
1125
+ menu: void 0
1126
+ }, { deep: false });
1127
+ const contentInternal = useSignal();
1128
+ const actionState = useSignal();
1129
+ const httpStatus = useSignal({
1130
+ status: 200,
1131
+ message: ""
1132
+ });
1133
+ useContextProvider(ContentContext, content);
1134
+ useContextProvider(ContentInternalContext, contentInternal);
1135
+ useContextProvider(DocumentHeadContext, documentHead);
1136
+ useContextProvider(HttpStatusContext, httpStatus);
1137
+ useContextProvider(RouteLocationContext, routeLocation);
1138
+ useContextProvider(RouteNavigateContext, goto);
1139
+ useContextProvider(RouteStateContext, loadersState);
1140
+ useContextProvider(RouteActionContext, actionState);
1141
+ const actionsMocks = props.actions?.reduce((acc, { action, handler }) => {
1142
+ acc[action.__id] = handler;
1143
+ return acc;
1144
+ }, {});
1145
+ useTaskQrl(/*#__PURE__*/ inlinedQrl(async ({ track }) => {
1146
+ let actionState = _capturesObj._[0], actionsMocks = _capturesObj._[1];
1147
+ const action = track(actionState);
1148
+ action?.resolveDispatch?.();
1149
+ if (action) action.resolveDispatch = void 0;
1150
+ if (!action?.resolve) return;
1151
+ const mock = actionsMocks?.[action.id];
1152
+ if (mock) {
1153
+ const actionResult = await mock(action.data);
1154
+ action.resolve(actionResult);
1155
+ }
1156
+ }, "useQwikMockRouter_useTask_tXTLR4tzCy0", [actionState, actionsMocks]));
1157
+ };
1158
+ var QwikRouterProvider = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
1116
1159
  useQwikRouter(props);
1117
- return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "5y_0");
1160
+ return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "dU_0");
1118
1161
  }, "QwikRouterProvider_component_6Kjfa79mqlY"));
1119
1162
  /**
1120
1163
  * @deprecated Use `useQwikRouter()` instead. Will be removed in v3.
1121
1164
  * @public
1122
- */ var QwikCityProvider = QwikRouterProvider;
1165
+ */
1166
+ var QwikCityProvider = QwikRouterProvider;
1167
+ /** @public */
1168
+ /** @public */
1169
+ /**
1170
+ * @deprecated Use `useQwikMockRouter()` instead. Will be removed in V3
1171
+ * @public
1172
+ */
1173
+ var QwikCityMockProvider = QwikRouterMockProvider;
1123
1174
  var handleRouterPopstate = (nav, event) => {
1124
1175
  const href = event.detail?.href;
1125
1176
  if (href) return nav(href, { type: "popstate" });
1126
1177
  };
1127
- /** @public */ var RouterOutlet = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(() => {
1178
+ /** @public */
1179
+ var RouterOutlet = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(() => {
1128
1180
  if (!useServerData("containerAttributes")) throw new Error("PrefetchServiceWorker component must be rendered on the server.");
1129
1181
  const internalContext = useContext(ContentInternalContext);
1130
1182
  const nav = useNavigate();
1131
1183
  const contents = internalContext.value;
1132
1184
  if (contents && contents.length > 0) {
1133
- const contentsLen = contents.length;
1134
1185
  let cmp = null;
1135
- for (let i = contentsLen - 1; i >= 0; i--) if (contents[i].default) cmp = _jsxSorted(contents[i].default, null, null, cmp, 1, "Fn_0");
1186
+ for (let i = contents.length - 1; i >= 0; i--) if (contents[i].default) cmp = /*#__PURE__*/ _jsxSorted(contents[i].default, null, null, cmp, 1, "yd_0");
1136
1187
  return /*#__PURE__*/ _jsxSorted(Fragment, null, null, [cmp, !__EXPERIMENTAL__.noSPA && /*#__PURE__*/ _jsxSorted("script", {
1188
+ "q-d:qcinit": [spa_init_default, linkPrefetchInit],
1137
1189
  "q-d:qinit": _qrlSync(() => {
1138
1190
  ((w, h) => {
1139
1191
  if (!w._qcs) {
1140
- w._qcs = !0;
1192
+ w._qcs = true;
1141
1193
  const s = h.state?._qRouterScroll;
1142
1194
  if (s) {
1143
1195
  h.scrollRestoration = "manual";
@@ -1147,126 +1199,19 @@ var handleRouterPopstate = (nav, event) => {
1147
1199
  }
1148
1200
  })(window, history);
1149
1201
  }, "()=>{((w,h)=>{if(!w._qcs){w._qcs=!0;const s=h.state?._qRouterScroll;if(s){h.scrollRestoration=\"manual\";w.scrollTo(s.x,s.y);}document.dispatchEvent(new Event(\"qcinit\"));}})(window,history);}"),
1150
- "q-d:qrouterpopstate": /*#__PURE__*/ inlinedQrl((event, _1, nav) => handleRouterPopstate(nav, event), "RouterOutlet_component_Fragment_script_q_d_qrouterpopstate_aRL6GvFyews").m(),
1151
1202
  "q:p": nav
1152
- }, { "q-d:qcinit": [spa_init_default, linkPrefetchInit] }, null, 6, "Fn_1")], 1, "Fn_2");
1203
+ }, { "q-d:qrouterpopstate": /*#__PURE__*/ inlinedQrl((event, _1, nav) => handleRouterPopstate(nav, event), "RouterOutlet_component_Fragment_script_q_d_qrouterpopstate_aRL6GvFyews").m() }, null, 6, "yd_0")], 1, "yd_1");
1153
1204
  }
1154
1205
  return SkipRender;
1155
1206
  }, "RouterOutlet_component_QwONcWD5gIg"));
1156
- /** @internal */ var validatorQrl = (validator) => {
1157
- if (isServer) return { validate: validator };
1158
- };
1159
- /** @public */ var validator$ = /*#__PURE__*/ implicit$FirstArg(validatorQrl);
1160
- var flattenValibotIssues = (issues) => {
1161
- return issues.reduce((acc, issue) => {
1162
- if (issue.path) {
1163
- if (issue.path.some((path) => path.type === "array")) {
1164
- const keySuffix = issue.expected === "Array" ? "[]" : "";
1165
- const key = issue.path.map((item) => item.type === "array" ? "*" : item.key).join(".").replace(/\.\*/g, "[]") + keySuffix;
1166
- acc[key] = acc[key] || [];
1167
- if (Array.isArray(acc[key])) acc[key].push(issue.message);
1168
- return acc;
1169
- } else acc[issue.path.map((item) => item.key).join(".")] = issue.message;
1170
- }
1171
- return acc;
1172
- }, {});
1173
- };
1174
- /** @internal */ var valibotQrl = (qrl) => {
1175
- if (!__EXPERIMENTAL__.valibot) throw new Error("Valibot is an experimental feature and is not enabled. Please enable the feature flag by adding `experimental: [\"valibot\"]` to your qwikVite plugin options.");
1176
- if (isServer) return {
1177
- __brand: "valibot",
1178
- async validate(ev, inputData) {
1179
- const schema = await qrl.resolve().then((obj) => typeof obj === "function" ? obj(ev) : obj);
1180
- const data = inputData ?? await ev.parseBody();
1181
- const result = await v.safeParseAsync(schema, data);
1182
- if (result.success) return {
1183
- success: true,
1184
- data: result.output
1185
- };
1186
- else {
1187
- if (isDev) console.error("ERROR: Valibot validation failed", result.issues);
1188
- return {
1189
- success: false,
1190
- status: 400,
1191
- error: {
1192
- formErrors: v.flatten(result.issues).root ?? [],
1193
- fieldErrors: flattenValibotIssues(result.issues)
1194
- }
1195
- };
1196
- }
1197
- }
1198
- };
1199
- };
1200
- /** @beta */ var valibot$ = /*#__PURE__*/ implicit$FirstArg(valibotQrl);
1201
- var flattenZodIssues = (issues) => {
1202
- issues = Array.isArray(issues) ? issues : [issues];
1203
- return issues.reduce((acc, issue) => {
1204
- const isExpectingArray = "expected" in issue && issue.expected === "array";
1205
- if (issue.path.some((path) => typeof path === "number") || isExpectingArray) {
1206
- const keySuffix = "expected" in issue && issue.expected === "array" ? "[]" : "";
1207
- const key = issue.path.map((path) => typeof path === "number" ? "*" : path).join(".").replace(/\.\*/g, "[]") + keySuffix;
1208
- acc[key] = acc[key] || [];
1209
- if (Array.isArray(acc[key])) acc[key].push(issue.message);
1210
- return acc;
1211
- } else acc[issue.path.join(".")] = issue.message;
1212
- return acc;
1213
- }, {});
1214
- };
1215
- /** @internal */ var zodQrl = (qrl) => {
1216
- if (isServer) return {
1217
- __brand: "zod",
1218
- async validate(ev, inputData) {
1219
- const schema = await qrl.resolve().then((obj) => {
1220
- if (typeof obj === "function") obj = obj(z$1, ev);
1221
- if (obj instanceof z$1.ZodType) return obj;
1222
- else return z$1.object(obj);
1223
- });
1224
- const data = inputData ?? await ev.parseBody();
1225
- const result = await withLocale(ev.locale(), () => schema.safeParseAsync(data));
1226
- if (result.success) return result;
1227
- else {
1228
- if (isDev) console.error("ERROR: Zod validation failed", result.error.issues);
1229
- return {
1230
- success: false,
1231
- status: 400,
1232
- error: {
1233
- formErrors: result.error.flatten().formErrors,
1234
- fieldErrors: flattenZodIssues(result.error.issues)
1235
- }
1236
- };
1237
- }
1238
- }
1239
- };
1240
- };
1241
- /** @public */ var zod$ = /*#__PURE__*/ implicit$FirstArg(zodQrl);
1242
- var getValidators = (rest, qrl) => {
1243
- let id;
1244
- let invalidate;
1245
- const validators = [];
1246
- if (rest.length === 1) {
1247
- const options = rest[0];
1248
- if (options && typeof options === "object") {
1249
- if ("validate" in options) validators.push(options);
1250
- else {
1251
- id = options.id;
1252
- if (options.validation) validators.push(...options.validation);
1253
- if (options.invalidate) invalidate = options.invalidate.map((loader) => loader.__id);
1254
- }
1255
- }
1256
- } else if (rest.length > 1) validators.push(...rest.filter((v) => !!v));
1257
- if (typeof id === "string") {
1258
- if (isDev) {
1259
- if (!/^[\w/.-]+$/.test(id)) throw new Error(`Invalid id: ${id}, id can only contain [a-zA-Z0-9_.-]`);
1260
- }
1261
- id = `id_${id}`;
1262
- } else id = qrl.getHash();
1263
- return {
1264
- validators: validators.reverse(),
1265
- id,
1266
- invalidate
1267
- };
1268
- };
1269
- /** @public */ var routeActionQrl = (actionQrl, ...rest) => {
1207
+ /**
1208
+ * Hoisted function declarations (not consts) on purpose, like `routeLoaderQrl`: the app's route
1209
+ * modules call these factories during their own evaluation, which a bundle may run before this
1210
+ * module, where a `const` binding would throw a TDZ ReferenceError.
1211
+ *
1212
+ * @public
1213
+ */
1214
+ function routeActionQrl(actionQrl, ...rest) {
1270
1215
  const { id, validators, invalidate } = getValidators(rest, actionQrl);
1271
1216
  function action() {
1272
1217
  const loc = useLocation();
@@ -1293,7 +1238,7 @@ var getValidators = (rest, qrl) => {
1293
1238
  return initialState;
1294
1239
  });
1295
1240
  initialState.submit = /* @__PURE__ */ inlinedQrl((input = {}) => {
1296
- const currentAction = _captures[0], id = _captures[1], loc = _captures[2], state = _captures[3];
1241
+ let currentAction = _capturesObj._[0], id = _capturesObj._[1], latestSubmission = _capturesObj._[2], loc = _capturesObj._[3], state = _capturesObj._[4];
1297
1242
  if (isServer) throw new Error(`Actions can not be invoked within the server during SSR.
1298
1243
  Action.run() can only be called on the browser, for example when a user clicks a button, or submits a form.`);
1299
1244
  let data;
@@ -1305,7 +1250,14 @@ Action.run() can only be called on the browser, for example when a user clicks a
1305
1250
  if (input.submitter.name) data.append(input.submitter.name, input.submitter.value);
1306
1251
  }
1307
1252
  } else data = input;
1308
- return new Promise((resolve) => {
1253
+ const submission = {};
1254
+ latestSubmission.current = submission;
1255
+ const previousDispatch = currentAction.pendingDispatch ?? Promise.resolve();
1256
+ let resolveDispatch;
1257
+ currentAction.pendingDispatch = noSerialize(new Promise((resolve) => {
1258
+ resolveDispatch = resolve;
1259
+ }));
1260
+ return previousDispatch.then(() => new Promise((resolve) => {
1309
1261
  if (data instanceof FormData) state.formData = data;
1310
1262
  state.submitted = true;
1311
1263
  state.isRunning = true;
@@ -1313,17 +1265,21 @@ Action.run() can only be called on the browser, for example when a user clicks a
1313
1265
  currentAction.value = {
1314
1266
  data,
1315
1267
  id,
1316
- resolve: noSerialize(resolve)
1268
+ resolve: noSerialize(resolve),
1269
+ resolveDispatch: noSerialize(resolveDispatch)
1317
1270
  };
1318
- }).then((_rawProps) => {
1319
- state.isRunning = false;
1320
- state.status = _rawProps.status;
1321
- state.value = _rawProps.result;
1271
+ })).then(({ result, status }) => {
1272
+ const isLatestSubmission = latestSubmission.current === submission;
1273
+ if (isLatestSubmission) {
1274
+ state.isRunning = false;
1275
+ state.status = status;
1276
+ state.value = result;
1277
+ }
1322
1278
  if (form) {
1323
- if (form.getAttribute("data-spa-reset") === "true") form.reset();
1279
+ if (isLatestSubmission && form.getAttribute("data-spa-reset") === "true") form.reset();
1324
1280
  const detail = {
1325
- status: _rawProps.status,
1326
- value: _rawProps.result
1281
+ status,
1282
+ value: result
1327
1283
  };
1328
1284
  form.dispatchEvent(new CustomEvent("submitcompleted", {
1329
1285
  bubbles: false,
@@ -1333,13 +1289,14 @@ Action.run() can only be called on the browser, for example when a user clicks a
1333
1289
  }));
1334
1290
  }
1335
1291
  return {
1336
- status: _rawProps.status,
1337
- value: _rawProps.result
1292
+ status,
1293
+ value: result
1338
1294
  };
1339
1295
  });
1340
1296
  }, "routeActionQrl_action_submit_YuS5bpdQ360", [
1341
1297
  currentAction,
1342
1298
  id,
1299
+ { current: void 0 },
1343
1300
  loc,
1344
1301
  state
1345
1302
  ]);
@@ -1352,15 +1309,16 @@ Action.run() can only be called on the browser, for example when a user clicks a
1352
1309
  action.__invalidate = invalidate;
1353
1310
  Object.freeze(action);
1354
1311
  return action;
1355
- };
1356
- /** @internal */ var globalActionQrl = (actionQrl, ...rest) => {
1312
+ }
1313
+ /** @internal */
1314
+ function globalActionQrl(actionQrl, ...rest) {
1357
1315
  const action = routeActionQrl(actionQrl, ...rest);
1358
1316
  if (isServer) {
1359
1317
  if (typeof globalThis._qwikActionsMap === "undefined") globalThis._qwikActionsMap = /* @__PURE__ */ new Map();
1360
1318
  globalThis._qwikActionsMap.set(action.__id, action);
1361
1319
  }
1362
1320
  return action;
1363
- };
1321
+ }
1364
1322
  /**
1365
1323
  * Define a route action that handles form submissions or programmatic invocations.
1366
1324
  *
@@ -1380,27 +1338,106 @@ Action.run() can only be called on the browser, for example when a user clicks a
1380
1338
  * don't specify an explicit `invalidate` option.
1381
1339
  *
1382
1340
  * @public
1383
- */ var routeAction$ = /*#__PURE__*/ implicit$FirstArg(routeActionQrl);
1384
- /** @public */ var globalAction$ = /*#__PURE__*/ implicit$FirstArg(globalActionQrl);
1385
- var deserializeStream = async function* (stream, abortSignal) {
1386
- const reader = stream.getReader();
1387
- try {
1388
- let buffer = "";
1389
- const decoder = new TextDecoder();
1390
- while (!abortSignal?.aborted) {
1391
- const result = await reader.read();
1392
- if (result.done) break;
1393
- buffer += decoder.decode(result.value, { stream: true });
1394
- const lines = buffer.split(/\n/);
1395
- buffer = lines.pop();
1396
- for (const line of lines) yield await _deserialize(line);
1341
+ */
1342
+ var routeAction$ = /*#__PURE__*/ implicit$FirstArg(routeActionQrl);
1343
+ /** @public */
1344
+ var globalAction$ = /*#__PURE__*/ implicit$FirstArg(globalActionQrl);
1345
+ /** @internal */
1346
+ function validatorQrl(validator) {
1347
+ if (isServer) return { validate: validator };
1348
+ }
1349
+ /** @public */
1350
+ var validator$ = /*#__PURE__*/ implicit$FirstArg(validatorQrl);
1351
+ var flattenValibotIssues = (issues) => {
1352
+ return issues.reduce((acc, issue) => {
1353
+ if (issue.path) {
1354
+ if (issue.path.some((path) => path.type === "array")) {
1355
+ const keySuffix = issue.expected === "Array" ? "[]" : "";
1356
+ const key = issue.path.map((item) => item.type === "array" ? "*" : item.key).join(".").replace(/\.\*/g, "[]") + keySuffix;
1357
+ acc[key] = acc[key] || [];
1358
+ if (Array.isArray(acc[key])) acc[key].push(issue.message);
1359
+ return acc;
1360
+ } else acc[issue.path.map((item) => item.key).join(".")] = issue.message;
1397
1361
  }
1398
- } finally {
1399
- reader.releaseLock();
1400
- }
1362
+ return acc;
1363
+ }, {});
1364
+ };
1365
+ /** @internal */
1366
+ function valibotQrl(qrl) {
1367
+ if (!__EXPERIMENTAL__.valibot) throw new Error("Valibot is an experimental feature and is not enabled. Please enable the feature flag by adding `experimental: [\"valibot\"]` to your qwikVite plugin options.");
1368
+ if (isServer) return {
1369
+ __brand: "valibot",
1370
+ async validate(ev, inputData) {
1371
+ const schema = await qrl.resolve().then((obj) => typeof obj === "function" ? obj(ev) : obj);
1372
+ const data = inputData ?? await ev.parseBody();
1373
+ const result = await v.safeParseAsync(schema, data);
1374
+ if (result.success) return {
1375
+ success: true,
1376
+ data: result.output
1377
+ };
1378
+ else {
1379
+ if (isDev) console.error("ERROR: Valibot validation failed", result.issues);
1380
+ return {
1381
+ success: false,
1382
+ status: 400,
1383
+ error: {
1384
+ formErrors: v.flatten(result.issues).root ?? [],
1385
+ fieldErrors: flattenValibotIssues(result.issues)
1386
+ }
1387
+ };
1388
+ }
1389
+ }
1390
+ };
1391
+ }
1392
+ /** @beta */
1393
+ var valibot$ = /*#__PURE__*/ implicit$FirstArg(valibotQrl);
1394
+ var flattenZodIssues = (issues) => {
1395
+ issues = Array.isArray(issues) ? issues : [issues];
1396
+ return issues.reduce((acc, issue) => {
1397
+ const isExpectingArray = "expected" in issue && issue.expected === "array";
1398
+ if (issue.path.some((path) => typeof path === "number") || isExpectingArray) {
1399
+ const keySuffix = "expected" in issue && issue.expected === "array" ? "[]" : "";
1400
+ const key = issue.path.map((path) => typeof path === "number" ? "*" : path).join(".").replace(/\.\*/g, "[]") + keySuffix;
1401
+ acc[key] = acc[key] || [];
1402
+ if (Array.isArray(acc[key])) acc[key].push(issue.message);
1403
+ return acc;
1404
+ } else acc[issue.path.join(".")] = issue.message;
1405
+ return acc;
1406
+ }, {});
1401
1407
  };
1402
- /** @internal */ var serverQrl = (qrl, options) => {
1408
+ /** @internal */
1409
+ function zodQrl(qrl) {
1410
+ if (isServer) return {
1411
+ __brand: "zod",
1412
+ async validate(ev, inputData) {
1413
+ const schema = await qrl.resolve().then((obj) => {
1414
+ if (typeof obj === "function") obj = obj(z$1, ev);
1415
+ if (obj instanceof z$1.ZodType) return obj;
1416
+ else return z$1.object(obj);
1417
+ });
1418
+ const data = inputData ?? await ev.parseBody();
1419
+ const result = await withLocale(ev.locale(), () => schema.safeParseAsync(data));
1420
+ if (result.success) return result;
1421
+ else {
1422
+ if (isDev) console.error("ERROR: Zod validation failed", result.error.issues);
1423
+ return {
1424
+ success: false,
1425
+ status: 400,
1426
+ error: {
1427
+ formErrors: result.error.flatten().formErrors,
1428
+ fieldErrors: flattenZodIssues(result.error.issues)
1429
+ }
1430
+ };
1431
+ }
1432
+ }
1433
+ };
1434
+ }
1435
+ /** @public */
1436
+ var zod$ = /*#__PURE__*/ implicit$FirstArg(zodQrl);
1437
+ /** @internal */
1438
+ function serverQrl(qrl, options) {
1403
1439
  if (isServer) {
1440
+ _regInlinedQrl(qrl);
1404
1441
  const captured = qrl.getCaptured();
1405
1442
  if (captured && captured.length > 0 && !_getContextHostElement()) throw new Error("For security reasons, we cannot serialize QRLs that capture lexical scope.");
1406
1443
  }
@@ -1409,7 +1446,7 @@ var deserializeStream = async function* (stream, abortSignal) {
1409
1446
  const origin = options?.origin || "";
1410
1447
  const fetchOptions = options?.fetchOptions || {};
1411
1448
  return /*#__PURE__*/ inlinedQrl(async function(...args) {
1412
- const fetchOptions = _captures[0], headers = _captures[1], method = _captures[2], origin = _captures[3], qrl = _captures[4];
1449
+ let fetchOptions = _capturesObj._[0], headers = _capturesObj._[1], method = _capturesObj._[2], origin = _capturesObj._[3], qrl = _capturesObj._[4];
1413
1450
  const abortSignal = args.length > 0 && args[0] instanceof AbortSignal ? args.shift() : void 0;
1414
1451
  if (isServer) return qrl.apply(getRequestEvent(this), args);
1415
1452
  else {
@@ -1442,13 +1479,13 @@ var deserializeStream = async function* (stream, abortSignal) {
1442
1479
  else config.body = body;
1443
1480
  const res = await fetch(`${origin}?${QFN_KEY}=${qrlHash}${query}`, config);
1444
1481
  const contentType = res.headers.get("Content-Type");
1445
- if (res.ok && contentType === "text/qwik-json-stream" && res.body) return async function* () {
1482
+ if (res.ok && contentType === "text/qwik-json-stream" && res.body) return (async function* () {
1446
1483
  try {
1447
1484
  for await (const result of deserializeStream(res.body, abortSignal)) yield result;
1448
1485
  } finally {
1449
1486
  if (!abortSignal?.aborted) await res.body.cancel();
1450
1487
  }
1451
- }();
1488
+ })();
1452
1489
  else if (contentType === "application/qwik-json") {
1453
1490
  const str = await res.text();
1454
1491
  const obj = await _deserialize(str);
@@ -1471,8 +1508,57 @@ var deserializeStream = async function* (stream, abortSignal) {
1471
1508
  origin,
1472
1509
  qrl
1473
1510
  ]);
1511
+ }
1512
+ /** @public */
1513
+ var server$ = /*#__PURE__*/ implicit$FirstArg(serverQrl);
1514
+ function getValidators(rest, qrl) {
1515
+ let id;
1516
+ let invalidate;
1517
+ const validators = [];
1518
+ if (rest.length === 1) {
1519
+ const options = rest[0];
1520
+ if (options && typeof options === "object") {
1521
+ if ("validate" in options) validators.push(options);
1522
+ else {
1523
+ id = options.id;
1524
+ if (options.validation) validators.push(...options.validation);
1525
+ if (options.invalidate) invalidate = options.invalidate.map((loader) => loader.__id);
1526
+ }
1527
+ }
1528
+ } else if (rest.length > 1) validators.push(...rest.filter((v) => !!v));
1529
+ if (typeof id === "string") {
1530
+ if (isDev) {
1531
+ if (!/^[\w/.-]+$/.test(id)) throw new Error(`Invalid id: ${id}, id can only contain [a-zA-Z0-9_.-]`);
1532
+ }
1533
+ id = `id_${id}`;
1534
+ } else id = qrl.getHash();
1535
+ return {
1536
+ validators: validators.reverse(),
1537
+ id,
1538
+ invalidate
1539
+ };
1540
+ }
1541
+ var deserializeStream = async function* (stream, abortSignal) {
1542
+ const reader = stream.getReader();
1543
+ try {
1544
+ let buffer = "";
1545
+ const decoder = new TextDecoder();
1546
+ while (!abortSignal?.aborted) {
1547
+ const result = await reader.read();
1548
+ if (result.done) break;
1549
+ buffer += decoder.decode(result.value, { stream: true });
1550
+ const lines = buffer.split(/\n/);
1551
+ buffer = lines.pop();
1552
+ for (const line of lines) yield await _deserialize(line);
1553
+ }
1554
+ } finally {
1555
+ reader.releaseLock();
1556
+ }
1474
1557
  };
1475
- /** @public */ var server$ = /*#__PURE__*/ implicit$FirstArg(serverQrl);
1558
+ var SW_REGISTER = `(()=>{if("serviceWorker"in navigator){navigator.serviceWorker.register("__url").catch(e=>console.error(e));"caches"in window&&caches.keys().then(r=>{const e=r.find(c=>c.startsWith("QwikBuild"));e&&caches.delete(e).catch(console.error)}).catch(console.error)}else console.log("Service worker not supported in this browser.")})()`;
1559
+ var SW_UNREGISTER = `"serviceWorker"in navigator&&navigator.serviceWorker.getRegistrations().then(r=>{for(const e of r){const c="__url".split("/").pop();e.active?.scriptURL.endsWith(c||"service-worker.js")&&e.unregister().catch(console.error)}}),"caches"in window&&caches.keys().then(r=>{const e=r.find(c=>c.startsWith("QwikBuild"));e&&caches.delete(e).catch(console.error)}).catch(console.error)`;
1560
+ /** @internal */
1561
+ var _getServiceWorkerScript = (serviceWorkerUrl) => (serviceWorkerUrl ? SW_REGISTER : SW_UNREGISTER).replace("__url", serviceWorkerUrl ?? "/service-worker.js");
1476
1562
  /**
1477
1563
  * Loads the service workers that are defined in the routes. Any file named `service-worker.*` (all
1478
1564
  * JS extensions are allowed) will be picked up, bundled into a separate file, and registered as a
@@ -1485,14 +1571,43 @@ var deserializeStream = async function* (stream, abortSignal) {
1485
1571
  * service-worker.ts file) as long as you want to unregister the service-worker.js for your users.
1486
1572
  *
1487
1573
  * @public
1488
- */ var ServiceWorkerRegister = (props) => /*#__PURE__*/ _jsxSorted("script", { nonce: _wrapProp(props, "nonce") }, {
1489
- type: "module",
1490
- dangerouslySetInnerHTML: swRegister
1491
- }, null, 3, "1x_0");
1492
- var _hf0 = (p0) => !p0.reloadDocument;
1493
- var _hf0_str = "!p0.reloadDocument";
1494
- var _hf1 = (p0) => p0.spaReset ? "true" : void 0;
1495
- var _hf1_str = "p0.spaReset?\"true\":undefined";
1574
+ */
1575
+ var ServiceWorkerRegister = (props) => /*#__PURE__*/ _jsxSorted("script", {
1576
+ dangerouslySetInnerHTML: _getServiceWorkerScript(_getServiceWorkerUrl()),
1577
+ nonce: _wrapProp(props, "nonce")
1578
+ }, { type: "module" }, null, 3, "UM_0");
1579
+ var _hf0 = (p0) => p0.spaReset ? "true" : void 0;
1580
+ var _hf0_str = "p0.spaReset?\"true\":undefined";
1581
+ /** @public */
1582
+ var Form = ({ action, spaReset, reloadDocument, onSubmit$, ...rest }, key) => {
1583
+ if (action) {
1584
+ if (Array.isArray(onSubmit$)) return /*#__PURE__*/ _jsxSplit("form", {
1585
+ ..._getVarProps(rest),
1586
+ ..._getConstProps(rest),
1587
+ action: _wrapProp(action, "actionPath"),
1588
+ "preventdefault:submit": !reloadDocument,
1589
+ "q-e:submit": [...onSubmit$, !reloadDocument ? /*#__PURE__*/ inlinedQrl((evt) => {
1590
+ let action = _capturesObj._[0];
1591
+ if (!action.submitted) return action.submit(evt);
1592
+ }, "Form_form_q_e_submit_6i0Jq5q8JFg", [action]) : void 0],
1593
+ ["data-spa-reset"]: spaReset ? "true" : void 0
1594
+ }, { method: "post" }, null, 0, key);
1595
+ return /*#__PURE__*/ _jsxSplit("form", {
1596
+ ..._getVarProps(rest),
1597
+ ..._getConstProps(rest),
1598
+ action: _wrapProp(action, "actionPath"),
1599
+ "preventdefault:submit": !reloadDocument,
1600
+ "q-e:submit": [onSubmit$, !reloadDocument ? action.submit : void 0],
1601
+ ["data-spa-reset"]: spaReset ? "true" : void 0
1602
+ }, { method: "post" }, null, 0, key);
1603
+ } else return /*#__PURE__*/ createElement(GetForm, {
1604
+ ...rest,
1605
+ spaReset,
1606
+ reloadDocument,
1607
+ onSubmit$,
1608
+ key
1609
+ });
1610
+ };
1496
1611
  var GetForm = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawProps) => {
1497
1612
  const rest = _restProps(_rawProps, [
1498
1613
  "action",
@@ -1503,14 +1618,12 @@ var GetForm = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawProps) =>
1503
1618
  const nav = useNavigate();
1504
1619
  return /*#__PURE__*/ _jsxSplit("form", {
1505
1620
  action: "get",
1506
- "preventdefault:submit": _fnSignal(_hf0, [_rawProps], _hf0_str),
1507
- "data-spa-reset": _fnSignal(_hf1, [_rawProps], _hf1_str),
1621
+ "data-spa-reset": _fnSignal(_hf0, [_rawProps], _hf0_str),
1508
1622
  ..._getVarProps(rest),
1509
- ..._getConstProps(rest),
1510
1623
  "q-e:submit": [
1511
1624
  ...Array.isArray(_rawProps.onSubmit$) ? _rawProps.onSubmit$ : [_rawProps.onSubmit$],
1512
1625
  /*#__PURE__*/ inlinedQrl(async (_evt, form) => {
1513
- const nav = _captures[0];
1626
+ let nav = _capturesObj._[0];
1514
1627
  const formData = new FormData(form);
1515
1628
  const params = new URLSearchParams();
1516
1629
  formData.forEach((value, key) => {
@@ -1531,40 +1644,16 @@ var GetForm = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawProps) =>
1531
1644
  }));
1532
1645
  }, "GetForm_component_form_q_e_submit_1_cuYklZAOHrA")
1533
1646
  ]
1534
- }, null, /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "Q4_0"), 0, "Q4_1");
1647
+ }, {
1648
+ ..._getConstProps(rest),
1649
+ "preventdefault:submit": true
1650
+ }, /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "TF_0"), 0, "TF_1");
1535
1651
  }, "GetForm_component_2U5Z2Z8ryc0"));
1536
- /** @public */ var Form = ({ action, spaReset, reloadDocument, onSubmit$, ...rest }, key) => {
1537
- if (action) {
1538
- if (Array.isArray(onSubmit$)) return _jsxSplit("form", {
1539
- ..._getVarProps(rest),
1540
- ..._getConstProps(rest),
1541
- action: _wrapProp(action, "actionPath"),
1542
- "preventdefault:submit": !reloadDocument,
1543
- "q-e:submit": [...onSubmit$, !reloadDocument ? /*#__PURE__*/ inlinedQrl((evt) => {
1544
- const action = _captures[0];
1545
- if (!action.submitted) return action.submit(evt);
1546
- }, "Form_form_q_e_submit_6i0Jq5q8JFg", [action]) : void 0],
1547
- ["data-spa-reset"]: spaReset ? "true" : void 0
1548
- }, { method: "post" }, null, 0, key);
1549
- return _jsxSplit("form", {
1550
- ..._getVarProps(rest),
1551
- ..._getConstProps(rest),
1552
- action: _wrapProp(action, "actionPath"),
1553
- "preventdefault:submit": !reloadDocument,
1554
- "q-e:submit": [onSubmit$, !reloadDocument ? action.submit : void 0],
1555
- ["data-spa-reset"]: spaReset ? "true" : void 0
1556
- }, { method: "post" }, null, 0, key);
1557
- } else return /*#__PURE__*/ _jsxSplit(GetForm, {
1558
- spaReset,
1559
- reloadDocument,
1560
- onSubmit$,
1561
- ...rest
1562
- }, null, null, 0, key);
1563
- };
1564
1652
  /**
1565
1653
  * @beta
1566
1654
  * @experimental
1567
- */ var untypedAppUrl = function appUrl(route, params, paramsPrefix = "") {
1655
+ */
1656
+ var untypedAppUrl = function appUrl(route, params, paramsPrefix = "") {
1568
1657
  const path = route.split("/");
1569
1658
  for (let i = 0; i < path.length; i++) {
1570
1659
  const segment = path[i];
@@ -1590,7 +1679,8 @@ var GetForm = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawProps) =>
1590
1679
  *
1591
1680
  * @beta
1592
1681
  * @experimental
1593
- */ function omitProps(obj, keys) {
1682
+ */
1683
+ function omitProps(obj, keys) {
1594
1684
  const omittedObj = {};
1595
1685
  for (const key in obj) if (!key.startsWith("param:") && !keys.includes(key)) omittedObj[key] = obj[key];
1596
1686
  return omittedObj;
@@ -1621,8 +1711,9 @@ var GetForm = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawProps) =>
1621
1711
  * ```
1622
1712
  *
1623
1713
  * @public
1624
- */ var createRenderer = (getOptions) => {
1625
- return (opts) => {
1714
+ */
1715
+ var createRenderer = (getOptions) => {
1716
+ return ((opts) => {
1626
1717
  const { jsx, options } = getOptions(opts);
1627
1718
  const renderOptions = opts.serverData.renderMode === "static" ? {
1628
1719
  ...options,
@@ -1632,7 +1723,7 @@ var GetForm = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawProps) =>
1632
1723
  }
1633
1724
  } : options;
1634
1725
  return renderToStream(jsx, renderOptions);
1635
- };
1726
+ });
1636
1727
  };
1637
1728
  /**
1638
1729
  * This renders all the tags collected from `head`.
@@ -1655,16 +1746,17 @@ var GetForm = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawProps) =>
1655
1746
  * `src/root.tsx` to make runtime changes to `<head>` if needed.
1656
1747
  *
1657
1748
  * @public
1658
- */ var DocumentHeadTags = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
1749
+ */
1750
+ var DocumentHeadTags = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
1659
1751
  let head = useDocumentHead();
1660
1752
  if (props) head = {
1661
1753
  ...head,
1662
1754
  ...props
1663
1755
  };
1664
1756
  return /*#__PURE__*/ _jsxSorted(Fragment, null, null, [
1665
- head.title && /*#__PURE__*/ _jsxSorted("title", null, null, head.title, 1, "r5_0"),
1666
- head.meta.map((m) => /*#__PURE__*/ _jsxSplit("meta", { ..._getVarProps(m) }, _getConstProps(m), null, 0, "r5_1")),
1667
- head.links.map((l) => /*#__PURE__*/ _jsxSplit("link", { ..._getVarProps(l) }, _getConstProps(l), null, 0, "r5_2")),
1757
+ head.title && /*#__PURE__*/ _jsxSorted("title", null, null, head.title, 1, "eL_0"),
1758
+ head.meta.map((m) => /*#__PURE__*/ _jsxSplit("meta", { ..._getVarProps(m) }, _getConstProps(m), null, 0, "eL_1")),
1759
+ head.links.map((l) => /*#__PURE__*/ _jsxSplit("link", { ..._getVarProps(l) }, _getConstProps(l), null, 0, "eL_2")),
1668
1760
  head.styles.map((s) => {
1669
1761
  const props = s.props || s;
1670
1762
  return /*#__PURE__*/ createElement("style", {
@@ -1681,6 +1773,6 @@ var GetForm = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawProps) =>
1681
1773
  key: s.key
1682
1774
  });
1683
1775
  })
1684
- ], 1, "r5_3");
1776
+ ], 1, "eL_3");
1685
1777
  }, "DocumentHeadTags_component_9CrWYOoCpgY"));
1686
- export { DocumentHeadTags, Form, Link, QWIK_CITY_SCROLLER, QWIK_ROUTER_SCROLLER, QwikCityMockProvider, QwikCityProvider, QwikRouterMockProvider, QwikRouterProvider, RouterOutlet, ServiceWorkerRegister, createRenderer, getRequestEvent, globalAction$, globalActionQrl, omitProps, routeAction$, routeActionQrl, routeLoader$, routeLoaderQrl, server$, serverQrl, untypedAppUrl, useContent, useDocumentHead, useHttpStatus, useLocation, useNavigate, usePreventNavigate$, usePreventNavigateQrl, useQwikRouter, valibot$, valibotQrl, validator$, validatorQrl, z, zod$, zodQrl };
1778
+ export { DocumentHeadTags, Form, Link, QWIK_CITY_SCROLLER, QWIK_ROUTER_SCROLLER, QwikCityMockProvider, QwikCityProvider, QwikRouterMockProvider, QwikRouterProvider, RouterOutlet, ServiceWorkerRegister, _getServiceWorkerScript, _setRouterConfig, createRenderer, getBasePathname, getRequestEvent, getRouterConfig, getRoutes, getTrailingSlash, globalAction$, globalActionQrl, omitProps, routeAction$, routeActionQrl, routeLoader$, routeLoaderQrl, server$, serverQrl, untypedAppUrl, useContent, useDocumentHead, useHttpStatus, useLocation, useNavigate, usePreventNavigate$, usePreventNavigateQrl, useQwikRouter, valibot$, valibotQrl, validator$, validatorQrl, z, zod$, zodQrl };