@qwik.dev/router 2.0.0-beta.35 → 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.");
@@ -414,9 +714,6 @@ const useQwikRouter = (props) => {
414
714
  }
415
715
  const serverHead = useServerData("documentHead");
416
716
  const manifestHash = useServerData("containerAttributes")?.["q:manifest-hash"];
417
- if (env.ev.originalUrl.pathname !== env.ev.url.pathname && !__EXPERIMENTAL__.enableRequestRewrite) {
418
- throw new Error(`enableRequestRewrite is an experimental feature and is not enabled. Please enable the feature flag by adding \`experimental: ["enableRequestRewrite"]\` to your qwikVite plugin options.`);
419
- }
420
717
  const url = new URL(urlEnv);
421
718
  const routeLocationTarget = {
422
719
  url,
@@ -428,27 +725,19 @@ const useQwikRouter = (props) => {
428
725
  deep: false
429
726
  });
430
727
  const navResolver = {};
431
- const container = _getContextContainer();
432
- const getSerializationStrategy = (loaderId) => {
433
- return env.response.loadersSerializationStrategy.get(loaderId) || DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
434
- };
435
- const loadersObject = {};
728
+ const routeLoaderCtx = useStore(env.routeLoaderCtx);
436
729
  const loaderState = {};
437
- for (const [key, value] of Object.entries(env.response.loaders)) {
438
- loadersObject[key] = value;
439
- loaderState[key] = createLoaderSignal(loadersObject, key, url, getSerializationStrategy(key), container);
440
- }
441
- loadersObject[SerializerSymbol] = (obj) => {
442
- const loadersSerializationObject = {};
443
- for (const [k, v] of Object.entries(obj)) {
444
- 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);
445
736
  }
446
- return loadersSerializationObject;
447
- };
737
+ }
448
738
  const routeInternal = useSignal({
449
739
  type: "initial",
450
- dest: url,
451
- scroll: true
740
+ dest: url
452
741
  });
453
742
  const documentHead = useStore(() => createDocumentHead(serverHead, manifestHash));
454
743
  const content = useStore({
@@ -456,12 +745,13 @@ const useQwikRouter = (props) => {
456
745
  menu: void 0
457
746
  });
458
747
  const contentInternal = useSignal();
748
+ const navContext = useSignal();
459
749
  const httpStatus = useSignal({
460
750
  status: env.response.status,
461
751
  message: env.loadedRoute.$notFound$ ? "Not Found" : env.response.statusMessage ?? ""
462
752
  });
463
753
  const currentActionId = env.response.action;
464
- const currentAction = currentActionId ? env.response.loaders[currentActionId] : void 0;
754
+ const currentAction = currentActionId ? env.response.actionResult : void 0;
465
755
  const actionState = useSignal(currentAction ? {
466
756
  id: currentActionId,
467
757
  data: env.response.formData,
@@ -470,6 +760,11 @@ const useQwikRouter = (props) => {
470
760
  status: env.response.status
471
761
  }
472
762
  } : void 0);
763
+ const actionDataSignal = useSignal(currentActionId ? {
764
+ action: currentActionId,
765
+ actionResult: currentAction,
766
+ status: env.response.status
767
+ } : void 0);
473
768
  const registerPreventNav = /* @__PURE__ */ inlinedQrl((fn$) => {
474
769
  if (!isBrowser) {
475
770
  return;
@@ -500,22 +795,11 @@ const useQwikRouter = (props) => {
500
795
  }
501
796
  };
502
797
  }, "useQwikRouter_registerPreventNav_69B0DK0eZJc");
503
- const getScroller = /* @__PURE__ */ inlinedQrl(() => {
504
- let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
505
- if (!scroller) {
506
- scroller = document.getElementById(QWIK_CITY_SCROLLER);
507
- if (scroller && isDev) {
508
- console.warn(`Please update your scroller ID to "${QWIK_ROUTER_SCROLLER}" as "${QWIK_CITY_SCROLLER}" is deprecated and will be removed in V3`);
509
- }
510
- }
511
- return scroller ?? document.documentElement;
512
- }, "useQwikRouter_getScroller_0UhDFwlxeFQ");
513
798
  const goto = /* @__PURE__ */ inlinedQrl(async (path, opt) => {
514
- 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];
515
800
  const { type = "link", forceReload = path === void 0, replaceState = false, scroll = true } = typeof opt === "object" ? opt : {
516
801
  forceReload: opt
517
802
  };
518
- internalState.navCount++;
519
803
  if (isBrowser && type === "link" && routeInternal2.value.type === "initial") {
520
804
  const url2 = new URL(window.location.href);
521
805
  routeInternal2.value.dest = url2;
@@ -523,6 +807,11 @@ const useQwikRouter = (props) => {
523
807
  }
524
808
  const lastDest = routeInternal2.value.dest;
525
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();
526
815
  if (preventNav.$cbs$ && (forceReload || typeof dest === "number" || !isSamePath(dest, lastDest) || !isSameOrigin(dest, lastDest))) {
527
816
  const ourNavId = internalState.navCount;
528
817
  const prevents = await Promise.all([
@@ -552,7 +841,7 @@ const useQwikRouter = (props) => {
552
841
  if (type === "link" && dest.href !== location.href) {
553
842
  history.pushState(null, "", dest);
554
843
  }
555
- const scroller = await getScroller2();
844
+ const scroller = getScroller();
556
845
  restoreScroll(type, dest, new URL(location.href), scroller, getScrollHistory());
557
846
  if (type === "popstate") {
558
847
  window._qRouterScrollEnabled = true;
@@ -567,7 +856,7 @@ const useQwikRouter = (props) => {
567
856
  }
568
857
  let historyUpdated = false;
569
858
  if (isBrowser && type === "link" && !forceReload) {
570
- const scroller = await getScroller2();
859
+ const scroller = getScroller();
571
860
  window._qRouterScrollEnabled = false;
572
861
  clearTimeout(window._qRouterScrollDebounce);
573
862
  const scrollState = currentScrollState(scroller);
@@ -584,17 +873,21 @@ const useQwikRouter = (props) => {
584
873
  historyUpdated
585
874
  };
586
875
  if (isBrowser) {
587
- loadClientData(dest);
588
- loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, dest.pathname);
876
+ prefetchRoute(dest, true, 0.8, manifestHash2);
589
877
  }
590
878
  actionState2.value = void 0;
591
879
  routeLocation2.isNavigating = true;
592
- return new Promise((resolve) => {
593
- 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
+ };
594
886
  });
887
+ return navResolver2.p;
595
888
  }, "useQwikRouter_goto_8j8Vrz2yUIM", [
596
889
  actionState,
597
- getScroller,
890
+ manifestHash,
598
891
  navResolver,
599
892
  routeInternal,
600
893
  routeLocation
@@ -606,25 +899,29 @@ const useQwikRouter = (props) => {
606
899
  useContextProvider(RouteLocationContext, routeLocation);
607
900
  useContextProvider(RouteNavigateContext, goto);
608
901
  useContextProvider(RouteStateContext, loaderState);
902
+ useContextProvider(RouteLoaderCtxContext, routeLoaderCtx);
609
903
  useContextProvider(RouteActionContext, actionState);
610
904
  useContextProvider(RoutePreventNavigateContext, registerPreventNav);
611
905
  useTaskQrl(
612
906
  /* @__PURE__ */ inlinedQrl(async ({ track }) => {
613
- 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];
614
- 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];
615
908
  const navigation = track(routeInternal2);
616
909
  const action = track(actionState2);
617
- const locale = getLocale("");
618
910
  const prevUrl = routeLocation2.url;
619
911
  const navType = action ? "form" : navigation.type;
620
912
  const replaceState = navigation.replaceState;
913
+ const navCountBefore = internalState.navCount;
621
914
  let trackUrl;
622
- let clientPageData;
915
+ let endpointResponse;
916
+ let actionData;
917
+ let actionLoaderHashes;
918
+ let shouldInvalidateActionLoaders = false;
623
919
  let loadedRoute;
624
920
  if (isServer) {
625
921
  trackUrl = new URL(navigation.dest, routeLocation2.url);
626
922
  loadedRoute = env2.loadedRoute;
627
- clientPageData = env2.response;
923
+ endpointResponse = env2.response;
924
+ actionData = endpointResponse;
628
925
  } else {
629
926
  trackUrl = new URL(navigation.dest, location);
630
927
  if (trackUrl.pathname.endsWith("/")) {
@@ -632,52 +929,90 @@ const useQwikRouter = (props) => {
632
929
  trackUrl.pathname = trackUrl.pathname.slice(0, -1);
633
930
  }
634
931
  } else if (!globalThis.__NO_TRAILING_SLASH__) {
635
- trackUrl.pathname += "/";
636
- }
637
- let loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, trackUrl.pathname);
638
- const pageData = clientPageData = await loadClientData(trackUrl, {
639
- action,
640
- clearCache: true
641
- });
642
- if (!pageData) {
643
- routeInternal2.untrackedValue = {
644
- type: navType,
645
- dest: trackUrl
646
- };
647
- return;
648
- }
649
- const newHref = pageData.href;
650
- const newURL = new URL(newHref, trackUrl);
651
- if (!isSamePath(newURL, trackUrl)) {
652
- if (!pageData.isRewrite) {
653
- trackUrl = newURL;
654
- }
655
- loadRoutePromise = loadRoute(
656
- qwikRouterConfig.routes,
657
- qwikRouterConfig.cacheModules,
658
- newURL.pathname
659
- // Load the actual required path.
660
- );
932
+ trackUrl.pathname = ensureSlash(trackUrl.pathname);
661
933
  }
934
+ const loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.cacheModules, trackUrl.pathname);
662
935
  try {
663
936
  loadedRoute = await loadRoutePromise;
664
937
  } catch (e) {
665
- console.error(e);
666
- 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) {
667
943
  return;
668
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
+ }
669
969
  }
670
970
  const { $routeName$, $params$, $mods$, $menu$, $notFound$ } = loadedRoute;
671
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
+ }
672
997
  if ($notFound$) {
673
998
  httpStatus2.value = {
674
999
  status: 404,
675
1000
  message: "Not Found"
676
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
+ };
677
1012
  } else {
678
1013
  httpStatus2.value = {
679
- status: clientPageData?.status ?? 200,
680
- message: clientPageData?.statusMessage ?? ""
1014
+ status: 200,
1015
+ message: "OK"
681
1016
  };
682
1017
  }
683
1018
  const pageModule = contentModules[contentModules.length - 1];
@@ -705,310 +1040,197 @@ const useQwikRouter = (props) => {
705
1040
  }
706
1041
  routeLocationTarget2.params = $params$;
707
1042
  }
708
- routeInternal2.untrackedValue = {
1043
+ const nextRouteInternal = {
709
1044
  type: navType,
710
1045
  dest: trackUrl
711
1046
  };
712
- 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;
713
1060
  content2.headings = pageModule.headings;
714
1061
  content2.menu = $menu$;
715
1062
  contentInternal2.untrackedValue = noSerialize(contentModules);
716
- documentHead2.links = resolvedHead.links;
717
- documentHead2.meta = resolvedHead.meta;
718
- documentHead2.styles = resolvedHead.styles;
719
- documentHead2.scripts = resolvedHead.scripts;
720
- documentHead2.title = resolvedHead.title;
721
- documentHead2.frontmatter = resolvedHead.frontmatter;
722
- if (isBrowser) {
723
- let scrollState;
724
- if (navType === "popstate") {
725
- scrollState = getScrollHistory();
726
- }
727
- const scroller = await getScroller2();
728
- if (navigation.scroll && (!navigation.forceReload || !isSamePath(trackUrl, prevUrl)) && (navType === "link" || navType === "popstate") || navType === "form" && !isSamePath(trackUrl, prevUrl)) {
729
- document.__q_scroll_restore__ = () => restoreScroll(navType, trackUrl, prevUrl, scroller, scrollState);
730
- }
731
- const loaders = clientPageData?.loaders;
732
- if (loaders) {
733
- for (const [key, value] of Object.entries(loaders)) {
734
- const signal = loaderState2[key];
735
- const awaitedValue = await value;
736
- loadersObject2[key] = awaitedValue;
737
- if (!signal) {
738
- loaderState2[key] = createLoaderSignal(loadersObject2, key, trackUrl, DEFAULT_LOADERS_SERIALIZATION_STRATEGY, container2);
739
- } else {
740
- signal.invalidate();
741
- }
742
- }
743
- }
744
- CLIENT_DATA_CACHE.clear();
745
- if (!window._qRouterSPA) {
746
- window._qRouterSPA = true;
747
- history.scrollRestoration = "manual";
748
- window.addEventListener("popstate", () => {
749
- window._qRouterScrollEnabled = false;
750
- clearTimeout(window._qRouterScrollDebounce);
751
- goto2(location.href, {
752
- type: "popstate"
753
- });
754
- });
755
- window.removeEventListener("popstate", window._qRouterInitPopstate);
756
- window._qRouterInitPopstate = void 0;
757
- if (!window._qRouterHistoryPatch) {
758
- window._qRouterHistoryPatch = true;
759
- const pushState = history.pushState;
760
- const replaceState2 = history.replaceState;
761
- const prepareState = (state) => {
762
- if (state === null || typeof state === "undefined") {
763
- state = {};
764
- } else if (state?.constructor !== Object) {
765
- state = {
766
- _data: state
767
- };
768
- if (isDev) {
769
- 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`");
770
- }
771
- }
772
- state._qRouterScroll = state._qRouterScroll || currentScrollState(scroller);
773
- return state;
774
- };
775
- history.pushState = (state, title, url2) => {
776
- state = prepareState(state);
777
- return pushState.call(history, state, title, url2);
778
- };
779
- history.replaceState = (state, title, url2) => {
780
- state = prepareState(state);
781
- return replaceState2.call(history, state, title, url2);
782
- };
783
- }
784
- document.addEventListener("click", (event) => {
785
- if (event.defaultPrevented) {
786
- return;
787
- }
788
- const target = event.target.closest("a[href]");
789
- if (target && !target.hasAttribute("preventdefault:click")) {
790
- const href = target.getAttribute("href");
791
- const prev = new URL(location.href);
792
- const dest = new URL(href, prev);
793
- if (isSameOrigin(dest, prev) && isSamePath(dest, prev)) {
794
- event.preventDefault();
795
- if (!dest.hash && !dest.href.endsWith("#")) {
796
- if (dest.href !== prev.href) {
797
- history.pushState(null, "", dest);
798
- }
799
- window._qRouterScrollEnabled = false;
800
- clearTimeout(window._qRouterScrollDebounce);
801
- saveScrollHistory({
802
- ...currentScrollState(scroller),
803
- x: 0,
804
- y: 0
805
- });
806
- location.reload();
807
- return;
808
- }
809
- goto2(target.getAttribute("href"));
810
- }
811
- }
812
- });
813
- document.removeEventListener("click", window._qRouterInitAnchors);
814
- window._qRouterInitAnchors = void 0;
815
- if (!window.navigation) {
816
- document.addEventListener("visibilitychange", () => {
817
- if ((window._qRouterScrollEnabled || window._qCityScrollEnabled) && document.visibilityState === "hidden") {
818
- if (window._qCityScrollEnabled) {
819
- console.warn('"_qCityScrollEnabled" is deprecated. Use "_qRouterScrollEnabled" instead.');
820
- }
821
- const scrollState2 = currentScrollState(scroller);
822
- saveScrollHistory(scrollState2);
823
- }
824
- }, {
825
- passive: true
826
- });
827
- document.removeEventListener("visibilitychange", window._qRouterInitVisibility);
828
- window._qRouterInitVisibility = void 0;
829
- }
830
- window.addEventListener("scroll", () => {
831
- if (!window._qRouterScrollEnabled && !window._qCityScrollEnabled) {
832
- return;
833
- }
834
- clearTimeout(window._qRouterScrollDebounce);
835
- window._qRouterScrollDebounce = setTimeout(() => {
836
- const scrollState2 = currentScrollState(scroller);
837
- saveScrollHistory(scrollState2);
838
- window._qRouterScrollDebounce = void 0;
839
- }, 200);
840
- }, {
841
- passive: true
842
- });
843
- removeEventListener("scroll", window._qRouterInitScroll);
844
- window._qRouterInitScroll = void 0;
845
- spaInit.resolve();
846
- }
847
- if (navType !== "popstate") {
848
- window._qRouterScrollEnabled = false;
849
- clearTimeout(window._qRouterScrollDebounce);
850
- if (!navigation.historyUpdated) {
851
- const scrollState2 = currentScrollState(scroller);
852
- saveScrollHistory(scrollState2);
853
- }
854
- }
855
- const navigate = () => {
856
- if (navigation.historyUpdated) {
857
- const currentPath = location.pathname + location.search + location.hash;
858
- const nextPath = toPath(trackUrl);
859
- if (currentPath !== nextPath) {
860
- history.replaceState(history.state, "", nextPath);
861
- }
862
- } else {
863
- clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
864
- }
865
- contentInternal2.trigger();
866
- return _waitUntilRendered(container2);
867
- };
868
- const _waitNextPage = () => {
869
- if (isServer || props2?.viewTransition === false) {
870
- return navigate();
871
- } else {
872
- const viewTransition = startViewTransition({
873
- update: navigate,
874
- types: [
875
- "qwik-navigation"
876
- ]
877
- });
878
- if (!viewTransition) {
879
- return Promise.resolve();
880
- }
881
- return viewTransition.ready;
882
- }
883
- };
884
- _waitNextPage().catch((err) => {
885
- navigate();
886
- if (err instanceof DOMException && err.name === "TimeoutError") {
887
- throw new Error('View transition timed out. This can happen if you have "disableCache" in your browser devtools enabled.');
888
- }
889
- throw err;
890
- }).finally(() => {
891
- container2.element.setAttribute?.(Q_ROUTE, $routeName$);
892
- const scrollState2 = currentScrollState(scroller);
893
- saveScrollHistory(scrollState2);
894
- window._qRouterScrollEnabled = true;
895
- if (isBrowser) {
896
- callRestoreScrollOnDocument();
897
- }
898
- if (shouldForcePrevUrl) {
899
- forceStoreEffects(routeLocation2, "prevUrl");
900
- }
901
- if (shouldForceUrl) {
902
- forceStoreEffects(routeLocation2, "url");
903
- }
904
- if (shouldForceParams) {
905
- forceStoreEffects(routeLocation2, "params");
906
- }
907
- routeLocation2.isNavigating = false;
908
- navResolver2.r?.();
909
- });
910
- }
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
+ });
911
1073
  }, "useQwikRouter_useTask_XpalYii770E", [
1074
+ actionDataSignal,
912
1075
  actionState,
913
1076
  content,
914
1077
  contentInternal,
915
- documentHead,
916
1078
  env,
917
- getScroller,
918
1079
  goto,
919
1080
  httpStatus,
920
1081
  loaderState,
921
- loadersObject,
922
- navResolver,
923
- props,
1082
+ navContext,
924
1083
  routeInternal,
1084
+ routeLoaderCtx,
925
1085
  routeLocation,
926
- routeLocationTarget,
927
- serverHead
1086
+ routeLocationTarget
928
1087
  ]),
929
- // We should only wait for navigation to complete on the server
1088
+ // We should only wait for head calculation to complete on the server
930
1089
  {
931
1090
  deferUpdates: isServer
932
1091
  }
933
1092
  );
934
- };
935
- const QwikRouterProvider = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
936
- useQwikRouter(props);
937
- return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "5y_0");
938
- }, "QwikRouterProvider_component_6Kjfa79mqlY"));
939
- const QwikCityProvider = QwikRouterProvider;
940
- const useQwikMockRouter = (props) => {
941
- const urlEnv = props.url ?? "http://localhost/";
942
- const url = new URL(urlEnv);
943
- const routeLocation = useStore({
944
- url,
945
- params: props.params ?? {},
946
- isNavigating: false,
947
- prevUrl: void 0
948
- }, {
949
- deep: false
950
- });
951
- const container = _getContextContainer();
952
- const loadersObject = {};
953
- const loadersState = {};
954
- if (props.loaders) {
955
- for (const { loader, data } of props.loaders) {
956
- const id = loader.__id;
957
- loadersObject[id] = data;
958
- 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;
959
1098
  }
960
- }
961
- const goto = props.goto ?? /* @__PURE__ */ inlinedQrl(async () => {
962
- console.warn("QwikRouterMockProvider: goto not provided");
963
- }, "useQwikMockRouter_goto_aViHFxQ1a3s");
964
- const documentHead = useStore(createDocumentHead, {
965
- 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
966
1116
  });
967
- const content = useStore({
968
- headings: void 0,
969
- menu: void 0
970
- }, {
971
- deep: false
972
- });
973
- const contentInternal = useSignal();
974
- const actionState = useSignal();
975
- const httpStatus = useSignal({
976
- status: 200,
977
- message: ""
978
- });
979
- useContextProvider(ContentContext, content);
980
- useContextProvider(ContentInternalContext, contentInternal);
981
- useContextProvider(DocumentHeadContext, documentHead);
982
- useContextProvider(HttpStatusContext, httpStatus);
983
- useContextProvider(RouteLocationContext, routeLocation);
984
- useContextProvider(RouteNavigateContext, goto);
985
- useContextProvider(RouteStateContext, loadersState);
986
- useContextProvider(RouteActionContext, actionState);
987
- const actionsMocks = props.actions?.reduce((acc, { action, handler }) => {
988
- acc[action.__id] = handler;
989
- return acc;
990
- }, {});
991
- useTaskQrl(/* @__PURE__ */ inlinedQrl(async ({ track }) => {
992
- const actionState2 = _captures[0], actionsMocks2 = _captures[1];
993
- const action = track(actionState2);
994
- 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) {
995
1121
  return;
996
1122
  }
997
- const mock = actionsMocks2?.[action.id];
998
- if (mock) {
999
- const actionResult = await mock(action.data);
1000
- action.resolve(actionResult);
1123
+ if (nav.navCount !== internalState.navCount) {
1124
+ return;
1001
1125
  }
1002
- }, "useQwikMockRouter_useTask_tXTLR4tzCy0", [
1003
- actionState,
1004
- actionsMocks
1005
- ]));
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
+ });
1006
1228
  };
1007
- const QwikRouterMockProvider = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
1008
- useQwikMockRouter(props);
1009
- return /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "5y_1");
1010
- }, "QwikRouterMockProvider_component_IN4dVpT0x74"));
1011
- 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;
1012
1234
 
1013
1235
  const handleRouterPopstate = (nav, event) => {
1014
1236
  const href = event.detail?.href;
@@ -1060,7 +1282,6 @@ const RouterOutlet = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl(()
1060
1282
  return SkipRender;
1061
1283
  }, "RouterOutlet_component_QwONcWD5gIg"));
1062
1284
 
1063
- const getValue = (obj) => obj.value;
1064
1285
  const validatorQrl = (validator) => {
1065
1286
  if (isServer) {
1066
1287
  return {
@@ -1185,7 +1406,7 @@ const zodQrl = (qrl) => {
1185
1406
  const zod$ = /* @__PURE__ */ implicit$FirstArg(zodQrl);
1186
1407
  const getValidators = (rest, qrl) => {
1187
1408
  let id;
1188
- let serializationStrategy = DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
1409
+ let invalidate;
1189
1410
  const validators = [];
1190
1411
  if (rest.length === 1) {
1191
1412
  const options = rest[0];
@@ -1194,12 +1415,12 @@ const getValidators = (rest, qrl) => {
1194
1415
  validators.push(options);
1195
1416
  } else {
1196
1417
  id = options.id;
1197
- if (options.serializationStrategy) {
1198
- serializationStrategy = options.serializationStrategy;
1199
- }
1200
1418
  if (options.validation) {
1201
1419
  validators.push(...options.validation);
1202
1420
  }
1421
+ if (options.invalidate) {
1422
+ invalidate = options.invalidate.map((loader) => loader.__id);
1423
+ }
1203
1424
  }
1204
1425
  }
1205
1426
  } else if (rest.length > 1) {
@@ -1218,11 +1439,11 @@ const getValidators = (rest, qrl) => {
1218
1439
  return {
1219
1440
  validators: validators.reverse(),
1220
1441
  id,
1221
- serializationStrategy
1442
+ invalidate
1222
1443
  };
1223
1444
  };
1224
1445
  const routeActionQrl = (actionQrl, ...rest) => {
1225
- const { id, validators } = getValidators(rest, actionQrl);
1446
+ const { id, validators, invalidate } = getValidators(rest, actionQrl);
1226
1447
  function action() {
1227
1448
  const loc = useLocation();
1228
1449
  const currentAction = useAction();
@@ -1317,6 +1538,7 @@ Action.run() can only be called on the browser, for example when a user clicks a
1317
1538
  action.__validators = validators;
1318
1539
  action.__qrl = actionQrl;
1319
1540
  action.__id = id;
1541
+ action.__invalidate = invalidate;
1320
1542
  Object.freeze(action);
1321
1543
  return action;
1322
1544
  };
@@ -1332,32 +1554,6 @@ const globalActionQrl = (actionQrl, ...rest) => {
1332
1554
  };
1333
1555
  const routeAction$ = /* @__PURE__ */ implicit$FirstArg(routeActionQrl);
1334
1556
  const globalAction$ = /* @__PURE__ */ implicit$FirstArg(globalActionQrl);
1335
- const routeLoaderQrl = (loaderQrl, ...rest) => {
1336
- const { id, validators, serializationStrategy } = getValidators(rest, loaderQrl);
1337
- function loader() {
1338
- const state = _resolveContextWithoutSequentialScope(RouteStateContext);
1339
- if (!(id in state)) {
1340
- throw new Error(`routeLoader$ "${loaderQrl.getSymbol()}" was invoked in a route where it was not declared.
1341
- This is because the routeLoader$ was not exported in a 'layout.tsx' or 'index.tsx' file of the existing route.
1342
- For more information check: https://qwik.dev/docs/route-loader/
1343
-
1344
- 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.
1345
- For more information check: https://qwik.dev/docs/re-exporting-loaders/`);
1346
- }
1347
- const loaderData = state[id];
1348
- untrack(getValue, loaderData);
1349
- return loaderData;
1350
- }
1351
- loader.__brand = "server_loader";
1352
- loader.__qrl = loaderQrl;
1353
- loader.__validators = validators;
1354
- loader.__id = id;
1355
- loader.__serializationStrategy = serializationStrategy;
1356
- loader.__expires = -1;
1357
- Object.freeze(loader);
1358
- return loader;
1359
- };
1360
- const routeLoader$ = /* @__PURE__ */ implicit$FirstArg(routeLoaderQrl);
1361
1557
  const deserializeStream = async function* (stream, abortSignal) {
1362
1558
  const reader = stream.getReader();
1363
1559
  try {
@@ -1397,16 +1593,7 @@ const serverQrl = (qrl, options) => {
1397
1593
  const fetchOptions2 = _captures[0], headers2 = _captures[1], method2 = _captures[2], origin2 = _captures[3], qrl2 = _captures[4];
1398
1594
  const abortSignal = args.length > 0 && args[0] instanceof AbortSignal ? args.shift() : void 0;
1399
1595
  if (isServer) {
1400
- let requestEvent = _asyncRequestStore?.getStore();
1401
- if (!requestEvent) {
1402
- const contexts = [
1403
- useQwikRouterEnv()?.ev,
1404
- this,
1405
- _getContextEvent()
1406
- ];
1407
- requestEvent = contexts.find((v2) => v2 && Object.prototype.hasOwnProperty.call(v2, "sharedMap") && Object.prototype.hasOwnProperty.call(v2, "cookie"));
1408
- }
1409
- return qrl2.apply(requestEvent, args);
1596
+ return qrl2.apply(getRequestEvent(this), args);
1410
1597
  } else {
1411
1598
  let filteredArgs = args.map((arg) => {
1412
1599
  if (arg instanceof SubmitEvent && arg.target instanceof HTMLFormElement) {
@@ -1633,9 +1820,7 @@ const untypedAppUrl = function appUrl(route, params, paramsPrefix = "") {
1633
1820
  let url = path.join("/");
1634
1821
  let baseURL = "/";
1635
1822
  if (baseURL) {
1636
- if (!baseURL.endsWith("/")) {
1637
- baseURL += "/";
1638
- }
1823
+ baseURL = ensureSlash(baseURL);
1639
1824
  while (url.startsWith("/")) {
1640
1825
  url = url.substring(1);
1641
1826
  }
@@ -1656,7 +1841,15 @@ function omitProps(obj, keys) {
1656
1841
  const createRenderer = (getOptions) => {
1657
1842
  return (opts) => {
1658
1843
  const { jsx, options } = getOptions(opts);
1659
- return renderToStream(jsx, options);
1844
+ const isStatic = opts.serverData.renderMode === "static";
1845
+ const renderOptions = isStatic ? {
1846
+ ...options,
1847
+ streaming: {
1848
+ ...options.streaming,
1849
+ outOfOrder: false
1850
+ }
1851
+ } : options;
1852
+ return renderToStream(jsx, renderOptions);
1660
1853
  };
1661
1854
  };
1662
1855
 
@@ -1695,4 +1888,4 @@ const DocumentHeadTags = /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl
1695
1888
  ], 1, "r5_3");
1696
1889
  }, "DocumentHeadTags_component_9CrWYOoCpgY"));
1697
1890
 
1698
- 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 };