@qwik.dev/router 2.0.0-beta.36 → 2.0.0-beta.37

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.
@@ -1,11 +1,14 @@
1
- import { componentQrl, inlinedQrl, useErrorBoundary, useOnWindow, _captures, _jsxSorted, Slot, useSignal, untrack, _qrlSync, useVisibleTaskQrl, _jsxSplit, _getConstProps, _getVarProps, isDev, eventQrl, isServer, useStylesQrl, useServerData, useStore, useContextProvider, useTaskQrl, getLocale, noSerialize, isBrowser, useContext, SkipRender, implicit$FirstArg, withLocale, _wrapProp, _restProps, _fnSignal, createElement } from '@qwik.dev/core';
1
+ import { componentQrl, inlinedQrl, useErrorBoundary, useOnWindow, _captures, _jsxSorted, Slot, isBrowser, useSignal, untrack, _qrlSync, useVisibleTaskQrl, _jsxSplit, _getConstProps, _getVarProps, isDev, eventQrl, isServer, useStylesQrl, useServerData, useStore, useContextProvider, useTaskQrl, noSerialize, getLocale, useContext, SkipRender, implicit$FirstArg, withLocale, _wrapProp, _restProps, _fnSignal, createElement } from '@qwik.dev/core';
2
2
  import { Fragment } from '@qwik.dev/core/jsx-runtime';
3
- import { g as getClientNavPath, s as shouldPreload, p as preloadRouteBundles, l as loadClientData, i as isSamePath, c as createLoaderSignal, a as createDocumentHead, b as loadRoute, r as resolveHead, C as CLIENT_DATA_CACHE, d as isSameOrigin, Q as Q_ROUTE, D as DEFAULT_LOADERS_SERIALIZATION_STRATEGY, t as toUrl, e as clientNavigate, f as toPath, h as QFN_KEY, j as QACTION_KEY, k as QDATA_KEY } from './chunks/routing.qwik.mjs';
4
- import { u as useNavigate, a as useLocation, b as useQwikRouterEnv, C as ContentContext, c as ContentInternalContext, D as DocumentHeadContext, H as HttpStatusContext, R as RouteLocationContext, d as RouteNavigateContext, e as RouteStateContext, f as RouteActionContext, g as RoutePreventNavigateContext, h as useAction, i as useDocumentHead } from './chunks/use-functions.qwik.mjs';
5
- export { j as useContent, k as useHttpStatus, l as usePreventNavigate$, m as usePreventNavigateQrl } from './chunks/use-functions.qwik.mjs';
6
3
  import * as qwikRouterConfig from '@qwik-router-config';
7
- import { _getContextContainer, SerializerSymbol, _UNINITIALIZED, _hasStoreEffects, forceStoreEffects, _waitUntilRendered, _getContextHostElement, _getContextEvent, _serialize, _deserialize, _resolveContextWithoutSequentialScope } from '@qwik.dev/core/internal';
8
- import { _asyncRequestStore } from '@qwik.dev/router/middleware/request-handler';
4
+ import { p } from '@qwik.dev/core/preloader';
5
+ import { e as ensureSlash } from './chunks/pathname.mjs';
6
+ import { f as fetchRouteLoaderData, Q as QACTION_KEY, e as ensureRouteLoaderSignals, s as setLoaderSignalValue, C as ContentContext, a as ContentInternalContext, D as DocumentHeadContext, H as HttpStatusContext, R as RouteLocationContext, b as RouteNavigateContext, c as RouteStateContext, d as RouteLoaderCtxContext, g as RouteActionContext, h as RoutePreventNavigateContext, u as updateRouteLoaderPaths, i as Q_ROUTE, j as getRequestEvent, k as QFN_KEY, l as QDATA_KEY } from './chunks/deepFreeze.qwik.mjs';
7
+ export { r as routeLoader$, m as routeLoaderQrl } from './chunks/deepFreeze.qwik.mjs';
8
+ import { l as loadRoute, g as getClientNavPath, s as shouldPreload, i as isSamePath, t as toPath, c as createDocumentHead, r as resolveHead, a as toUrl, b as isSameOrigin } from './chunks/head.qwik.mjs';
9
+ import { u as useNavigate, a as useLocation, b as useDocumentHead, c as useQwikRouterEnv, d as useAction } from './chunks/use-functions.qwik.mjs';
10
+ export { e as useContent, f as useHttpStatus, g as usePreventNavigate$, h as usePreventNavigateQrl } from './chunks/use-functions.qwik.mjs';
11
+ import { _deserialize, _hasStoreEffects, _getContextContainer, forceStoreEffects, createAsyncQrl, _waitUntilRendered, _getContextHostElement, _serialize } from '@qwik.dev/core/internal';
9
12
  import * as v from 'valibot';
10
13
  import * as z from 'zod';
11
14
  export { z } from 'zod';
@@ -26,10 +29,52 @@ const ErrorBoundary = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((p
26
29
  return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "bA_1");
27
30
  }, "ErrorBoundary_component_pOa6vjtC7ik"));
28
31
 
32
+ async function prefetchRoute(url, prefetchData, probability = 0.8, manifestHash, prefetchBundle = true) {
33
+ if (!isBrowser) {
34
+ return;
35
+ }
36
+ try {
37
+ const loadedRoute = await loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, url.pathname);
38
+ if (!loadedRoute) {
39
+ return;
40
+ }
41
+ if (prefetchBundle) {
42
+ let routeName = loadedRoute.$routeName$;
43
+ routeName = ensureSlash(routeName);
44
+ if (routeName.length > 1 && routeName.startsWith("/")) {
45
+ routeName = routeName.slice(1);
46
+ }
47
+ p(routeName, probability);
48
+ }
49
+ if (!prefetchData || !manifestHash) {
50
+ return;
51
+ }
52
+ if (loadedRoute.$loaders$?.length && loadedRoute.$loaderPaths$) {
53
+ const basePath = qwikRouterConfig.basePathname ?? "/";
54
+ for (const hash of loadedRoute.$loaders$) {
55
+ let loaderPath = loadedRoute.$loaderPaths$?.[hash];
56
+ if (!loaderPath) {
57
+ continue;
58
+ }
59
+ if (basePath !== "/" && !loaderPath.startsWith(basePath)) {
60
+ loaderPath = basePath + loaderPath.slice(1);
61
+ }
62
+ fetchRouteLoaderData(hash, loaderPath, manifestHash, {
63
+ pageUrl: url,
64
+ basePath
65
+ }).catch(() => {
66
+ });
67
+ }
68
+ }
69
+ } catch {
70
+ }
71
+ }
72
+
29
73
  const __vite_import_meta_env__ = {};
30
74
  const Link = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
31
75
  const nav = useNavigate();
32
76
  const loc = useLocation();
77
+ const head = useDocumentHead();
33
78
  const originalHref = props.href;
34
79
  const anchorRef = useSignal();
35
80
  const { onClick$, prefetch: prefetchProp, reload, replaceState, scroll, prefetchBundle: prefetchBundleProp = "visible", prefetchData: prefetchDataProp = prefetchProp === "js" ? "off" : "intent", ...linkProps } = props;
@@ -42,27 +87,18 @@ const Link = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) =>
42
87
  const shouldPrefetch = untrack(shouldPreload, clientNavPath, loc);
43
88
  const shouldPrefetchBundle = !!clientNavPath && prefetchBundleProp !== "off" && shouldPrefetch && !isDepratedPrefetchDisabled;
44
89
  const shouldPrefetchData = !!clientNavPath && prefetchDataProp !== "off" && shouldPrefetch && !isDepratedPrefetchDisabled;
45
- const handleBundlePrefetch = shouldPrefetchBundle ? /* @__PURE__ */ inlinedQrl((_, elm) => {
46
- if (navigator.connection?.saveData) {
47
- return;
48
- }
49
- if (elm && elm.href) {
50
- const url = new URL(elm.href);
51
- preloadRouteBundles(url.pathname);
52
- }
53
- }, "Link_component_handleBundlePrefetch_ZttUP0kLKj0") : null;
54
90
  const handleDataPrefetch = shouldPrefetchData ? /* @__PURE__ */ inlinedQrl((_, elm) => {
91
+ const head2 = _captures[0];
55
92
  if (navigator.connection?.saveData) {
56
93
  return;
57
94
  }
58
95
  if (elm && elm.href) {
59
96
  const url = new URL(elm.href);
60
- loadClientData(url, {
61
- preloadRouteBundles: false,
62
- isPrefetch: true
63
- });
97
+ prefetchRoute(url, true, 0.8, head2.manifestHash, false);
64
98
  }
65
- }, "Link_component_handleDataPrefetch_lcd4O9LHbbA") : null;
99
+ }, "Link_component_handleDataPrefetch_lcd4O9LHbbA", [
100
+ head
101
+ ]) : null;
66
102
  const preventDefault = clientNavPath ? _qrlSync((event) => {
67
103
  if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) {
68
104
  event.preventDefault();
@@ -104,10 +140,10 @@ const Link = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) =>
104
140
  ]) : null;
105
141
  const handlePreload = /* @__PURE__ */ inlinedQrl((_, elm) => {
106
142
  const url = new URL(elm.href);
107
- preloadRouteBundles(url.pathname, 1);
143
+ prefetchRoute(url, false, 1);
108
144
  }, "Link_component_handlePreload_AAemwtuBjsE");
109
145
  useVisibleTaskQrl(/* @__PURE__ */ inlinedQrl(({ track }) => {
110
- const anchorRef2 = _captures[0], handleBundlePrefetch2 = _captures[1], handleDataPrefetch2 = _captures[2], linkProps2 = _captures[3], loc2 = _captures[4], prefetchBundleProp2 = _captures[5], prefetchDataProp2 = _captures[6], prefetchProp2 = _captures[7];
146
+ const anchorRef2 = _captures[0], handleDataPrefetch2 = _captures[1], head2 = _captures[2], linkProps2 = _captures[3], loc2 = _captures[4], prefetchBundleProp2 = _captures[5], prefetchDataProp2 = _captures[6], prefetchProp2 = _captures[7], shouldPrefetchBundle2 = _captures[8];
111
147
  track(() => loc2.url.pathname);
112
148
  const handler = linkProps2.onQVisible$;
113
149
  if (handler) {
@@ -119,25 +155,27 @@ const Link = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) =>
119
155
  }
120
156
  }
121
157
  const isProdOrTest = !isDev || __vite_import_meta_env__?.TEST;
122
- if (isProdOrTest && anchorRef2.value) {
123
- if (prefetchBundleProp2 === "visible" || // deprecated prop below, remove in favor of prefetchBundle
124
- prefetchProp2 === "js" || prefetchProp2 === true) {
125
- handleBundlePrefetch2?.(null, anchorRef2.value);
126
- }
127
- if (prefetchDataProp2 === "visible" || // deprecated prop below, remove in favor of prefetchData
128
- prefetchProp2 === true) {
129
- handleDataPrefetch2?.(null, anchorRef2.value);
158
+ if (isProdOrTest && anchorRef2.value?.href && !navigator.connection?.saveData) {
159
+ if (handleDataPrefetch2 && (prefetchDataProp2 === "visible" || // deprecated prop below, remove in favor of prefetchData
160
+ prefetchProp2 === true)) {
161
+ const url = new URL(anchorRef2.value.href);
162
+ prefetchRoute(url, true, 0.8, head2.manifestHash, shouldPrefetchBundle2);
163
+ } else if (shouldPrefetchBundle2 && (prefetchBundleProp2 === "visible" || // deprecated prop below, remove in favor of prefetchBundle
164
+ prefetchProp2 === "js" || prefetchProp2 === true)) {
165
+ const url = new URL(anchorRef2.value.href);
166
+ prefetchRoute(url, false, 0.8);
130
167
  }
131
168
  }
132
169
  }, "Link_component_useVisibleTask_xKeuRmnoNSA", [
133
170
  anchorRef,
134
- handleBundlePrefetch,
135
171
  handleDataPrefetch,
172
+ head,
136
173
  linkProps,
137
174
  loc,
138
175
  prefetchBundleProp,
139
176
  prefetchDataProp,
140
- prefetchProp
177
+ prefetchProp,
178
+ shouldPrefetchBundle
141
179
  ]));
142
180
  return /* @__PURE__ */ _jsxSplit("a", {
143
181
  ref: anchorRef,
@@ -172,6 +210,31 @@ const Link = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) =>
172
210
  }, /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "jO_0"), 0, "jO_1");
173
211
  }, "Link_component_VPmar9tb3t4"));
174
212
 
213
+ const newScrollState = () => {
214
+ return {
215
+ x: 0,
216
+ y: 0,
217
+ w: 0,
218
+ h: 0
219
+ };
220
+ };
221
+ const clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
222
+ if (navType !== "popstate") {
223
+ const samePath = isSamePath(fromURL, toURL);
224
+ const sameHash = fromURL.hash === toURL.hash;
225
+ if (!samePath || !sameHash) {
226
+ const newState = {
227
+ _qRouterScroll: newScrollState()
228
+ };
229
+ if (replaceState) {
230
+ win.history.replaceState(newState, "", toPath(toURL));
231
+ } else {
232
+ win.history.pushState(newState, "", toPath(toURL));
233
+ }
234
+ }
235
+ }
236
+ };
237
+
175
238
  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}}}";
176
239
 
177
240
  function callRestoreScrollOnDocument() {
@@ -357,25 +420,67 @@ const spaInit = eventQrl(/* @__PURE__ */ inlinedQrl((_, el) => {
357
420
  }, 200);
358
421
  };
359
422
  window._qRouterScrollEnabled = true;
360
- setTimeout(() => {
361
- window.addEventListener("popstate", window._qRouterInitPopstate);
362
- window.addEventListener("scroll", window._qRouterInitScroll, {
423
+ window.addEventListener("popstate", window._qRouterInitPopstate);
424
+ window.addEventListener("scroll", window._qRouterInitScroll, {
425
+ passive: true
426
+ });
427
+ document.addEventListener("click", window._qRouterInitAnchors);
428
+ if (!window.navigation) {
429
+ document.addEventListener("visibilitychange", window._qRouterInitVisibility, {
363
430
  passive: true
364
431
  });
365
- document.addEventListener("click", window._qRouterInitAnchors);
366
- if (!window.navigation) {
367
- document.addEventListener("visibilitychange", window._qRouterInitVisibility, {
368
- passive: true
369
- });
370
- }
371
- }, 0);
432
+ }
372
433
  }
373
434
  }, "spa_init_event_igI1pUsax0E"));
374
435
 
375
- const startViewTransition = (params) => {
376
- if (!params.update) {
377
- return;
436
+ async function submitAction(action, routePath) {
437
+ const pathBase = ensureSlash(routePath);
438
+ const url = `${pathBase}?${QACTION_KEY}=${encodeURIComponent(action.id)}`;
439
+ const actionData = action.data;
440
+ action.data = void 0;
441
+ let fetchOptions;
442
+ if (actionData instanceof FormData) {
443
+ fetchOptions = {
444
+ method: "POST",
445
+ body: actionData,
446
+ headers: {
447
+ Accept: "application/json"
448
+ }
449
+ };
450
+ } else {
451
+ fetchOptions = {
452
+ method: "POST",
453
+ body: JSON.stringify(actionData),
454
+ headers: {
455
+ "Content-Type": "application/json; charset=UTF-8",
456
+ Accept: "application/json"
457
+ }
458
+ };
459
+ }
460
+ const response = await fetch(url, fetchOptions);
461
+ if (response.redirected) {
462
+ const redirectedURL = new URL(response.url);
463
+ if (redirectedURL.origin !== location.origin) {
464
+ location.href = redirectedURL.href;
465
+ return void 0;
466
+ }
467
+ location.href = redirectedURL.href;
468
+ return void 0;
378
469
  }
470
+ if ((response.headers.get("content-type") || "").includes("json")) {
471
+ const text = await response.text();
472
+ const data = _deserialize(text);
473
+ return {
474
+ status: response.status,
475
+ result: data?.result,
476
+ redirect: data?.redirect,
477
+ loaderHashes: data?.loaderHashes
478
+ };
479
+ }
480
+ return void 0;
481
+ }
482
+
483
+ const startViewTransition = (params) => {
379
484
  if ("startViewTransition" in document) {
380
485
  let transition;
381
486
  try {
@@ -387,9 +492,14 @@ const startViewTransition = (params) => {
387
492
  detail: transition
388
493
  });
389
494
  document.dispatchEvent(event);
390
- return transition;
495
+ return {
496
+ ready: transition.ready,
497
+ transition
498
+ };
391
499
  } else {
392
- params.update?.();
500
+ return {
501
+ ready: params.update()
502
+ };
393
503
  }
394
504
  };
395
505
 
@@ -399,6 +509,196 @@ const preventNav = {};
399
509
  const internalState = {
400
510
  navCount: 0
401
511
  };
512
+ const getScroller = () => {
513
+ let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
514
+ if (!scroller) {
515
+ scroller = document.getElementById(QWIK_CITY_SCROLLER);
516
+ if (scroller && isDev) {
517
+ console.warn(`Please update your scroller ID to "${QWIK_ROUTER_SCROLLER}" as "${QWIK_CITY_SCROLLER}" is deprecated and will be removed in V3`);
518
+ }
519
+ }
520
+ return scroller ?? document.documentElement;
521
+ };
522
+ const useQwikMockRouter = (props) => {
523
+ const urlEnv = props.url ?? "http://localhost/";
524
+ const url = new URL(urlEnv);
525
+ const routeLocation = useStore({
526
+ url,
527
+ params: props.params ?? {},
528
+ isNavigating: false,
529
+ prevUrl: void 0
530
+ }, {
531
+ deep: false
532
+ });
533
+ const loadersData = props.loaders?.reduce((acc, { loader, data }) => {
534
+ acc[loader.__id] = data;
535
+ return acc;
536
+ }, {});
537
+ const loadersState = useStore({}, {
538
+ deep: false
539
+ });
540
+ for (const [loaderId, data] of Object.entries(loadersData ?? {})) {
541
+ loadersState[loaderId] ||= createAsyncQrl(/* @__PURE__ */ inlinedQrl(async () => {
542
+ const data2 = _captures[0];
543
+ return data2;
544
+ }, "useQwikMockRouter_createAsync_clbxpuXqpEU", [
545
+ data
546
+ ]), {
547
+ initial: data
548
+ });
549
+ }
550
+ const goto = props.goto ?? /* @__PURE__ */ inlinedQrl(async () => {
551
+ console.warn("QwikRouterMockProvider: goto not provided");
552
+ }, "useQwikMockRouter_goto_aViHFxQ1a3s");
553
+ const documentHead = useStore(createDocumentHead, {
554
+ deep: false
555
+ });
556
+ const content = useStore({
557
+ headings: void 0,
558
+ menu: void 0
559
+ }, {
560
+ deep: false
561
+ });
562
+ const contentInternal = useSignal();
563
+ const actionState = useSignal();
564
+ const httpStatus = useSignal({
565
+ status: 200,
566
+ message: ""
567
+ });
568
+ useContextProvider(ContentContext, content);
569
+ useContextProvider(ContentInternalContext, contentInternal);
570
+ useContextProvider(DocumentHeadContext, documentHead);
571
+ useContextProvider(HttpStatusContext, httpStatus);
572
+ useContextProvider(RouteLocationContext, routeLocation);
573
+ useContextProvider(RouteNavigateContext, goto);
574
+ useContextProvider(RouteStateContext, loadersState);
575
+ useContextProvider(RouteActionContext, actionState);
576
+ const actionsMocks = props.actions?.reduce((acc, { action, handler }) => {
577
+ acc[action.__id] = handler;
578
+ return acc;
579
+ }, {});
580
+ useTaskQrl(/* @__PURE__ */ inlinedQrl(async ({ track }) => {
581
+ const actionState2 = _captures[0], actionsMocks2 = _captures[1];
582
+ const action = track(actionState2);
583
+ if (!action?.resolve) {
584
+ return;
585
+ }
586
+ const mock = actionsMocks2?.[action.id];
587
+ if (mock) {
588
+ const actionResult = await mock(action.data);
589
+ action.resolve(actionResult);
590
+ }
591
+ }, "useQwikMockRouter_useTask_tXTLR4tzCy0", [
592
+ actionState,
593
+ actionsMocks
594
+ ]));
595
+ };
596
+ const QwikRouterMockProvider = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
597
+ useQwikMockRouter(props);
598
+ return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "5y_1");
599
+ }, "QwikRouterMockProvider_component_IN4dVpT0x74"));
600
+ const QwikCityMockProvider = QwikRouterMockProvider;
601
+ function initializeSPA(goto, scroller) {
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, {
609
+ type: "popstate"
610
+ });
611
+ });
612
+ window.removeEventListener("popstate", window._qRouterInitPopstate);
613
+ window._qRouterInitPopstate = void 0;
614
+ if (!window._qRouterHistoryPatch) {
615
+ window._qRouterHistoryPatch = true;
616
+ const pushState = history.pushState;
617
+ const replaceState = history.replaceState;
618
+ const prepareState = (state) => {
619
+ if (state === null || typeof state === "undefined") {
620
+ state = {};
621
+ } else if (state?.constructor !== Object) {
622
+ state = {
623
+ _data: state
624
+ };
625
+ if (isDev) {
626
+ 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`");
627
+ }
628
+ }
629
+ state._qRouterScroll = state._qRouterScroll || currentScrollState(scroller);
630
+ return state;
631
+ };
632
+ history.pushState = (state, title, url) => {
633
+ state = prepareState(state);
634
+ return pushState.call(history, state, title, url);
635
+ };
636
+ history.replaceState = (state, title, url) => {
637
+ state = prepareState(state);
638
+ return replaceState.call(history, state, title, url);
639
+ };
640
+ }
641
+ document.addEventListener("click", (event) => {
642
+ if (event.defaultPrevented) {
643
+ return;
644
+ }
645
+ const target = event.target.closest("a[href]");
646
+ if (target && !target.hasAttribute("preventdefault:click")) {
647
+ const href = target.getAttribute("href");
648
+ const prev = new URL(location.href);
649
+ const dest = new URL(href, prev);
650
+ if (isSameOrigin(dest, prev) && isSamePath(dest, prev)) {
651
+ event.preventDefault();
652
+ if (!dest.hash && !dest.href.endsWith("#")) {
653
+ if (dest.href !== prev.href) {
654
+ history.pushState(null, "", dest);
655
+ }
656
+ window._qRouterScrollEnabled = false;
657
+ clearTimeout(window._qRouterScrollDebounce);
658
+ saveScrollHistory({
659
+ ...currentScrollState(scroller),
660
+ x: 0,
661
+ y: 0
662
+ });
663
+ location.reload();
664
+ return;
665
+ }
666
+ goto(target.getAttribute("href"));
667
+ }
668
+ }
669
+ });
670
+ document.removeEventListener("click", window._qRouterInitAnchors);
671
+ window._qRouterInitAnchors = void 0;
672
+ if (!window.navigation) {
673
+ document.addEventListener("visibilitychange", () => {
674
+ if (window._qRouterScrollEnabled && document.visibilityState === "hidden") {
675
+ const scrollState = currentScrollState(scroller);
676
+ saveScrollHistory(scrollState);
677
+ }
678
+ }, {
679
+ passive: true
680
+ });
681
+ document.removeEventListener("visibilitychange", window._qRouterInitVisibility);
682
+ window._qRouterInitVisibility = void 0;
683
+ }
684
+ window.addEventListener("scroll", () => {
685
+ if (!window._qRouterScrollEnabled) {
686
+ return;
687
+ }
688
+ clearTimeout(window._qRouterScrollDebounce);
689
+ window._qRouterScrollDebounce = setTimeout(() => {
690
+ const scrollState = currentScrollState(scroller);
691
+ saveScrollHistory(scrollState);
692
+ window._qRouterScrollDebounce = void 0;
693
+ }, 200);
694
+ }, {
695
+ passive: true
696
+ });
697
+ removeEventListener("scroll", window._qRouterInitScroll);
698
+ window._qRouterInitScroll = void 0;
699
+ spaInit.resolve();
700
+ }
701
+ }
402
702
  const useQwikRouter = (props) => {
403
703
  if (!isServer) {
404
704
  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.");
@@ -425,27 +725,19 @@ const useQwikRouter = (props) => {
425
725
  deep: false
426
726
  });
427
727
  const navResolver = {};
428
- const container = _getContextContainer();
429
- const getSerializationStrategy = (loaderId) => {
430
- return env.response.loadersSerializationStrategy.get(loaderId) || DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
431
- };
432
- const loadersObject = {};
728
+ const routeLoaderCtx = useStore(env.routeLoaderCtx);
433
729
  const loaderState = {};
434
- for (const [key, value] of Object.entries(env.response.loaders)) {
435
- loadersObject[key] = value;
436
- loaderState[key] = createLoaderSignal(loadersObject, key, url, getSerializationStrategy(key), container);
437
- }
438
- loadersObject[SerializerSymbol] = (obj) => {
439
- const loadersSerializationObject = {};
440
- for (const [k, v] of Object.entries(obj)) {
441
- loadersSerializationObject[k] = getSerializationStrategy(k) === "always" ? v : _UNINITIALIZED;
730
+ const contentModulesForInit = env.loadedRoute.$mods$;
731
+ const loaders = ensureRouteLoaderSignals(contentModulesForInit, loaderState, routeLoaderCtx);
732
+ for (const loader of loaders) {
733
+ if (loader.__id in env.loaderValues) {
734
+ const value = env.loaderValues[loader.__id];
735
+ setLoaderSignalValue(loaderState[loader.__id], value);
442
736
  }
443
- return loadersSerializationObject;
444
- };
737
+ }
445
738
  const routeInternal = useSignal({
446
739
  type: "initial",
447
- dest: url,
448
- scroll: true
740
+ dest: url
449
741
  });
450
742
  const documentHead = useStore(() => createDocumentHead(serverHead, manifestHash));
451
743
  const content = useStore({
@@ -453,12 +745,13 @@ const useQwikRouter = (props) => {
453
745
  menu: void 0
454
746
  });
455
747
  const contentInternal = useSignal();
748
+ const navContext = useSignal();
456
749
  const httpStatus = useSignal({
457
750
  status: env.response.status,
458
751
  message: env.loadedRoute.$notFound$ ? "Not Found" : env.response.statusMessage ?? ""
459
752
  });
460
753
  const currentActionId = env.response.action;
461
- const currentAction = currentActionId ? env.response.loaders[currentActionId] : void 0;
754
+ const currentAction = currentActionId ? env.response.actionResult : void 0;
462
755
  const actionState = useSignal(currentAction ? {
463
756
  id: currentActionId,
464
757
  data: env.response.formData,
@@ -467,6 +760,11 @@ const useQwikRouter = (props) => {
467
760
  status: env.response.status
468
761
  }
469
762
  } : void 0);
763
+ const actionDataSignal = useSignal(currentActionId ? {
764
+ action: currentActionId,
765
+ actionResult: currentAction,
766
+ status: env.response.status
767
+ } : void 0);
470
768
  const registerPreventNav = /* @__PURE__ */ inlinedQrl((fn$) => {
471
769
  if (!isBrowser) {
472
770
  return;
@@ -497,22 +795,11 @@ const useQwikRouter = (props) => {
497
795
  }
498
796
  };
499
797
  }, "useQwikRouter_registerPreventNav_69B0DK0eZJc");
500
- const getScroller = /* @__PURE__ */ inlinedQrl(() => {
501
- let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
502
- if (!scroller) {
503
- scroller = document.getElementById(QWIK_CITY_SCROLLER);
504
- if (scroller && isDev) {
505
- console.warn(`Please update your scroller ID to "${QWIK_ROUTER_SCROLLER}" as "${QWIK_CITY_SCROLLER}" is deprecated and will be removed in V3`);
506
- }
507
- }
508
- return scroller ?? document.documentElement;
509
- }, "useQwikRouter_getScroller_0UhDFwlxeFQ");
510
798
  const goto = /* @__PURE__ */ inlinedQrl(async (path, opt) => {
511
- const actionState2 = _captures[0], getScroller2 = _captures[1], navResolver2 = _captures[2], routeInternal2 = _captures[3], routeLocation2 = _captures[4];
799
+ const actionState2 = _captures[0], manifestHash2 = _captures[1], navResolver2 = _captures[2], routeInternal2 = _captures[3], routeLocation2 = _captures[4];
512
800
  const { type = "link", forceReload = path === void 0, replaceState = false, scroll = true } = typeof opt === "object" ? opt : {
513
801
  forceReload: opt
514
802
  };
515
- internalState.navCount++;
516
803
  if (isBrowser && type === "link" && routeInternal2.value.type === "initial") {
517
804
  const url2 = new URL(window.location.href);
518
805
  routeInternal2.value.dest = url2;
@@ -520,6 +807,11 @@ const useQwikRouter = (props) => {
520
807
  }
521
808
  const lastDest = routeInternal2.value.dest;
522
809
  const dest = path === void 0 ? lastDest : typeof path === "number" ? path : toUrl(path, routeLocation2.url);
810
+ if (navResolver2.p && !forceReload && typeof dest !== "number" && isSamePath(dest, lastDest) && dest.href === lastDest.href) {
811
+ return navResolver2.p;
812
+ }
813
+ internalState.navCount++;
814
+ internalState.currentTransition?.skipTransition();
523
815
  if (preventNav.$cbs$ && (forceReload || typeof dest === "number" || !isSamePath(dest, lastDest) || !isSameOrigin(dest, lastDest))) {
524
816
  const ourNavId = internalState.navCount;
525
817
  const prevents = await Promise.all([
@@ -549,7 +841,7 @@ const useQwikRouter = (props) => {
549
841
  if (type === "link" && dest.href !== location.href) {
550
842
  history.pushState(null, "", dest);
551
843
  }
552
- const scroller = await getScroller2();
844
+ const scroller = getScroller();
553
845
  restoreScroll(type, dest, new URL(location.href), scroller, getScrollHistory());
554
846
  if (type === "popstate") {
555
847
  window._qRouterScrollEnabled = true;
@@ -564,7 +856,7 @@ const useQwikRouter = (props) => {
564
856
  }
565
857
  let historyUpdated = false;
566
858
  if (isBrowser && type === "link" && !forceReload) {
567
- const scroller = await getScroller2();
859
+ const scroller = getScroller();
568
860
  window._qRouterScrollEnabled = false;
569
861
  clearTimeout(window._qRouterScrollDebounce);
570
862
  const scrollState = currentScrollState(scroller);
@@ -581,17 +873,21 @@ const useQwikRouter = (props) => {
581
873
  historyUpdated
582
874
  };
583
875
  if (isBrowser) {
584
- loadClientData(dest);
585
- loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, dest.pathname);
876
+ prefetchRoute(dest, true, 0.8, manifestHash2);
586
877
  }
587
878
  actionState2.value = void 0;
588
879
  routeLocation2.isNavigating = true;
589
- return new Promise((resolve) => {
590
- navResolver2.r = resolve;
880
+ navResolver2.p = new Promise((resolve) => {
881
+ navResolver2.r = () => {
882
+ navResolver2.r = void 0;
883
+ navResolver2.p = void 0;
884
+ resolve();
885
+ };
591
886
  });
887
+ return navResolver2.p;
592
888
  }, "useQwikRouter_goto_8j8Vrz2yUIM", [
593
889
  actionState,
594
- getScroller,
890
+ manifestHash,
595
891
  navResolver,
596
892
  routeInternal,
597
893
  routeLocation
@@ -603,25 +899,29 @@ const useQwikRouter = (props) => {
603
899
  useContextProvider(RouteLocationContext, routeLocation);
604
900
  useContextProvider(RouteNavigateContext, goto);
605
901
  useContextProvider(RouteStateContext, loaderState);
902
+ useContextProvider(RouteLoaderCtxContext, routeLoaderCtx);
606
903
  useContextProvider(RouteActionContext, actionState);
607
904
  useContextProvider(RoutePreventNavigateContext, registerPreventNav);
608
905
  useTaskQrl(
609
906
  /* @__PURE__ */ inlinedQrl(async ({ track }) => {
610
- const actionState2 = _captures[0], content2 = _captures[1], contentInternal2 = _captures[2], documentHead2 = _captures[3], env2 = _captures[4], getScroller2 = _captures[5], goto2 = _captures[6], httpStatus2 = _captures[7], loaderState2 = _captures[8], loadersObject2 = _captures[9], navResolver2 = _captures[10], props2 = _captures[11], routeInternal2 = _captures[12], routeLocation2 = _captures[13], routeLocationTarget2 = _captures[14], serverHead2 = _captures[15];
611
- const container2 = _getContextContainer();
907
+ 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];
612
908
  const navigation = track(routeInternal2);
613
909
  const action = track(actionState2);
614
- const locale = getLocale("");
615
910
  const prevUrl = routeLocation2.url;
616
911
  const navType = action ? "form" : navigation.type;
617
912
  const replaceState = navigation.replaceState;
913
+ const navCountBefore = internalState.navCount;
618
914
  let trackUrl;
619
- let clientPageData;
915
+ let endpointResponse;
916
+ let actionData;
917
+ let actionLoaderHashes;
918
+ let shouldInvalidateActionLoaders = false;
620
919
  let loadedRoute;
621
920
  if (isServer) {
622
921
  trackUrl = new URL(navigation.dest, routeLocation2.url);
623
922
  loadedRoute = env2.loadedRoute;
624
- clientPageData = env2.response;
923
+ endpointResponse = env2.response;
924
+ actionData = endpointResponse;
625
925
  } else {
626
926
  trackUrl = new URL(navigation.dest, location);
627
927
  if (trackUrl.pathname.endsWith("/")) {
@@ -629,52 +929,90 @@ const useQwikRouter = (props) => {
629
929
  trackUrl.pathname = trackUrl.pathname.slice(0, -1);
630
930
  }
631
931
  } else if (!globalThis.__NO_TRAILING_SLASH__) {
632
- trackUrl.pathname += "/";
633
- }
634
- let loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, trackUrl.pathname);
635
- const pageData = clientPageData = await loadClientData(trackUrl, {
636
- action,
637
- clearCache: true
638
- });
639
- if (!pageData) {
640
- routeInternal2.untrackedValue = {
641
- type: navType,
642
- dest: trackUrl
643
- };
644
- return;
645
- }
646
- const newHref = pageData.href;
647
- const newURL = new URL(newHref, trackUrl);
648
- if (!isSamePath(newURL, trackUrl)) {
649
- if (!pageData.isRewrite) {
650
- trackUrl = newURL;
651
- }
652
- loadRoutePromise = loadRoute(
653
- qwikRouterConfig.routes,
654
- qwikRouterConfig.cacheModules,
655
- newURL.pathname
656
- // Load the actual required path.
657
- );
932
+ trackUrl.pathname = ensureSlash(trackUrl.pathname);
658
933
  }
934
+ const loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, trackUrl.pathname);
659
935
  try {
660
936
  loadedRoute = await loadRoutePromise;
661
937
  } catch (e) {
662
- console.error(e);
663
- window.location.href = newHref;
938
+ console.error(`Could not load route ${trackUrl.pathname}, reloading:`, e);
939
+ window.location.href = trackUrl.href;
940
+ return;
941
+ }
942
+ if (internalState.navCount !== navCountBefore) {
664
943
  return;
665
944
  }
945
+ if (action) {
946
+ const result = await submitAction(action, trackUrl.pathname);
947
+ if (!result) {
948
+ routeInternal2.untrackedValue = {
949
+ type: navType,
950
+ dest: trackUrl
951
+ };
952
+ return;
953
+ }
954
+ actionData = {
955
+ status: result.status,
956
+ action: action.id,
957
+ actionResult: result.result
958
+ };
959
+ if (action.resolve) {
960
+ action.resolve({
961
+ status: result.status,
962
+ result: result.result
963
+ });
964
+ action.resolve = void 0;
965
+ }
966
+ actionLoaderHashes = result.loaderHashes;
967
+ shouldInvalidateActionLoaders = true;
968
+ }
666
969
  }
667
970
  const { $routeName$, $params$, $mods$, $menu$, $notFound$ } = loadedRoute;
668
971
  const contentModules = $mods$;
972
+ if (!isServer) {
973
+ routeLoaderCtx2.goto = noSerialize(goto2);
974
+ }
975
+ updateRouteLoaderPaths(routeLoaderCtx2, loadedRoute.$loaderPaths$, trackUrl);
976
+ const routeLoaders = ensureRouteLoaderSignals(contentModules, loaderState2, routeLoaderCtx2);
977
+ if (shouldInvalidateActionLoaders) {
978
+ if (actionLoaderHashes !== void 0) {
979
+ for (const hash of actionLoaderHashes) {
980
+ loaderState2[hash]?.invalidate(true);
981
+ }
982
+ } else {
983
+ for (const loader of routeLoaders) {
984
+ loaderState2[loader.__id].invalidate(true);
985
+ }
986
+ }
987
+ }
988
+ if (routeLoaders.length > 0) {
989
+ for (let i = 0; i < routeLoaders.length; i++) {
990
+ const loader = routeLoaders[i];
991
+ loaderState2[loader.__id].untrackedLoading;
992
+ }
993
+ }
994
+ if (internalState.navCount !== navCountBefore) {
995
+ return;
996
+ }
669
997
  if ($notFound$) {
670
998
  httpStatus2.value = {
671
999
  status: 404,
672
1000
  message: "Not Found"
673
1001
  };
1002
+ } else if (endpointResponse) {
1003
+ httpStatus2.value = {
1004
+ status: endpointResponse.status,
1005
+ message: endpointResponse.statusMessage ?? "OK"
1006
+ };
1007
+ } else if (actionData) {
1008
+ httpStatus2.value = {
1009
+ status: actionData.status,
1010
+ message: "OK"
1011
+ };
674
1012
  } else {
675
1013
  httpStatus2.value = {
676
- status: clientPageData?.status ?? 200,
677
- message: clientPageData?.statusMessage ?? ""
1014
+ status: 200,
1015
+ message: "OK"
678
1016
  };
679
1017
  }
680
1018
  const pageModule = contentModules[contentModules.length - 1];
@@ -702,310 +1040,197 @@ const useQwikRouter = (props) => {
702
1040
  }
703
1041
  routeLocationTarget2.params = $params$;
704
1042
  }
705
- routeInternal2.untrackedValue = {
1043
+ const nextRouteInternal = {
706
1044
  type: navType,
707
1045
  dest: trackUrl
708
1046
  };
709
- const resolvedHead = resolveHead(clientPageData, routeLocation2, contentModules, locale, serverHead2);
1047
+ if (navigation.forceReload !== void 0) {
1048
+ nextRouteInternal.forceReload = navigation.forceReload;
1049
+ }
1050
+ if (navigation.replaceState !== void 0) {
1051
+ nextRouteInternal.replaceState = navigation.replaceState;
1052
+ }
1053
+ if (navigation.scroll !== void 0) {
1054
+ nextRouteInternal.scroll = navigation.scroll;
1055
+ }
1056
+ if (navigation.historyUpdated !== void 0) {
1057
+ nextRouteInternal.historyUpdated = navigation.historyUpdated;
1058
+ }
1059
+ routeInternal2.untrackedValue = nextRouteInternal;
710
1060
  content2.headings = pageModule.headings;
711
1061
  content2.menu = $menu$;
712
1062
  contentInternal2.untrackedValue = noSerialize(contentModules);
713
- documentHead2.links = resolvedHead.links;
714
- documentHead2.meta = resolvedHead.meta;
715
- documentHead2.styles = resolvedHead.styles;
716
- documentHead2.scripts = resolvedHead.scripts;
717
- documentHead2.title = resolvedHead.title;
718
- documentHead2.frontmatter = resolvedHead.frontmatter;
719
- if (isBrowser) {
720
- let scrollState;
721
- if (navType === "popstate") {
722
- scrollState = getScrollHistory();
723
- }
724
- const scroller = await getScroller2();
725
- if (navigation.scroll && (!navigation.forceReload || !isSamePath(trackUrl, prevUrl)) && (navType === "link" || navType === "popstate") || navType === "form" && !isSamePath(trackUrl, prevUrl)) {
726
- document.__q_scroll_restore__ = () => restoreScroll(navType, trackUrl, prevUrl, scroller, scrollState);
727
- }
728
- const loaders = clientPageData?.loaders;
729
- if (loaders) {
730
- for (const [key, value] of Object.entries(loaders)) {
731
- const signal = loaderState2[key];
732
- const awaitedValue = await value;
733
- loadersObject2[key] = awaitedValue;
734
- if (!signal) {
735
- loaderState2[key] = createLoaderSignal(loadersObject2, key, trackUrl, DEFAULT_LOADERS_SERIALIZATION_STRATEGY, container2);
736
- } else {
737
- signal.invalidate();
738
- }
739
- }
740
- }
741
- CLIENT_DATA_CACHE.clear();
742
- if (!window._qRouterSPA) {
743
- window._qRouterSPA = true;
744
- history.scrollRestoration = "manual";
745
- window.addEventListener("popstate", () => {
746
- window._qRouterScrollEnabled = false;
747
- clearTimeout(window._qRouterScrollDebounce);
748
- goto2(location.href, {
749
- type: "popstate"
750
- });
751
- });
752
- window.removeEventListener("popstate", window._qRouterInitPopstate);
753
- window._qRouterInitPopstate = void 0;
754
- if (!window._qRouterHistoryPatch) {
755
- window._qRouterHistoryPatch = true;
756
- const pushState = history.pushState;
757
- const replaceState2 = history.replaceState;
758
- const prepareState = (state) => {
759
- if (state === null || typeof state === "undefined") {
760
- state = {};
761
- } else if (state?.constructor !== Object) {
762
- state = {
763
- _data: state
764
- };
765
- if (isDev) {
766
- 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`");
767
- }
768
- }
769
- state._qRouterScroll = state._qRouterScroll || currentScrollState(scroller);
770
- return state;
771
- };
772
- history.pushState = (state, title, url2) => {
773
- state = prepareState(state);
774
- return pushState.call(history, state, title, url2);
775
- };
776
- history.replaceState = (state, title, url2) => {
777
- state = prepareState(state);
778
- return replaceState2.call(history, state, title, url2);
779
- };
780
- }
781
- document.addEventListener("click", (event) => {
782
- if (event.defaultPrevented) {
783
- return;
784
- }
785
- const target = event.target.closest("a[href]");
786
- if (target && !target.hasAttribute("preventdefault:click")) {
787
- const href = target.getAttribute("href");
788
- const prev = new URL(location.href);
789
- const dest = new URL(href, prev);
790
- if (isSameOrigin(dest, prev) && isSamePath(dest, prev)) {
791
- event.preventDefault();
792
- if (!dest.hash && !dest.href.endsWith("#")) {
793
- if (dest.href !== prev.href) {
794
- history.pushState(null, "", dest);
795
- }
796
- window._qRouterScrollEnabled = false;
797
- clearTimeout(window._qRouterScrollDebounce);
798
- saveScrollHistory({
799
- ...currentScrollState(scroller),
800
- x: 0,
801
- y: 0
802
- });
803
- location.reload();
804
- return;
805
- }
806
- goto2(target.getAttribute("href"));
807
- }
808
- }
809
- });
810
- document.removeEventListener("click", window._qRouterInitAnchors);
811
- window._qRouterInitAnchors = void 0;
812
- if (!window.navigation) {
813
- document.addEventListener("visibilitychange", () => {
814
- if ((window._qRouterScrollEnabled || window._qCityScrollEnabled) && document.visibilityState === "hidden") {
815
- if (window._qCityScrollEnabled) {
816
- console.warn('"_qCityScrollEnabled" is deprecated. Use "_qRouterScrollEnabled" instead.');
817
- }
818
- const scrollState2 = currentScrollState(scroller);
819
- saveScrollHistory(scrollState2);
820
- }
821
- }, {
822
- passive: true
823
- });
824
- document.removeEventListener("visibilitychange", window._qRouterInitVisibility);
825
- window._qRouterInitVisibility = void 0;
826
- }
827
- window.addEventListener("scroll", () => {
828
- if (!window._qRouterScrollEnabled && !window._qCityScrollEnabled) {
829
- return;
830
- }
831
- clearTimeout(window._qRouterScrollDebounce);
832
- window._qRouterScrollDebounce = setTimeout(() => {
833
- const scrollState2 = currentScrollState(scroller);
834
- saveScrollHistory(scrollState2);
835
- window._qRouterScrollDebounce = void 0;
836
- }, 200);
837
- }, {
838
- passive: true
839
- });
840
- removeEventListener("scroll", window._qRouterInitScroll);
841
- window._qRouterInitScroll = void 0;
842
- spaInit.resolve();
843
- }
844
- if (navType !== "popstate") {
845
- window._qRouterScrollEnabled = false;
846
- clearTimeout(window._qRouterScrollDebounce);
847
- if (!navigation.historyUpdated) {
848
- const scrollState2 = currentScrollState(scroller);
849
- saveScrollHistory(scrollState2);
850
- }
851
- }
852
- const navigate = () => {
853
- if (navigation.historyUpdated) {
854
- const currentPath = location.pathname + location.search + location.hash;
855
- const nextPath = toPath(trackUrl);
856
- if (currentPath !== nextPath) {
857
- history.replaceState(history.state, "", nextPath);
858
- }
859
- } else {
860
- clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
861
- }
862
- contentInternal2.trigger();
863
- return _waitUntilRendered(container2);
864
- };
865
- const _waitNextPage = () => {
866
- if (isServer || props2?.viewTransition === false) {
867
- return navigate();
868
- } else {
869
- const viewTransition = startViewTransition({
870
- update: navigate,
871
- types: [
872
- "qwik-navigation"
873
- ]
874
- });
875
- if (!viewTransition) {
876
- return Promise.resolve();
877
- }
878
- return viewTransition.ready;
879
- }
880
- };
881
- _waitNextPage().catch((err) => {
882
- navigate();
883
- if (err instanceof DOMException && err.name === "TimeoutError") {
884
- throw new Error('View transition timed out. This can happen if you have "disableCache" in your browser devtools enabled.');
885
- }
886
- throw err;
887
- }).finally(() => {
888
- container2.element.setAttribute?.(Q_ROUTE, $routeName$);
889
- const scrollState2 = currentScrollState(scroller);
890
- saveScrollHistory(scrollState2);
891
- window._qRouterScrollEnabled = true;
892
- if (isBrowser) {
893
- callRestoreScrollOnDocument();
894
- }
895
- if (shouldForcePrevUrl) {
896
- forceStoreEffects(routeLocation2, "prevUrl");
897
- }
898
- if (shouldForceUrl) {
899
- forceStoreEffects(routeLocation2, "url");
900
- }
901
- if (shouldForceParams) {
902
- forceStoreEffects(routeLocation2, "params");
903
- }
904
- routeLocation2.isNavigating = false;
905
- navResolver2.r?.();
906
- });
907
- }
1063
+ actionDataSignal2.value = actionData;
1064
+ navContext2.value = noSerialize({
1065
+ routeName: $routeName$,
1066
+ navType,
1067
+ replaceState,
1068
+ shouldForcePrevUrl,
1069
+ shouldForceUrl,
1070
+ shouldForceParams,
1071
+ navCount: navCountBefore
1072
+ });
908
1073
  }, "useQwikRouter_useTask_XpalYii770E", [
1074
+ actionDataSignal,
909
1075
  actionState,
910
1076
  content,
911
1077
  contentInternal,
912
- documentHead,
913
1078
  env,
914
- getScroller,
915
1079
  goto,
916
1080
  httpStatus,
917
1081
  loaderState,
918
- loadersObject,
919
- navResolver,
920
- props,
1082
+ navContext,
921
1083
  routeInternal,
1084
+ routeLoaderCtx,
922
1085
  routeLocation,
923
- routeLocationTarget,
924
- serverHead
1086
+ routeLocationTarget
925
1087
  ]),
926
- // We should only wait for navigation to complete on the server
1088
+ // We should only wait for head calculation to complete on the server
927
1089
  {
928
1090
  deferUpdates: isServer
929
1091
  }
930
1092
  );
931
- };
932
- const QwikRouterProvider = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
933
- useQwikRouter(props);
934
- return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "5y_0");
935
- }, "QwikRouterProvider_component_6Kjfa79mqlY"));
936
- const QwikCityProvider = QwikRouterProvider;
937
- const useQwikMockRouter = (props) => {
938
- const urlEnv = props.url ?? "http://localhost/";
939
- const url = new URL(urlEnv);
940
- const routeLocation = useStore({
941
- url,
942
- params: props.params ?? {},
943
- isNavigating: false,
944
- prevUrl: void 0
945
- }, {
946
- deep: false
947
- });
948
- const container = _getContextContainer();
949
- const loadersObject = {};
950
- const loadersState = {};
951
- if (props.loaders) {
952
- for (const { loader, data } of props.loaders) {
953
- const id = loader.__id;
954
- loadersObject[id] = data;
955
- loadersState[id] = createLoaderSignal(loadersObject, id, url, DEFAULT_LOADERS_SERIALIZATION_STRATEGY, container);
1093
+ useTaskQrl(/* @__PURE__ */ inlinedQrl(({ track }) => {
1094
+ const actionDataSignal2 = _captures[0], contentInternal2 = _captures[1], documentHead2 = _captures[2], loaderState2 = _captures[3], routeLocation2 = _captures[4], serverHead2 = _captures[5];
1095
+ const contentModules = track(contentInternal2);
1096
+ if (!contentModules) {
1097
+ return;
956
1098
  }
957
- }
958
- const goto = props.goto ?? /* @__PURE__ */ inlinedQrl(async () => {
959
- console.warn("QwikRouterMockProvider: goto not provided");
960
- }, "useQwikMockRouter_goto_aViHFxQ1a3s");
961
- const documentHead = useStore(createDocumentHead, {
962
- deep: false
1099
+ const actionData = track(actionDataSignal2);
1100
+ const head = track(() => resolveHead(actionData, loaderState2, routeLocation2, contentModules, getLocale(""), serverHead2));
1101
+ documentHead2.links = head.links;
1102
+ documentHead2.meta = head.meta;
1103
+ documentHead2.styles = head.styles;
1104
+ documentHead2.scripts = head.scripts;
1105
+ documentHead2.title = head.title;
1106
+ documentHead2.frontmatter = head.frontmatter;
1107
+ }, "useQwikRouter_useTask_1_1sKEZ9Pg1ow", [
1108
+ actionDataSignal,
1109
+ contentInternal,
1110
+ documentHead,
1111
+ loaderState,
1112
+ routeLocation,
1113
+ serverHead
1114
+ ]), {
1115
+ deferUpdates: isServer
963
1116
  });
964
- const content = useStore({
965
- headings: void 0,
966
- menu: void 0
967
- }, {
968
- deep: false
969
- });
970
- const contentInternal = useSignal();
971
- const actionState = useSignal();
972
- const httpStatus = useSignal({
973
- status: 200,
974
- message: ""
975
- });
976
- useContextProvider(ContentContext, content);
977
- useContextProvider(ContentInternalContext, contentInternal);
978
- useContextProvider(DocumentHeadContext, documentHead);
979
- useContextProvider(HttpStatusContext, httpStatus);
980
- useContextProvider(RouteLocationContext, routeLocation);
981
- useContextProvider(RouteNavigateContext, goto);
982
- useContextProvider(RouteStateContext, loadersState);
983
- useContextProvider(RouteActionContext, actionState);
984
- const actionsMocks = props.actions?.reduce((acc, { action, handler }) => {
985
- acc[action.__id] = handler;
986
- return acc;
987
- }, {});
988
- useTaskQrl(/* @__PURE__ */ inlinedQrl(async ({ track }) => {
989
- const actionState2 = _captures[0], actionsMocks2 = _captures[1];
990
- const action = track(actionState2);
991
- if (!action?.resolve) {
1117
+ useTaskQrl(/* @__PURE__ */ inlinedQrl(({ track }) => {
1118
+ const contentInternal2 = _captures[0], goto2 = _captures[1], navContext2 = _captures[2], navResolver2 = _captures[3], props2 = _captures[4], routeInternal2 = _captures[5], routeLocation2 = _captures[6];
1119
+ const nav = track(navContext2);
1120
+ if (isServer || !nav) {
992
1121
  return;
993
1122
  }
994
- const mock = actionsMocks2?.[action.id];
995
- if (mock) {
996
- const actionResult = await mock(action.data);
997
- action.resolve(actionResult);
1123
+ if (nav.navCount !== internalState.navCount) {
1124
+ return;
998
1125
  }
999
- }, "useQwikMockRouter_useTask_tXTLR4tzCy0", [
1000
- actionState,
1001
- actionsMocks
1002
- ]));
1126
+ const container = _getContextContainer();
1127
+ const navigation = routeInternal2.untrackedValue;
1128
+ const { navType, replaceState, routeName } = nav;
1129
+ const trackUrl = routeLocation2.url;
1130
+ const prevUrl = routeLocation2.prevUrl ?? trackUrl;
1131
+ const scroller = getScroller();
1132
+ let scrollState;
1133
+ if (navType === "popstate") {
1134
+ scrollState = getScrollHistory();
1135
+ }
1136
+ if (navigation.scroll && (!navigation.forceReload || !isSamePath(trackUrl, prevUrl)) && (navType === "link" || navType === "popstate") || navType === "form" && !isSamePath(trackUrl, prevUrl)) {
1137
+ document.__q_scroll_restore__ = () => restoreScroll(navType, trackUrl, prevUrl, scroller, scrollState);
1138
+ }
1139
+ initializeSPA(goto2, scroller);
1140
+ if (navType !== "popstate") {
1141
+ window._qRouterScrollEnabled = false;
1142
+ clearTimeout(window._qRouterScrollDebounce);
1143
+ if (!navigation.historyUpdated) {
1144
+ const scrollState2 = currentScrollState(scroller);
1145
+ saveScrollHistory(scrollState2);
1146
+ }
1147
+ }
1148
+ let didNavigate = false;
1149
+ let navigatePromise;
1150
+ let currentTransition;
1151
+ const navigate = () => {
1152
+ if (navigatePromise) {
1153
+ return navigatePromise;
1154
+ }
1155
+ if (nav.navCount !== internalState.navCount) {
1156
+ return Promise.resolve();
1157
+ }
1158
+ didNavigate = true;
1159
+ if (navigation.historyUpdated) {
1160
+ const currentPath = location.pathname + location.search + location.hash;
1161
+ const nextPath = toPath(trackUrl);
1162
+ if (currentPath !== nextPath) {
1163
+ history.replaceState(history.state, "", nextPath);
1164
+ }
1165
+ } else {
1166
+ clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1167
+ }
1168
+ contentInternal2.trigger();
1169
+ return navigatePromise = _waitUntilRendered(container);
1170
+ };
1171
+ const _waitNextPage = () => {
1172
+ if (props2?.viewTransition === false || !("startViewTransition" in document)) {
1173
+ return navigate().then(() => void 0);
1174
+ }
1175
+ const { ready, transition } = startViewTransition({
1176
+ update: navigate,
1177
+ types: [
1178
+ "qwik-navigation"
1179
+ ]
1180
+ });
1181
+ currentTransition = transition;
1182
+ internalState.currentTransition = transition;
1183
+ return ready.then(() => transition, (reason) => {
1184
+ if (!didNavigate && nav.navCount === internalState.navCount) {
1185
+ return navigate().then(() => transition);
1186
+ }
1187
+ if (reason?.name === "AbortError") {
1188
+ return transition;
1189
+ }
1190
+ throw reason;
1191
+ });
1192
+ };
1193
+ _waitNextPage().finally(() => {
1194
+ if (currentTransition && internalState.currentTransition === currentTransition) {
1195
+ internalState.currentTransition = void 0;
1196
+ }
1197
+ if (nav.navCount !== internalState.navCount) {
1198
+ return;
1199
+ }
1200
+ container.element.setAttribute?.(Q_ROUTE, routeName);
1201
+ const scrollState2 = currentScrollState(scroller);
1202
+ saveScrollHistory(scrollState2);
1203
+ window._qRouterScrollEnabled = true;
1204
+ callRestoreScrollOnDocument();
1205
+ if (nav.shouldForcePrevUrl) {
1206
+ forceStoreEffects(routeLocation2, "prevUrl");
1207
+ }
1208
+ if (nav.shouldForceUrl) {
1209
+ forceStoreEffects(routeLocation2, "url");
1210
+ }
1211
+ if (nav.shouldForceParams) {
1212
+ forceStoreEffects(routeLocation2, "params");
1213
+ }
1214
+ routeLocation2.isNavigating = false;
1215
+ navResolver2.r?.();
1216
+ });
1217
+ }, "useQwikRouter_useTask_2_yw17chooOac", [
1218
+ contentInternal,
1219
+ goto,
1220
+ navContext,
1221
+ navResolver,
1222
+ props,
1223
+ routeInternal,
1224
+ routeLocation
1225
+ ]), {
1226
+ deferUpdates: false
1227
+ });
1003
1228
  };
1004
- const QwikRouterMockProvider = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
1005
- useQwikMockRouter(props);
1006
- return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "5y_1");
1007
- }, "QwikRouterMockProvider_component_IN4dVpT0x74"));
1008
- const QwikCityMockProvider = QwikRouterMockProvider;
1229
+ const QwikRouterProvider = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
1230
+ useQwikRouter(props);
1231
+ return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "5y_0");
1232
+ }, "QwikRouterProvider_component_6Kjfa79mqlY"));
1233
+ const QwikCityProvider = QwikRouterProvider;
1009
1234
 
1010
1235
  const handleRouterPopstate = (nav, event) => {
1011
1236
  const href = event.detail?.href;
@@ -1057,7 +1282,6 @@ const RouterOutlet = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl(()
1057
1282
  return SkipRender;
1058
1283
  }, "RouterOutlet_component_QwONcWD5gIg"));
1059
1284
 
1060
- const getValue = (obj) => obj.value;
1061
1285
  const validatorQrl = (validator) => {
1062
1286
  if (isServer) {
1063
1287
  return {
@@ -1182,7 +1406,7 @@ const zodQrl = (qrl) => {
1182
1406
  const zod$ = /* @__PURE__ */ implicit$FirstArg(zodQrl);
1183
1407
  const getValidators = (rest, qrl) => {
1184
1408
  let id;
1185
- let serializationStrategy = DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
1409
+ let invalidate;
1186
1410
  const validators = [];
1187
1411
  if (rest.length === 1) {
1188
1412
  const options = rest[0];
@@ -1191,12 +1415,12 @@ const getValidators = (rest, qrl) => {
1191
1415
  validators.push(options);
1192
1416
  } else {
1193
1417
  id = options.id;
1194
- if (options.serializationStrategy) {
1195
- serializationStrategy = options.serializationStrategy;
1196
- }
1197
1418
  if (options.validation) {
1198
1419
  validators.push(...options.validation);
1199
1420
  }
1421
+ if (options.invalidate) {
1422
+ invalidate = options.invalidate.map((loader) => loader.__id);
1423
+ }
1200
1424
  }
1201
1425
  }
1202
1426
  } else if (rest.length > 1) {
@@ -1215,11 +1439,11 @@ const getValidators = (rest, qrl) => {
1215
1439
  return {
1216
1440
  validators: validators.reverse(),
1217
1441
  id,
1218
- serializationStrategy
1442
+ invalidate
1219
1443
  };
1220
1444
  };
1221
1445
  const routeActionQrl = (actionQrl, ...rest) => {
1222
- const { id, validators } = getValidators(rest, actionQrl);
1446
+ const { id, validators, invalidate } = getValidators(rest, actionQrl);
1223
1447
  function action() {
1224
1448
  const loc = useLocation();
1225
1449
  const currentAction = useAction();
@@ -1314,6 +1538,7 @@ Action.run() can only be called on the browser, for example when a user clicks a
1314
1538
  action.__validators = validators;
1315
1539
  action.__qrl = actionQrl;
1316
1540
  action.__id = id;
1541
+ action.__invalidate = invalidate;
1317
1542
  Object.freeze(action);
1318
1543
  return action;
1319
1544
  };
@@ -1329,32 +1554,6 @@ const globalActionQrl = (actionQrl, ...rest) => {
1329
1554
  };
1330
1555
  const routeAction$ = /* @__PURE__ */ implicit$FirstArg(routeActionQrl);
1331
1556
  const globalAction$ = /* @__PURE__ */ implicit$FirstArg(globalActionQrl);
1332
- const routeLoaderQrl = (loaderQrl, ...rest) => {
1333
- const { id, validators, serializationStrategy } = getValidators(rest, loaderQrl);
1334
- function loader() {
1335
- const state = _resolveContextWithoutSequentialScope(RouteStateContext);
1336
- if (!(id in state)) {
1337
- throw new Error(`routeLoader$ "${loaderQrl.getSymbol()}" was invoked in a route where it was not declared.
1338
- This is because the routeLoader$ was not exported in a 'layout.tsx' or 'index.tsx' file of the existing route.
1339
- For more information check: https://qwik.dev/docs/route-loader/
1340
-
1341
- If your are managing reusable logic or a library it is essential that this function is re-exported from within 'layout.tsx' or 'index.tsx file of the existing route otherwise it will not run or throw exception.
1342
- For more information check: https://qwik.dev/docs/re-exporting-loaders/`);
1343
- }
1344
- const loaderData = state[id];
1345
- untrack(getValue, loaderData);
1346
- return loaderData;
1347
- }
1348
- loader.__brand = "server_loader";
1349
- loader.__qrl = loaderQrl;
1350
- loader.__validators = validators;
1351
- loader.__id = id;
1352
- loader.__serializationStrategy = serializationStrategy;
1353
- loader.__expires = -1;
1354
- Object.freeze(loader);
1355
- return loader;
1356
- };
1357
- const routeLoader$ = /* @__PURE__ */ implicit$FirstArg(routeLoaderQrl);
1358
1557
  const deserializeStream = async function* (stream, abortSignal) {
1359
1558
  const reader = stream.getReader();
1360
1559
  try {
@@ -1394,16 +1593,7 @@ const serverQrl = (qrl, options) => {
1394
1593
  const fetchOptions2 = _captures[0], headers2 = _captures[1], method2 = _captures[2], origin2 = _captures[3], qrl2 = _captures[4];
1395
1594
  const abortSignal = args.length > 0 && args[0] instanceof AbortSignal ? args.shift() : void 0;
1396
1595
  if (isServer) {
1397
- let requestEvent = _asyncRequestStore?.getStore();
1398
- if (!requestEvent) {
1399
- const contexts = [
1400
- useQwikRouterEnv()?.ev,
1401
- this,
1402
- _getContextEvent()
1403
- ];
1404
- requestEvent = contexts.find((v2) => v2 && Object.prototype.hasOwnProperty.call(v2, "sharedMap") && Object.prototype.hasOwnProperty.call(v2, "cookie"));
1405
- }
1406
- return qrl2.apply(requestEvent, args);
1596
+ return qrl2.apply(getRequestEvent(this), args);
1407
1597
  } else {
1408
1598
  let filteredArgs = args.map((arg) => {
1409
1599
  if (arg instanceof SubmitEvent && arg.target instanceof HTMLFormElement) {
@@ -1630,9 +1820,7 @@ const untypedAppUrl = function appUrl(route, params, paramsPrefix = "") {
1630
1820
  let url = path.join("/");
1631
1821
  let baseURL = "/";
1632
1822
  if (baseURL) {
1633
- if (!baseURL.endsWith("/")) {
1634
- baseURL += "/";
1635
- }
1823
+ baseURL = ensureSlash(baseURL);
1636
1824
  while (url.startsWith("/")) {
1637
1825
  url = url.substring(1);
1638
1826
  }
@@ -1700,4 +1888,4 @@ const DocumentHeadTags = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl
1700
1888
  ], 1, "r5_3");
1701
1889
  }, "DocumentHeadTags_component_9CrWYOoCpgY"));
1702
1890
 
1703
- export { DocumentHeadTags, ErrorBoundary, Form, Link, QWIK_CITY_SCROLLER, QWIK_ROUTER_SCROLLER, QwikCityMockProvider, QwikCityProvider, QwikRouterMockProvider, QwikRouterProvider, RouterOutlet, ServiceWorkerRegister, createRenderer, globalAction$, globalActionQrl, omitProps, routeAction$, routeActionQrl, routeLoader$, routeLoaderQrl, server$, serverQrl, untypedAppUrl, useDocumentHead, useLocation, useNavigate, useQwikRouter, valibot$, valibotQrl, validator$, validatorQrl, zod$, zodQrl };
1891
+ export { DocumentHeadTags, ErrorBoundary, Form, Link, QWIK_CITY_SCROLLER, QWIK_ROUTER_SCROLLER, QwikCityMockProvider, QwikCityProvider, QwikRouterMockProvider, QwikRouterProvider, RouterOutlet, ServiceWorkerRegister, createRenderer, globalAction$, globalActionQrl, omitProps, routeAction$, routeActionQrl, server$, serverQrl, untypedAppUrl, useDocumentHead, useLocation, useNavigate, useQwikRouter, valibot$, valibotQrl, validator$, validatorQrl, zod$, zodQrl };