kiru 0.54.0-preview.1 → 0.54.0
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.
- package/dist/components/derive.d.ts +1 -1
- package/dist/components/derive.d.ts.map +1 -1
- package/dist/components/derive.js +2 -3
- package/dist/components/derive.js.map +1 -1
- package/dist/components/memo.d.ts +1 -3
- package/dist/components/memo.d.ts.map +1 -1
- package/dist/components/memo.js +2 -2
- package/dist/components/memo.js.map +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +1 -23
- package/dist/context.js.map +1 -1
- package/dist/dom.d.ts.map +1 -1
- package/dist/dom.js +111 -78
- package/dist/dom.js.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +2 -4
- package/dist/error.js.map +1 -1
- package/dist/form/index.d.ts.map +1 -1
- package/dist/form/index.js +6 -10
- package/dist/form/index.js.map +1 -1
- package/dist/globals.d.ts +1 -1
- package/dist/globals.d.ts.map +1 -1
- package/dist/globals.js.map +1 -1
- package/dist/hmr.d.ts +1 -0
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +11 -3
- package/dist/hmr.js.map +1 -1
- package/dist/hooks/useEffectEvent.d.ts.map +1 -1
- package/dist/hooks/useEffectEvent.js.map +1 -1
- package/dist/hooks/usePromise.d.ts +1 -2
- package/dist/hooks/usePromise.d.ts.map +1 -1
- package/dist/hooks/usePromise.js +62 -31
- package/dist/hooks/usePromise.js.map +1 -1
- package/dist/hooks/utils.d.ts.map +1 -1
- package/dist/hooks/utils.js +10 -10
- package/dist/hooks/utils.js.map +1 -1
- package/dist/hydration.d.ts +6 -13
- package/dist/hydration.d.ts.map +1 -1
- package/dist/hydration.js +20 -50
- package/dist/hydration.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/reconciler.d.ts.map +1 -1
- package/dist/reconciler.js +3 -6
- package/dist/reconciler.js.map +1 -1
- package/dist/recursiveRender.d.ts.map +1 -1
- package/dist/recursiveRender.js +9 -8
- package/dist/recursiveRender.js.map +1 -1
- package/dist/renderToString.d.ts.map +1 -1
- package/dist/renderToString.js.map +1 -1
- package/dist/router/client/index.d.ts +2 -4
- package/dist/router/client/index.d.ts.map +1 -1
- package/dist/router/client/index.js +13 -59
- package/dist/router/client/index.js.map +1 -1
- package/dist/router/context.d.ts +5 -2
- package/dist/router/context.d.ts.map +1 -1
- package/dist/router/context.js +1 -5
- package/dist/router/context.js.map +1 -1
- package/dist/router/fileRouter.d.ts.map +1 -1
- package/dist/router/fileRouter.js +2 -4
- package/dist/router/fileRouter.js.map +1 -1
- package/dist/router/fileRouterController.d.ts +2 -2
- package/dist/router/fileRouterController.d.ts.map +1 -1
- package/dist/router/fileRouterController.js +135 -214
- package/dist/router/fileRouterController.js.map +1 -1
- package/dist/router/globals.d.ts +0 -3
- package/dist/router/globals.d.ts.map +1 -1
- package/dist/router/globals.js +0 -3
- package/dist/router/globals.js.map +1 -1
- package/dist/router/head.d.ts.map +1 -1
- package/dist/router/head.js +7 -5
- package/dist/router/head.js.map +1 -1
- package/dist/router/index.d.ts +1 -2
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +1 -2
- package/dist/router/index.js.map +1 -1
- package/dist/router/link.js +3 -3
- package/dist/router/link.js.map +1 -1
- package/dist/router/{ssg → server}/index.d.ts +3 -4
- package/dist/router/server/index.d.ts.map +1 -0
- package/dist/router/{ssg → server}/index.js +6 -9
- package/dist/router/server/index.js.map +1 -0
- package/dist/router/types.d.ts +16 -42
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/types.internal.d.ts +0 -4
- package/dist/router/types.internal.d.ts.map +1 -1
- package/dist/router/utils/index.d.ts +3 -8
- package/dist/router/utils/index.d.ts.map +1 -1
- package/dist/router/utils/index.js +8 -40
- package/dist/router/utils/index.js.map +1 -1
- package/dist/scheduler.d.ts +3 -14
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +64 -56
- package/dist/scheduler.js.map +1 -1
- package/dist/signals/base.d.ts +0 -2
- package/dist/signals/base.d.ts.map +1 -1
- package/dist/signals/base.js +0 -6
- package/dist/signals/base.js.map +1 -1
- package/dist/signals/computed.d.ts +3 -0
- package/dist/signals/computed.d.ts.map +1 -1
- package/dist/signals/computed.js +29 -20
- package/dist/signals/computed.js.map +1 -1
- package/dist/signals/for.d.ts +3 -3
- package/dist/signals/for.d.ts.map +1 -1
- package/dist/signals/for.js +2 -1
- package/dist/signals/for.js.map +1 -1
- package/dist/signals/utils.d.ts.map +1 -1
- package/dist/signals/utils.js +2 -1
- package/dist/signals/utils.js.map +1 -1
- package/dist/signals/watch.d.ts.map +1 -1
- package/dist/signals/watch.js +18 -22
- package/dist/signals/watch.js.map +1 -1
- package/dist/ssr/client.d.ts +1 -1
- package/dist/ssr/client.d.ts.map +1 -1
- package/dist/ssr/client.js +0 -2
- package/dist/ssr/client.js.map +1 -1
- package/dist/ssr/server.d.ts +3 -9
- package/dist/ssr/server.d.ts.map +1 -1
- package/dist/ssr/server.js +30 -37
- package/dist/ssr/server.js.map +1 -1
- package/dist/types.d.ts +0 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.dom.d.ts +3 -3
- package/dist/types.dom.d.ts.map +1 -1
- package/dist/utils/format.d.ts +1 -2
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js +1 -4
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/promise.d.ts +0 -2
- package/dist/utils/promise.d.ts.map +1 -1
- package/dist/utils/promise.js +1 -45
- package/dist/utils/promise.js.map +1 -1
- package/dist/utils/runtime.d.ts +3 -2
- package/dist/utils/runtime.d.ts.map +1 -1
- package/dist/utils/runtime.js +5 -2
- package/dist/utils/runtime.js.map +1 -1
- package/dist/utils/vdom.d.ts.map +1 -1
- package/dist/utils/vdom.js +2 -2
- package/dist/utils/vdom.js.map +1 -1
- package/package.json +4 -8
- package/src/components/derive.ts +3 -5
- package/src/components/memo.ts +3 -11
- package/src/context.ts +1 -24
- package/src/dom.ts +146 -101
- package/src/error.ts +2 -4
- package/src/form/index.ts +6 -9
- package/src/globals.ts +1 -1
- package/src/hmr.ts +14 -5
- package/src/hooks/useEffectEvent.ts +0 -1
- package/src/hooks/usePromise.ts +77 -58
- package/src/hooks/utils.ts +12 -12
- package/src/hydration.ts +21 -57
- package/src/index.ts +1 -1
- package/src/reconciler.ts +2 -6
- package/src/recursiveRender.ts +10 -9
- package/src/renderToString.ts +0 -1
- package/src/router/client/index.ts +16 -114
- package/src/router/context.ts +6 -7
- package/src/router/fileRouter.ts +2 -6
- package/src/router/fileRouterController.ts +161 -324
- package/src/router/globals.ts +0 -4
- package/src/router/head.ts +7 -5
- package/src/router/index.ts +1 -12
- package/src/router/link.ts +3 -3
- package/src/router/{ssg → server}/index.ts +11 -18
- package/src/router/types.internal.ts +0 -5
- package/src/router/types.ts +16 -53
- package/src/router/utils/index.ts +16 -79
- package/src/scheduler.ts +85 -89
- package/src/signals/base.ts +0 -8
- package/src/signals/computed.ts +30 -18
- package/src/signals/for.ts +15 -10
- package/src/signals/utils.ts +2 -1
- package/src/signals/watch.ts +27 -22
- package/src/ssr/client.ts +1 -4
- package/src/ssr/server.ts +34 -59
- package/src/types.dom.ts +4 -5
- package/src/types.ts +0 -10
- package/src/utils/format.ts +0 -5
- package/src/utils/index.ts +1 -1
- package/src/utils/promise.ts +1 -70
- package/src/utils/runtime.ts +6 -2
- package/src/utils/vdom.ts +2 -7
- package/dist/router/constants.d.ts +0 -2
- package/dist/router/constants.d.ts.map +0 -1
- package/dist/router/constants.js +0 -2
- package/dist/router/constants.js.map +0 -1
- package/dist/router/guard.d.ts +0 -17
- package/dist/router/guard.d.ts.map +0 -1
- package/dist/router/guard.js +0 -45
- package/dist/router/guard.js.map +0 -1
- package/dist/router/ssg/index.d.ts.map +0 -1
- package/dist/router/ssg/index.js.map +0 -1
- package/dist/router/ssr/index.d.ts +0 -20
- package/dist/router/ssr/index.d.ts.map +0 -1
- package/dist/router/ssr/index.js +0 -163
- package/dist/router/ssr/index.js.map +0 -1
- package/src/router/constants.ts +0 -1
- package/src/router/guard.ts +0 -72
- package/src/router/ssr/index.ts +0 -252
|
@@ -2,16 +2,14 @@ import { Signal } from "../signals/base.js";
|
|
|
2
2
|
import { watch } from "../signals/watch.js";
|
|
3
3
|
import { __DEV__ } from "../env.js";
|
|
4
4
|
import { flushSync, nextIdle } from "../scheduler.js";
|
|
5
|
-
import { toArray } from "../utils/format.js";
|
|
6
5
|
import { FileRouterDataLoadError } from "./errors.js";
|
|
7
|
-
import { fileRouterInstance, fileRouterRoute,
|
|
8
|
-
import { formatViteImportMap,
|
|
6
|
+
import { fileRouterInstance, fileRouterRoute, routerCache } from "./globals.js";
|
|
7
|
+
import { formatViteImportMap, matchLayouts, matchRoute, match404Route, normalizePrefixPath, parseQuery, wrapWithLayouts, } from "./utils/index.js";
|
|
9
8
|
import { RouterCache } from "./cache.js";
|
|
10
9
|
import { scrollStack } from "./scrollStack.js";
|
|
11
|
-
let transitionId = 0;
|
|
12
|
-
let currentTransition = null;
|
|
13
10
|
export class FileRouterController {
|
|
14
11
|
constructor() {
|
|
12
|
+
this.baseUrl = "/";
|
|
15
13
|
routerCache.current ?? (routerCache.current = new RouterCache());
|
|
16
14
|
this.abortController = new AbortController();
|
|
17
15
|
this.currentPage = new Signal(null);
|
|
@@ -21,7 +19,6 @@ export class FileRouterController {
|
|
|
21
19
|
this.historyIndex = 0;
|
|
22
20
|
this.layouts = {};
|
|
23
21
|
this.pages = {};
|
|
24
|
-
this.guards = {};
|
|
25
22
|
this.state = {
|
|
26
23
|
pathname: window.location.pathname,
|
|
27
24
|
hash: window.location.hash,
|
|
@@ -29,27 +26,7 @@ export class FileRouterController {
|
|
|
29
26
|
query: {},
|
|
30
27
|
signal: this.abortController.signal,
|
|
31
28
|
};
|
|
32
|
-
|
|
33
|
-
this.contextValue = {
|
|
34
|
-
invalidate: async (...paths) => {
|
|
35
|
-
if (this.invalidate(...paths)) {
|
|
36
|
-
return this.loadRoute();
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
get state() {
|
|
40
|
-
return { ...__this.state };
|
|
41
|
-
},
|
|
42
|
-
navigate: this.navigate.bind(this),
|
|
43
|
-
prefetchRouteModules: this.prefetchRouteModules.bind(this),
|
|
44
|
-
reload: async (options) => {
|
|
45
|
-
if (options?.invalidate ?? true) {
|
|
46
|
-
this.invalidate(this.state.pathname);
|
|
47
|
-
}
|
|
48
|
-
return this.loadRoute({ transition: options?.transition });
|
|
49
|
-
},
|
|
50
|
-
setQuery: this.setQuery.bind(this),
|
|
51
|
-
setHash: this.setHash.bind(this),
|
|
52
|
-
};
|
|
29
|
+
this.contextValue = this.createContextValue();
|
|
53
30
|
if (__DEV__) {
|
|
54
31
|
this.filePathToPageRoute = new Map();
|
|
55
32
|
this.pageRouteToConfig = new Map();
|
|
@@ -66,10 +43,11 @@ export class FileRouterController {
|
|
|
66
43
|
const loader = config.loader;
|
|
67
44
|
if (curPage?.route === existing.route && loader) {
|
|
68
45
|
const p = this.currentPageProps.value;
|
|
69
|
-
const transition = (
|
|
46
|
+
const transition = (loader.mode !== "static" && loader.transition) ??
|
|
47
|
+
this.enableTransitions;
|
|
70
48
|
// Check cache first if caching is enabled
|
|
71
49
|
let cachedData = null;
|
|
72
|
-
if (
|
|
50
|
+
if (loader.mode !== "static" && loader.cache) {
|
|
73
51
|
const cacheKey = {
|
|
74
52
|
path: this.state.pathname,
|
|
75
53
|
params: this.state.params,
|
|
@@ -85,7 +63,9 @@ export class FileRouterController {
|
|
|
85
63
|
error: null,
|
|
86
64
|
loading: false,
|
|
87
65
|
};
|
|
88
|
-
handleStateTransition(
|
|
66
|
+
handleStateTransition(this.state.signal, transition, () => {
|
|
67
|
+
this.currentPageProps.value = props;
|
|
68
|
+
});
|
|
89
69
|
}
|
|
90
70
|
else {
|
|
91
71
|
// No cached data - show loading state and load data
|
|
@@ -95,8 +75,10 @@ export class FileRouterController {
|
|
|
95
75
|
data: null,
|
|
96
76
|
error: null,
|
|
97
77
|
};
|
|
98
|
-
handleStateTransition(
|
|
99
|
-
|
|
78
|
+
handleStateTransition(this.state.signal, transition, () => {
|
|
79
|
+
this.currentPageProps.value = props;
|
|
80
|
+
});
|
|
81
|
+
this.loadRouteData(config, props, this.state, transition);
|
|
100
82
|
}
|
|
101
83
|
}
|
|
102
84
|
this.pageRouteToConfig?.set(existing.route, config);
|
|
@@ -121,25 +103,15 @@ export class FileRouterController {
|
|
|
121
103
|
}
|
|
122
104
|
}
|
|
123
105
|
init(config) {
|
|
124
|
-
const { pages, layouts,
|
|
106
|
+
const { pages, layouts, dir = "/pages", baseUrl = "/", transition, preloaded, } = config;
|
|
125
107
|
this.enableTransitions = !!transition;
|
|
126
108
|
const [normalizedDir, normalizedBaseUrl] = [
|
|
127
109
|
normalizePrefixPath(dir),
|
|
128
110
|
normalizePrefixPath(baseUrl),
|
|
129
111
|
];
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
this.guards = !guards
|
|
134
|
-
? {}
|
|
135
|
-
: formatViteImportMap(guards, normalizedDir, normalizedBaseUrl);
|
|
136
|
-
if (__DEV__) {
|
|
137
|
-
validateRoutes(this.pages);
|
|
138
|
-
}
|
|
139
|
-
this.loadRoute();
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
const { pages, layouts, guards, page, pageProps, pagePropsPromise, pageLayouts, route, params, query, cacheData, } = preloaded;
|
|
112
|
+
this.baseUrl = normalizedBaseUrl.slice(0, -1);
|
|
113
|
+
if (preloaded) {
|
|
114
|
+
const { pages, layouts, page, pageProps, pageLayouts, route, params, query, cacheData, } = preloaded;
|
|
143
115
|
this.state = {
|
|
144
116
|
params,
|
|
145
117
|
query,
|
|
@@ -156,42 +128,45 @@ export class FileRouterController {
|
|
|
156
128
|
this.currentLayouts.value = pageLayouts.map((l) => l.default);
|
|
157
129
|
this.pages = pages;
|
|
158
130
|
this.layouts = layouts;
|
|
159
|
-
this.guards = (guards ??
|
|
160
|
-
{});
|
|
161
131
|
if (__DEV__) {
|
|
162
|
-
validateRoutes(this.pages);
|
|
163
132
|
if (page.config) {
|
|
164
133
|
this.dev_onPageConfigDefined(route, page.config);
|
|
165
134
|
}
|
|
166
135
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (loader && pagePropsPromise) {
|
|
170
|
-
const prevState = this.state;
|
|
171
|
-
pagePropsPromise.then(({ data, error }) => {
|
|
172
|
-
if (this.state !== prevState)
|
|
173
|
-
return;
|
|
174
|
-
handleStateTransition(transition, transitionId, () => (this.currentPageProps.value = { loading: false, data, error }));
|
|
175
|
-
});
|
|
136
|
+
if (__DEV__) {
|
|
137
|
+
validateRoutes(this.pages);
|
|
176
138
|
}
|
|
177
|
-
|
|
178
|
-
|
|
139
|
+
const loader = page.config?.loader;
|
|
140
|
+
if (loader &&
|
|
141
|
+
((loader.mode !== "static" && pageProps.loading === true) || __DEV__)) {
|
|
179
142
|
if (cacheData === null) {
|
|
180
|
-
this.loadRouteData(page.config, this.state);
|
|
143
|
+
this.loadRouteData(page.config, pageProps, this.state);
|
|
181
144
|
}
|
|
182
145
|
else {
|
|
183
146
|
nextIdle(() => {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
147
|
+
const props = {
|
|
148
|
+
...pageProps,
|
|
149
|
+
data: cacheData.value,
|
|
150
|
+
error: null,
|
|
151
|
+
loading: false,
|
|
152
|
+
};
|
|
153
|
+
// @ts-ignore
|
|
154
|
+
const transition = loader.transition ?? this.enableTransitions;
|
|
155
|
+
handleStateTransition(this.state.signal, transition, () => {
|
|
156
|
+
this.currentPageProps.value = props;
|
|
190
157
|
});
|
|
191
158
|
});
|
|
192
159
|
}
|
|
193
160
|
}
|
|
194
161
|
}
|
|
162
|
+
else {
|
|
163
|
+
this.pages = formatViteImportMap(pages, normalizedDir, normalizedBaseUrl);
|
|
164
|
+
this.layouts = formatViteImportMap(layouts, normalizedDir, normalizedBaseUrl);
|
|
165
|
+
if (__DEV__) {
|
|
166
|
+
validateRoutes(this.pages);
|
|
167
|
+
}
|
|
168
|
+
this.loadRoute();
|
|
169
|
+
}
|
|
195
170
|
window.history.scrollRestoration = "manual";
|
|
196
171
|
const historyState = window.history.state;
|
|
197
172
|
if (typeof historyState !== "object" ||
|
|
@@ -219,59 +194,20 @@ export class FileRouterController {
|
|
|
219
194
|
scrollStack.replace(this.historyIndex, window.scrollX, window.scrollY);
|
|
220
195
|
window.history.scrollRestoration = "auto";
|
|
221
196
|
});
|
|
222
|
-
let ignorePopState = false;
|
|
223
197
|
window.addEventListener("popstate", (e) => {
|
|
224
198
|
e.preventDefault();
|
|
225
|
-
if (!ignorePopState &&
|
|
226
|
-
this.onBeforeLeave(window.location.pathname) === false) {
|
|
227
|
-
ignorePopState = true;
|
|
228
|
-
if (e.state !== null) {
|
|
229
|
-
if (e.state.index > this.historyIndex) {
|
|
230
|
-
window.history.go(-1);
|
|
231
|
-
}
|
|
232
|
-
else if (e.state.index < this.historyIndex) {
|
|
233
|
-
window.history.go(1);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
if (ignorePopState) {
|
|
239
|
-
ignorePopState = false;
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
199
|
scrollStack.replace(this.historyIndex, window.scrollX, window.scrollY);
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
let onPaint;
|
|
246
|
-
if (e.state != null) {
|
|
247
|
-
onPaint = () => {
|
|
200
|
+
this.loadRoute().then(() => {
|
|
201
|
+
if (e.state != null) {
|
|
248
202
|
this.historyIndex = e.state.index;
|
|
249
203
|
const offset = scrollStack.getItem(e.state.index);
|
|
250
204
|
if (offset !== undefined) {
|
|
251
205
|
window.scrollTo(...offset);
|
|
252
206
|
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
this.loadRoute({ onPaint });
|
|
207
|
+
}
|
|
208
|
+
});
|
|
256
209
|
});
|
|
257
210
|
}
|
|
258
|
-
onBeforeLeave(to) {
|
|
259
|
-
const currentPage = this.currentPage.peek();
|
|
260
|
-
if (!currentPage) {
|
|
261
|
-
return true;
|
|
262
|
-
}
|
|
263
|
-
let config = currentPage.config ?? {};
|
|
264
|
-
if (__DEV__) {
|
|
265
|
-
if (this.pageRouteToConfig?.has(currentPage.route)) {
|
|
266
|
-
config = this.pageRouteToConfig.get(currentPage.route);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
const onBeforeLeave = config.hooks?.onBeforeLeave;
|
|
270
|
-
if (onBeforeLeave) {
|
|
271
|
-
return runBeforeLeaveHooks(toArray(onBeforeLeave), { ...requestContext.current }, to, this.state.pathname);
|
|
272
|
-
}
|
|
273
|
-
return true;
|
|
274
|
-
}
|
|
275
211
|
getChildren() {
|
|
276
212
|
const page = this.currentPage.value;
|
|
277
213
|
if (!page)
|
|
@@ -288,8 +224,7 @@ export class FileRouterController {
|
|
|
288
224
|
fileRouterRoute.current = null;
|
|
289
225
|
fileRouterInstance.current = null;
|
|
290
226
|
}
|
|
291
|
-
async loadRoute(
|
|
292
|
-
const { transition: enableTransition = this.enableTransitions, isStatic404 = false, path = window.location.pathname, onPaint, } = options ?? {};
|
|
227
|
+
async loadRoute(path = window.location.pathname, props = {}, enableTransition = this.enableTransitions, isStatic404 = false) {
|
|
293
228
|
this.abortController?.abort();
|
|
294
229
|
const signal = (this.abortController = new AbortController()).signal;
|
|
295
230
|
try {
|
|
@@ -308,22 +243,9 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`);
|
|
|
308
243
|
routeMatch = _404Match;
|
|
309
244
|
}
|
|
310
245
|
const { route, pageEntry, params, routeSegments } = routeMatch;
|
|
311
|
-
// Apply beforeEach guards before loading route
|
|
312
|
-
const guardEntries = matchModules(this.guards, routeSegments);
|
|
313
|
-
const guardModules = await Promise.all(guardEntries.map((entry) => entry.load()));
|
|
314
|
-
const fromPath = this.state.pathname;
|
|
315
|
-
const redirectPath = await runBeforeEachGuards(guardModules, { ...requestContext.current }, path, fromPath);
|
|
316
|
-
// If redirect was requested, navigate to that path instead
|
|
317
|
-
if (redirectPath !== null) {
|
|
318
|
-
this.state.pathname = path;
|
|
319
|
-
return this.navigate(redirectPath, {
|
|
320
|
-
replace: true,
|
|
321
|
-
transition: enableTransition,
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
246
|
fileRouterRoute.current = route;
|
|
325
247
|
const pagePromise = pageEntry.load();
|
|
326
|
-
const layoutPromises =
|
|
248
|
+
const layoutPromises = matchLayouts(this.layouts, routeSegments).map((layoutEntry) => layoutEntry.load());
|
|
327
249
|
const [page, ...layouts] = await Promise.all([
|
|
328
250
|
pagePromise,
|
|
329
251
|
...layoutPromises,
|
|
@@ -348,67 +270,56 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`);
|
|
|
348
270
|
config = this.pageRouteToConfig.get(route);
|
|
349
271
|
}
|
|
350
272
|
}
|
|
351
|
-
const { loader
|
|
352
|
-
if (
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
273
|
+
const { loader } = config;
|
|
274
|
+
if (loader) {
|
|
275
|
+
if (loader.mode !== "static" || __DEV__) {
|
|
276
|
+
// Check cache first if caching is enabled
|
|
277
|
+
let cachedData = null;
|
|
278
|
+
if (loader.mode !== "static" && loader.cache) {
|
|
279
|
+
const cacheKey = {
|
|
280
|
+
path: routerState.pathname,
|
|
281
|
+
params: routerState.params,
|
|
282
|
+
query: routerState.query,
|
|
283
|
+
};
|
|
284
|
+
cachedData = routerCache.current.get(cacheKey, loader.cache);
|
|
285
|
+
}
|
|
286
|
+
if (cachedData !== null) {
|
|
287
|
+
// Use cached data immediately - no loading state needed
|
|
288
|
+
props = {
|
|
289
|
+
...props,
|
|
290
|
+
data: cachedData.value,
|
|
291
|
+
error: null,
|
|
292
|
+
loading: false,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
// No cached data - show loading state and load data
|
|
297
|
+
props = {
|
|
298
|
+
...props,
|
|
299
|
+
loading: true,
|
|
300
|
+
data: null,
|
|
301
|
+
error: null,
|
|
302
|
+
};
|
|
303
|
+
this.loadRouteData(config, props, routerState, enableTransition);
|
|
304
|
+
}
|
|
379
305
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
error: new FileRouterDataLoadError(error),
|
|
385
|
-
loading: false,
|
|
306
|
+
else {
|
|
307
|
+
const staticProps = page.__KIRU_STATIC_PROPS__?.[path];
|
|
308
|
+
if (!staticProps) {
|
|
309
|
+
return this.loadRoute(path, props, enableTransition, true);
|
|
386
310
|
}
|
|
387
|
-
|
|
388
|
-
data: data,
|
|
389
|
-
error: null,
|
|
390
|
-
loading: false,
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
else if (!loader?.static && loader?.cache) {
|
|
394
|
-
const cacheKey = {
|
|
395
|
-
path: routerState.pathname,
|
|
396
|
-
params: routerState.params,
|
|
397
|
-
query: routerState.query,
|
|
398
|
-
};
|
|
399
|
-
const cachedData = routerCache.current.get(cacheKey, loader.cache);
|
|
400
|
-
if (cachedData !== null) {
|
|
311
|
+
const { data, error } = staticProps;
|
|
401
312
|
props = {
|
|
402
|
-
|
|
403
|
-
|
|
313
|
+
...props,
|
|
314
|
+
data: data,
|
|
315
|
+
error: error ? new FileRouterDataLoadError(error) : null,
|
|
404
316
|
loading: false,
|
|
405
317
|
};
|
|
406
318
|
}
|
|
407
319
|
}
|
|
408
|
-
|
|
409
|
-
let tId = transitionId++;
|
|
410
|
-
return await handleStateTransition(enableTransition, tId, () => {
|
|
320
|
+
return handleStateTransition(signal, enableTransition, () => {
|
|
411
321
|
this.state = routerState;
|
|
322
|
+
this.contextValue = this.createContextValue();
|
|
412
323
|
this.currentPage.value = {
|
|
413
324
|
component: page.default,
|
|
414
325
|
config,
|
|
@@ -418,15 +329,6 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`);
|
|
|
418
329
|
this.currentLayouts.value = layouts
|
|
419
330
|
.filter((m) => typeof m.default === "function")
|
|
420
331
|
.map((m) => m.default);
|
|
421
|
-
nextIdle(() => {
|
|
422
|
-
runAfterEachGuards(guardModules, { ...requestContext.current }, path, fromPath);
|
|
423
|
-
if (props.loading) {
|
|
424
|
-
this.loadRouteData(config, routerState, enableTransition, tId).then(() => signal.aborted || onPaint?.());
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
onPaint?.();
|
|
428
|
-
}
|
|
429
|
-
});
|
|
430
332
|
});
|
|
431
333
|
}
|
|
432
334
|
catch (error) {
|
|
@@ -434,14 +336,14 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`);
|
|
|
434
336
|
this.currentPage.value = null;
|
|
435
337
|
}
|
|
436
338
|
}
|
|
437
|
-
async loadRouteData(config, routerState, enableTransition = this.enableTransitions
|
|
339
|
+
async loadRouteData(config, props, routerState, enableTransition = this.enableTransitions) {
|
|
438
340
|
const { loader } = config;
|
|
439
341
|
// Load data from loader (cache check is now done earlier in loadRoute)
|
|
440
|
-
|
|
441
|
-
.load(
|
|
342
|
+
loader
|
|
343
|
+
.load(routerState)
|
|
442
344
|
.then((data) => {
|
|
443
345
|
// Cache the data if caching is enabled
|
|
444
|
-
if (
|
|
346
|
+
if (loader.mode !== "static" && loader.cache) {
|
|
445
347
|
const cacheKey = {
|
|
446
348
|
path: routerState.pathname,
|
|
447
349
|
params: routerState.params,
|
|
@@ -462,8 +364,13 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`);
|
|
|
462
364
|
.then((state) => {
|
|
463
365
|
if (routerState.signal.aborted)
|
|
464
366
|
return;
|
|
465
|
-
const transition = (
|
|
466
|
-
|
|
367
|
+
const transition = (loader.mode !== "static" && loader.transition) ?? enableTransition;
|
|
368
|
+
handleStateTransition(routerState.signal, transition, () => {
|
|
369
|
+
this.currentPageProps.value = {
|
|
370
|
+
...props,
|
|
371
|
+
...state,
|
|
372
|
+
};
|
|
373
|
+
});
|
|
467
374
|
});
|
|
468
375
|
}
|
|
469
376
|
invalidate(...paths) {
|
|
@@ -478,13 +385,11 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`);
|
|
|
478
385
|
const url = new URL(path, "http://localhost");
|
|
479
386
|
const { hash: nextHash, pathname: nextPath } = url;
|
|
480
387
|
const { hash: prevHash, pathname: prevPath } = this.state;
|
|
481
|
-
if (
|
|
482
|
-
this.onBeforeLeave(prevPath) === false) {
|
|
388
|
+
if (nextHash === prevHash && nextPath === prevPath) {
|
|
483
389
|
return;
|
|
484
390
|
}
|
|
485
391
|
this.updateHistoryState(path, options);
|
|
486
|
-
|
|
487
|
-
this.loadRoute({ transition }).then(() => {
|
|
392
|
+
this.loadRoute(void 0, void 0, options?.transition ?? this.enableTransitions).then(() => {
|
|
488
393
|
if (nextHash !== prevHash) {
|
|
489
394
|
window.dispatchEvent(new HashChangeEvent("hashchange"));
|
|
490
395
|
}
|
|
@@ -507,7 +412,7 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`);
|
|
|
507
412
|
const { pageEntry, route } = routeMatch;
|
|
508
413
|
fileRouterRoute.current = route;
|
|
509
414
|
const pagePromise = pageEntry.load();
|
|
510
|
-
const layoutPromises =
|
|
415
|
+
const layoutPromises = matchLayouts(this.layouts, route.split("/")).map((layoutEntry) => layoutEntry.load());
|
|
511
416
|
await Promise.all([pagePromise, ...layoutPromises]);
|
|
512
417
|
fileRouterRoute.current = null;
|
|
513
418
|
}
|
|
@@ -542,10 +447,10 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`);
|
|
|
542
447
|
window.history.replaceState({ ...window.history.state, index: this.historyIndex }, "", path);
|
|
543
448
|
}
|
|
544
449
|
else {
|
|
545
|
-
const current = scrollStack.get();
|
|
546
450
|
// if we've gone back and are now going forward, we need to
|
|
547
451
|
// truncate the scroll stack so it doesn't just permanently grow.
|
|
548
452
|
// this should keep it at the same length as the history stack.
|
|
453
|
+
const current = scrollStack.get();
|
|
549
454
|
if (this.historyIndex < window.history.length - 1) {
|
|
550
455
|
current.length = this.historyIndex;
|
|
551
456
|
}
|
|
@@ -553,6 +458,32 @@ See https://kirujs.dev/docs/api/file-router#404 for more information.`);
|
|
|
553
458
|
window.history.pushState({ ...window.history.state, index: ++this.historyIndex }, "", path);
|
|
554
459
|
}
|
|
555
460
|
}
|
|
461
|
+
createContextValue() {
|
|
462
|
+
const __this = this;
|
|
463
|
+
return {
|
|
464
|
+
get baseUrl() {
|
|
465
|
+
return __this.baseUrl;
|
|
466
|
+
},
|
|
467
|
+
invalidate: async (...paths) => {
|
|
468
|
+
if (this.invalidate(...paths)) {
|
|
469
|
+
return this.loadRoute(void 0, void 0, true);
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
get state() {
|
|
473
|
+
return { ...__this.state };
|
|
474
|
+
},
|
|
475
|
+
navigate: this.navigate.bind(this),
|
|
476
|
+
prefetchRouteModules: this.prefetchRouteModules.bind(this),
|
|
477
|
+
reload: async (options) => {
|
|
478
|
+
if (options?.invalidate ?? true) {
|
|
479
|
+
this.invalidate(this.state.pathname);
|
|
480
|
+
}
|
|
481
|
+
return this.loadRoute(void 0, void 0, options?.transition);
|
|
482
|
+
},
|
|
483
|
+
setQuery: this.setQuery.bind(this),
|
|
484
|
+
setHash: this.setHash.bind(this),
|
|
485
|
+
};
|
|
486
|
+
}
|
|
556
487
|
}
|
|
557
488
|
function buildQueryString(query) {
|
|
558
489
|
const params = new URLSearchParams();
|
|
@@ -568,29 +499,19 @@ function buildQueryString(query) {
|
|
|
568
499
|
}
|
|
569
500
|
return params.toString();
|
|
570
501
|
}
|
|
571
|
-
async function handleStateTransition(
|
|
572
|
-
if (currentTransition) {
|
|
573
|
-
const { id: currentId, transition } = currentTransition;
|
|
574
|
-
// for cross-page navigations, we skip any existing transitions.
|
|
575
|
-
// otherwise (eg. loaders), we wait for the existing transition to finish
|
|
576
|
-
if (id !== currentId) {
|
|
577
|
-
transition.skipTransition();
|
|
578
|
-
}
|
|
579
|
-
await transition.finished;
|
|
580
|
-
}
|
|
502
|
+
async function handleStateTransition(signal, enableTransition, callback) {
|
|
581
503
|
if (!enableTransition || typeof document.startViewTransition !== "function") {
|
|
582
504
|
return new Promise((resolve) => {
|
|
583
505
|
callback();
|
|
584
506
|
nextIdle(resolve);
|
|
585
507
|
});
|
|
586
508
|
}
|
|
587
|
-
const
|
|
509
|
+
const vt = document.startViewTransition(() => {
|
|
588
510
|
callback();
|
|
589
511
|
flushSync();
|
|
590
512
|
});
|
|
591
|
-
|
|
592
|
-
await
|
|
593
|
-
currentTransition = null;
|
|
513
|
+
signal.addEventListener("abort", () => vt.skipTransition());
|
|
514
|
+
await vt.ready;
|
|
594
515
|
}
|
|
595
516
|
function validateRoutes(pageMap) {
|
|
596
517
|
const routeConflicts = [];
|