@qwik.dev/router 2.0.0-beta.39 → 2.0.0-beta.40

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 (40) hide show
  1. package/lib/adapters/azure-swa/vite/index.mjs +45 -54
  2. package/lib/adapters/bun-server/vite/index.mjs +16 -22
  3. package/lib/adapters/cloud-run/vite/index.mjs +15 -19
  4. package/lib/adapters/cloudflare-pages/vite/index.mjs +46 -67
  5. package/lib/adapters/deno-server/vite/index.mjs +25 -39
  6. package/lib/adapters/netlify-edge/vite/index.mjs +50 -76
  7. package/lib/adapters/node-server/vite/index.mjs +16 -22
  8. package/lib/adapters/shared/vite/index.mjs +271 -360
  9. package/lib/adapters/ssg/vite/index.mjs +11 -15
  10. package/lib/adapters/vercel-edge/vite/index.mjs +74 -95
  11. package/lib/chunks/dev-preloaded-route-loader.mjs +2 -3
  12. package/lib/chunks/format.mjs +16 -23
  13. package/lib/chunks/fs.mjs +93 -106
  14. package/lib/chunks/head.qwik.mjs +1174 -1382
  15. package/lib/chunks/http-error.qwik.mjs +20 -28
  16. package/lib/chunks/pathname.mjs +50 -69
  17. package/lib/chunks/request-body-limit.mjs +25 -35
  18. package/lib/chunks/request-path.mjs +44 -55
  19. package/lib/chunks/routes.mjs +20 -41
  20. package/lib/chunks/server-error.mjs +15 -18
  21. package/lib/chunks/system.mjs +258 -326
  22. package/lib/chunks/url.mjs +56 -58
  23. package/lib/chunks/user-response.mjs +1616 -1804
  24. package/lib/chunks/worker-thread.mjs +254 -307
  25. package/lib/index.qwik.mjs +1637 -1918
  26. package/lib/middleware/aws-lambda/index.mjs +44 -52
  27. package/lib/middleware/azure-swa/index.mjs +85 -94
  28. package/lib/middleware/bun/index.mjs +118 -138
  29. package/lib/middleware/cloudflare-pages/index.mjs +83 -96
  30. package/lib/middleware/deno/index.mjs +104 -125
  31. package/lib/middleware/firebase/index.mjs +21 -25
  32. package/lib/middleware/netlify-edge/index.mjs +63 -71
  33. package/lib/middleware/node/index.mjs +297 -357
  34. package/lib/middleware/request-handler/index.mjs +110 -133
  35. package/lib/middleware/vercel-edge/index.mjs +82 -98
  36. package/lib/service-worker/index.mjs +12 -3
  37. package/lib/ssg/index.mjs +249 -289
  38. package/lib/vite/index.mjs +2344 -3030
  39. package/package.json +5 -5
  40. package/lib/chunks/use-functions.qwik.mjs +0 -23
@@ -1,1969 +1,1688 @@
1
- import { componentQrl, inlinedQrl, useErrorBoundary, useOnWindow, _captures, _jsxSorted, Slot, isBrowser, isDev, untrack, _qrlSync, _jsxSplit, _getConstProps, _getVarProps, eventQrl, isServer, useServerData, useStore, useSignal, useContextProvider, useTaskQrl, noSerialize, getLocale, createComputedQrl, useContext, SkipRender, implicit$FirstArg, withLocale, _wrapProp, _restProps, _fnSignal, createElement } from '@qwik.dev/core';
2
- import { Fragment } from '@qwik.dev/core/jsx-runtime';
3
- import * as qwikRouterConfig from '@qwik-router-config';
4
- import { p } from '@qwik.dev/core/preloader';
5
- import { e as ensureSlash } from './chunks/pathname.mjs';
6
- import { l as loadRoute, g as getModuleRouteLoaders, f as fetchRouteLoaderData, a as getClientNavPath, s as shouldPreload, i as isSamePath, t as toPath, b as isSameOrigin, Q as QACTION_KEY, e as ensureRouteLoaderSignals, c as setLoaderSignalValue, d as createDocumentHead, C as ContentContext, h as ContentInternalContext, D as DocumentHeadContext, H as HttpStatusContext, j as RouteLocationContext, k as RouteNavigateContext, m as RouteStateContext, n as RouteLoaderCtxContext, o as RouteActionContext, p as RoutePreventNavigateContext, u as updateRouteLoaderPaths, q as invalidateNavRouteLoaders, r as isImmutableLoader, v as clearNavFetchCache, w as resolveHead, x as Q_ROUTE, y as toUrl, z as getRequestEvent, A as QFN_KEY, B as QDATA_KEY } from './chunks/head.qwik.mjs';
7
- export { E as routeLoader$, G as routeLoaderQrl } from './chunks/head.qwik.mjs';
8
- import { u as useNavigate, a as useLocation, b as useDocumentHead, c as useQwikRouterEnv, d as useAction } from './chunks/use-functions.qwik.mjs';
9
- export { e as useContent, f as useHttpStatus, g as usePreventNavigate$, h as usePreventNavigateQrl } from './chunks/use-functions.qwik.mjs';
10
- import { _deserialize, _hasStoreEffects, _getContextContainer, forceStoreEffects, _waitUntilRendered, _getContextHostElement, _serialize } from '@qwik.dev/core/internal';
11
- import * as v from 'valibot';
12
- import * as z from 'zod';
13
- export { z } from 'zod';
14
- import swRegister from '@qwik-router-sw-register';
15
- import { renderToStream } from '@qwik.dev/core/server';
16
-
17
- const ErrorBoundary = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
18
- const store = useErrorBoundary();
19
- useOnWindow("qerror", /* @__PURE__ */ inlinedQrl((e) => {
20
- const store2 = _captures[0];
21
- store2.error = e.detail.error;
22
- }, "ErrorBoundary_component_useOnWindow_G0jFRpoNY0M", [
23
- store
24
- ]));
25
- if (store.error && props.fallback$) {
26
- return /* @__PURE__ */ _jsxSorted(Fragment, null, null, props.fallback$(store.error), 1, "bA_0");
27
- }
28
- return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "bA_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, 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, useErrorBoundary, useOnWindow, useServerData, useSignal, useStore, useTaskQrl, useVisibleTaskQrl, withLocale } from "@qwik.dev/core";
4
+ import { Fragment } from "@qwik.dev/core/jsx-runtime";
5
+ import * as qwikRouterConfig from "@qwik-router-config";
6
+ import { p } from "@qwik.dev/core/preloader";
7
+ import { _deserialize, _getContextContainer, _getContextHostElement, _hasStoreEffects, _serialize, _waitUntilRendered, forceStoreEffects } from "@qwik.dev/core/internal";
8
+ import * as v from "valibot";
9
+ import * as z$1 from "zod";
10
+ import { z } from "zod";
11
+ import swRegister from "@qwik-router-sw-register";
12
+ import { renderToStream } from "@qwik.dev/core/server";
13
+ /** @public */ var ErrorBoundary = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
14
+ const store = useErrorBoundary();
15
+ useOnWindow("qerror", /*#__PURE__*/ inlinedQrl((e) => {
16
+ const store = _captures[0];
17
+ store.error = e.detail.error;
18
+ }, "ErrorBoundary_component_useOnWindow_G0jFRpoNY0M", [store]));
19
+ if (store.error && props.fallback$) return /*#__PURE__*/ _jsxSorted(Fragment, null, null, props.fallback$(store.error), 1, "bA_0");
20
+ return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "bA_1");
29
21
  }, "ErrorBoundary_component_pOa6vjtC7ik"));
30
-
31
- const prefetchLoaderData = (loadedRoute, url, manifestHash) => {
32
- if (!loadedRoute.$loaders$?.length || !loadedRoute.$loaderPaths$) {
33
- return;
34
- }
35
- const immutableIds = new Set(getModuleRouteLoaders(loadedRoute.$mods$).filter((loader) => loader.__cacheControl === "immutable").map((loader) => loader.__id));
36
- const basePath = qwikRouterConfig.basePathname ?? "/";
37
- for (const hash of loadedRoute.$loaders$) {
38
- if (immutableIds.has(hash)) {
39
- continue;
40
- }
41
- let loaderPath = loadedRoute.$loaderPaths$[hash];
42
- if (!loaderPath) {
43
- continue;
44
- }
45
- if (basePath !== "/" && !loaderPath.startsWith(basePath)) {
46
- loaderPath = basePath + loaderPath.slice(1);
47
- }
48
- fetchRouteLoaderData(hash, loaderPath, manifestHash, {
49
- pageUrl: url,
50
- basePath
51
- }).catch(() => {
52
- });
53
- }
22
+ /**
23
+ * Prefetch a route's loader data in parallel (fire-and-forget). The per-nav fetch map dedupes
24
+ * repeat hovers and shares the promise with the navigation's own fetch; the browser HTTP cache
25
+ * handles freshness. Immutable loaders are skipped: they download lazily on first actual read and
26
+ * are then browser-cached for the life of the deploy.
27
+ */ var prefetchLoaderData = (loadedRoute, url, manifestHash) => {
28
+ if (!loadedRoute.$loaders$?.length || !loadedRoute.$loaderPaths$) return;
29
+ const immutableIds = new Set(getModuleRouteLoaders(loadedRoute.$mods$).filter((loader) => loader.__cacheControl === "immutable").map((loader) => loader.__id));
30
+ const basePath = qwikRouterConfig.basePathname ?? "/";
31
+ for (const hash of loadedRoute.$loaders$) {
32
+ if (immutableIds.has(hash)) continue;
33
+ let loaderPath = loadedRoute.$loaderPaths$[hash];
34
+ if (!loaderPath) continue;
35
+ if (basePath !== "/" && !loaderPath.startsWith(basePath)) loaderPath = basePath + loaderPath.slice(1);
36
+ fetchRouteLoaderData(hash, loaderPath, manifestHash, {
37
+ pageUrl: url,
38
+ basePath
39
+ }).catch(() => {});
40
+ }
54
41
  };
55
- async function prefetchRoute(url, prefetchData, probability = 0.8, manifestHash, prefetchBundle = true) {
56
- if (!isBrowser || isDev) {
57
- return;
58
- }
59
- try {
60
- const loadedRoute = await loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, url.pathname);
61
- if (!loadedRoute) {
62
- return;
63
- }
64
- if (prefetchBundle) {
65
- let routeName = loadedRoute.$routeName$;
66
- routeName = ensureSlash(routeName);
67
- if (routeName.length > 1 && routeName.startsWith("/")) {
68
- routeName = routeName.slice(1);
69
- }
70
- p(routeName, probability);
71
- }
72
- if (!prefetchData || !manifestHash) {
73
- return;
74
- }
75
- prefetchLoaderData(loadedRoute, url, manifestHash);
76
- } catch {
77
- }
42
+ /**
43
+ * Prefetch a route's JS bundles and optionally its loader data.
44
+ *
45
+ * Resolves the route from the trie to get the routeName (for the bundle graph preloader) and
46
+ * `$loaders$` (for data prefetching). The bundle graph is keyed by route name (e.g.
47
+ * `products/[id]/`), not by actual pathname (e.g. `products/123/`).
48
+ *
49
+ * @param url - The URL pathname to prefetch
50
+ * @param prefetchData - Whether to prefetch loader data
51
+ * @param probability - Bundle preload probability (0-1, default 0.8)
52
+ * @param manifestHash - Build manifest hash for loader URLs (from `useDocumentHead().manifestHash`)
53
+ * @param prefetchBundle - Whether to prefetch route JS bundles
54
+ */ async function prefetchRoute(url, prefetchData, probability = .8, manifestHash, prefetchBundle = true) {
55
+ if (!isBrowser || isDev) return;
56
+ try {
57
+ const loadedRoute = await loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, url.pathname);
58
+ if (!loadedRoute) return;
59
+ if (prefetchBundle) {
60
+ let routeName = loadedRoute.$routeName$;
61
+ routeName = ensureSlash(routeName);
62
+ if (routeName.length > 1 && routeName.startsWith("/")) routeName = routeName.slice(1);
63
+ p(routeName, probability);
64
+ }
65
+ if (!prefetchData || !manifestHash) return;
66
+ prefetchLoaderData(loadedRoute, url, manifestHash);
67
+ } catch {}
78
68
  }
79
-
80
- const Link = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
81
- const nav = useNavigate();
82
- const loc = useLocation();
83
- const head = useDocumentHead();
84
- const originalHref = props.href;
85
- const { onClick$, prefetch: prefetchProp, reload, replaceState, scroll, prefetchBundles: prefetchBundlesProp = "visible", prefetchData: prefetchDataProp = prefetchProp === "js" ? "off" : "intent", ...linkProps } = props;
86
- const clientNavPath = untrack(getClientNavPath, {
87
- ...linkProps,
88
- reload
89
- }, loc);
90
- linkProps.href = clientNavPath || originalHref;
91
- const isDepratedPrefetchDisabled = prefetchProp === false;
92
- const shouldPrefetch = untrack(shouldPreload, clientNavPath, loc);
93
- const shouldVisiblePrefetchBundles = !!clientNavPath && shouldPrefetch && !isDepratedPrefetchDisabled && (prefetchBundlesProp === "visible" || // deprecated prop below, remove in favor of prefetchBundles
94
- prefetchProp === "js" || prefetchProp === true);
95
- const shouldVisiblePrefetchData = !!clientNavPath && shouldPrefetch && !isDepratedPrefetchDisabled && (prefetchDataProp === "visible" || // deprecated prop below, remove in favor of prefetchData
96
- prefetchProp === true);
97
- const shouldPrefetchData = !!clientNavPath && prefetchDataProp !== "off" && shouldPrefetch && !isDepratedPrefetchDisabled;
98
- const handleDataPrefetch = shouldPrefetchData ? /* @__PURE__ */ inlinedQrl((_, elm) => {
99
- const head2 = _captures[0];
100
- if (navigator.connection?.saveData) {
101
- return;
102
- }
103
- if (elm && elm.href) {
104
- const url = new URL(elm.href);
105
- prefetchRoute(url, true, 0.8, head2.manifestHash, false);
106
- }
107
- }, "Link_component_handleDataPrefetch_lcd4O9LHbbA", [
108
- head
109
- ]) : null;
110
- const preventDefault = clientNavPath ? _qrlSync((event) => {
111
- if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) {
112
- event.preventDefault();
113
- }
114
- }, "event=>{if(!(event.metaKey||event.ctrlKey||event.shiftKey||event.altKey)){event.preventDefault();}}") : null;
115
- const prefetchData = /* @__PURE__ */ inlinedQrl(async (_, elm) => {
116
- const handleDataPrefetch2 = _captures[0];
117
- handleDataPrefetch2?.(null, elm);
118
- }, "Link_component_prefetchData_UwVx4NhHkSo", [
119
- handleDataPrefetch
120
- ]);
121
- const onEnterKeyDown = /* @__PURE__ */ inlinedQrl((event, element) => {
122
- const prefetchData2 = _captures[0];
123
- if (event.key === "Enter") {
124
- prefetchData2(null, element);
125
- }
126
- }, "Link_component_onEnterKeyDown_z274ws00irY", [
127
- prefetchData
128
- ]);
129
- const handleClientSideNavigation = clientNavPath ? /* @__PURE__ */ inlinedQrl((event, elm) => {
130
- const nav2 = _captures[0], reload2 = _captures[1], replaceState2 = _captures[2], scroll2 = _captures[3];
131
- if (event.defaultPrevented) {
132
- if (elm.href) {
133
- elm.setAttribute("aria-pressed", "true");
134
- nav2(elm.href, {
135
- forceReload: reload2,
136
- replaceState: replaceState2,
137
- scroll: scroll2
138
- }).then(() => {
139
- elm.removeAttribute("aria-pressed");
140
- });
141
- }
142
- }
143
- }, "Link_component_handleClientSideNavigation_h3qenoGeI6M", [
144
- nav,
145
- reload,
146
- replaceState,
147
- scroll
148
- ]) : null;
149
- const handlePreload = /* @__PURE__ */ inlinedQrl((_, elm) => {
150
- const url = new URL(elm.href);
151
- prefetchRoute(url, false, 1);
152
- }, "Link_component_handlePreload_AAemwtuBjsE");
153
- return /* @__PURE__ */ _jsxSplit("a", {
154
- "q:link": !!clientNavPath,
155
- ..._getVarProps(linkProps),
156
- ..._getConstProps(linkProps),
157
- "data-q-prefetch": shouldVisiblePrefetchBundles && shouldVisiblePrefetchData ? "bd" : shouldVisiblePrefetchBundles ? "b" : shouldVisiblePrefetchData ? "d" : null,
158
- "q-e:click": [
159
- preventDefault,
160
- handlePreload,
161
- onClick$,
162
- handleClientSideNavigation
163
- ],
164
- "q-e:pointerenter": [
165
- linkProps.onMouseOver$,
166
- prefetchDataProp === "intent" ? prefetchData : null
167
- ],
168
- "q-e:focus": [
169
- linkProps.onFocus$,
170
- prefetchDataProp === "intent" ? prefetchData : null
171
- ],
172
- "q-e:pointerdown": [
173
- linkProps.onPointerDown$,
174
- prefetchDataProp === "commit" ? prefetchData : null
175
- ],
176
- "q-e:keydown": [
177
- linkProps.onKeyDown$,
178
- prefetchDataProp === "commit" ? onEnterKeyDown : null
179
- ]
180
- }, null, /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "jO_0"), 0, "jO_1");
69
+ /** @public */ var useHttpStatus = () => useContext(HttpStatusContext).value;
70
+ /** @public */ var useContent = () => useContext(ContentContext);
71
+ /**
72
+ * Returns the document head for the current page. The generic type describes the front matter.
73
+ *
74
+ * @public
75
+ */ var useDocumentHead = () => useContext(DocumentHeadContext);
76
+ /** @public */ var useLocation = () => useContext(RouteLocationContext);
77
+ /** @public */ var useNavigate = () => useContext(RouteNavigateContext);
78
+ /** @internal Implementation of usePreventNavigate$ */ var usePreventNavigateQrl = (fn) => {
79
+ const registerPreventNav = useContext(RoutePreventNavigateContext);
80
+ useVisibleTaskQrl(/*#__PURE__*/ inlinedQrl(() => {
81
+ const fn = _captures[0], registerPreventNav = _captures[1];
82
+ return registerPreventNav(fn);
83
+ }, "usePreventNavigateQrl_useVisibleTask_BsYUaz9XhUs", [fn, registerPreventNav]));
84
+ };
85
+ /**
86
+ * Prevent navigation attempts. This hook registers a callback that will be called before SPA or
87
+ * browser navigation.
88
+ *
89
+ * Return `true` to prevent navigation.
90
+ *
91
+ * #### SPA Navigation
92
+ *
93
+ * For Single-Page-App (SPA) navigation (via `<Link />`, `const nav = useNavigate()`, and browser
94
+ * backwards/forwards inside SPA history), the callback will be provided with the target, either a
95
+ * URL or a number. It will only be a number if `nav(number)` was called to navigate forwards or
96
+ * backwards in SPA history.
97
+ *
98
+ * If you return a Promise, the navigation will be blocked until the promise resolves.
99
+ *
100
+ * This can be used to show a nice dialog to the user, and wait for the user to confirm, or to
101
+ * record the url, prevent the navigation, and navigate there later via `nav(url)`.
102
+ *
103
+ * #### Browser Navigation
104
+ *
105
+ * However, when the user navigates away by clicking on a regular `<a />`, reloading, or moving
106
+ * backwards/forwards outside SPA history, this callback will not be awaited. This is because the
107
+ * browser does not provide a way to asynchronously prevent these navigations.
108
+ *
109
+ * In this case, returning returning `true` will tell the browser to show a confirmation dialog,
110
+ * which cannot be customized. You are also not able to show your own `window.confirm()` dialog
111
+ * during the callback, the browser won't allow it. If you return a Promise, it will be considered
112
+ * as `true`.
113
+ *
114
+ * When the callback is called from the browser, no url will be provided. Use this to know whether
115
+ * you can show a dialog or just return `true` to prevent the navigation.
116
+ *
117
+ * @public
118
+ */ var usePreventNavigate$ = implicit$FirstArg(usePreventNavigateQrl);
119
+ var useAction = () => useContext(RouteActionContext);
120
+ var useQwikRouterEnv = () => noSerialize(useServerData("qwikrouter"));
121
+ /** @public */ var Link = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
122
+ const nav = useNavigate();
123
+ const loc = useLocation();
124
+ const head = useDocumentHead();
125
+ const originalHref = props.href;
126
+ const { onClick$, prefetch: prefetchProp, reload, replaceState, scroll, prefetchBundles: prefetchBundlesProp = "visible", prefetchData: prefetchDataProp = prefetchProp === "js" ? "off" : "intent", ...linkProps } = props;
127
+ const clientNavPath = untrack(getClientNavPath, {
128
+ ...linkProps,
129
+ reload
130
+ }, loc);
131
+ linkProps.href = clientNavPath || originalHref;
132
+ const isDepratedPrefetchDisabled = prefetchProp === false;
133
+ const shouldPrefetch = untrack(shouldPreload, clientNavPath, loc);
134
+ const shouldVisiblePrefetchBundles = !!clientNavPath && shouldPrefetch && !isDepratedPrefetchDisabled && (prefetchBundlesProp === "visible" || prefetchProp === "js" || prefetchProp === true);
135
+ const shouldVisiblePrefetchData = !!clientNavPath && shouldPrefetch && !isDepratedPrefetchDisabled && (prefetchDataProp === "visible" || prefetchProp === true);
136
+ const handleDataPrefetch = !!clientNavPath && prefetchDataProp !== "off" && shouldPrefetch && !isDepratedPrefetchDisabled ? /*#__PURE__*/ inlinedQrl((_, elm) => {
137
+ const head = _captures[0];
138
+ if (navigator.connection?.saveData) return;
139
+ if (elm && elm.href) prefetchRoute(new URL(elm.href), true, .8, head.manifestHash, false);
140
+ }, "Link_component_handleDataPrefetch_lcd4O9LHbbA", [head]) : null;
141
+ const preventDefault = clientNavPath ? _qrlSync((event) => {
142
+ if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) event.preventDefault();
143
+ }, "event=>{if(!(event.metaKey||event.ctrlKey||event.shiftKey||event.altKey)){event.preventDefault();}}") : null;
144
+ const prefetchData = /*#__PURE__*/ inlinedQrl(async (_, elm) => {
145
+ const handleDataPrefetch = _captures[0];
146
+ handleDataPrefetch?.(null, elm);
147
+ }, "Link_component_prefetchData_UwVx4NhHkSo", [handleDataPrefetch]);
148
+ const onEnterKeyDown = /*#__PURE__*/ inlinedQrl((event, element) => {
149
+ const prefetchData = _captures[0];
150
+ if (event.key === "Enter") prefetchData(null, element);
151
+ }, "Link_component_onEnterKeyDown_z274ws00irY", [prefetchData]);
152
+ const handleClientSideNavigation = clientNavPath ? /*#__PURE__*/ inlinedQrl((event, elm) => {
153
+ const nav = _captures[0], reload = _captures[1], replaceState = _captures[2], scroll = _captures[3];
154
+ if (event.defaultPrevented) {
155
+ if (elm.href) {
156
+ elm.setAttribute("aria-pressed", "true");
157
+ nav(elm.href, {
158
+ forceReload: reload,
159
+ replaceState,
160
+ scroll
161
+ }).then(() => {
162
+ elm.removeAttribute("aria-pressed");
163
+ });
164
+ }
165
+ }
166
+ }, "Link_component_handleClientSideNavigation_h3qenoGeI6M", [
167
+ nav,
168
+ reload,
169
+ replaceState,
170
+ scroll
171
+ ]) : null;
172
+ const handlePreload = /*#__PURE__*/ inlinedQrl((_, elm) => {
173
+ prefetchRoute(new URL(elm.href), false, 1);
174
+ }, "Link_component_handlePreload_AAemwtuBjsE");
175
+ return /*#__PURE__*/ _jsxSplit("a", {
176
+ "q:link": !!clientNavPath,
177
+ ..._getVarProps(linkProps),
178
+ ..._getConstProps(linkProps),
179
+ "data-q-prefetch": shouldVisiblePrefetchBundles && shouldVisiblePrefetchData ? "bd" : shouldVisiblePrefetchBundles ? "b" : shouldVisiblePrefetchData ? "d" : null,
180
+ "q-e:click": [
181
+ preventDefault,
182
+ handlePreload,
183
+ onClick$,
184
+ handleClientSideNavigation
185
+ ],
186
+ "q-e:pointerenter": [linkProps.onMouseOver$, prefetchDataProp === "intent" ? prefetchData : null],
187
+ "q-e:focus": [linkProps.onFocus$, prefetchDataProp === "intent" ? prefetchData : null],
188
+ "q-e:pointerdown": [linkProps.onPointerDown$, prefetchDataProp === "commit" ? prefetchData : null],
189
+ "q-e:keydown": [linkProps.onKeyDown$, prefetchDataProp === "commit" ? onEnterKeyDown : null]
190
+ }, null, /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "jO_0"), 0, "jO_1");
181
191
  }, "Link_component_VPmar9tb3t4"));
182
-
183
- const newScrollState = () => {
184
- return {
185
- x: 0,
186
- y: 0,
187
- w: 0,
188
- h: 0
189
- };
192
+ var newScrollState = () => {
193
+ return {
194
+ x: 0,
195
+ y: 0,
196
+ w: 0,
197
+ h: 0
198
+ };
190
199
  };
191
- const clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
192
- if (navType !== "popstate") {
193
- const samePath = isSamePath(fromURL, toURL);
194
- const sameHash = fromURL.hash === toURL.hash;
195
- if (!samePath || !sameHash) {
196
- const newState = {
197
- _qRouterScroll: newScrollState()
198
- };
199
- if (replaceState) {
200
- win.history.replaceState(newState, "", toPath(toURL));
201
- } else {
202
- win.history.pushState(newState, "", toPath(toURL));
203
- }
204
- }
205
- }
200
+ var clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
201
+ if (navType !== "popstate") {
202
+ const samePath = isSamePath(fromURL, toURL);
203
+ const sameHash = fromURL.hash === toURL.hash;
204
+ if (!samePath || !sameHash) {
205
+ const newState = { _qRouterScroll: newScrollState() };
206
+ if (replaceState) win.history.replaceState(newState, "", toPath(toURL));
207
+ else win.history.pushState(newState, "", toPath(toURL));
208
+ }
209
+ }
206
210
  };
207
- const preloadRouteBundles = (path, probability = 0.8) => {
208
- if (isBrowser) {
209
- path = ensureSlash(path);
210
- path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
211
- p(path, probability);
212
- }
211
+ var preloadRouteBundles = (path, probability = .8) => {
212
+ if (isBrowser) {
213
+ path = ensureSlash(path);
214
+ path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
215
+ p(path, probability);
216
+ }
213
217
  };
214
-
215
- let prefetchedLinks = /* @__PURE__ */ new WeakSet();
216
- let cleanupPrefetchObserver;
217
- const resetLinkPrefetchState = () => {
218
- prefetchedLinks = /* @__PURE__ */ new WeakSet();
218
+ var prefetchedLinks = /* @__PURE__ */ new WeakSet();
219
+ var cleanupPrefetchObserver;
220
+ var resetLinkPrefetchState = () => {
221
+ prefetchedLinks = /* @__PURE__ */ new WeakSet();
219
222
  };
220
- const createLinkPrefetchObserver = (manifestHash) => {
221
- const anchors = document.querySelectorAll("a[q\\:link][data-q-prefetch]");
222
- const prefetchAnchor = (anchor, observer2) => {
223
- if (prefetchedLinks.has(anchor)) {
224
- return;
225
- }
226
- prefetchedLinks.add(anchor);
227
- observer2?.unobserve(anchor);
228
- if (navigator.connection?.saveData || !anchor.href) {
229
- return;
230
- }
231
- let url;
232
- try {
233
- url = new URL(anchor.href);
234
- } catch {
235
- return;
236
- }
237
- const currentUrl = new URL(location.href);
238
- if (!isSameOrigin(url, currentUrl) || !shouldPreload(toPath(url), {
239
- url: currentUrl
240
- })) {
241
- return;
242
- }
243
- const mode = anchor.getAttribute("data-q-prefetch") || "";
244
- if (mode.includes("b")) {
245
- preloadRouteBundles(url.pathname);
246
- }
247
- if (mode.includes("d")) {
248
- prefetchRoute(url, true, 0.8, manifestHash, false);
249
- }
250
- };
251
- if (typeof IntersectionObserver === "undefined") {
252
- anchors.forEach((anchor) => prefetchAnchor(anchor));
253
- return () => {
254
- };
255
- }
256
- const observer = new IntersectionObserver((entries) => {
257
- for (const entry of entries) {
258
- if (entry.isIntersecting) {
259
- prefetchAnchor(entry.target, observer);
260
- }
261
- }
262
- });
263
- anchors.forEach((anchor) => observer.observe(anchor));
264
- return () => {
265
- observer.disconnect();
266
- };
223
+ var createLinkPrefetchObserver = (manifestHash) => {
224
+ const anchors = document.querySelectorAll("a[q\\:link][data-q-prefetch]");
225
+ const prefetchAnchor = (anchor, observer) => {
226
+ if (prefetchedLinks.has(anchor)) return;
227
+ prefetchedLinks.add(anchor);
228
+ observer?.unobserve(anchor);
229
+ if (navigator.connection?.saveData || !anchor.href) return;
230
+ let url;
231
+ try {
232
+ url = new URL(anchor.href);
233
+ } catch {
234
+ return;
235
+ }
236
+ const currentUrl = new URL(location.href);
237
+ if (!isSameOrigin(url, currentUrl) || !shouldPreload(toPath(url), { url: currentUrl })) return;
238
+ const mode = anchor.getAttribute("data-q-prefetch") || "";
239
+ if (mode.includes("b")) preloadRouteBundles(url.pathname);
240
+ if (mode.includes("d")) prefetchRoute(url, true, .8, manifestHash, false);
241
+ };
242
+ if (typeof IntersectionObserver === "undefined") {
243
+ anchors.forEach((anchor) => prefetchAnchor(anchor));
244
+ return () => {};
245
+ }
246
+ const observer = new IntersectionObserver((entries) => {
247
+ for (const entry of entries) if (entry.isIntersecting) prefetchAnchor(entry.target, observer);
248
+ });
249
+ anchors.forEach((anchor) => observer.observe(anchor));
250
+ return () => {
251
+ observer.disconnect();
252
+ };
267
253
  };
268
- const refreshLinkPrefetchObserver = (manifestHash) => {
269
- resetLinkPrefetchState();
270
- cleanupPrefetchObserver?.();
271
- cleanupPrefetchObserver = createLinkPrefetchObserver(manifestHash);
254
+ var refreshLinkPrefetchObserver = (manifestHash) => {
255
+ resetLinkPrefetchState();
256
+ cleanupPrefetchObserver?.();
257
+ cleanupPrefetchObserver = createLinkPrefetchObserver(manifestHash);
272
258
  };
273
- const linkPrefetchInit = eventQrl(/* @__PURE__ */ inlinedQrl((_, element) => {
274
- const manifestHash = element.closest("[q\\:manifest-hash]")?.getAttribute("q:manifest-hash") || void 0;
275
- refreshLinkPrefetchObserver(manifestHash);
259
+ var linkPrefetchInit = eventQrl(/*#__PURE__*/ inlinedQrl((_, element) => {
260
+ refreshLinkPrefetchObserver(element.closest("[q\\:manifest-hash]")?.getAttribute("q:manifest-hash") || void 0);
276
261
  }, "linkPrefetchInit_event_hoZr9O26Irg"));
277
-
278
262
  function callRestoreScrollOnDocument() {
279
- if (document.__q_scroll_restore__) {
280
- document.__q_scroll_restore__();
281
- document.__q_scroll_restore__ = void 0;
282
- }
263
+ if (document.__q_scroll_restore__) {
264
+ document.__q_scroll_restore__();
265
+ document.__q_scroll_restore__ = void 0;
266
+ }
283
267
  }
284
- const hashScroll = (toUrl, fromUrl) => {
285
- const elmId = toUrl.hash.slice(1);
286
- const elm = elmId && document.getElementById(elmId);
287
- if (elm) {
288
- elm.scrollIntoView();
289
- return true;
290
- } else if (!elm && toUrl.hash && isSamePath(toUrl, fromUrl)) {
291
- return true;
292
- }
293
- return false;
268
+ var hashScroll = (toUrl, fromUrl) => {
269
+ const elmId = toUrl.hash.slice(1);
270
+ const elm = elmId && document.getElementById(elmId);
271
+ if (elm) {
272
+ elm.scrollIntoView();
273
+ return true;
274
+ } else if (!elm && toUrl.hash && isSamePath(toUrl, fromUrl)) return true;
275
+ return false;
294
276
  };
295
- const restoreScroll = (type, toUrl, fromUrl, scroller, scrollState) => {
296
- if (type === "popstate" && scrollState) {
297
- scroller.scrollTo(scrollState.x, scrollState.y);
298
- } else if (type === "link" || type === "form") {
299
- if (!hashScroll(toUrl, fromUrl)) {
300
- scroller.scrollTo(0, 0);
301
- }
302
- }
277
+ var restoreScroll = (type, toUrl, fromUrl, scroller, scrollState) => {
278
+ if (type === "popstate" && scrollState) scroller.scrollTo(scrollState.x, scrollState.y);
279
+ else if (type === "link" || type === "form") {
280
+ if (!hashScroll(toUrl, fromUrl)) scroller.scrollTo(0, 0);
281
+ }
303
282
  };
304
- const currentScrollState = (elm) => {
305
- return {
306
- x: elm.scrollLeft,
307
- y: elm.scrollTop,
308
- w: Math.max(elm.scrollWidth, elm.clientWidth),
309
- h: Math.max(elm.scrollHeight, elm.clientHeight)
310
- };
283
+ var currentScrollState = (elm) => {
284
+ return {
285
+ x: elm.scrollLeft,
286
+ y: elm.scrollTop,
287
+ w: Math.max(elm.scrollWidth, elm.clientWidth),
288
+ h: Math.max(elm.scrollHeight, elm.clientHeight)
289
+ };
311
290
  };
312
- const getScrollHistory = () => {
313
- const state = history.state;
314
- return state?._qRouterScroll;
291
+ var getScrollHistory = () => {
292
+ return history.state?._qRouterScroll;
315
293
  };
316
- const saveScrollHistory = (scrollState) => {
317
- const state = history.state || {};
318
- state._qRouterScroll = scrollState;
319
- history.replaceState(state, "");
294
+ var saveScrollHistory = (scrollState) => {
295
+ const state = history.state || {};
296
+ state._qRouterScroll = scrollState;
297
+ history.replaceState(state, "");
320
298
  };
321
-
322
- const Q_ROUTER_POPSTATE_EVENT = "qrouterpopstate";
323
- const createCurrentPathTracker = (initialPath) => {
324
- let currentPath = initialPath;
325
- return (nextPath) => {
326
- if (currentPath !== nextPath) {
327
- currentPath = nextPath;
328
- return true;
329
- }
330
- return false;
331
- };
299
+ var Q_ROUTER_POPSTATE_EVENT = "qrouterpopstate";
300
+ var createCurrentPathTracker = (initialPath) => {
301
+ let currentPath = initialPath;
302
+ return (nextPath) => {
303
+ if (currentPath !== nextPath) {
304
+ currentPath = nextPath;
305
+ return true;
306
+ }
307
+ return false;
308
+ };
332
309
  };
333
- const dispatchRouterPopstate = (document1, href) => {
334
- document1.dispatchEvent(new CustomEvent(Q_ROUTER_POPSTATE_EVENT, {
335
- detail: {
336
- href
337
- }
338
- }));
310
+ var dispatchRouterPopstate = (document1, href) => {
311
+ document1.dispatchEvent(new CustomEvent(Q_ROUTER_POPSTATE_EVENT, { detail: { href } }));
339
312
  };
340
- const spaInit = eventQrl(/* @__PURE__ */ inlinedQrl((_, el) => {
341
- if (!window._qRouterSPA && !window._qRouterInitPopstate) {
342
- const hasPathChanged = createCurrentPathTracker(location.pathname + location.search);
343
- const checkAndScroll = (scrollState) => {
344
- if (scrollState) {
345
- window.scrollTo(scrollState.x, scrollState.y);
346
- }
347
- };
348
- const currentScrollState = () => {
349
- const elm = document.documentElement;
350
- return {
351
- x: elm.scrollLeft,
352
- y: elm.scrollTop,
353
- w: Math.max(elm.scrollWidth, elm.clientWidth),
354
- h: Math.max(elm.scrollHeight, elm.clientHeight)
355
- };
356
- };
357
- const saveScrollState = (scrollState) => {
358
- const state = history.state || {};
359
- state._qRouterScroll = scrollState || currentScrollState();
360
- history.replaceState(state, "");
361
- };
362
- saveScrollState();
363
- window._qRouterInitPopstate = () => {
364
- if (window._qRouterSPA) {
365
- return;
366
- }
367
- window._qRouterScrollEnabled = false;
368
- clearTimeout(window._qRouterScrollDebounce);
369
- if (hasPathChanged(location.pathname + location.search)) {
370
- dispatchRouterPopstate(document, location.href);
371
- } else {
372
- if (history.scrollRestoration === "manual") {
373
- const scrollState = history.state?._qRouterScroll;
374
- checkAndScroll(scrollState);
375
- window._qRouterScrollEnabled = true;
376
- }
377
- }
378
- };
379
- if (!window._qRouterHistoryPatch) {
380
- window._qRouterHistoryPatch = true;
381
- const pushState = history.pushState;
382
- const replaceState = history.replaceState;
383
- const prepareState = (state) => {
384
- if (state === null || typeof state === "undefined") {
385
- state = {};
386
- } else if (state?.constructor !== Object) {
387
- state = {
388
- _data: state
389
- };
390
- if (isDev) {
391
- 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`");
392
- }
393
- }
394
- state._qRouterScroll = state._qRouterScroll || currentScrollState();
395
- return state;
396
- };
397
- history.pushState = (state, title, url) => {
398
- state = prepareState(state);
399
- return pushState.call(history, state, title, url);
400
- };
401
- history.replaceState = (state, title, url) => {
402
- state = prepareState(state);
403
- return replaceState.call(history, state, title, url);
404
- };
405
- }
406
- window._qRouterInitAnchors = (event) => {
407
- if (window._qRouterSPA || event.defaultPrevented) {
408
- return;
409
- }
410
- const target = event.target.closest("a[href]");
411
- if (target && !target.hasAttribute("preventdefault:click")) {
412
- const href = target.getAttribute("href");
413
- const prev = new URL(location.href);
414
- const dest = new URL(href, prev);
415
- const sameOrigin = dest.origin === prev.origin;
416
- const samePath = dest.pathname + dest.search === prev.pathname + prev.search;
417
- if (sameOrigin && samePath) {
418
- event.preventDefault();
419
- if (dest.href !== prev.href) {
420
- history.pushState(null, "", dest);
421
- }
422
- if (!dest.hash) {
423
- if (dest.href.endsWith("#")) {
424
- window.scrollTo(0, 0);
425
- } else {
426
- window._qRouterScrollEnabled = false;
427
- clearTimeout(window._qRouterScrollDebounce);
428
- saveScrollState({
429
- ...currentScrollState(),
430
- x: 0,
431
- y: 0
432
- });
433
- location.reload();
434
- }
435
- } else {
436
- const elmId = dest.hash.slice(1);
437
- const elm = document.getElementById(elmId);
438
- if (elm) {
439
- elm.scrollIntoView();
440
- }
441
- }
442
- }
443
- }
444
- };
445
- window._qRouterInitVisibility = () => {
446
- if (!window._qRouterSPA && window._qRouterScrollEnabled && document.visibilityState === "hidden") {
447
- saveScrollState();
448
- }
449
- };
450
- window._qRouterInitScroll = () => {
451
- if (window._qRouterSPA || !window._qRouterScrollEnabled) {
452
- return;
453
- }
454
- clearTimeout(window._qRouterScrollDebounce);
455
- window._qRouterScrollDebounce = setTimeout(() => {
456
- saveScrollState();
457
- window._qRouterScrollDebounce = void 0;
458
- }, 200);
459
- };
460
- window._qRouterScrollEnabled = true;
461
- window.addEventListener("popstate", window._qRouterInitPopstate);
462
- window.addEventListener("scroll", window._qRouterInitScroll, {
463
- passive: true
464
- });
465
- document.addEventListener("click", window._qRouterInitAnchors);
466
- if (!window.navigation) {
467
- document.addEventListener("visibilitychange", window._qRouterInitVisibility, {
468
- passive: true
469
- });
470
- }
471
- }
313
+ var spa_init_default = eventQrl(/*#__PURE__*/ inlinedQrl((_, el) => {
314
+ if (!window._qRouterSPA && !window._qRouterInitPopstate) {
315
+ const hasPathChanged = createCurrentPathTracker(location.pathname + location.search);
316
+ const checkAndScroll = (scrollState) => {
317
+ if (scrollState) window.scrollTo(scrollState.x, scrollState.y);
318
+ };
319
+ const currentScrollState = () => {
320
+ const elm = document.documentElement;
321
+ return {
322
+ x: elm.scrollLeft,
323
+ y: elm.scrollTop,
324
+ w: Math.max(elm.scrollWidth, elm.clientWidth),
325
+ h: Math.max(elm.scrollHeight, elm.clientHeight)
326
+ };
327
+ };
328
+ const saveScrollState = (scrollState) => {
329
+ const state = history.state || {};
330
+ state._qRouterScroll = scrollState || currentScrollState();
331
+ history.replaceState(state, "");
332
+ };
333
+ saveScrollState();
334
+ window._qRouterInitPopstate = () => {
335
+ if (window._qRouterSPA) return;
336
+ window._qRouterScrollEnabled = false;
337
+ clearTimeout(window._qRouterScrollDebounce);
338
+ if (hasPathChanged(location.pathname + location.search)) dispatchRouterPopstate(document, location.href);
339
+ else if (history.scrollRestoration === "manual") {
340
+ const scrollState = history.state?._qRouterScroll;
341
+ checkAndScroll(scrollState);
342
+ window._qRouterScrollEnabled = true;
343
+ }
344
+ };
345
+ if (!window._qRouterHistoryPatch) {
346
+ window._qRouterHistoryPatch = true;
347
+ const pushState = history.pushState;
348
+ const replaceState = history.replaceState;
349
+ const prepareState = (state) => {
350
+ if (state === null || typeof state === "undefined") state = {};
351
+ else if (state?.constructor !== Object) {
352
+ state = { _data: state };
353
+ 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`");
354
+ }
355
+ state._qRouterScroll = state._qRouterScroll || currentScrollState();
356
+ return state;
357
+ };
358
+ history.pushState = (state, title, url) => {
359
+ state = prepareState(state);
360
+ return pushState.call(history, state, title, url);
361
+ };
362
+ history.replaceState = (state, title, url) => {
363
+ state = prepareState(state);
364
+ return replaceState.call(history, state, title, url);
365
+ };
366
+ }
367
+ window._qRouterInitAnchors = (event) => {
368
+ if (window._qRouterSPA || event.defaultPrevented) return;
369
+ const target = event.target.closest("a[href]");
370
+ if (target && !target.hasAttribute("preventdefault:click")) {
371
+ const href = target.getAttribute("href");
372
+ const prev = new URL(location.href);
373
+ const dest = new URL(href, prev);
374
+ const sameOrigin = dest.origin === prev.origin;
375
+ const samePath = dest.pathname + dest.search === prev.pathname + prev.search;
376
+ if (sameOrigin && samePath) {
377
+ event.preventDefault();
378
+ if (dest.href !== prev.href) history.pushState(null, "", dest);
379
+ if (!dest.hash) {
380
+ if (dest.href.endsWith("#")) window.scrollTo(0, 0);
381
+ else {
382
+ window._qRouterScrollEnabled = false;
383
+ clearTimeout(window._qRouterScrollDebounce);
384
+ saveScrollState({
385
+ ...currentScrollState(),
386
+ x: 0,
387
+ y: 0
388
+ });
389
+ location.reload();
390
+ }
391
+ } else {
392
+ const elmId = dest.hash.slice(1);
393
+ const elm = document.getElementById(elmId);
394
+ if (elm) elm.scrollIntoView();
395
+ }
396
+ }
397
+ }
398
+ };
399
+ window._qRouterInitVisibility = () => {
400
+ if (!window._qRouterSPA && window._qRouterScrollEnabled && document.visibilityState === "hidden") saveScrollState();
401
+ };
402
+ window._qRouterInitScroll = () => {
403
+ if (window._qRouterSPA || !window._qRouterScrollEnabled) return;
404
+ clearTimeout(window._qRouterScrollDebounce);
405
+ window._qRouterScrollDebounce = setTimeout(() => {
406
+ saveScrollState();
407
+ window._qRouterScrollDebounce = void 0;
408
+ }, 200);
409
+ };
410
+ window._qRouterScrollEnabled = true;
411
+ window.addEventListener("popstate", window._qRouterInitPopstate);
412
+ window.addEventListener("scroll", window._qRouterInitScroll, { passive: true });
413
+ document.addEventListener("click", window._qRouterInitAnchors);
414
+ if (!window.navigation) document.addEventListener("visibilitychange", window._qRouterInitVisibility, { passive: true });
415
+ }
472
416
  }, "spa_init_event_igI1pUsax0E"));
473
-
474
- async function submitAction(action, routeUrl) {
475
- const pathBase = ensureSlash(routeUrl.pathname);
476
- const searchParams = new URLSearchParams(routeUrl.search);
477
- searchParams.set(QACTION_KEY, action.id);
478
- const search = searchParams.toString();
479
- const url = `${pathBase}?${search}`;
480
- const actionData = action.data;
481
- action.data = void 0;
482
- let fetchOptions;
483
- if (actionData instanceof FormData) {
484
- fetchOptions = {
485
- method: "POST",
486
- body: actionData,
487
- headers: {
488
- Accept: "application/json"
489
- }
490
- };
491
- } else {
492
- fetchOptions = {
493
- method: "POST",
494
- body: JSON.stringify(actionData),
495
- headers: {
496
- "Content-Type": "application/json; charset=UTF-8",
497
- Accept: "application/json"
498
- }
499
- };
500
- }
501
- const response = await fetch(url, fetchOptions);
502
- if (response.redirected) {
503
- const redirectedURL = new URL(response.url);
504
- if (redirectedURL.origin !== location.origin) {
505
- location.href = redirectedURL.href;
506
- return void 0;
507
- }
508
- location.href = redirectedURL.href;
509
- return void 0;
510
- }
511
- if ((response.headers.get("content-type") || "").includes("json")) {
512
- const text = await response.text();
513
- const data = await _deserialize(text);
514
- return {
515
- status: response.status,
516
- result: data?.result,
517
- redirect: data?.redirect,
518
- loaderHashes: data?.loaderHashes
519
- };
520
- }
521
- return void 0;
417
+ /**
418
+ * Submit an action to the server and get the result.
419
+ *
420
+ * POSTs to the route URL with `qaction={actionId}` appended and `Accept: application/json`. The
421
+ * server runs the action and returns the action result, optionally with the loader hashes that
422
+ * should be invalidated.
423
+ */ async function submitAction(action, routeUrl) {
424
+ const pathBase = ensureSlash(routeUrl.pathname);
425
+ const searchParams = new URLSearchParams(routeUrl.search);
426
+ searchParams.set(QACTION_KEY, action.id);
427
+ const url = `${pathBase}?${searchParams.toString()}`;
428
+ const actionData = action.data;
429
+ action.data = void 0;
430
+ let fetchOptions;
431
+ if (actionData instanceof FormData) fetchOptions = {
432
+ method: "POST",
433
+ body: actionData,
434
+ headers: { Accept: "application/json" }
435
+ };
436
+ else fetchOptions = {
437
+ method: "POST",
438
+ body: JSON.stringify(actionData),
439
+ headers: {
440
+ "Content-Type": "application/json; charset=UTF-8",
441
+ Accept: "application/json"
442
+ }
443
+ };
444
+ const response = await fetch(url, fetchOptions);
445
+ if (response.redirected) {
446
+ const redirectedURL = new URL(response.url);
447
+ if (redirectedURL.origin !== location.origin) {
448
+ location.href = redirectedURL.href;
449
+ return;
450
+ }
451
+ location.href = redirectedURL.href;
452
+ return;
453
+ }
454
+ if ((response.headers.get("content-type") || "").includes("json")) {
455
+ const text = await response.text();
456
+ const data = await _deserialize(text);
457
+ return {
458
+ status: response.status,
459
+ result: data?.result,
460
+ redirect: data?.redirect,
461
+ loaderHashes: data?.loaderHashes
462
+ };
463
+ }
522
464
  }
523
-
524
- const transitionCss = "@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}}}";
525
-
526
- const shouldStartViewTransition = (viewTransition) => viewTransition === true && "startViewTransition" in document;
527
- const VIEW_TRANSITION_STYLE_ID = "qwik-view-transition";
528
- const ensureViewTransitionStyles = () => {
529
- if (document.getElementById(VIEW_TRANSITION_STYLE_ID)) {
530
- return;
531
- }
532
- const style = document.createElement("style");
533
- style.id = VIEW_TRANSITION_STYLE_ID;
534
- style.textContent = transitionCss;
535
- document.head.appendChild(style);
536
- };
537
- const startViewTransition = (params) => {
538
- if ("startViewTransition" in document) {
539
- ensureViewTransitionStyles();
540
- let transition;
541
- try {
542
- transition = document.startViewTransition(params);
543
- } catch {
544
- transition = document.startViewTransition(params.update);
545
- }
546
- const event = new CustomEvent("qviewtransition", {
547
- detail: transition
548
- });
549
- document.dispatchEvent(event);
550
- return {
551
- ready: transition.ready,
552
- transition
553
- };
554
- } else {
555
- return {
556
- ready: params.update()
557
- };
558
- }
465
+ 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}}}";
466
+ /** View transitions are opt-in and require browser support. */ var shouldStartViewTransition = (viewTransition) => viewTransition === true && "startViewTransition" in document;
467
+ var VIEW_TRANSITION_STYLE_ID = "qwik-view-transition";
468
+ /** Inject the view-transition stylesheet once, only when a transition actually runs. */ var ensureViewTransitionStyles = () => {
469
+ if (document.getElementById(VIEW_TRANSITION_STYLE_ID)) return;
470
+ const style = document.createElement("style");
471
+ style.id = VIEW_TRANSITION_STYLE_ID;
472
+ style.textContent = qwik_view_transition_default;
473
+ document.head.appendChild(style);
559
474
  };
560
-
561
- const QWIK_CITY_SCROLLER = "_qCityScroller";
562
- const QWIK_ROUTER_SCROLLER = "_qRouterScroller";
563
- const preventNav = {};
564
- const internalState = {
565
- navCount: 0
475
+ var startViewTransition = (params) => {
476
+ if ("startViewTransition" in document) {
477
+ ensureViewTransitionStyles();
478
+ let transition;
479
+ try {
480
+ transition = document.startViewTransition(params);
481
+ } catch {
482
+ transition = document.startViewTransition(params.update);
483
+ }
484
+ const event = new CustomEvent("qviewtransition", { detail: transition });
485
+ document.dispatchEvent(event);
486
+ return {
487
+ ready: transition.ready,
488
+ transition
489
+ };
490
+ } else return { ready: params.update() };
566
491
  };
567
- const getScroller = () => {
568
- let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
569
- if (!scroller) {
570
- scroller = document.getElementById(QWIK_CITY_SCROLLER);
571
- if (scroller && isDev) {
572
- console.warn(`Please update your scroller ID to "${QWIK_ROUTER_SCROLLER}" as "${QWIK_CITY_SCROLLER}" is deprecated and will be removed in V3`);
573
- }
574
- }
575
- return scroller ?? document.documentElement;
492
+ /**
493
+ * Qwik Router Component
494
+ *
495
+ * This file contains the main Qwik Router component, which initializes the router and provides the
496
+ * necessary context for it to work. It also contains the logic for handling navigation, including
497
+ * updating the URL, managing scroll restoration, and resolving document head changes.
498
+ *
499
+ * Note: This component is designed to work both on the server and the client. During server-side
500
+ * rendering (SSR), it initializes the router state based on the URL and route data provided by the
501
+ * server environment. On the client, it handles navigation events and updates the router state
502
+ * accordingly.
503
+ *
504
+ * SSR is _required_ for the initial load.
505
+ *
506
+ * The flow of navigation is as follows:
507
+ *
508
+ * 1. During SSR, the server environment parses the initial URL and collects the route data.
509
+ * 2. It runs the middleware hooks (`onRequest`, `onGet`, `onPost`, etc.), and responds to q-loader,
510
+ * action$ and server$ requests.
511
+ * 3. If SSR is deemed appropriate, the route data is provided via `useServerData` and this component
512
+ * uses it to initialize the router contexts, register Tasks, and render the Slot. This component
513
+ * will never render again.
514
+ * 4. Then, slotted components like `<DocumentHeadTags />` and `<RouterOutlet />` can consume the route
515
+ * data to render the page.
516
+ * 5. On the client, when a navigation event occurs, this calls `goto()`, which updates the URL in the
517
+ * same tick, loads the route data and adjusts the router context.
518
+ * 6. The changed contexts trigger the slotted components to re-render with the new route data.
519
+ *
520
+ * Since the head data can depend on route loaders and they get their data asynchronously and can
521
+ * update without navigation, the head is resolved in a separate Task that tracks the relevant
522
+ * signals.
523
+ */
524
+ /**
525
+ * @deprecated Use `QWIK_ROUTER_SCROLLER` instead (will be removed in V3)
526
+ * @public
527
+ */ var QWIK_CITY_SCROLLER = "_qCityScroller";
528
+ /** @public */ var QWIK_ROUTER_SCROLLER = "_qRouterScroller";
529
+ var preventNav = {};
530
+ var internalState = { navCount: 0 };
531
+ var getScroller = () => {
532
+ let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
533
+ if (!scroller) {
534
+ scroller = document.getElementById(QWIK_CITY_SCROLLER);
535
+ if (scroller && isDev) console.warn(`Please update your scroller ID to "${QWIK_ROUTER_SCROLLER}" as "${QWIK_CITY_SCROLLER}" is deprecated and will be removed in V3`);
536
+ }
537
+ return scroller ?? document.documentElement;
576
538
  };
577
- const useQwikMockRouter = (props) => {
578
- const urlEnv = props.url ?? "http://localhost/";
579
- const url = new URL(urlEnv);
580
- const routeLocation = useStore({
581
- url,
582
- params: props.params ?? {},
583
- isNavigating: false,
584
- prevUrl: void 0
585
- }, {
586
- deep: false
587
- });
588
- const loadersData = props.loaders?.reduce((acc, { loader, data }) => {
589
- acc[loader.__id] = data;
590
- return acc;
591
- }, {});
592
- const loadersState = useStore({}, {
593
- deep: false
594
- });
595
- for (const [loaderId, data] of Object.entries(loadersData ?? {})) {
596
- loadersState[loaderId] ||= createComputedQrl(/* @__PURE__ */ inlinedQrl(() => {
597
- const data2 = _captures[0];
598
- return data2;
599
- }, "useQwikMockRouter_createComputed_JL6bChMwwyc", [
600
- data
601
- ]));
602
- }
603
- const goto = props.goto ?? /* @__PURE__ */ inlinedQrl(async () => {
604
- console.warn("QwikRouterMockProvider: goto not provided");
605
- }, "useQwikMockRouter_goto_aViHFxQ1a3s");
606
- const documentHead = useStore(createDocumentHead, {
607
- deep: false
608
- });
609
- const content = useStore({
610
- headings: void 0,
611
- menu: void 0
612
- }, {
613
- deep: false
614
- });
615
- const contentInternal = useSignal();
616
- const actionState = useSignal();
617
- const httpStatus = useSignal({
618
- status: 200,
619
- message: ""
620
- });
621
- useContextProvider(ContentContext, content);
622
- useContextProvider(ContentInternalContext, contentInternal);
623
- useContextProvider(DocumentHeadContext, documentHead);
624
- useContextProvider(HttpStatusContext, httpStatus);
625
- useContextProvider(RouteLocationContext, routeLocation);
626
- useContextProvider(RouteNavigateContext, goto);
627
- useContextProvider(RouteStateContext, loadersState);
628
- useContextProvider(RouteActionContext, actionState);
629
- const actionsMocks = props.actions?.reduce((acc, { action, handler }) => {
630
- acc[action.__id] = handler;
631
- return acc;
632
- }, {});
633
- useTaskQrl(/* @__PURE__ */ inlinedQrl(async ({ track }) => {
634
- const actionState2 = _captures[0], actionsMocks2 = _captures[1];
635
- const action = track(actionState2);
636
- if (!action?.resolve) {
637
- return;
638
- }
639
- const mock = actionsMocks2?.[action.id];
640
- if (mock) {
641
- const actionResult = await mock(action.data);
642
- action.resolve(actionResult);
643
- }
644
- }, "useQwikMockRouter_useTask_tXTLR4tzCy0", [
645
- actionState,
646
- actionsMocks
647
- ]));
539
+ /** @public */ var useQwikMockRouter = (props) => {
540
+ const urlEnv = props.url ?? "http://localhost/";
541
+ const url = new URL(urlEnv);
542
+ const routeLocation = useStore({
543
+ url,
544
+ params: props.params ?? {},
545
+ isNavigating: false,
546
+ prevUrl: void 0
547
+ }, { deep: false });
548
+ const loadersData = props.loaders?.reduce((acc, { loader, data }) => {
549
+ acc[loader.__id] = data;
550
+ return acc;
551
+ }, {});
552
+ const loadersState = useStore({}, { deep: false });
553
+ for (const [loaderId, data] of Object.entries(loadersData ?? {})) loadersState[loaderId] ||= createComputedQrl(/*#__PURE__*/ inlinedQrl(() => {
554
+ return _captures[0];
555
+ }, "useQwikMockRouter_createComputed_JL6bChMwwyc", [data]));
556
+ const goto = props.goto ?? /*#__PURE__*/ inlinedQrl(async () => {
557
+ console.warn("QwikRouterMockProvider: goto not provided");
558
+ }, "useQwikMockRouter_goto_aViHFxQ1a3s");
559
+ const documentHead = useStore(createDocumentHead, { deep: false });
560
+ const content = useStore({
561
+ headings: void 0,
562
+ menu: void 0
563
+ }, { deep: false });
564
+ const contentInternal = useSignal();
565
+ const actionState = useSignal();
566
+ const httpStatus = useSignal({
567
+ status: 200,
568
+ message: ""
569
+ });
570
+ useContextProvider(ContentContext, content);
571
+ useContextProvider(ContentInternalContext, contentInternal);
572
+ useContextProvider(DocumentHeadContext, documentHead);
573
+ useContextProvider(HttpStatusContext, httpStatus);
574
+ useContextProvider(RouteLocationContext, routeLocation);
575
+ useContextProvider(RouteNavigateContext, goto);
576
+ useContextProvider(RouteStateContext, loadersState);
577
+ useContextProvider(RouteActionContext, actionState);
578
+ const actionsMocks = props.actions?.reduce((acc, { action, handler }) => {
579
+ acc[action.__id] = handler;
580
+ return acc;
581
+ }, {});
582
+ useTaskQrl(/*#__PURE__*/ inlinedQrl(async ({ track }) => {
583
+ const actionState = _captures[0], actionsMocks = _captures[1];
584
+ const action = track(actionState);
585
+ if (!action?.resolve) return;
586
+ const mock = actionsMocks?.[action.id];
587
+ if (mock) {
588
+ const actionResult = await mock(action.data);
589
+ action.resolve(actionResult);
590
+ }
591
+ }, "useQwikMockRouter_useTask_tXTLR4tzCy0", [actionState, actionsMocks]));
648
592
  };
649
- const QwikRouterMockProvider = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
650
- useQwikMockRouter(props);
651
- return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "5y_1");
593
+ /** @public */ var QwikRouterMockProvider = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
594
+ useQwikMockRouter(props);
595
+ return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "5y_1");
652
596
  }, "QwikRouterMockProvider_component_IN4dVpT0x74"));
653
- const QwikCityMockProvider = QwikRouterMockProvider;
597
+ /**
598
+ * @deprecated Use `useQwikMockRouter()` instead. Will be removed in V3
599
+ * @public
600
+ */ var QwikCityMockProvider = QwikRouterMockProvider;
654
601
  function initializeSPA(goto, scroller) {
655
- if (!window._qRouterSPA) {
656
- window._qRouterSPA = true;
657
- history.scrollRestoration = "manual";
658
- window.addEventListener("popstate", () => {
659
- window._qRouterScrollEnabled = false;
660
- clearTimeout(window._qRouterScrollDebounce);
661
- goto(location.href, {
662
- type: "popstate"
663
- });
664
- });
665
- window.removeEventListener("popstate", window._qRouterInitPopstate);
666
- window._qRouterInitPopstate = void 0;
667
- if (!window._qRouterHistoryPatch) {
668
- window._qRouterHistoryPatch = true;
669
- const pushState = history.pushState;
670
- const replaceState = history.replaceState;
671
- const prepareState = (state) => {
672
- if (state === null || typeof state === "undefined") {
673
- state = {};
674
- } else if (state?.constructor !== Object) {
675
- state = {
676
- _data: state
677
- };
678
- if (isDev) {
679
- 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`");
680
- }
681
- }
682
- state._qRouterScroll = state._qRouterScroll || currentScrollState(scroller);
683
- return state;
684
- };
685
- history.pushState = (state, title, url) => {
686
- state = prepareState(state);
687
- return pushState.call(history, state, title, url);
688
- };
689
- history.replaceState = (state, title, url) => {
690
- state = prepareState(state);
691
- return replaceState.call(history, state, title, url);
692
- };
693
- }
694
- document.addEventListener("click", (event) => {
695
- if (event.defaultPrevented) {
696
- return;
697
- }
698
- const target = event.target.closest("a[href]");
699
- if (target && !target.hasAttribute("preventdefault:click")) {
700
- const href = target.getAttribute("href");
701
- const prev = new URL(location.href);
702
- const dest = new URL(href, prev);
703
- if (isSameOrigin(dest, prev) && isSamePath(dest, prev)) {
704
- event.preventDefault();
705
- if (!dest.hash && !dest.href.endsWith("#")) {
706
- if (dest.href !== prev.href) {
707
- history.pushState(null, "", dest);
708
- }
709
- window._qRouterScrollEnabled = false;
710
- clearTimeout(window._qRouterScrollDebounce);
711
- saveScrollHistory({
712
- ...currentScrollState(scroller),
713
- x: 0,
714
- y: 0
715
- });
716
- location.reload();
717
- return;
718
- }
719
- goto(target.getAttribute("href"));
720
- }
721
- }
722
- });
723
- document.removeEventListener("click", window._qRouterInitAnchors);
724
- window._qRouterInitAnchors = void 0;
725
- if (!window.navigation) {
726
- document.addEventListener("visibilitychange", () => {
727
- if (window._qRouterScrollEnabled && document.visibilityState === "hidden") {
728
- const scrollState = currentScrollState(scroller);
729
- saveScrollHistory(scrollState);
730
- }
731
- }, {
732
- passive: true
733
- });
734
- document.removeEventListener("visibilitychange", window._qRouterInitVisibility);
735
- window._qRouterInitVisibility = void 0;
736
- }
737
- window.addEventListener("scroll", () => {
738
- if (!window._qRouterScrollEnabled) {
739
- return;
740
- }
741
- clearTimeout(window._qRouterScrollDebounce);
742
- window._qRouterScrollDebounce = setTimeout(() => {
743
- const scrollState = currentScrollState(scroller);
744
- saveScrollHistory(scrollState);
745
- window._qRouterScrollDebounce = void 0;
746
- }, 200);
747
- }, {
748
- passive: true
749
- });
750
- removeEventListener("scroll", window._qRouterInitScroll);
751
- window._qRouterInitScroll = void 0;
752
- spaInit.resolve();
753
- }
602
+ if (!window._qRouterSPA) {
603
+ window._qRouterSPA = true;
604
+ history.scrollRestoration = "manual";
605
+ window.addEventListener("popstate", () => {
606
+ window._qRouterScrollEnabled = false;
607
+ clearTimeout(window._qRouterScrollDebounce);
608
+ goto(location.href, { type: "popstate" });
609
+ });
610
+ window.removeEventListener("popstate", window._qRouterInitPopstate);
611
+ window._qRouterInitPopstate = void 0;
612
+ if (!window._qRouterHistoryPatch) {
613
+ window._qRouterHistoryPatch = true;
614
+ const pushState = history.pushState;
615
+ const replaceState = history.replaceState;
616
+ const prepareState = (state) => {
617
+ if (state === null || typeof state === "undefined") state = {};
618
+ else if (state?.constructor !== Object) {
619
+ state = { _data: state };
620
+ 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`");
621
+ }
622
+ state._qRouterScroll = state._qRouterScroll || currentScrollState(scroller);
623
+ return state;
624
+ };
625
+ history.pushState = (state, title, url) => {
626
+ state = prepareState(state);
627
+ return pushState.call(history, state, title, url);
628
+ };
629
+ history.replaceState = (state, title, url) => {
630
+ state = prepareState(state);
631
+ return replaceState.call(history, state, title, url);
632
+ };
633
+ }
634
+ document.addEventListener("click", (event) => {
635
+ if (event.defaultPrevented) return;
636
+ const target = event.target.closest("a[href]");
637
+ if (target && !target.hasAttribute("preventdefault:click")) {
638
+ const href = target.getAttribute("href");
639
+ const prev = new URL(location.href);
640
+ const dest = new URL(href, prev);
641
+ if (isSameOrigin(dest, prev) && isSamePath(dest, prev)) {
642
+ event.preventDefault();
643
+ if (!dest.hash && !dest.href.endsWith("#")) {
644
+ if (dest.href !== prev.href) history.pushState(null, "", dest);
645
+ window._qRouterScrollEnabled = false;
646
+ clearTimeout(window._qRouterScrollDebounce);
647
+ saveScrollHistory({
648
+ ...currentScrollState(scroller),
649
+ x: 0,
650
+ y: 0
651
+ });
652
+ location.reload();
653
+ return;
654
+ }
655
+ goto(target.getAttribute("href"));
656
+ }
657
+ }
658
+ });
659
+ document.removeEventListener("click", window._qRouterInitAnchors);
660
+ window._qRouterInitAnchors = void 0;
661
+ if (!window.navigation) {
662
+ document.addEventListener("visibilitychange", () => {
663
+ if (window._qRouterScrollEnabled && document.visibilityState === "hidden") saveScrollHistory(currentScrollState(scroller));
664
+ }, { passive: true });
665
+ document.removeEventListener("visibilitychange", window._qRouterInitVisibility);
666
+ window._qRouterInitVisibility = void 0;
667
+ }
668
+ window.addEventListener("scroll", () => {
669
+ if (!window._qRouterScrollEnabled) return;
670
+ clearTimeout(window._qRouterScrollDebounce);
671
+ window._qRouterScrollDebounce = setTimeout(() => {
672
+ saveScrollHistory(currentScrollState(scroller));
673
+ window._qRouterScrollDebounce = void 0;
674
+ }, 200);
675
+ }, { passive: true });
676
+ removeEventListener("scroll", window._qRouterInitScroll);
677
+ window._qRouterInitScroll = void 0;
678
+ spa_init_default.resolve();
679
+ }
754
680
  }
755
- const useQwikRouter = (props) => {
756
- if (!isServer) {
757
- 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.");
758
- }
759
- const env = useQwikRouterEnv();
760
- if (!env?.params) {
761
- throw new Error(`Missing Qwik Router Env Data for help visit https://github.com/QwikDev/qwik/issues/6237`);
762
- }
763
- const urlEnv = useServerData("url");
764
- if (!urlEnv) {
765
- throw new Error(`Missing Qwik URL Env Data`);
766
- }
767
- const serverHead = useServerData("documentHead");
768
- const manifestHash = useServerData("containerAttributes")?.["q:manifest-hash"];
769
- const url = new URL(urlEnv);
770
- const routeLocationTarget = {
771
- url,
772
- params: env.params,
773
- isNavigating: false,
774
- prevUrl: void 0
775
- };
776
- const routeLocation = useStore(routeLocationTarget, {
777
- deep: false
778
- });
779
- const navResolver = {};
780
- const routeLoaderCtx = useStore(env.routeLoaderCtx);
781
- routeLoaderCtx.manifestHash = manifestHash;
782
- const loaderState = {};
783
- const contentModulesForInit = env.loadedRoute.$mods$;
784
- const loaders = ensureRouteLoaderSignals(contentModulesForInit, loaderState, routeLoaderCtx);
785
- for (const loader of loaders) {
786
- if (loader.__id in env.loaderValues) {
787
- const value = env.loaderValues[loader.__id];
788
- setLoaderSignalValue(loaderState[loader.__id], value);
789
- }
790
- }
791
- const routeInternal = useSignal({
792
- type: "initial",
793
- dest: url
794
- });
795
- const documentHead = useStore(() => createDocumentHead(serverHead, manifestHash));
796
- const content = useStore({
797
- headings: void 0,
798
- menu: void 0
799
- });
800
- const contentInternal = useSignal();
801
- const navContext = useSignal();
802
- const httpStatus = useSignal({
803
- status: env.response.status,
804
- message: env.loadedRoute.$notFound$ ? "Not Found" : env.response.statusMessage ?? ""
805
- });
806
- const currentActionId = env.response.action;
807
- const currentAction = currentActionId ? env.response.actionResult : void 0;
808
- const actionState = useSignal(currentAction ? {
809
- id: currentActionId,
810
- data: env.response.formData,
811
- output: {
812
- result: currentAction,
813
- status: env.response.status
814
- }
815
- } : void 0);
816
- const actionDataSignal = useSignal(currentActionId ? {
817
- action: currentActionId,
818
- actionResult: currentAction,
819
- status: env.response.status
820
- } : void 0);
821
- const registerPreventNav = /* @__PURE__ */ inlinedQrl((fn$) => {
822
- if (!isBrowser) {
823
- return;
824
- }
825
- preventNav.$handler$ ||= (event) => {
826
- internalState.navCount++;
827
- if (!preventNav.$cbs$) {
828
- return;
829
- }
830
- const prevents = [
831
- ...preventNav.$cbs$.values()
832
- ].map((cb) => cb.resolved ? cb.resolved() : cb());
833
- if (prevents.some(Boolean)) {
834
- event.preventDefault();
835
- event.returnValue = true;
836
- }
837
- };
838
- (preventNav.$cbs$ ||= /* @__PURE__ */ new Set()).add(fn$);
839
- fn$.resolve();
840
- window.addEventListener("beforeunload", preventNav.$handler$);
841
- return () => {
842
- if (preventNav.$cbs$) {
843
- preventNav.$cbs$.delete(fn$);
844
- if (!preventNav.$cbs$.size) {
845
- preventNav.$cbs$ = void 0;
846
- window.removeEventListener("beforeunload", preventNav.$handler$);
847
- }
848
- }
849
- };
850
- }, "useQwikRouter_registerPreventNav_69B0DK0eZJc");
851
- const goto = /* @__PURE__ */ inlinedQrl(async (path, opt) => {
852
- const actionState2 = _captures[0], manifestHash2 = _captures[1], navResolver2 = _captures[2], routeInternal2 = _captures[3], routeLocation2 = _captures[4];
853
- const { type = "link", forceReload = path === void 0, replaceState = false, scroll = true } = typeof opt === "object" ? opt : {
854
- forceReload: opt
855
- };
856
- if (isBrowser && type === "link" && routeInternal2.value.type === "initial") {
857
- const url2 = new URL(window.location.href);
858
- routeInternal2.value.dest = url2;
859
- routeLocation2.url = url2;
860
- }
861
- const lastDest = routeInternal2.value.dest;
862
- const dest = path === void 0 ? lastDest : typeof path === "number" ? path : toUrl(path, routeLocation2.url);
863
- if (navResolver2.p && !forceReload && typeof dest !== "number" && isSamePath(dest, lastDest) && dest.href === lastDest.href) {
864
- return navResolver2.p;
865
- }
866
- const navCount = ++internalState.navCount;
867
- internalState.currentTransition?.skipTransition();
868
- if (preventNav.$cbs$ && (forceReload || typeof dest === "number" || !isSamePath(dest, lastDest) || !isSameOrigin(dest, lastDest))) {
869
- const prevents = await Promise.all([
870
- ...preventNav.$cbs$.values()
871
- ].map((cb) => cb(dest)));
872
- if (navCount !== internalState.navCount || prevents.some(Boolean)) {
873
- if (navCount === internalState.navCount && type === "popstate") {
874
- history.pushState(null, "", lastDest);
875
- }
876
- return;
877
- }
878
- }
879
- if (typeof dest === "number") {
880
- if (isBrowser) {
881
- history.go(dest);
882
- }
883
- return;
884
- }
885
- if (!isSameOrigin(dest, lastDest)) {
886
- if (isBrowser) {
887
- location.href = dest.href;
888
- }
889
- return;
890
- }
891
- if (!forceReload && isSamePath(dest, lastDest)) {
892
- if (isBrowser) {
893
- if (type === "link" && dest.href !== location.href) {
894
- history.pushState(null, "", dest);
895
- }
896
- const scroller = getScroller();
897
- restoreScroll(type, dest, new URL(location.href), scroller, getScrollHistory());
898
- if (type === "popstate") {
899
- window._qRouterScrollEnabled = true;
900
- }
901
- }
902
- if (dest.href !== routeLocation2.url.href) {
903
- const newUrl = new URL(dest.href);
904
- routeInternal2.value.dest = newUrl;
905
- routeLocation2.url = newUrl;
906
- }
907
- return;
908
- }
909
- let historyUpdated = false;
910
- if (isBrowser && type === "link" && !forceReload) {
911
- const scroller = getScroller();
912
- window._qRouterScrollEnabled = false;
913
- clearTimeout(window._qRouterScrollDebounce);
914
- const scrollState = currentScrollState(scroller);
915
- saveScrollHistory(scrollState);
916
- clientNavigate(window, type, new URL(location.href), dest, replaceState);
917
- historyUpdated = true;
918
- }
919
- routeLocation2.isNavigating = true;
920
- const container = isBrowser ? _getContextContainer() : void 0;
921
- if (container) {
922
- await _waitUntilRendered(container);
923
- if (navCount !== internalState.navCount) {
924
- return;
925
- }
926
- }
927
- actionState2.value = void 0;
928
- routeInternal2.value = {
929
- type,
930
- dest,
931
- forceReload,
932
- replaceState,
933
- scroll,
934
- historyUpdated
935
- };
936
- if (isBrowser) {
937
- prefetchRoute(dest, true, 0.8, manifestHash2);
938
- }
939
- navResolver2.p = new Promise((resolve) => {
940
- navResolver2.r = () => {
941
- navResolver2.r = void 0;
942
- navResolver2.p = void 0;
943
- resolve();
944
- };
945
- });
946
- return navResolver2.p;
947
- }, "useQwikRouter_goto_8j8Vrz2yUIM", [
948
- actionState,
949
- manifestHash,
950
- navResolver,
951
- routeInternal,
952
- routeLocation
953
- ]);
954
- useContextProvider(ContentContext, content);
955
- useContextProvider(ContentInternalContext, contentInternal);
956
- useContextProvider(DocumentHeadContext, documentHead);
957
- useContextProvider(HttpStatusContext, httpStatus);
958
- useContextProvider(RouteLocationContext, routeLocation);
959
- useContextProvider(RouteNavigateContext, goto);
960
- useContextProvider(RouteStateContext, loaderState);
961
- useContextProvider(RouteLoaderCtxContext, routeLoaderCtx);
962
- useContextProvider(RouteActionContext, actionState);
963
- useContextProvider(RoutePreventNavigateContext, registerPreventNav);
964
- useTaskQrl(
965
- /* @__PURE__ */ inlinedQrl(async ({ track }) => {
966
- const actionDataSignal2 = _captures[0], actionState2 = _captures[1], content2 = _captures[2], contentInternal2 = _captures[3], env2 = _captures[4], goto2 = _captures[5], httpStatus2 = _captures[6], loaderState2 = _captures[7], navContext2 = _captures[8], routeInternal2 = _captures[9], routeLoaderCtx2 = _captures[10], routeLocation2 = _captures[11], routeLocationTarget2 = _captures[12];
967
- const navigation = track(routeInternal2);
968
- const action = track(actionState2);
969
- const prevUrl = routeLocation2.url;
970
- const navType = action ? "form" : navigation.type;
971
- const replaceState = navigation.replaceState;
972
- const navCountBefore = internalState.navCount;
973
- let trackUrl;
974
- let endpointResponse;
975
- let actionData;
976
- let actionLoaderHashes;
977
- let shouldInvalidateActionLoaders = false;
978
- let loadedRoute;
979
- if (isServer) {
980
- trackUrl = new URL(navigation.dest, routeLocation2.url);
981
- loadedRoute = env2.loadedRoute;
982
- endpointResponse = env2.response;
983
- actionData = endpointResponse;
984
- } else {
985
- trackUrl = new URL(navigation.dest, location);
986
- if (trackUrl.pathname.endsWith("/")) {
987
- if (globalThis.__NO_TRAILING_SLASH__) {
988
- trackUrl.pathname = trackUrl.pathname.slice(0, -1);
989
- }
990
- } else if (!globalThis.__NO_TRAILING_SLASH__) {
991
- trackUrl.pathname = ensureSlash(trackUrl.pathname);
992
- }
993
- const loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, trackUrl.pathname);
994
- try {
995
- loadedRoute = await loadRoutePromise;
996
- } catch (e) {
997
- console.error(`Could not load route ${trackUrl.pathname}, reloading:`, e);
998
- window.location.href = trackUrl.href;
999
- return;
1000
- }
1001
- if (internalState.navCount !== navCountBefore) {
1002
- return;
1003
- }
1004
- if (action) {
1005
- const result = await submitAction(action, trackUrl);
1006
- if (!result) {
1007
- routeInternal2.untrackedValue = {
1008
- type: navType,
1009
- dest: trackUrl
1010
- };
1011
- return;
1012
- }
1013
- if (action.resolve) {
1014
- action.resolve({
1015
- status: result.status,
1016
- result: result.result
1017
- });
1018
- action.resolve = void 0;
1019
- }
1020
- if (result.redirect) {
1021
- goto2(result.redirect, {
1022
- replaceState: true
1023
- });
1024
- return;
1025
- }
1026
- actionData = {
1027
- status: result.status,
1028
- action: action.id,
1029
- actionResult: result.result
1030
- };
1031
- actionLoaderHashes = result.loaderHashes;
1032
- shouldInvalidateActionLoaders = true;
1033
- }
1034
- }
1035
- const { $routeName$, $params$, $mods$, $menu$, $notFound$ } = loadedRoute;
1036
- const contentModules = $mods$;
1037
- if (!isServer) {
1038
- routeLoaderCtx2.goto = noSerialize(goto2);
1039
- }
1040
- updateRouteLoaderPaths(routeLoaderCtx2, loadedRoute.$loaderPaths$, trackUrl);
1041
- const routeLoaders = ensureRouteLoaderSignals(contentModules, loaderState2, routeLoaderCtx2);
1042
- if (!isServer) {
1043
- invalidateNavRouteLoaders(loaderState2);
1044
- }
1045
- if (shouldInvalidateActionLoaders) {
1046
- if (actionLoaderHashes !== void 0) {
1047
- for (const hash of actionLoaderHashes) {
1048
- loaderState2[hash]?.invalidate(true);
1049
- }
1050
- } else {
1051
- for (const loader of routeLoaders) {
1052
- loaderState2[loader.__id].invalidate(true);
1053
- }
1054
- }
1055
- }
1056
- if (routeLoaders.length > 0) {
1057
- for (let i = 0; i < routeLoaders.length; i++) {
1058
- const loader = routeLoaders[i];
1059
- if (!isImmutableLoader(loader.__id)) {
1060
- loaderState2[loader.__id].untrackedPending;
1061
- }
1062
- }
1063
- }
1064
- if (!isServer) {
1065
- clearNavFetchCache();
1066
- }
1067
- if (internalState.navCount !== navCountBefore) {
1068
- return;
1069
- }
1070
- if ($notFound$) {
1071
- httpStatus2.value = {
1072
- status: 404,
1073
- message: "Not Found"
1074
- };
1075
- } else if (endpointResponse) {
1076
- httpStatus2.value = {
1077
- status: endpointResponse.status,
1078
- message: endpointResponse.statusMessage ?? "OK"
1079
- };
1080
- } else if (actionData) {
1081
- httpStatus2.value = {
1082
- status: actionData.status,
1083
- message: "OK"
1084
- };
1085
- } else {
1086
- httpStatus2.value = {
1087
- status: 200,
1088
- message: "OK"
1089
- };
1090
- }
1091
- const pageModule = contentModules[contentModules.length - 1];
1092
- if (navigation.dest.search && !!isSamePath(trackUrl, prevUrl)) {
1093
- trackUrl.search = navigation.dest.search;
1094
- }
1095
- let shouldForcePrevUrl = false;
1096
- let shouldForceUrl = false;
1097
- let shouldForceParams = false;
1098
- if (!isSamePath(trackUrl, prevUrl)) {
1099
- if (_hasStoreEffects(routeLocation2, "prevUrl")) {
1100
- shouldForcePrevUrl = true;
1101
- }
1102
- routeLocationTarget2.prevUrl = prevUrl;
1103
- }
1104
- if (routeLocationTarget2.url !== trackUrl) {
1105
- if (_hasStoreEffects(routeLocation2, "url")) {
1106
- shouldForceUrl = true;
1107
- }
1108
- routeLocationTarget2.url = trackUrl;
1109
- }
1110
- if (routeLocationTarget2.params !== $params$) {
1111
- if (_hasStoreEffects(routeLocation2, "params")) {
1112
- shouldForceParams = true;
1113
- }
1114
- routeLocationTarget2.params = $params$;
1115
- }
1116
- const nextRouteInternal = {
1117
- type: navType,
1118
- dest: trackUrl
1119
- };
1120
- if (navigation.forceReload !== void 0) {
1121
- nextRouteInternal.forceReload = navigation.forceReload;
1122
- }
1123
- if (navigation.replaceState !== void 0) {
1124
- nextRouteInternal.replaceState = navigation.replaceState;
1125
- }
1126
- if (navigation.scroll !== void 0) {
1127
- nextRouteInternal.scroll = navigation.scroll;
1128
- }
1129
- if (navigation.historyUpdated !== void 0) {
1130
- nextRouteInternal.historyUpdated = navigation.historyUpdated;
1131
- }
1132
- routeInternal2.untrackedValue = nextRouteInternal;
1133
- content2.headings = pageModule.headings;
1134
- content2.menu = $menu$;
1135
- contentInternal2.untrackedValue = noSerialize(contentModules);
1136
- actionDataSignal2.value = actionData;
1137
- navContext2.value = noSerialize({
1138
- routeName: $routeName$,
1139
- navType,
1140
- prevUrl,
1141
- replaceState,
1142
- shouldForcePrevUrl,
1143
- shouldForceUrl,
1144
- shouldForceParams,
1145
- navCount: navCountBefore
1146
- });
1147
- }, "useQwikRouter_useTask_XpalYii770E", [
1148
- actionDataSignal,
1149
- actionState,
1150
- content,
1151
- contentInternal,
1152
- env,
1153
- goto,
1154
- httpStatus,
1155
- loaderState,
1156
- navContext,
1157
- routeInternal,
1158
- routeLoaderCtx,
1159
- routeLocation,
1160
- routeLocationTarget
1161
- ]),
1162
- // We should only wait for head calculation to complete on the server
1163
- {
1164
- deferUpdates: isServer
1165
- }
1166
- );
1167
- useTaskQrl(/* @__PURE__ */ inlinedQrl(({ track }) => {
1168
- const actionDataSignal2 = _captures[0], contentInternal2 = _captures[1], documentHead2 = _captures[2], loaderState2 = _captures[3], routeLocation2 = _captures[4], serverHead2 = _captures[5];
1169
- const contentModules = track(contentInternal2);
1170
- if (!contentModules) {
1171
- return;
1172
- }
1173
- const actionData = track(actionDataSignal2);
1174
- const head = track(() => resolveHead(actionData, loaderState2, routeLocation2, contentModules, getLocale(""), serverHead2));
1175
- documentHead2.links = head.links;
1176
- documentHead2.meta = head.meta;
1177
- documentHead2.styles = head.styles;
1178
- documentHead2.scripts = head.scripts;
1179
- documentHead2.title = head.title;
1180
- documentHead2.frontmatter = head.frontmatter;
1181
- }, "useQwikRouter_useTask_1_1sKEZ9Pg1ow", [
1182
- actionDataSignal,
1183
- contentInternal,
1184
- documentHead,
1185
- loaderState,
1186
- routeLocation,
1187
- serverHead
1188
- ]), {
1189
- deferUpdates: isServer
1190
- });
1191
- useTaskQrl(/* @__PURE__ */ inlinedQrl(({ track }) => {
1192
- const contentInternal2 = _captures[0], goto2 = _captures[1], manifestHash2 = _captures[2], navContext2 = _captures[3], navResolver2 = _captures[4], props2 = _captures[5], routeInternal2 = _captures[6], routeLocation2 = _captures[7];
1193
- const nav = track(navContext2);
1194
- if (isServer || !nav) {
1195
- return;
1196
- }
1197
- if (nav.navCount !== internalState.navCount) {
1198
- return;
1199
- }
1200
- const container = _getContextContainer();
1201
- const navigation = routeInternal2.untrackedValue;
1202
- const { navType, prevUrl, replaceState, routeName } = nav;
1203
- const trackUrl = routeLocation2.url;
1204
- const scroller = getScroller();
1205
- let scrollState;
1206
- if (navType === "popstate") {
1207
- scrollState = getScrollHistory();
1208
- }
1209
- if (navigation.scroll && (!navigation.forceReload || !isSamePath(trackUrl, prevUrl)) && (navType === "link" || navType === "popstate") || navType === "form" && !isSamePath(trackUrl, prevUrl)) {
1210
- document.__q_scroll_restore__ = () => restoreScroll(navType, trackUrl, prevUrl, scroller, scrollState);
1211
- }
1212
- initializeSPA(goto2, scroller);
1213
- if (navType !== "popstate") {
1214
- window._qRouterScrollEnabled = false;
1215
- clearTimeout(window._qRouterScrollDebounce);
1216
- if (!navigation.historyUpdated) {
1217
- const scrollState2 = currentScrollState(scroller);
1218
- saveScrollHistory(scrollState2);
1219
- }
1220
- }
1221
- let didNavigate = false;
1222
- let navigatePromise;
1223
- let currentTransition;
1224
- const navigate = () => {
1225
- if (navigatePromise) {
1226
- return navigatePromise;
1227
- }
1228
- if (nav.navCount !== internalState.navCount) {
1229
- return Promise.resolve();
1230
- }
1231
- didNavigate = true;
1232
- if (navigation.historyUpdated) {
1233
- const currentPath = location.pathname + location.search + location.hash;
1234
- const nextPath = toPath(trackUrl);
1235
- if (currentPath !== nextPath) {
1236
- history.replaceState(history.state, "", nextPath);
1237
- }
1238
- } else {
1239
- clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1240
- }
1241
- contentInternal2.trigger();
1242
- return navigatePromise = _waitUntilRendered(container);
1243
- };
1244
- const _waitNextPage = () => {
1245
- if (!shouldStartViewTransition(props2?.viewTransition)) {
1246
- return navigate().then(() => void 0);
1247
- }
1248
- const { ready, transition } = startViewTransition({
1249
- update: navigate,
1250
- types: [
1251
- "qwik-navigation"
1252
- ]
1253
- });
1254
- currentTransition = transition;
1255
- internalState.currentTransition = transition;
1256
- return ready.then(() => transition, (reason) => {
1257
- if (!didNavigate && nav.navCount === internalState.navCount) {
1258
- return navigate().then(() => transition);
1259
- }
1260
- if (reason?.name === "AbortError") {
1261
- return transition;
1262
- }
1263
- throw reason;
1264
- });
1265
- };
1266
- _waitNextPage().finally(() => {
1267
- if (currentTransition && internalState.currentTransition === currentTransition) {
1268
- internalState.currentTransition = void 0;
1269
- }
1270
- if (nav.navCount !== internalState.navCount) {
1271
- return;
1272
- }
1273
- container.element.setAttribute?.(Q_ROUTE, routeName);
1274
- const scrollState2 = currentScrollState(scroller);
1275
- saveScrollHistory(scrollState2);
1276
- window._qRouterScrollEnabled = true;
1277
- callRestoreScrollOnDocument();
1278
- refreshLinkPrefetchObserver(manifestHash2);
1279
- if (nav.shouldForcePrevUrl) {
1280
- forceStoreEffects(routeLocation2, "prevUrl");
1281
- }
1282
- if (nav.shouldForceUrl) {
1283
- forceStoreEffects(routeLocation2, "url");
1284
- }
1285
- if (nav.shouldForceParams) {
1286
- forceStoreEffects(routeLocation2, "params");
1287
- }
1288
- routeLocation2.isNavigating = false;
1289
- navResolver2.r?.();
1290
- });
1291
- }, "useQwikRouter_useTask_2_yw17chooOac", [
1292
- contentInternal,
1293
- goto,
1294
- manifestHash,
1295
- navContext,
1296
- navResolver,
1297
- props,
1298
- routeInternal,
1299
- routeLocation
1300
- ]), {
1301
- deferUpdates: false
1302
- });
681
+ /**
682
+ * @public
683
+ * This hook initializes Qwik Router, providing the necessary context for it to work.
684
+ *
685
+ * This hook should be used once, at the root of your application.
686
+ */ var useQwikRouter = (props) => {
687
+ 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.");
688
+ const env = useQwikRouterEnv();
689
+ if (!env?.params) throw new Error(`Missing Qwik Router Env Data for help visit https://github.com/QwikDev/qwik/issues/6237`);
690
+ const urlEnv = useServerData("url");
691
+ if (!urlEnv) throw new Error(`Missing Qwik URL Env Data`);
692
+ const serverHead = useServerData("documentHead");
693
+ const manifestHash = useServerData("containerAttributes")?.["q:manifest-hash"];
694
+ const url = new URL(urlEnv);
695
+ const routeLocationTarget = {
696
+ url,
697
+ params: env.params,
698
+ isNavigating: false,
699
+ prevUrl: void 0
700
+ };
701
+ const routeLocation = useStore(routeLocationTarget, { deep: false });
702
+ const navResolver = {};
703
+ const routeLoaderCtx = useStore(env.routeLoaderCtx);
704
+ routeLoaderCtx.manifestHash = manifestHash;
705
+ const loaderState = {};
706
+ const contentModulesForInit = env.loadedRoute.$mods$;
707
+ const loaders = ensureRouteLoaderSignals(contentModulesForInit, loaderState, routeLoaderCtx);
708
+ for (const loader of loaders) if (loader.__id in env.loaderValues) {
709
+ const value = env.loaderValues[loader.__id];
710
+ setLoaderSignalValue(loaderState[loader.__id], value);
711
+ }
712
+ const routeInternal = useSignal({
713
+ type: "initial",
714
+ dest: url
715
+ });
716
+ const documentHead = useStore(() => createDocumentHead(serverHead, manifestHash));
717
+ const content = useStore({
718
+ headings: void 0,
719
+ menu: void 0
720
+ });
721
+ const contentInternal = useSignal();
722
+ /**
723
+ * Non-serializable navigation context passed from the nav task to the head+commit task. Only the
724
+ * data that can't be derived from existing stores/signals.
725
+ */ const navContext = useSignal();
726
+ const httpStatus = useSignal({
727
+ status: env.response.status,
728
+ message: env.loadedRoute.$notFound$ ? "Not Found" : env.response.statusMessage ?? ""
729
+ });
730
+ const currentActionId = env.response.action;
731
+ const currentAction = currentActionId ? env.response.actionResult : void 0;
732
+ const actionState = useSignal(currentAction ? {
733
+ id: currentActionId,
734
+ data: env.response.formData,
735
+ output: {
736
+ result: currentAction,
737
+ status: env.response.status
738
+ }
739
+ } : void 0);
740
+ const actionDataSignal = useSignal(currentActionId ? {
741
+ action: currentActionId,
742
+ actionResult: currentAction,
743
+ status: env.response.status
744
+ } : void 0);
745
+ const registerPreventNav = /*#__PURE__*/ inlinedQrl((fn$) => {
746
+ if (!isBrowser) return;
747
+ preventNav.$handler$ ||= (event) => {
748
+ internalState.navCount++;
749
+ if (!preventNav.$cbs$) return;
750
+ if ([...preventNav.$cbs$.values()].map((cb) => cb.resolved ? cb.resolved() : cb()).some(Boolean)) {
751
+ event.preventDefault();
752
+ event.returnValue = true;
753
+ }
754
+ };
755
+ (preventNav.$cbs$ ||= /* @__PURE__ */ new Set()).add(fn$);
756
+ fn$.resolve();
757
+ window.addEventListener("beforeunload", preventNav.$handler$);
758
+ return () => {
759
+ if (preventNav.$cbs$) {
760
+ preventNav.$cbs$.delete(fn$);
761
+ if (!preventNav.$cbs$.size) {
762
+ preventNav.$cbs$ = void 0;
763
+ window.removeEventListener("beforeunload", preventNav.$handler$);
764
+ }
765
+ }
766
+ };
767
+ }, "useQwikRouter_registerPreventNav_69B0DK0eZJc");
768
+ /**
769
+ * This is the `nav()` function that `useNavigation()` returns. It is also used internally for SPA
770
+ * navigations and is provided in context for use in loaders and actions.
771
+ *
772
+ * Note: when goto is called, the address bar change must happen in the same tick for Safari to
773
+ * treat it as a user-initiated navigation and allow scroll restoration to work. For this reason,
774
+ * make sure to change the address bar before awaiting anything.
775
+ */ const goto = /*#__PURE__*/ inlinedQrl(async (path, opt) => {
776
+ const actionState = _captures[0], manifestHash = _captures[1], navResolver = _captures[2], routeInternal = _captures[3], routeLocation = _captures[4];
777
+ const { type = "link", forceReload = path === void 0, replaceState = false, scroll = true } = typeof opt === "object" ? opt : { forceReload: opt };
778
+ if (isBrowser && type === "link" && routeInternal.value.type === "initial") {
779
+ const url = new URL(window.location.href);
780
+ routeInternal.value.dest = url;
781
+ routeLocation.url = url;
782
+ }
783
+ const lastDest = routeInternal.value.dest;
784
+ const dest = path === void 0 ? lastDest : typeof path === "number" ? path : toUrl(path, routeLocation.url);
785
+ if (navResolver.p && !forceReload && typeof dest !== "number" && isSamePath(dest, lastDest) && dest.href === lastDest.href) return navResolver.p;
786
+ const navCount = ++internalState.navCount;
787
+ internalState.currentTransition?.skipTransition();
788
+ if (preventNav.$cbs$ && (forceReload || typeof dest === "number" || !isSamePath(dest, lastDest) || !isSameOrigin(dest, lastDest))) {
789
+ const prevents = await Promise.all([...preventNav.$cbs$.values()].map((cb) => cb(dest)));
790
+ if (navCount !== internalState.navCount || prevents.some(Boolean)) {
791
+ if (navCount === internalState.navCount && type === "popstate") history.pushState(null, "", lastDest);
792
+ return;
793
+ }
794
+ }
795
+ if (typeof dest === "number") {
796
+ if (isBrowser) history.go(dest);
797
+ return;
798
+ }
799
+ if (!isSameOrigin(dest, lastDest)) {
800
+ if (isBrowser) location.href = dest.href;
801
+ return;
802
+ }
803
+ if (!forceReload && isSamePath(dest, lastDest)) {
804
+ if (isBrowser) {
805
+ if (type === "link" && dest.href !== location.href) history.pushState(null, "", dest);
806
+ const scroller = getScroller();
807
+ restoreScroll(type, dest, new URL(location.href), scroller, getScrollHistory());
808
+ if (type === "popstate") window._qRouterScrollEnabled = true;
809
+ }
810
+ if (dest.href !== routeLocation.url.href) {
811
+ const newUrl = new URL(dest.href);
812
+ routeInternal.value.dest = newUrl;
813
+ routeLocation.url = newUrl;
814
+ }
815
+ return;
816
+ }
817
+ let historyUpdated = false;
818
+ if (isBrowser && type === "link" && !forceReload) {
819
+ const scroller = getScroller();
820
+ window._qRouterScrollEnabled = false;
821
+ clearTimeout(window._qRouterScrollDebounce);
822
+ saveScrollHistory(currentScrollState(scroller));
823
+ clientNavigate(window, type, new URL(location.href), dest, replaceState);
824
+ historyUpdated = true;
825
+ }
826
+ routeLocation.isNavigating = true;
827
+ const container = isBrowser ? _getContextContainer() : void 0;
828
+ if (container) {
829
+ await _waitUntilRendered(container);
830
+ if (navCount !== internalState.navCount) return;
831
+ }
832
+ actionState.value = void 0;
833
+ routeInternal.value = {
834
+ type,
835
+ dest,
836
+ forceReload,
837
+ replaceState,
838
+ scroll,
839
+ historyUpdated
840
+ };
841
+ if (isBrowser) prefetchRoute(dest, true, .8, manifestHash);
842
+ navResolver.p = new Promise((resolve) => {
843
+ navResolver.r = () => {
844
+ navResolver.r = void 0;
845
+ navResolver.p = void 0;
846
+ resolve();
847
+ };
848
+ });
849
+ return navResolver.p;
850
+ }, "useQwikRouter_goto_8j8Vrz2yUIM", [
851
+ actionState,
852
+ manifestHash,
853
+ navResolver,
854
+ routeInternal,
855
+ routeLocation
856
+ ]);
857
+ useContextProvider(ContentContext, content);
858
+ useContextProvider(ContentInternalContext, contentInternal);
859
+ useContextProvider(DocumentHeadContext, documentHead);
860
+ useContextProvider(HttpStatusContext, httpStatus);
861
+ useContextProvider(RouteLocationContext, routeLocation);
862
+ useContextProvider(RouteNavigateContext, goto);
863
+ useContextProvider(RouteStateContext, loaderState);
864
+ useContextProvider(RouteLoaderCtxContext, routeLoaderCtx);
865
+ useContextProvider(RouteActionContext, actionState);
866
+ useContextProvider(RoutePreventNavigateContext, registerPreventNav);
867
+ /**
868
+ * This is split in 3 tasks because we need to update the head once we figured out the route, and
869
+ * before we trigger the render, and we need to subscribe only head to loader signal updates
870
+ */ useTaskQrl(/*#__PURE__*/ inlinedQrl(async ({ track }) => {
871
+ 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];
872
+ const navigation = track(routeInternal);
873
+ const action = track(actionState);
874
+ const prevUrl = routeLocation.url;
875
+ const navType = action ? "form" : navigation.type;
876
+ const replaceState = navigation.replaceState;
877
+ const navCountBefore = internalState.navCount;
878
+ let trackUrl;
879
+ let endpointResponse;
880
+ let actionData;
881
+ let actionLoaderHashes;
882
+ let shouldInvalidateActionLoaders = false;
883
+ let loadedRoute;
884
+ if (isServer) {
885
+ trackUrl = new URL(navigation.dest, routeLocation.url);
886
+ loadedRoute = env.loadedRoute;
887
+ endpointResponse = env.response;
888
+ actionData = endpointResponse;
889
+ } else {
890
+ trackUrl = new URL(navigation.dest, location);
891
+ if (trackUrl.pathname.endsWith("/")) {
892
+ if (globalThis.__NO_TRAILING_SLASH__) trackUrl.pathname = trackUrl.pathname.slice(0, -1);
893
+ } else if (!globalThis.__NO_TRAILING_SLASH__) trackUrl.pathname = ensureSlash(trackUrl.pathname);
894
+ const loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, trackUrl.pathname);
895
+ try {
896
+ loadedRoute = await loadRoutePromise;
897
+ } catch (e) {
898
+ console.error(`Could not load route ${trackUrl.pathname}, reloading:`, e);
899
+ window.location.href = trackUrl.href;
900
+ return;
901
+ }
902
+ if (internalState.navCount !== navCountBefore) return;
903
+ if (action) {
904
+ const result = await submitAction(action, trackUrl);
905
+ if (!result) {
906
+ routeInternal.untrackedValue = {
907
+ type: navType,
908
+ dest: trackUrl
909
+ };
910
+ return;
911
+ }
912
+ if (action.resolve) {
913
+ action.resolve({
914
+ status: result.status,
915
+ result: result.result
916
+ });
917
+ action.resolve = void 0;
918
+ }
919
+ if (result.redirect) {
920
+ goto(result.redirect, { replaceState: true });
921
+ return;
922
+ }
923
+ actionData = {
924
+ status: result.status,
925
+ action: action.id,
926
+ actionResult: result.result
927
+ };
928
+ actionLoaderHashes = result.loaderHashes;
929
+ shouldInvalidateActionLoaders = true;
930
+ }
931
+ }
932
+ const { $routeName$, $params$, $mods$, $menu$, $notFound$ } = loadedRoute;
933
+ const contentModules = $mods$;
934
+ if (!isServer) routeLoaderCtx.goto = noSerialize(goto);
935
+ updateRouteLoaderPaths(routeLoaderCtx, loadedRoute.$loaderPaths$, trackUrl);
936
+ const routeLoaders = ensureRouteLoaderSignals(contentModules, loaderState, routeLoaderCtx);
937
+ if (!isServer) invalidateNavRouteLoaders(loaderState);
938
+ if (shouldInvalidateActionLoaders) {
939
+ if (actionLoaderHashes !== void 0) for (const hash of actionLoaderHashes) loaderState[hash]?.invalidate(true);
940
+ else for (const loader of routeLoaders) loaderState[loader.__id].invalidate(true);
941
+ }
942
+ if (routeLoaders.length > 0) for (let i = 0; i < routeLoaders.length; i++) {
943
+ const loader = routeLoaders[i];
944
+ if (!isImmutableLoader(loader.__id)) loaderState[loader.__id].untrackedPending;
945
+ }
946
+ if (!isServer) clearNavFetchCache();
947
+ if (internalState.navCount !== navCountBefore) return;
948
+ if ($notFound$) httpStatus.value = {
949
+ status: 404,
950
+ message: "Not Found"
951
+ };
952
+ else if (endpointResponse) httpStatus.value = {
953
+ status: endpointResponse.status,
954
+ message: endpointResponse.statusMessage ?? "OK"
955
+ };
956
+ else if (actionData) httpStatus.value = {
957
+ status: actionData.status,
958
+ message: "OK"
959
+ };
960
+ else httpStatus.value = {
961
+ status: 200,
962
+ message: "OK"
963
+ };
964
+ const pageModule = contentModules[contentModules.length - 1];
965
+ if (navigation.dest.search && !!isSamePath(trackUrl, prevUrl)) trackUrl.search = navigation.dest.search;
966
+ let shouldForcePrevUrl = false;
967
+ let shouldForceUrl = false;
968
+ let shouldForceParams = false;
969
+ if (!isSamePath(trackUrl, prevUrl)) {
970
+ if (_hasStoreEffects(routeLocation, "prevUrl")) shouldForcePrevUrl = true;
971
+ routeLocationTarget.prevUrl = prevUrl;
972
+ }
973
+ if (routeLocationTarget.url !== trackUrl) {
974
+ if (_hasStoreEffects(routeLocation, "url")) shouldForceUrl = true;
975
+ routeLocationTarget.url = trackUrl;
976
+ }
977
+ if (routeLocationTarget.params !== $params$) {
978
+ if (_hasStoreEffects(routeLocation, "params")) shouldForceParams = true;
979
+ routeLocationTarget.params = $params$;
980
+ }
981
+ const nextRouteInternal = {
982
+ type: navType,
983
+ dest: trackUrl
984
+ };
985
+ if (navigation.forceReload !== void 0) nextRouteInternal.forceReload = navigation.forceReload;
986
+ if (navigation.replaceState !== void 0) nextRouteInternal.replaceState = navigation.replaceState;
987
+ if (navigation.scroll !== void 0) nextRouteInternal.scroll = navigation.scroll;
988
+ if (navigation.historyUpdated !== void 0) nextRouteInternal.historyUpdated = navigation.historyUpdated;
989
+ routeInternal.untrackedValue = nextRouteInternal;
990
+ content.headings = pageModule.headings;
991
+ content.menu = $menu$;
992
+ contentInternal.untrackedValue = noSerialize(contentModules);
993
+ actionDataSignal.value = actionData;
994
+ navContext.value = noSerialize({
995
+ routeName: $routeName$,
996
+ navType,
997
+ prevUrl,
998
+ replaceState,
999
+ shouldForcePrevUrl,
1000
+ shouldForceUrl,
1001
+ shouldForceParams,
1002
+ navCount: navCountBefore
1003
+ });
1004
+ }, "useQwikRouter_useTask_XpalYii770E", [
1005
+ actionDataSignal,
1006
+ actionState,
1007
+ content,
1008
+ contentInternal,
1009
+ env,
1010
+ goto,
1011
+ httpStatus,
1012
+ loaderState,
1013
+ navContext,
1014
+ routeInternal,
1015
+ routeLoaderCtx,
1016
+ routeLocation,
1017
+ routeLocationTarget
1018
+ ]), { deferUpdates: isServer });
1019
+ /**
1020
+ * Calc head. This is in a separate task so that loader updates can trigger head recalculation
1021
+ * without re-running the navigation logic.
1022
+ *
1023
+ * Note that on the server these tasks run sequentially.
1024
+ */ useTaskQrl(/*#__PURE__*/ inlinedQrl(({ track }) => {
1025
+ const actionDataSignal = _captures[0], contentInternal = _captures[1], documentHead = _captures[2], loaderState = _captures[3], routeLocation = _captures[4], serverHead = _captures[5];
1026
+ const contentModules = track(contentInternal);
1027
+ if (!contentModules) return;
1028
+ const actionData = track(actionDataSignal);
1029
+ const head = track(() => resolveHead(actionData, loaderState, routeLocation, contentModules, getLocale(""), serverHead));
1030
+ documentHead.links = head.links;
1031
+ documentHead.meta = head.meta;
1032
+ documentHead.styles = head.styles;
1033
+ documentHead.scripts = head.scripts;
1034
+ documentHead.title = head.title;
1035
+ documentHead.frontmatter = head.frontmatter;
1036
+ }, "useQwikRouter_useTask_1_1sKEZ9Pg1ow", [
1037
+ actionDataSignal,
1038
+ contentInternal,
1039
+ documentHead,
1040
+ loaderState,
1041
+ routeLocation,
1042
+ serverHead
1043
+ ]), { deferUpdates: isServer });
1044
+ /** Actual navigation */ useTaskQrl(/*#__PURE__*/ inlinedQrl(({ track }) => {
1045
+ 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];
1046
+ const nav = track(navContext);
1047
+ if (isServer || !nav) return;
1048
+ if (nav.navCount !== internalState.navCount) return;
1049
+ const container = _getContextContainer();
1050
+ const navigation = routeInternal.untrackedValue;
1051
+ const { navType, prevUrl, replaceState, routeName } = nav;
1052
+ const trackUrl = routeLocation.url;
1053
+ const scroller = getScroller();
1054
+ let scrollState;
1055
+ if (navType === "popstate") scrollState = getScrollHistory();
1056
+ if (navigation.scroll && (!navigation.forceReload || !isSamePath(trackUrl, prevUrl)) && (navType === "link" || navType === "popstate") || navType === "form" && !isSamePath(trackUrl, prevUrl)) document.__q_scroll_restore__ = () => restoreScroll(navType, trackUrl, prevUrl, scroller, scrollState);
1057
+ initializeSPA(goto, scroller);
1058
+ if (navType !== "popstate") {
1059
+ window._qRouterScrollEnabled = false;
1060
+ clearTimeout(window._qRouterScrollDebounce);
1061
+ if (!navigation.historyUpdated) saveScrollHistory(currentScrollState(scroller));
1062
+ }
1063
+ let didNavigate = false;
1064
+ let navigatePromise;
1065
+ let currentTransition;
1066
+ const navigate = () => {
1067
+ if (navigatePromise) return navigatePromise;
1068
+ if (nav.navCount !== internalState.navCount) return Promise.resolve();
1069
+ didNavigate = true;
1070
+ if (navigation.historyUpdated) {
1071
+ const currentPath = location.pathname + location.search + location.hash;
1072
+ const nextPath = toPath(trackUrl);
1073
+ if (currentPath !== nextPath) history.replaceState(history.state, "", nextPath);
1074
+ } else clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1075
+ contentInternal.trigger();
1076
+ return navigatePromise = _waitUntilRendered(container);
1077
+ };
1078
+ const _waitNextPage = () => {
1079
+ if (!shouldStartViewTransition(props?.viewTransition)) return navigate().then(() => void 0);
1080
+ const { ready, transition } = startViewTransition({
1081
+ update: navigate,
1082
+ types: ["qwik-navigation"]
1083
+ });
1084
+ currentTransition = transition;
1085
+ internalState.currentTransition = transition;
1086
+ return ready.then(() => transition, (reason) => {
1087
+ if (!didNavigate && nav.navCount === internalState.navCount) return navigate().then(() => transition);
1088
+ if (reason?.name === "AbortError") return transition;
1089
+ throw reason;
1090
+ });
1091
+ };
1092
+ _waitNextPage().finally(() => {
1093
+ if (currentTransition && internalState.currentTransition === currentTransition) internalState.currentTransition = void 0;
1094
+ if (nav.navCount !== internalState.navCount) return;
1095
+ container.element.setAttribute?.(Q_ROUTE, routeName);
1096
+ saveScrollHistory(currentScrollState(scroller));
1097
+ window._qRouterScrollEnabled = true;
1098
+ callRestoreScrollOnDocument();
1099
+ refreshLinkPrefetchObserver(manifestHash);
1100
+ if (nav.shouldForcePrevUrl) forceStoreEffects(routeLocation, "prevUrl");
1101
+ if (nav.shouldForceUrl) forceStoreEffects(routeLocation, "url");
1102
+ if (nav.shouldForceParams) forceStoreEffects(routeLocation, "params");
1103
+ routeLocation.isNavigating = false;
1104
+ navResolver.r?.();
1105
+ });
1106
+ }, "useQwikRouter_useTask_2_yw17chooOac", [
1107
+ contentInternal,
1108
+ goto,
1109
+ manifestHash,
1110
+ navContext,
1111
+ navResolver,
1112
+ props,
1113
+ routeInternal,
1114
+ routeLocation
1115
+ ]), { deferUpdates: false });
1303
1116
  };
1304
- const QwikRouterProvider = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
1305
- useQwikRouter(props);
1306
- return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "5y_0");
1117
+ /** @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) => {
1118
+ useQwikRouter(props);
1119
+ return /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "5y_0");
1307
1120
  }, "QwikRouterProvider_component_6Kjfa79mqlY"));
1308
- const QwikCityProvider = QwikRouterProvider;
1309
-
1310
- const handleRouterPopstate = (nav, event) => {
1311
- const href = event.detail?.href;
1312
- if (href) {
1313
- return nav(href, {
1314
- type: "popstate"
1315
- });
1316
- }
1121
+ /**
1122
+ * @deprecated Use `useQwikRouter()` instead. Will be removed in v3.
1123
+ * @public
1124
+ */ var QwikCityProvider = QwikRouterProvider;
1125
+ var handleRouterPopstate = (nav, event) => {
1126
+ const href = event.detail?.href;
1127
+ if (href) return nav(href, { type: "popstate" });
1317
1128
  };
1318
- const RouterOutlet = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl(() => {
1319
- const serverData = useServerData("containerAttributes");
1320
- if (!serverData) {
1321
- throw new Error("PrefetchServiceWorker component must be rendered on the server.");
1322
- }
1323
- const internalContext = useContext(ContentInternalContext);
1324
- const nav = useNavigate();
1325
- const contents = internalContext.value;
1326
- if (contents && contents.length > 0) {
1327
- const contentsLen = contents.length;
1328
- let cmp = null;
1329
- for (let i = contentsLen - 1; i >= 0; i--) {
1330
- if (contents[i].default) {
1331
- cmp = _jsxSorted(contents[i].default, null, null, cmp, 1, "Fn_0");
1332
- }
1333
- }
1334
- return /* @__PURE__ */ _jsxSorted(Fragment, null, null, [
1335
- cmp,
1336
- !__EXPERIMENTAL__.noSPA && /* @__PURE__ */ _jsxSorted("script", {
1337
- "q-d:qinit": _qrlSync(() => {
1338
- ((w, h) => {
1339
- if (!w._qcs) {
1340
- w._qcs = true;
1341
- const s = h.state?._qRouterScroll;
1342
- if (s) {
1343
- h.scrollRestoration = "manual";
1344
- w.scrollTo(s.x, s.y);
1345
- }
1346
- document.dispatchEvent(new Event("qcinit"));
1347
- }
1348
- })(window, history);
1349
- }, '()=>{((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);}'),
1350
- "q-d:qrouterpopstate": /* @__PURE__ */ inlinedQrl((event, _1, nav2) => handleRouterPopstate(nav2, event), "RouterOutlet_component_Fragment_script_q_d_qrouterpopstate_aRL6GvFyews").m(),
1351
- "q:p": nav
1352
- }, {
1353
- "q-d:qcinit": [
1354
- spaInit,
1355
- linkPrefetchInit
1356
- ]
1357
- }, null, 6, "Fn_1")
1358
- ], 1, "Fn_2");
1359
- }
1360
- return SkipRender;
1129
+ /** @public */ var RouterOutlet = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(() => {
1130
+ if (!useServerData("containerAttributes")) throw new Error("PrefetchServiceWorker component must be rendered on the server.");
1131
+ const internalContext = useContext(ContentInternalContext);
1132
+ const nav = useNavigate();
1133
+ const contents = internalContext.value;
1134
+ if (contents && contents.length > 0) {
1135
+ const contentsLen = contents.length;
1136
+ let cmp = null;
1137
+ for (let i = contentsLen - 1; i >= 0; i--) if (contents[i].default) cmp = _jsxSorted(contents[i].default, null, null, cmp, 1, "Fn_0");
1138
+ return /*#__PURE__*/ _jsxSorted(Fragment, null, null, [cmp, !__EXPERIMENTAL__.noSPA && /*#__PURE__*/ _jsxSorted("script", {
1139
+ "q-d:qinit": _qrlSync(() => {
1140
+ ((w, h) => {
1141
+ if (!w._qcs) {
1142
+ w._qcs = !0;
1143
+ const s = h.state?._qRouterScroll;
1144
+ if (s) {
1145
+ h.scrollRestoration = "manual";
1146
+ w.scrollTo(s.x, s.y);
1147
+ }
1148
+ document.dispatchEvent(new Event("qcinit"));
1149
+ }
1150
+ })(window, history);
1151
+ }, "()=>{((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);}"),
1152
+ "q-d:qrouterpopstate": /*#__PURE__*/ inlinedQrl((event, _1, nav) => handleRouterPopstate(nav, event), "RouterOutlet_component_Fragment_script_q_d_qrouterpopstate_aRL6GvFyews").m(),
1153
+ "q:p": nav
1154
+ }, { "q-d:qcinit": [spa_init_default, linkPrefetchInit] }, null, 6, "Fn_1")], 1, "Fn_2");
1155
+ }
1156
+ return SkipRender;
1361
1157
  }, "RouterOutlet_component_QwONcWD5gIg"));
1362
-
1363
- const validatorQrl = (validator) => {
1364
- if (isServer) {
1365
- return {
1366
- validate: validator
1367
- };
1368
- }
1369
- return void 0;
1158
+ /** @internal */ var validatorQrl = (validator) => {
1159
+ if (isServer) return { validate: validator };
1370
1160
  };
1371
- const validator$ = /* @__PURE__ */ implicit$FirstArg(validatorQrl);
1372
- const flattenValibotIssues = (issues) => {
1373
- return issues.reduce((acc, issue) => {
1374
- if (issue.path) {
1375
- const hasArrayType = issue.path.some((path) => path.type === "array");
1376
- if (hasArrayType) {
1377
- const keySuffix = issue.expected === "Array" ? "[]" : "";
1378
- const key = issue.path.map((item) => item.type === "array" ? "*" : item.key).join(".").replace(/\.\*/g, "[]") + keySuffix;
1379
- acc[key] = acc[key] || [];
1380
- if (Array.isArray(acc[key])) {
1381
- acc[key].push(issue.message);
1382
- }
1383
- return acc;
1384
- } else {
1385
- acc[issue.path.map((item) => item.key).join(".")] = issue.message;
1386
- }
1387
- }
1388
- return acc;
1389
- }, {});
1161
+ /** @public */ var validator$ = /*#__PURE__*/ implicit$FirstArg(validatorQrl);
1162
+ var flattenValibotIssues = (issues) => {
1163
+ return issues.reduce((acc, issue) => {
1164
+ if (issue.path) {
1165
+ if (issue.path.some((path) => path.type === "array")) {
1166
+ const keySuffix = issue.expected === "Array" ? "[]" : "";
1167
+ const key = issue.path.map((item) => item.type === "array" ? "*" : item.key).join(".").replace(/\.\*/g, "[]") + keySuffix;
1168
+ acc[key] = acc[key] || [];
1169
+ if (Array.isArray(acc[key])) acc[key].push(issue.message);
1170
+ return acc;
1171
+ } else acc[issue.path.map((item) => item.key).join(".")] = issue.message;
1172
+ }
1173
+ return acc;
1174
+ }, {});
1390
1175
  };
1391
- const valibotQrl = (qrl) => {
1392
- if (!__EXPERIMENTAL__.valibot) {
1393
- 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.');
1394
- }
1395
- if (isServer) {
1396
- return {
1397
- __brand: "valibot",
1398
- async validate(ev, inputData) {
1399
- const schema = await qrl.resolve().then((obj) => typeof obj === "function" ? obj(ev) : obj);
1400
- const data = inputData ?? await ev.parseBody();
1401
- const result = await v.safeParseAsync(schema, data);
1402
- if (result.success) {
1403
- return {
1404
- success: true,
1405
- data: result.output
1406
- };
1407
- } else {
1408
- if (isDev) {
1409
- console.error("ERROR: Valibot validation failed", result.issues);
1410
- }
1411
- return {
1412
- success: false,
1413
- status: 400,
1414
- error: {
1415
- formErrors: v.flatten(result.issues).root ?? [],
1416
- fieldErrors: flattenValibotIssues(result.issues)
1417
- }
1418
- };
1419
- }
1420
- }
1421
- };
1422
- }
1423
- return void 0;
1176
+ /** @internal */ var valibotQrl = (qrl) => {
1177
+ 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.");
1178
+ if (isServer) return {
1179
+ __brand: "valibot",
1180
+ async validate(ev, inputData) {
1181
+ const schema = await qrl.resolve().then((obj) => typeof obj === "function" ? obj(ev) : obj);
1182
+ const data = inputData ?? await ev.parseBody();
1183
+ const result = await v.safeParseAsync(schema, data);
1184
+ if (result.success) return {
1185
+ success: true,
1186
+ data: result.output
1187
+ };
1188
+ else {
1189
+ if (isDev) console.error("ERROR: Valibot validation failed", result.issues);
1190
+ return {
1191
+ success: false,
1192
+ status: 400,
1193
+ error: {
1194
+ formErrors: v.flatten(result.issues).root ?? [],
1195
+ fieldErrors: flattenValibotIssues(result.issues)
1196
+ }
1197
+ };
1198
+ }
1199
+ }
1200
+ };
1424
1201
  };
1425
- const valibot$ = /* @__PURE__ */ implicit$FirstArg(valibotQrl);
1426
- const flattenZodIssues = (issues) => {
1427
- issues = Array.isArray(issues) ? issues : [
1428
- issues
1429
- ];
1430
- return issues.reduce((acc, issue) => {
1431
- const isExpectingArray = "expected" in issue && issue.expected === "array";
1432
- const hasArrayType = issue.path.some((path) => typeof path === "number") || isExpectingArray;
1433
- if (hasArrayType) {
1434
- const keySuffix = "expected" in issue && issue.expected === "array" ? "[]" : "";
1435
- const key = issue.path.map((path) => typeof path === "number" ? "*" : path).join(".").replace(/\.\*/g, "[]") + keySuffix;
1436
- acc[key] = acc[key] || [];
1437
- if (Array.isArray(acc[key])) {
1438
- acc[key].push(issue.message);
1439
- }
1440
- return acc;
1441
- } else {
1442
- acc[issue.path.join(".")] = issue.message;
1443
- }
1444
- return acc;
1445
- }, {});
1202
+ /** @beta */ var valibot$ = /*#__PURE__*/ implicit$FirstArg(valibotQrl);
1203
+ var flattenZodIssues = (issues) => {
1204
+ issues = Array.isArray(issues) ? issues : [issues];
1205
+ return issues.reduce((acc, issue) => {
1206
+ const isExpectingArray = "expected" in issue && issue.expected === "array";
1207
+ if (issue.path.some((path) => typeof path === "number") || isExpectingArray) {
1208
+ const keySuffix = "expected" in issue && issue.expected === "array" ? "[]" : "";
1209
+ const key = issue.path.map((path) => typeof path === "number" ? "*" : path).join(".").replace(/\.\*/g, "[]") + keySuffix;
1210
+ acc[key] = acc[key] || [];
1211
+ if (Array.isArray(acc[key])) acc[key].push(issue.message);
1212
+ return acc;
1213
+ } else acc[issue.path.join(".")] = issue.message;
1214
+ return acc;
1215
+ }, {});
1446
1216
  };
1447
- const zodQrl = (qrl) => {
1448
- if (isServer) {
1449
- return {
1450
- __brand: "zod",
1451
- async validate(ev, inputData) {
1452
- const schema = await qrl.resolve().then((obj) => {
1453
- if (typeof obj === "function") {
1454
- obj = obj(z, ev);
1455
- }
1456
- if (obj instanceof z.Schema) {
1457
- return obj;
1458
- } else {
1459
- return z.object(obj);
1460
- }
1461
- });
1462
- const data = inputData ?? await ev.parseBody();
1463
- const result = await withLocale(ev.locale(), () => schema.safeParseAsync(data));
1464
- if (result.success) {
1465
- return result;
1466
- } else {
1467
- if (isDev) {
1468
- console.error("ERROR: Zod validation failed", result.error.issues);
1469
- }
1470
- return {
1471
- success: false,
1472
- status: 400,
1473
- error: {
1474
- formErrors: result.error.flatten().formErrors,
1475
- fieldErrors: flattenZodIssues(result.error.issues)
1476
- }
1477
- };
1478
- }
1479
- }
1480
- };
1481
- }
1482
- return void 0;
1217
+ /** @internal */ var zodQrl = (qrl) => {
1218
+ if (isServer) return {
1219
+ __brand: "zod",
1220
+ async validate(ev, inputData) {
1221
+ const schema = await qrl.resolve().then((obj) => {
1222
+ if (typeof obj === "function") obj = obj(z$1, ev);
1223
+ if (obj instanceof z$1.Schema) return obj;
1224
+ else return z$1.object(obj);
1225
+ });
1226
+ const data = inputData ?? await ev.parseBody();
1227
+ const result = await withLocale(ev.locale(), () => schema.safeParseAsync(data));
1228
+ if (result.success) return result;
1229
+ else {
1230
+ if (isDev) console.error("ERROR: Zod validation failed", result.error.issues);
1231
+ return {
1232
+ success: false,
1233
+ status: 400,
1234
+ error: {
1235
+ formErrors: result.error.flatten().formErrors,
1236
+ fieldErrors: flattenZodIssues(result.error.issues)
1237
+ }
1238
+ };
1239
+ }
1240
+ }
1241
+ };
1483
1242
  };
1484
- const zod$ = /* @__PURE__ */ implicit$FirstArg(zodQrl);
1485
- const getValidators = (rest, qrl) => {
1486
- let id;
1487
- let invalidate;
1488
- const validators = [];
1489
- if (rest.length === 1) {
1490
- const options = rest[0];
1491
- if (options && typeof options === "object") {
1492
- if ("validate" in options) {
1493
- validators.push(options);
1494
- } else {
1495
- id = options.id;
1496
- if (options.validation) {
1497
- validators.push(...options.validation);
1498
- }
1499
- if (options.invalidate) {
1500
- invalidate = options.invalidate.map((loader) => loader.__id);
1501
- }
1502
- }
1503
- }
1504
- } else if (rest.length > 1) {
1505
- validators.push(...rest.filter((v2) => !!v2));
1506
- }
1507
- if (typeof id === "string") {
1508
- if (isDev) {
1509
- if (!/^[\w/.-]+$/.test(id)) {
1510
- throw new Error(`Invalid id: ${id}, id can only contain [a-zA-Z0-9_.-]`);
1511
- }
1512
- }
1513
- id = `id_${id}`;
1514
- } else {
1515
- id = qrl.getHash();
1516
- }
1517
- return {
1518
- validators: validators.reverse(),
1519
- id,
1520
- invalidate
1521
- };
1243
+ /** @public */ var zod$ = /*#__PURE__*/ implicit$FirstArg(zodQrl);
1244
+ var getValidators = (rest, qrl) => {
1245
+ let id;
1246
+ let invalidate;
1247
+ const validators = [];
1248
+ if (rest.length === 1) {
1249
+ const options = rest[0];
1250
+ if (options && typeof options === "object") {
1251
+ if ("validate" in options) validators.push(options);
1252
+ else {
1253
+ id = options.id;
1254
+ if (options.validation) validators.push(...options.validation);
1255
+ if (options.invalidate) invalidate = options.invalidate.map((loader) => loader.__id);
1256
+ }
1257
+ }
1258
+ } else if (rest.length > 1) validators.push(...rest.filter((v) => !!v));
1259
+ if (typeof id === "string") {
1260
+ if (isDev) {
1261
+ if (!/^[\w/.-]+$/.test(id)) throw new Error(`Invalid id: ${id}, id can only contain [a-zA-Z0-9_.-]`);
1262
+ }
1263
+ id = `id_${id}`;
1264
+ } else id = qrl.getHash();
1265
+ return {
1266
+ validators: validators.reverse(),
1267
+ id,
1268
+ invalidate
1269
+ };
1522
1270
  };
1523
- const routeActionQrl = (actionQrl, ...rest) => {
1524
- const { id, validators, invalidate } = getValidators(rest, actionQrl);
1525
- function action() {
1526
- const loc = useLocation();
1527
- const currentAction = useAction();
1528
- const initialState = {
1529
- actionPath: `?${QACTION_KEY}=${id}`,
1530
- submitted: false,
1531
- isRunning: false,
1532
- status: void 0,
1533
- value: void 0,
1534
- formData: void 0
1535
- };
1536
- const state = useStore(() => {
1537
- const value = currentAction.value;
1538
- if (value && value?.id === id) {
1539
- const data = value.data;
1540
- if (data instanceof FormData) {
1541
- initialState.formData = data;
1542
- }
1543
- if (value.output) {
1544
- const { status, result } = value.output;
1545
- initialState.status = status;
1546
- initialState.value = result;
1547
- }
1548
- }
1549
- return initialState;
1550
- });
1551
- const submit = /* @__PURE__ */ inlinedQrl((input = {}) => {
1552
- const currentAction2 = _captures[0], id2 = _captures[1], loc2 = _captures[2], state2 = _captures[3];
1553
- if (isServer) {
1554
- throw new Error(`Actions can not be invoked within the server during SSR.
1271
+ /** @public */ var routeActionQrl = (actionQrl, ...rest) => {
1272
+ const { id, validators, invalidate } = getValidators(rest, actionQrl);
1273
+ function action() {
1274
+ const loc = useLocation();
1275
+ const currentAction = useAction();
1276
+ const initialState = {
1277
+ actionPath: `?${QACTION_KEY}=${id}`,
1278
+ submitted: false,
1279
+ isRunning: false,
1280
+ status: void 0,
1281
+ value: void 0,
1282
+ formData: void 0
1283
+ };
1284
+ const state = useStore(() => {
1285
+ const value = currentAction.value;
1286
+ if (value && value?.id === id) {
1287
+ const data = value.data;
1288
+ if (data instanceof FormData) initialState.formData = data;
1289
+ if (value.output) {
1290
+ const { status, result } = value.output;
1291
+ initialState.status = status;
1292
+ initialState.value = result;
1293
+ }
1294
+ }
1295
+ return initialState;
1296
+ });
1297
+ initialState.submit = /* @__PURE__ */ inlinedQrl((input = {}) => {
1298
+ const currentAction = _captures[0], id = _captures[1], loc = _captures[2], state = _captures[3];
1299
+ if (isServer) throw new Error(`Actions can not be invoked within the server during SSR.
1555
1300
  Action.run() can only be called on the browser, for example when a user clicks a button, or submits a form.`);
1556
- }
1557
- let data;
1558
- let form;
1559
- if (input instanceof SubmitEvent) {
1560
- form = input.target;
1561
- data = new FormData(form);
1562
- if ((input.submitter instanceof HTMLInputElement || input.submitter instanceof HTMLButtonElement) && input.submitter.name) {
1563
- if (input.submitter.name) {
1564
- data.append(input.submitter.name, input.submitter.value);
1565
- }
1566
- }
1567
- } else {
1568
- data = input;
1569
- }
1570
- return new Promise((resolve) => {
1571
- if (data instanceof FormData) {
1572
- state2.formData = data;
1573
- }
1574
- state2.submitted = true;
1575
- state2.isRunning = true;
1576
- loc2.isNavigating = true;
1577
- currentAction2.value = {
1578
- data,
1579
- id: id2,
1580
- resolve: noSerialize(resolve)
1581
- };
1582
- }).then((_rawProps) => {
1583
- state2.isRunning = false;
1584
- state2.status = _rawProps.status;
1585
- state2.value = _rawProps.result;
1586
- if (form) {
1587
- if (form.getAttribute("data-spa-reset") === "true") {
1588
- form.reset();
1589
- }
1590
- const detail = {
1591
- status: _rawProps.status,
1592
- value: _rawProps.result
1593
- };
1594
- form.dispatchEvent(new CustomEvent("submitcompleted", {
1595
- bubbles: false,
1596
- cancelable: false,
1597
- composed: false,
1598
- detail
1599
- }));
1600
- }
1601
- return {
1602
- status: _rawProps.status,
1603
- value: _rawProps.result
1604
- };
1605
- });
1606
- }, "routeActionQrl_action_submit_YuS5bpdQ360", [
1607
- currentAction,
1608
- id,
1609
- loc,
1610
- state
1611
- ]);
1612
- initialState.submit = submit;
1613
- return state;
1614
- }
1615
- action.__brand = "server_action";
1616
- action.__validators = validators;
1617
- action.__qrl = actionQrl;
1618
- action.__id = id;
1619
- action.__invalidate = invalidate;
1620
- Object.freeze(action);
1621
- return action;
1301
+ let data;
1302
+ let form;
1303
+ if (input instanceof SubmitEvent) {
1304
+ form = input.target;
1305
+ data = new FormData(form);
1306
+ if ((input.submitter instanceof HTMLInputElement || input.submitter instanceof HTMLButtonElement) && input.submitter.name) {
1307
+ if (input.submitter.name) data.append(input.submitter.name, input.submitter.value);
1308
+ }
1309
+ } else data = input;
1310
+ return new Promise((resolve) => {
1311
+ if (data instanceof FormData) state.formData = data;
1312
+ state.submitted = true;
1313
+ state.isRunning = true;
1314
+ loc.isNavigating = true;
1315
+ currentAction.value = {
1316
+ data,
1317
+ id,
1318
+ resolve: noSerialize(resolve)
1319
+ };
1320
+ }).then((_rawProps) => {
1321
+ state.isRunning = false;
1322
+ state.status = _rawProps.status;
1323
+ state.value = _rawProps.result;
1324
+ if (form) {
1325
+ if (form.getAttribute("data-spa-reset") === "true") form.reset();
1326
+ const detail = {
1327
+ status: _rawProps.status,
1328
+ value: _rawProps.result
1329
+ };
1330
+ form.dispatchEvent(new CustomEvent("submitcompleted", {
1331
+ bubbles: false,
1332
+ cancelable: false,
1333
+ composed: false,
1334
+ detail
1335
+ }));
1336
+ }
1337
+ return {
1338
+ status: _rawProps.status,
1339
+ value: _rawProps.result
1340
+ };
1341
+ });
1342
+ }, "routeActionQrl_action_submit_YuS5bpdQ360", [
1343
+ currentAction,
1344
+ id,
1345
+ loc,
1346
+ state
1347
+ ]);
1348
+ return state;
1349
+ }
1350
+ action.__brand = "server_action";
1351
+ action.__validators = validators;
1352
+ action.__qrl = actionQrl;
1353
+ action.__id = id;
1354
+ action.__invalidate = invalidate;
1355
+ Object.freeze(action);
1356
+ return action;
1622
1357
  };
1623
- const globalActionQrl = (actionQrl, ...rest) => {
1624
- const action = routeActionQrl(actionQrl, ...rest);
1625
- if (isServer) {
1626
- if (typeof globalThis._qwikActionsMap === "undefined") {
1627
- globalThis._qwikActionsMap = /* @__PURE__ */ new Map();
1628
- }
1629
- globalThis._qwikActionsMap.set(action.__id, action);
1630
- }
1631
- return action;
1358
+ /** @internal */ var globalActionQrl = (actionQrl, ...rest) => {
1359
+ const action = routeActionQrl(actionQrl, ...rest);
1360
+ if (isServer) {
1361
+ if (typeof globalThis._qwikActionsMap === "undefined") globalThis._qwikActionsMap = /* @__PURE__ */ new Map();
1362
+ globalThis._qwikActionsMap.set(action.__id, action);
1363
+ }
1364
+ return action;
1632
1365
  };
1633
- const routeAction$ = /* @__PURE__ */ implicit$FirstArg(routeActionQrl);
1634
- const globalAction$ = /* @__PURE__ */ implicit$FirstArg(globalActionQrl);
1635
- const deserializeStream = async function* (stream, abortSignal) {
1636
- const reader = stream.getReader();
1637
- try {
1638
- let buffer = "";
1639
- const decoder = new TextDecoder();
1640
- while (!abortSignal?.aborted) {
1641
- const result = await reader.read();
1642
- if (result.done) {
1643
- break;
1644
- }
1645
- buffer += decoder.decode(result.value, {
1646
- stream: true
1647
- });
1648
- const lines = buffer.split(/\n/);
1649
- buffer = lines.pop();
1650
- for (const line of lines) {
1651
- const deserializedData = await _deserialize(line);
1652
- yield deserializedData;
1653
- }
1654
- }
1655
- } finally {
1656
- reader.releaseLock();
1657
- }
1366
+ /**
1367
+ * Define a route action that handles form submissions or programmatic invocations.
1368
+ *
1369
+ * Actions run on the server when submitted from the client. The result is returned as an
1370
+ * `ActionStore` with `.value` for success data and `.error` for errors (including validation errors
1371
+ * from `zod$`/`valibot$` where `.fieldErrors` etc. are accessible directly on `.error`).
1372
+ *
1373
+ * By default, after an action completes, ALL current route loaders are invalidated on the client
1374
+ * and re-fetched as needed (so that the browser cache is correct). This can be controlled with:
1375
+ *
1376
+ * - `invalidate: [loader1, loader2]`: Only invalidate specific loaders. The client re-fetches them
1377
+ * individually. Other loaders keep their current data.
1378
+ * - `invalidate: []`: No loaders are invalidated. The action response only contains the action
1379
+ * result. Use this when the action doesn't affect any loader data.
1380
+ *
1381
+ * The `strictLoaders` Vite plugin option applies `invalidate: []` globally for all actions that
1382
+ * don't specify an explicit `invalidate` option.
1383
+ *
1384
+ * @public
1385
+ */ var routeAction$ = /*#__PURE__*/ implicit$FirstArg(routeActionQrl);
1386
+ /** @public */ var globalAction$ = /*#__PURE__*/ implicit$FirstArg(globalActionQrl);
1387
+ var deserializeStream = async function* (stream, abortSignal) {
1388
+ const reader = stream.getReader();
1389
+ try {
1390
+ let buffer = "";
1391
+ const decoder = new TextDecoder();
1392
+ while (!abortSignal?.aborted) {
1393
+ const result = await reader.read();
1394
+ if (result.done) break;
1395
+ buffer += decoder.decode(result.value, { stream: true });
1396
+ const lines = buffer.split(/\n/);
1397
+ buffer = lines.pop();
1398
+ for (const line of lines) yield await _deserialize(line);
1399
+ }
1400
+ } finally {
1401
+ reader.releaseLock();
1402
+ }
1658
1403
  };
1659
- const serverQrl = (qrl, options) => {
1660
- if (isServer) {
1661
- const captured = qrl.getCaptured();
1662
- if (captured && captured.length > 0 && !_getContextHostElement()) {
1663
- throw new Error("For security reasons, we cannot serialize QRLs that capture lexical scope.");
1664
- }
1665
- }
1666
- const method = options?.method?.toUpperCase?.() || "POST";
1667
- const headers = options?.headers || {};
1668
- const origin = options?.origin || "";
1669
- const fetchOptions = options?.fetchOptions || {};
1670
- return /* @__PURE__ */ inlinedQrl(async function(...args) {
1671
- const fetchOptions2 = _captures[0], headers2 = _captures[1], method2 = _captures[2], origin2 = _captures[3], qrl2 = _captures[4];
1672
- const abortSignal = args.length > 0 && args[0] instanceof AbortSignal ? args.shift() : void 0;
1673
- if (isServer) {
1674
- return qrl2.apply(getRequestEvent(this), args);
1675
- } else {
1676
- let filteredArgs = args.map((arg) => {
1677
- if (arg instanceof SubmitEvent && arg.target instanceof HTMLFormElement) {
1678
- return new FormData(arg.target);
1679
- } else if (arg instanceof Event) {
1680
- return null;
1681
- } else if (arg instanceof Node) {
1682
- return null;
1683
- }
1684
- return arg;
1685
- });
1686
- if (!filteredArgs.length) {
1687
- filteredArgs = void 0;
1688
- }
1689
- const qrlHash = qrl2.getHash();
1690
- let query = "";
1691
- const config = {
1692
- ...fetchOptions2,
1693
- method: method2,
1694
- headers: {
1695
- ...headers2,
1696
- "Content-Type": "application/qwik-json",
1697
- Accept: "application/json, application/qwik-json, text/qwik-json-stream, text/plain",
1698
- // Required so we don't call accidentally
1699
- "X-QRL": qrlHash
1700
- },
1701
- signal: abortSignal
1702
- };
1703
- const captured = qrl2.getCaptured();
1704
- let toSend = [
1705
- filteredArgs
1706
- ];
1707
- if (captured?.length) {
1708
- toSend = [
1709
- filteredArgs,
1710
- ...captured
1711
- ];
1712
- } else {
1713
- toSend = filteredArgs ? [
1714
- filteredArgs
1715
- ] : [];
1716
- }
1717
- const body = await _serialize(toSend);
1718
- if (method2 === "GET") {
1719
- query += `&${QDATA_KEY}=${encodeURIComponent(body)}`;
1720
- } else {
1721
- config.body = body;
1722
- }
1723
- const res = await fetch(`${origin2}?${QFN_KEY}=${qrlHash}${query}`, config);
1724
- const contentType = res.headers.get("Content-Type");
1725
- if (res.ok && contentType === "text/qwik-json-stream" && res.body) {
1726
- return (async function* () {
1727
- try {
1728
- for await (const result of deserializeStream(res.body, abortSignal)) {
1729
- yield result;
1730
- }
1731
- } finally {
1732
- if (!abortSignal?.aborted) {
1733
- await res.body.cancel();
1734
- }
1735
- }
1736
- })();
1737
- } else if (contentType === "application/qwik-json") {
1738
- const str = await res.text();
1739
- const obj = await _deserialize(str);
1740
- if (res.status >= 400) {
1741
- throw obj;
1742
- }
1743
- return obj;
1744
- } else if (contentType === "application/json") {
1745
- const obj = await res.json();
1746
- if (res.status >= 400) {
1747
- throw obj;
1748
- }
1749
- return obj;
1750
- } else if (contentType === "text/plain" || contentType === "text/html") {
1751
- const str = await res.text();
1752
- if (res.status >= 400) {
1753
- throw str;
1754
- }
1755
- return str;
1756
- }
1757
- }
1758
- }, "serverQrl_w03grD0Ag68", [
1759
- fetchOptions,
1760
- headers,
1761
- method,
1762
- origin,
1763
- qrl
1764
- ]);
1404
+ /** @internal */ var serverQrl = (qrl, options) => {
1405
+ if (isServer) {
1406
+ const captured = qrl.getCaptured();
1407
+ if (captured && captured.length > 0 && !_getContextHostElement()) throw new Error("For security reasons, we cannot serialize QRLs that capture lexical scope.");
1408
+ }
1409
+ const method = options?.method?.toUpperCase?.() || "POST";
1410
+ const headers = options?.headers || {};
1411
+ const origin = options?.origin || "";
1412
+ const fetchOptions = options?.fetchOptions || {};
1413
+ return /*#__PURE__*/ inlinedQrl(async function(...args) {
1414
+ const fetchOptions = _captures[0], headers = _captures[1], method = _captures[2], origin = _captures[3], qrl = _captures[4];
1415
+ const abortSignal = args.length > 0 && args[0] instanceof AbortSignal ? args.shift() : void 0;
1416
+ if (isServer) return qrl.apply(getRequestEvent(this), args);
1417
+ else {
1418
+ let filteredArgs = args.map((arg) => {
1419
+ if (arg instanceof SubmitEvent && arg.target instanceof HTMLFormElement) return new FormData(arg.target);
1420
+ else if (arg instanceof Event) return null;
1421
+ else if (arg instanceof Node) return null;
1422
+ return arg;
1423
+ });
1424
+ if (!filteredArgs.length) filteredArgs = void 0;
1425
+ const qrlHash = qrl.getHash();
1426
+ let query = "";
1427
+ const config = {
1428
+ ...fetchOptions,
1429
+ method,
1430
+ headers: {
1431
+ ...headers,
1432
+ "Content-Type": "application/qwik-json",
1433
+ Accept: "application/json, application/qwik-json, text/qwik-json-stream, text/plain",
1434
+ "X-QRL": qrlHash
1435
+ },
1436
+ signal: abortSignal
1437
+ };
1438
+ const captured = qrl.getCaptured();
1439
+ let toSend = [filteredArgs];
1440
+ if (captured?.length) toSend = [filteredArgs, ...captured];
1441
+ else toSend = filteredArgs ? [filteredArgs] : [];
1442
+ const body = await _serialize(toSend);
1443
+ if (method === "GET") query += `&${QDATA_KEY}=${encodeURIComponent(body)}`;
1444
+ else config.body = body;
1445
+ const res = await fetch(`${origin}?${QFN_KEY}=${qrlHash}${query}`, config);
1446
+ const contentType = res.headers.get("Content-Type");
1447
+ if (res.ok && contentType === "text/qwik-json-stream" && res.body) return async function* () {
1448
+ try {
1449
+ for await (const result of deserializeStream(res.body, abortSignal)) yield result;
1450
+ } finally {
1451
+ if (!abortSignal?.aborted) await res.body.cancel();
1452
+ }
1453
+ }();
1454
+ else if (contentType === "application/qwik-json") {
1455
+ const str = await res.text();
1456
+ const obj = await _deserialize(str);
1457
+ if (res.status >= 400) throw obj;
1458
+ return obj;
1459
+ } else if (contentType === "application/json") {
1460
+ const obj = await res.json();
1461
+ if (res.status >= 400) throw obj;
1462
+ return obj;
1463
+ } else if (contentType === "text/plain" || contentType === "text/html") {
1464
+ const str = await res.text();
1465
+ if (res.status >= 400) throw str;
1466
+ return str;
1467
+ }
1468
+ }
1469
+ }, "serverQrl_w03grD0Ag68", [
1470
+ fetchOptions,
1471
+ headers,
1472
+ method,
1473
+ origin,
1474
+ qrl
1475
+ ]);
1765
1476
  };
1766
- const server$ = /* @__PURE__ */ implicit$FirstArg(serverQrl);
1767
-
1768
- const ServiceWorkerRegister = (props) => /* @__PURE__ */ _jsxSorted("script", {
1769
- nonce: _wrapProp(props, "nonce")
1770
- }, {
1771
- type: "module",
1772
- dangerouslySetInnerHTML: swRegister
1477
+ /** @public */ var server$ = /*#__PURE__*/ implicit$FirstArg(serverQrl);
1478
+ /**
1479
+ * Loads the service workers that are defined in the routes. Any file named `service-worker.*` (all
1480
+ * JS extensions are allowed) will be picked up, bundled into a separate file, and registered as a
1481
+ * service worker.
1482
+ *
1483
+ * Qwik 1.14.0 and above now use `<link rel="modulepreload">` by default. If you didn't add custom
1484
+ * service-worker logic, you should remove your service-worker.ts file(s) for the
1485
+ * `ServiceWorkerRegister` Component to actually unregister the service-worker.js and delete its
1486
+ * related cache. Make sure to keep the `ServiceWorkerRegister` Component in your app (without any
1487
+ * service-worker.ts file) as long as you want to unregister the service-worker.js for your users.
1488
+ *
1489
+ * @public
1490
+ */ var ServiceWorkerRegister = (props) => /*#__PURE__*/ _jsxSorted("script", { nonce: _wrapProp(props, "nonce") }, {
1491
+ type: "module",
1492
+ dangerouslySetInnerHTML: swRegister
1773
1493
  }, null, 3, "1x_0");
1774
-
1775
- const _hf0 = (p0) => !p0.reloadDocument;
1776
- const _hf0_str = "!p0.reloadDocument";
1777
- const _hf1 = (p0) => p0.spaReset ? "true" : void 0;
1778
- const _hf1_str = 'p0.spaReset?"true":undefined';
1779
- const GetForm = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((_rawProps) => {
1780
- const rest = _restProps(_rawProps, [
1781
- "action",
1782
- "spaReset",
1783
- "reloadDocument",
1784
- "onSubmit$"
1785
- ]);
1786
- const nav = useNavigate();
1787
- return /* @__PURE__ */ _jsxSplit("form", {
1788
- action: "get",
1789
- "preventdefault:submit": _fnSignal(_hf0, [
1790
- _rawProps
1791
- ], _hf0_str),
1792
- "data-spa-reset": _fnSignal(_hf1, [
1793
- _rawProps
1794
- ], _hf1_str),
1795
- ..._getVarProps(rest),
1796
- ..._getConstProps(rest),
1797
- "q-e:submit": [
1798
- ...Array.isArray(_rawProps.onSubmit$) ? _rawProps.onSubmit$ : [
1799
- _rawProps.onSubmit$
1800
- ],
1801
- /* @__PURE__ */ inlinedQrl(async (_evt, form) => {
1802
- const nav2 = _captures[0];
1803
- const formData = new FormData(form);
1804
- const params = new URLSearchParams();
1805
- formData.forEach((value, key) => {
1806
- if (typeof value === "string") {
1807
- params.append(key, value);
1808
- }
1809
- });
1810
- await nav2("?" + params.toString(), {
1811
- type: "form",
1812
- forceReload: true
1813
- });
1814
- }, "GetForm_component_form_q_e_submit_r3dkP9d2cF8", [
1815
- nav
1816
- ]),
1817
- /* @__PURE__ */ inlinedQrl((_evt, form) => {
1818
- if (form.getAttribute("data-spa-reset") === "true") {
1819
- form.reset();
1820
- }
1821
- form.dispatchEvent(new CustomEvent("submitcompleted", {
1822
- bubbles: false,
1823
- cancelable: false,
1824
- composed: false,
1825
- detail: {
1826
- status: 200
1827
- }
1828
- }));
1829
- }, "GetForm_component_form_q_e_submit_1_cuYklZAOHrA")
1830
- ]
1831
- }, null, /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "Q4_0"), 0, "Q4_1");
1494
+ var _hf0 = (p0) => !p0.reloadDocument;
1495
+ var _hf0_str = "!p0.reloadDocument";
1496
+ var _hf1 = (p0) => p0.spaReset ? "true" : void 0;
1497
+ var _hf1_str = "p0.spaReset?\"true\":undefined";
1498
+ var GetForm = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((_rawProps) => {
1499
+ const rest = _restProps(_rawProps, [
1500
+ "action",
1501
+ "spaReset",
1502
+ "reloadDocument",
1503
+ "onSubmit$"
1504
+ ]);
1505
+ const nav = useNavigate();
1506
+ return /*#__PURE__*/ _jsxSplit("form", {
1507
+ action: "get",
1508
+ "preventdefault:submit": _fnSignal(_hf0, [_rawProps], _hf0_str),
1509
+ "data-spa-reset": _fnSignal(_hf1, [_rawProps], _hf1_str),
1510
+ ..._getVarProps(rest),
1511
+ ..._getConstProps(rest),
1512
+ "q-e:submit": [
1513
+ ...Array.isArray(_rawProps.onSubmit$) ? _rawProps.onSubmit$ : [_rawProps.onSubmit$],
1514
+ /*#__PURE__*/ inlinedQrl(async (_evt, form) => {
1515
+ const nav = _captures[0];
1516
+ const formData = new FormData(form);
1517
+ const params = new URLSearchParams();
1518
+ formData.forEach((value, key) => {
1519
+ if (typeof value === "string") params.append(key, value);
1520
+ });
1521
+ await nav("?" + params.toString(), {
1522
+ type: "form",
1523
+ forceReload: true
1524
+ });
1525
+ }, "GetForm_component_form_q_e_submit_r3dkP9d2cF8", [nav]),
1526
+ /*#__PURE__*/ inlinedQrl((_evt, form) => {
1527
+ if (form.getAttribute("data-spa-reset") === "true") form.reset();
1528
+ form.dispatchEvent(new CustomEvent("submitcompleted", {
1529
+ bubbles: false,
1530
+ cancelable: false,
1531
+ composed: false,
1532
+ detail: { status: 200 }
1533
+ }));
1534
+ }, "GetForm_component_form_q_e_submit_1_cuYklZAOHrA")
1535
+ ]
1536
+ }, null, /*#__PURE__*/ _jsxSorted(Slot, null, null, null, 3, "Q4_0"), 0, "Q4_1");
1832
1537
  }, "GetForm_component_2U5Z2Z8ryc0"));
1833
- const Form = ({ action, spaReset, reloadDocument, onSubmit$, ...rest }, key) => {
1834
- if (action) {
1835
- const isArrayApi = Array.isArray(onSubmit$);
1836
- if (isArrayApi) {
1837
- return _jsxSplit("form", {
1838
- ..._getVarProps(rest),
1839
- ..._getConstProps(rest),
1840
- action: _wrapProp(action, "actionPath"),
1841
- "preventdefault:submit": !reloadDocument,
1842
- "q-e:submit": [
1843
- ...onSubmit$,
1844
- // action.submit "submitcompleted" event for onSubmitCompleted$ events
1845
- !reloadDocument ? /* @__PURE__ */ inlinedQrl((evt) => {
1846
- const action2 = _captures[0];
1847
- if (!action2.submitted) {
1848
- return action2.submit(evt);
1849
- }
1850
- }, "Form_form_q_e_submit_6i0Jq5q8JFg", [
1851
- action
1852
- ]) : void 0
1853
- ],
1854
- ["data-spa-reset"]: spaReset ? "true" : void 0
1855
- }, {
1856
- method: "post"
1857
- }, null, 0, key);
1858
- }
1859
- return _jsxSplit("form", {
1860
- ..._getVarProps(rest),
1861
- ..._getConstProps(rest),
1862
- action: _wrapProp(action, "actionPath"),
1863
- "preventdefault:submit": !reloadDocument,
1864
- "q-e:submit": [
1865
- // Since v2, this fires before the action is executed so it can be prevented
1866
- onSubmit$,
1867
- // action.submit "submitcompleted" event for onSubmitCompleted$ events
1868
- !reloadDocument ? action.submit : void 0
1869
- ],
1870
- ["data-spa-reset"]: spaReset ? "true" : void 0
1871
- }, {
1872
- method: "post"
1873
- }, null, 0, key);
1874
- } else {
1875
- return /* @__PURE__ */ _jsxSplit(GetForm, {
1876
- spaReset,
1877
- reloadDocument,
1878
- onSubmit$,
1879
- ...rest
1880
- }, null, null, 0, key);
1881
- }
1538
+ /** @public */ var Form = ({ action, spaReset, reloadDocument, onSubmit$, ...rest }, key) => {
1539
+ if (action) {
1540
+ if (Array.isArray(onSubmit$)) return _jsxSplit("form", {
1541
+ ..._getVarProps(rest),
1542
+ ..._getConstProps(rest),
1543
+ action: _wrapProp(action, "actionPath"),
1544
+ "preventdefault:submit": !reloadDocument,
1545
+ "q-e:submit": [...onSubmit$, !reloadDocument ? /*#__PURE__*/ inlinedQrl((evt) => {
1546
+ const action = _captures[0];
1547
+ if (!action.submitted) return action.submit(evt);
1548
+ }, "Form_form_q_e_submit_6i0Jq5q8JFg", [action]) : void 0],
1549
+ ["data-spa-reset"]: spaReset ? "true" : void 0
1550
+ }, { method: "post" }, null, 0, key);
1551
+ return _jsxSplit("form", {
1552
+ ..._getVarProps(rest),
1553
+ ..._getConstProps(rest),
1554
+ action: _wrapProp(action, "actionPath"),
1555
+ "preventdefault:submit": !reloadDocument,
1556
+ "q-e:submit": [onSubmit$, !reloadDocument ? action.submit : void 0],
1557
+ ["data-spa-reset"]: spaReset ? "true" : void 0
1558
+ }, { method: "post" }, null, 0, key);
1559
+ } else return /*#__PURE__*/ _jsxSplit(GetForm, {
1560
+ spaReset,
1561
+ reloadDocument,
1562
+ onSubmit$,
1563
+ ...rest
1564
+ }, null, null, 0, key);
1882
1565
  };
1883
-
1884
- const untypedAppUrl = function appUrl(route, params, paramsPrefix = "") {
1885
- const path = route.split("/");
1886
- for (let i = 0; i < path.length; i++) {
1887
- const segment = path[i];
1888
- if (segment.startsWith("[") && segment.endsWith("]")) {
1889
- const isSpread = segment.startsWith("[...");
1890
- const key = segment.substring(segment.startsWith("[...") ? 4 : 1, segment.length - 1);
1891
- const value = params ? params[paramsPrefix + key] || params[key] : "";
1892
- path[i] = isSpread ? value : encodeURIComponent(value);
1893
- }
1894
- if (segment.startsWith("(") && segment.endsWith(")")) {
1895
- path.splice(i, 1);
1896
- }
1897
- }
1898
- let url = path.join("/");
1899
- let baseURL = "/";
1900
- if (baseURL) {
1901
- baseURL = ensureSlash(baseURL);
1902
- while (url.startsWith("/")) {
1903
- url = url.substring(1);
1904
- }
1905
- url = baseURL + url;
1906
- }
1907
- return url;
1566
+ /**
1567
+ * @beta
1568
+ * @experimental
1569
+ */ var untypedAppUrl = function appUrl(route, params, paramsPrefix = "") {
1570
+ const path = route.split("/");
1571
+ for (let i = 0; i < path.length; i++) {
1572
+ const segment = path[i];
1573
+ if (segment.startsWith("[") && segment.endsWith("]")) {
1574
+ const isSpread = segment.startsWith("[...");
1575
+ const key = segment.substring(segment.startsWith("[...") ? 4 : 1, segment.length - 1);
1576
+ const value = params ? params[paramsPrefix + key] || params[key] : "";
1577
+ path[i] = isSpread ? value : encodeURIComponent(value);
1578
+ }
1579
+ if (segment.startsWith("(") && segment.endsWith(")")) path.splice(i, 1);
1580
+ }
1581
+ let url = path.join("/");
1582
+ let baseURL = "/";
1583
+ if (baseURL) {
1584
+ baseURL = ensureSlash(baseURL);
1585
+ while (url.startsWith("/")) url = url.substring(1);
1586
+ url = baseURL + url;
1587
+ }
1588
+ return url;
1908
1589
  };
1909
- function omitProps(obj, keys) {
1910
- const omittedObj = {};
1911
- for (const key in obj) {
1912
- if (!key.startsWith("param:") && !keys.includes(key)) {
1913
- omittedObj[key] = obj[key];
1914
- }
1915
- }
1916
- return omittedObj;
1590
+ /**
1591
+ * Creates a new object from `obj` by omitting a set of `keys`.
1592
+ *
1593
+ * @beta
1594
+ * @experimental
1595
+ */ function omitProps(obj, keys) {
1596
+ const omittedObj = {};
1597
+ for (const key in obj) if (!key.startsWith("param:") && !keys.includes(key)) omittedObj[key] = obj[key];
1598
+ return omittedObj;
1917
1599
  }
1918
-
1919
- const createRenderer = (getOptions) => {
1920
- return (opts) => {
1921
- const { jsx, options } = getOptions(opts);
1922
- const isStatic = opts.serverData.renderMode === "static";
1923
- const renderOptions = isStatic ? {
1924
- ...options,
1925
- streaming: {
1926
- ...options.streaming,
1927
- outOfOrder: false
1928
- }
1929
- } : options;
1930
- return renderToStream(jsx, renderOptions);
1931
- };
1600
+ /**
1601
+ * Creates the `render()` function that is required by `createQwikRouter()`. It requires a function
1602
+ * that returns the `jsx` and `options` for the renderer.
1603
+ *
1604
+ * @example
1605
+ *
1606
+ * ```tsx
1607
+ * const renderer = createRenderer((opts) => {
1608
+ * if (opts.requestHeaders['x-hello'] === 'world') {
1609
+ * return { jsx: <Hello />, options: opts };
1610
+ * }
1611
+ * return { jsx: <Root />, options: {
1612
+ * ...opts,
1613
+ * serverData: {
1614
+ * ...opts.serverData,
1615
+ * documentHead: {
1616
+ * meta: [
1617
+ * { name: 'renderedAt', content: new Date().toISOString() },
1618
+ * ],
1619
+ * },
1620
+ * },
1621
+ * } };
1622
+ * });
1623
+ * ```
1624
+ *
1625
+ * @public
1626
+ */ var createRenderer = (getOptions) => {
1627
+ return (opts) => {
1628
+ const { jsx, options } = getOptions(opts);
1629
+ const renderOptions = opts.serverData.renderMode === "static" ? {
1630
+ ...options,
1631
+ streaming: {
1632
+ ...options.streaming,
1633
+ outOfOrder: false
1634
+ }
1635
+ } : options;
1636
+ return renderToStream(jsx, renderOptions);
1637
+ };
1932
1638
  };
1933
-
1934
- const DocumentHeadTags = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
1935
- let head = useDocumentHead();
1936
- if (props) {
1937
- head = {
1938
- ...head,
1939
- ...props
1940
- };
1941
- }
1942
- return /* @__PURE__ */ _jsxSorted(Fragment, null, null, [
1943
- head.title && /* @__PURE__ */ _jsxSorted("title", null, null, head.title, 1, "r5_0"),
1944
- head.meta.map((m) => /* @__PURE__ */ _jsxSplit("meta", {
1945
- ..._getVarProps(m)
1946
- }, _getConstProps(m), null, 0, "r5_1")),
1947
- head.links.map((l) => /* @__PURE__ */ _jsxSplit("link", {
1948
- ..._getVarProps(l)
1949
- }, _getConstProps(l), null, 0, "r5_2")),
1950
- head.styles.map((s) => {
1951
- const props2 = s.props || s;
1952
- return /* @__PURE__ */ createElement("style", {
1953
- ...props2,
1954
- dangerouslySetInnerHTML: s.style || props2.dangerouslySetInnerHTML,
1955
- key: s.key
1956
- });
1957
- }),
1958
- head.scripts.map((s) => {
1959
- const props2 = s.props || s;
1960
- return /* @__PURE__ */ createElement("script", {
1961
- ...props2,
1962
- dangerouslySetInnerHTML: s.script || props2.dangerouslySetInnerHTML,
1963
- key: s.key
1964
- });
1965
- })
1966
- ], 1, "r5_3");
1639
+ /**
1640
+ * This renders all the tags collected from `head`.
1641
+ *
1642
+ * You can partially override the head, for example if you want to change the title:
1643
+ *
1644
+ * ```tsx
1645
+ * import { DocumentHeadTags, useDocumentHead } from '@qwik.dev/router';
1646
+ *
1647
+ * export default component$(() => {
1648
+ * const head = useDocumentHead();
1649
+ * return <DocumentHeadTags title={`${head.title} - My App`} />;
1650
+ * });
1651
+ * ```
1652
+ *
1653
+ * You don't have to use this component, you can also do it yourself for full control. Just copy the
1654
+ * code from this component and modify it to your needs.
1655
+ *
1656
+ * Note that this component normally only runs once, during SSR. You can use Signals in your
1657
+ * `src/root.tsx` to make runtime changes to `<head>` if needed.
1658
+ *
1659
+ * @public
1660
+ */ var DocumentHeadTags = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props) => {
1661
+ let head = useDocumentHead();
1662
+ if (props) head = {
1663
+ ...head,
1664
+ ...props
1665
+ };
1666
+ return /*#__PURE__*/ _jsxSorted(Fragment, null, null, [
1667
+ head.title && /*#__PURE__*/ _jsxSorted("title", null, null, head.title, 1, "r5_0"),
1668
+ head.meta.map((m) => /*#__PURE__*/ _jsxSplit("meta", { ..._getVarProps(m) }, _getConstProps(m), null, 0, "r5_1")),
1669
+ head.links.map((l) => /*#__PURE__*/ _jsxSplit("link", { ..._getVarProps(l) }, _getConstProps(l), null, 0, "r5_2")),
1670
+ head.styles.map((s) => {
1671
+ const props = s.props || s;
1672
+ return /*#__PURE__*/ createElement("style", {
1673
+ ...props,
1674
+ dangerouslySetInnerHTML: s.style || props.dangerouslySetInnerHTML,
1675
+ key: s.key
1676
+ });
1677
+ }),
1678
+ head.scripts.map((s) => {
1679
+ const props = s.props || s;
1680
+ return /*#__PURE__*/ createElement("script", {
1681
+ ...props,
1682
+ dangerouslySetInnerHTML: s.script || props.dangerouslySetInnerHTML,
1683
+ key: s.key
1684
+ });
1685
+ })
1686
+ ], 1, "r5_3");
1967
1687
  }, "DocumentHeadTags_component_9CrWYOoCpgY"));
1968
-
1969
- export { DocumentHeadTags, ErrorBoundary, Form, Link, QWIK_CITY_SCROLLER, QWIK_ROUTER_SCROLLER, QwikCityMockProvider, QwikCityProvider, QwikRouterMockProvider, QwikRouterProvider, RouterOutlet, ServiceWorkerRegister, createRenderer, getRequestEvent, globalAction$, globalActionQrl, omitProps, routeAction$, routeActionQrl, server$, serverQrl, untypedAppUrl, useDocumentHead, useLocation, useNavigate, useQwikRouter, valibot$, valibotQrl, validator$, validatorQrl, zod$, zodQrl };
1688
+ export { DocumentHeadTags, ErrorBoundary, 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 };