@fictjs/router 0.2.3 → 0.3.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/index.cjs +2373 -3
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1136 -2
- package/dist/index.d.ts +1136 -2
- package/dist/index.js +2305 -3
- package/dist/index.js.map +1 -0
- package/package.json +33 -7
- package/src/components.tsx +926 -0
- package/src/context.ts +404 -0
- package/src/data.ts +545 -0
- package/src/history.ts +659 -0
- package/src/index.ts +217 -0
- package/src/lazy.tsx +242 -0
- package/src/link.tsx +601 -0
- package/src/scroll.ts +245 -0
- package/src/types.ts +447 -0
- package/src/utils.ts +570 -0
package/dist/index.cjs
CHANGED
|
@@ -20,12 +20,2382 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
23
|
+
Form: () => Form,
|
|
24
|
+
HashRouter: () => HashRouter,
|
|
25
|
+
Link: () => Link,
|
|
26
|
+
MemoryRouter: () => MemoryRouter,
|
|
27
|
+
NavLink: () => NavLink,
|
|
28
|
+
Navigate: () => Navigate,
|
|
29
|
+
Outlet: () => Outlet,
|
|
30
|
+
Redirect: () => Redirect,
|
|
31
|
+
Route: () => Route,
|
|
32
|
+
Router: () => Router,
|
|
33
|
+
Routes: () => Routes,
|
|
34
|
+
StaticRouter: () => StaticRouter,
|
|
35
|
+
action: () => action,
|
|
36
|
+
cleanupDataUtilities: () => cleanupDataUtilities,
|
|
37
|
+
clearAllScrollPositions: () => clearAllScrollPositions,
|
|
38
|
+
clearScrollPosition: () => clearScrollPosition,
|
|
39
|
+
compileRoute: () => compileRoute,
|
|
40
|
+
configureScrollRestoration: () => configureScrollRestoration,
|
|
41
|
+
createBranches: () => createBranches,
|
|
42
|
+
createBrowserHistory: () => createBrowserHistory,
|
|
43
|
+
createHashHistory: () => createHashHistory,
|
|
44
|
+
createLazyRoutes: () => createLazyRoutes,
|
|
45
|
+
createLocation: () => createLocation,
|
|
46
|
+
createMemoryHistory: () => createMemoryHistory,
|
|
47
|
+
createPreload: () => createPreload,
|
|
48
|
+
createResource: () => createResource,
|
|
49
|
+
createRouter: () => createRouter,
|
|
50
|
+
createRoutes: () => createRoutes,
|
|
51
|
+
createScrollRestoration: () => createScrollRestoration,
|
|
52
|
+
createStaticHistory: () => createStaticHistory,
|
|
53
|
+
createURL: () => createURL,
|
|
54
|
+
getAction: () => getAction,
|
|
55
|
+
getScrollRestoration: () => getScrollRestoration,
|
|
56
|
+
isBrowser: () => isBrowser,
|
|
57
|
+
isLazyComponent: () => isLazyComponent,
|
|
58
|
+
isServer: () => isServer,
|
|
59
|
+
joinPaths: () => joinPaths,
|
|
60
|
+
lazy: () => lazy,
|
|
61
|
+
lazyRoute: () => lazyRoute,
|
|
62
|
+
locationsAreEqual: () => locationsAreEqual,
|
|
63
|
+
matchRoutes: () => matchRoutes,
|
|
64
|
+
normalizePath: () => normalizePath,
|
|
65
|
+
parseSearchParams: () => parseSearchParams,
|
|
66
|
+
parseURL: () => parseURL,
|
|
67
|
+
preloadLazy: () => preloadLazy,
|
|
68
|
+
preloadQuery: () => preloadQuery,
|
|
69
|
+
prependBasePath: () => prependBasePath,
|
|
70
|
+
query: () => query,
|
|
71
|
+
resolvePath: () => resolvePath,
|
|
72
|
+
restoreScrollPosition: () => restoreScrollPosition,
|
|
73
|
+
revalidate: () => revalidate,
|
|
74
|
+
saveScrollPosition: () => saveScrollPosition,
|
|
75
|
+
scoreRoute: () => scoreRoute,
|
|
76
|
+
scrollToHash: () => scrollToHash,
|
|
77
|
+
scrollToTop: () => scrollToTop,
|
|
78
|
+
stringifySearchParams: () => stringifySearchParams,
|
|
79
|
+
stripBasePath: () => stripBasePath,
|
|
80
|
+
submitAction: () => submitAction,
|
|
81
|
+
useBeforeLeave: () => useBeforeLeave,
|
|
82
|
+
useHref: () => useHref,
|
|
83
|
+
useIsActive: () => useIsActive,
|
|
84
|
+
useIsRouting: () => useIsRouting,
|
|
85
|
+
useLocation: () => useLocation,
|
|
86
|
+
useMatch: () => useMatch,
|
|
87
|
+
useMatches: () => useMatches,
|
|
88
|
+
useNavigate: () => useNavigate,
|
|
89
|
+
useParams: () => useParams,
|
|
90
|
+
usePendingLocation: () => usePendingLocation,
|
|
91
|
+
useResolvedPath: () => useResolvedPath,
|
|
92
|
+
useRoute: () => useRoute,
|
|
93
|
+
useRouteData: () => useRouteData,
|
|
94
|
+
useRouteError: () => useRouteError,
|
|
95
|
+
useRouter: () => useRouter,
|
|
96
|
+
useSearchParams: () => useSearchParams,
|
|
97
|
+
useSubmission: () => useSubmission,
|
|
98
|
+
useSubmissions: () => useSubmissions
|
|
24
99
|
});
|
|
25
100
|
module.exports = __toCommonJS(index_exports);
|
|
26
|
-
|
|
101
|
+
|
|
102
|
+
// src/components.tsx
|
|
103
|
+
var import_runtime2 = require("@fictjs/runtime");
|
|
104
|
+
var import_advanced = require("@fictjs/runtime/advanced");
|
|
105
|
+
|
|
106
|
+
// src/context.ts
|
|
107
|
+
var import_runtime = require("@fictjs/runtime");
|
|
108
|
+
|
|
109
|
+
// src/utils.ts
|
|
110
|
+
function normalizePath(path) {
|
|
111
|
+
if (!path || path === "/") return "/";
|
|
112
|
+
let normalized = path.startsWith("/") ? path : "/" + path;
|
|
113
|
+
if (normalized.length > 1 && normalized.endsWith("/")) {
|
|
114
|
+
normalized = normalized.slice(0, -1);
|
|
115
|
+
}
|
|
116
|
+
return normalized;
|
|
117
|
+
}
|
|
118
|
+
function joinPaths(...paths) {
|
|
119
|
+
return normalizePath(
|
|
120
|
+
paths.filter((p) => p != null && p !== "").join("/").replace(/\/+/g, "/")
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
function resolvePath(base, to) {
|
|
124
|
+
const toPath = typeof to === "string" ? to : to.pathname || "";
|
|
125
|
+
if (toPath.startsWith("/")) {
|
|
126
|
+
return normalizePath(toPath);
|
|
127
|
+
}
|
|
128
|
+
const baseSegments = base.split("/").filter(Boolean);
|
|
129
|
+
const toSegments = toPath.split("/").filter(Boolean);
|
|
130
|
+
for (const segment of toSegments) {
|
|
131
|
+
if (segment === "..") {
|
|
132
|
+
baseSegments.pop();
|
|
133
|
+
} else if (segment !== ".") {
|
|
134
|
+
baseSegments.push(segment);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return "/" + baseSegments.join("/");
|
|
138
|
+
}
|
|
139
|
+
function createLocation(to, state, key) {
|
|
140
|
+
if (typeof to === "string") {
|
|
141
|
+
const url = parseURL(to);
|
|
142
|
+
return {
|
|
143
|
+
pathname: url.pathname,
|
|
144
|
+
search: url.search,
|
|
145
|
+
hash: url.hash,
|
|
146
|
+
state: state ?? null,
|
|
147
|
+
key: key ?? createKey()
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
pathname: to.pathname || "/",
|
|
152
|
+
search: to.search || "",
|
|
153
|
+
hash: to.hash || "",
|
|
154
|
+
state: state ?? to.state ?? null,
|
|
155
|
+
key: key ?? to.key ?? createKey()
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function parseURL(url) {
|
|
159
|
+
const hashIndex = url.indexOf("#");
|
|
160
|
+
let hash = "";
|
|
161
|
+
if (hashIndex >= 0) {
|
|
162
|
+
hash = url.slice(hashIndex);
|
|
163
|
+
url = url.slice(0, hashIndex);
|
|
164
|
+
}
|
|
165
|
+
const searchIndex = url.indexOf("?");
|
|
166
|
+
let search = "";
|
|
167
|
+
if (searchIndex >= 0) {
|
|
168
|
+
search = url.slice(searchIndex);
|
|
169
|
+
url = url.slice(0, searchIndex);
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
pathname: normalizePath(url || "/"),
|
|
173
|
+
search,
|
|
174
|
+
hash
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function createURL(location) {
|
|
178
|
+
const pathname = location.pathname || "/";
|
|
179
|
+
const search = location.search || "";
|
|
180
|
+
const hash = location.hash || "";
|
|
181
|
+
return pathname + search + hash;
|
|
182
|
+
}
|
|
183
|
+
var keyIndex = 0;
|
|
184
|
+
function createKey() {
|
|
185
|
+
return String(++keyIndex);
|
|
186
|
+
}
|
|
187
|
+
function parsePathPattern(pattern) {
|
|
188
|
+
const segments = [];
|
|
189
|
+
const parts = pattern.split("/").filter(Boolean);
|
|
190
|
+
for (const part of parts) {
|
|
191
|
+
if (part === "*" || part.startsWith("*")) {
|
|
192
|
+
const paramName = part.length > 1 ? part.slice(1) : "*";
|
|
193
|
+
segments.push({ type: "splat", value: part, paramName });
|
|
194
|
+
} else if (part.startsWith(":")) {
|
|
195
|
+
const isOptional = part.endsWith("?");
|
|
196
|
+
const paramName = isOptional ? part.slice(1, -1) : part.slice(1);
|
|
197
|
+
segments.push({
|
|
198
|
+
type: isOptional ? "optional" : "dynamic",
|
|
199
|
+
value: part,
|
|
200
|
+
paramName
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
segments.push({ type: "static", value: part.toLowerCase() });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return segments;
|
|
207
|
+
}
|
|
208
|
+
function scoreRoute(pattern, isIndex = false) {
|
|
209
|
+
const segments = parsePathPattern(pattern);
|
|
210
|
+
let score = 0;
|
|
211
|
+
for (const segment of segments) {
|
|
212
|
+
switch (segment.type) {
|
|
213
|
+
case "static":
|
|
214
|
+
score += 3;
|
|
215
|
+
break;
|
|
216
|
+
case "dynamic":
|
|
217
|
+
score += 2;
|
|
218
|
+
break;
|
|
219
|
+
case "optional":
|
|
220
|
+
score += 1;
|
|
221
|
+
break;
|
|
222
|
+
case "splat":
|
|
223
|
+
score += 0.5;
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (isIndex) {
|
|
228
|
+
score += 0.5;
|
|
229
|
+
}
|
|
230
|
+
return score;
|
|
231
|
+
}
|
|
232
|
+
function createMatcher(pattern, matchFilters) {
|
|
233
|
+
const segments = parsePathPattern(pattern);
|
|
234
|
+
const normalizedPattern = normalizePath(pattern);
|
|
235
|
+
return (pathname) => {
|
|
236
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
237
|
+
const params = {};
|
|
238
|
+
let matchedPath = "";
|
|
239
|
+
let pathIndex = 0;
|
|
240
|
+
for (let i = 0; i < segments.length; i++) {
|
|
241
|
+
const segment = segments[i];
|
|
242
|
+
const pathSegment = pathSegments[pathIndex];
|
|
243
|
+
switch (segment.type) {
|
|
244
|
+
case "static":
|
|
245
|
+
if (!pathSegment || pathSegment.toLowerCase() !== segment.value) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
matchedPath += "/" + pathSegment;
|
|
249
|
+
pathIndex++;
|
|
250
|
+
break;
|
|
251
|
+
case "dynamic":
|
|
252
|
+
if (!pathSegment) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
if (matchFilters && segment.paramName && matchFilters[segment.paramName]) {
|
|
256
|
+
if (!validateParam(pathSegment, matchFilters[segment.paramName])) {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
params[segment.paramName] = decodeURIComponent(pathSegment);
|
|
261
|
+
matchedPath += "/" + pathSegment;
|
|
262
|
+
pathIndex++;
|
|
263
|
+
break;
|
|
264
|
+
case "optional": {
|
|
265
|
+
if (pathSegment) {
|
|
266
|
+
const nextSegment = segments[i + 1];
|
|
267
|
+
if (nextSegment && nextSegment.type === "static" && pathSegment.toLowerCase() === nextSegment.value) {
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
if (matchFilters && segment.paramName && matchFilters[segment.paramName]) {
|
|
271
|
+
if (!validateParam(pathSegment, matchFilters[segment.paramName])) {
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
params[segment.paramName] = decodeURIComponent(pathSegment);
|
|
276
|
+
matchedPath += "/" + pathSegment;
|
|
277
|
+
pathIndex++;
|
|
278
|
+
}
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
case "splat": {
|
|
282
|
+
const remainingSegments = pathSegments.slice(pathIndex);
|
|
283
|
+
const decodedSegments = remainingSegments.map((seg) => {
|
|
284
|
+
try {
|
|
285
|
+
return decodeURIComponent(seg);
|
|
286
|
+
} catch {
|
|
287
|
+
return seg;
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
params[segment.paramName] = decodedSegments.join("/");
|
|
291
|
+
matchedPath += remainingSegments.length > 0 ? "/" + remainingSegments.join("/") : "";
|
|
292
|
+
pathIndex = pathSegments.length;
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (pathIndex < pathSegments.length) {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
route: {},
|
|
302
|
+
// Will be filled in by caller
|
|
303
|
+
pathname: matchedPath || "/",
|
|
304
|
+
params,
|
|
305
|
+
pattern: normalizedPattern
|
|
306
|
+
};
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function validateParam(value, filter) {
|
|
310
|
+
if (filter instanceof RegExp) {
|
|
311
|
+
return filter.test(value);
|
|
312
|
+
}
|
|
313
|
+
if (Array.isArray(filter)) {
|
|
314
|
+
return filter.includes(value);
|
|
315
|
+
}
|
|
316
|
+
if (typeof filter === "function") {
|
|
317
|
+
return filter(value);
|
|
318
|
+
}
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
var routeKeyCounter = 0;
|
|
322
|
+
function compileRoute(route, parentPattern = "") {
|
|
323
|
+
const pattern = normalizePath(
|
|
324
|
+
joinPaths(parentPattern, route.path || (route.index ? "" : void 0))
|
|
325
|
+
);
|
|
326
|
+
const compiled = {
|
|
327
|
+
route,
|
|
328
|
+
pattern,
|
|
329
|
+
matcher: createMatcher(pattern, route.matchFilters),
|
|
330
|
+
score: scoreRoute(pattern, route.index),
|
|
331
|
+
key: route.key || `route-${++routeKeyCounter}`
|
|
332
|
+
};
|
|
333
|
+
if (route.children && route.children.length > 0) {
|
|
334
|
+
compiled.children = route.children.map(
|
|
335
|
+
(child) => compileRoute(child, route.index ? parentPattern : pattern)
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
return compiled;
|
|
339
|
+
}
|
|
340
|
+
function createBranches(routes) {
|
|
341
|
+
const branches = [];
|
|
342
|
+
function buildBranches(route, parentRoutes = []) {
|
|
343
|
+
const currentRoutes = [...parentRoutes, route];
|
|
344
|
+
if (route.children && route.children.length > 0) {
|
|
345
|
+
for (const child of route.children) {
|
|
346
|
+
buildBranches(child, currentRoutes);
|
|
347
|
+
}
|
|
348
|
+
} else {
|
|
349
|
+
const score = currentRoutes.reduce((sum, r) => sum + r.score, 0);
|
|
350
|
+
const branchMatcher = (pathname) => {
|
|
351
|
+
const matches = [];
|
|
352
|
+
let remainingPath = pathname;
|
|
353
|
+
let accumulatedParams = {};
|
|
354
|
+
for (const compiledRoute of currentRoutes) {
|
|
355
|
+
const match = compiledRoute.matcher(remainingPath);
|
|
356
|
+
if (!match) {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
accumulatedParams = { ...accumulatedParams, ...match.params };
|
|
360
|
+
matches.push({
|
|
361
|
+
...match,
|
|
362
|
+
route: compiledRoute.route,
|
|
363
|
+
params: { ...accumulatedParams }
|
|
364
|
+
});
|
|
365
|
+
if (compiledRoute !== currentRoutes[currentRoutes.length - 1]) {
|
|
366
|
+
if (match.pathname !== "/") {
|
|
367
|
+
remainingPath = remainingPath.slice(match.pathname.length) || "/";
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return matches;
|
|
372
|
+
};
|
|
373
|
+
branches.push({
|
|
374
|
+
routes: currentRoutes,
|
|
375
|
+
score,
|
|
376
|
+
matcher: branchMatcher
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
for (const route of routes) {
|
|
381
|
+
buildBranches(route);
|
|
382
|
+
}
|
|
383
|
+
branches.sort((a, b) => b.score - a.score);
|
|
384
|
+
return branches;
|
|
385
|
+
}
|
|
386
|
+
function matchRoutes(branches, pathname) {
|
|
387
|
+
const normalizedPath = normalizePath(pathname);
|
|
388
|
+
for (const branch of branches) {
|
|
389
|
+
const matches = branch.matcher(normalizedPath);
|
|
390
|
+
if (matches) {
|
|
391
|
+
return matches;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
function parseSearchParams(search) {
|
|
397
|
+
return new URLSearchParams(search);
|
|
398
|
+
}
|
|
399
|
+
function stringifySearchParams(params) {
|
|
400
|
+
const searchParams = params instanceof URLSearchParams ? params : new URLSearchParams(params);
|
|
401
|
+
const str = searchParams.toString();
|
|
402
|
+
return str ? "?" + str : "";
|
|
403
|
+
}
|
|
404
|
+
function locationsAreEqual(a, b) {
|
|
405
|
+
return a.pathname === b.pathname && a.search === b.search && a.hash === b.hash;
|
|
406
|
+
}
|
|
407
|
+
function stripBasePath(pathname, basePath) {
|
|
408
|
+
if (basePath === "/" || basePath === "") {
|
|
409
|
+
return pathname;
|
|
410
|
+
}
|
|
411
|
+
const normalizedBase = normalizePath(basePath);
|
|
412
|
+
if (pathname.startsWith(normalizedBase)) {
|
|
413
|
+
const stripped = pathname.slice(normalizedBase.length);
|
|
414
|
+
return stripped || "/";
|
|
415
|
+
}
|
|
416
|
+
return pathname;
|
|
417
|
+
}
|
|
418
|
+
function prependBasePath(pathname, basePath) {
|
|
419
|
+
if (basePath === "/" || basePath === "") {
|
|
420
|
+
return pathname;
|
|
421
|
+
}
|
|
422
|
+
return joinPaths(basePath, pathname);
|
|
423
|
+
}
|
|
424
|
+
function hashParams(params) {
|
|
425
|
+
const entries = Object.entries(params).sort(([a], [b]) => a.localeCompare(b));
|
|
426
|
+
return JSON.stringify(entries);
|
|
427
|
+
}
|
|
428
|
+
function isServer() {
|
|
429
|
+
return typeof window === "undefined";
|
|
430
|
+
}
|
|
431
|
+
function isBrowser() {
|
|
432
|
+
return typeof window !== "undefined";
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// src/context.ts
|
|
436
|
+
var defaultRouterContext = {
|
|
437
|
+
location: () => ({
|
|
438
|
+
pathname: "/",
|
|
439
|
+
search: "",
|
|
440
|
+
hash: "",
|
|
441
|
+
state: null,
|
|
442
|
+
key: "default"
|
|
443
|
+
}),
|
|
444
|
+
params: () => ({}),
|
|
445
|
+
matches: () => [],
|
|
446
|
+
navigate: () => {
|
|
447
|
+
console.warn("[fict-router] No router found. Wrap your app in a <Router>");
|
|
448
|
+
},
|
|
449
|
+
isRouting: () => false,
|
|
450
|
+
pendingLocation: () => null,
|
|
451
|
+
base: "",
|
|
452
|
+
resolvePath: (to) => typeof to === "string" ? to : to.pathname || "/"
|
|
453
|
+
};
|
|
454
|
+
var RouterContext = (0, import_runtime.createContext)(defaultRouterContext);
|
|
455
|
+
RouterContext.displayName = "RouterContext";
|
|
456
|
+
function useRouter() {
|
|
457
|
+
return (0, import_runtime.useContext)(RouterContext);
|
|
458
|
+
}
|
|
459
|
+
var defaultRouteContext = {
|
|
460
|
+
match: () => void 0,
|
|
461
|
+
data: () => void 0,
|
|
462
|
+
outlet: () => null,
|
|
463
|
+
resolvePath: (to) => typeof to === "string" ? to : to.pathname || "/"
|
|
464
|
+
};
|
|
465
|
+
var RouteContext = (0, import_runtime.createContext)(defaultRouteContext);
|
|
466
|
+
RouteContext.displayName = "RouteContext";
|
|
467
|
+
function useRoute() {
|
|
468
|
+
return (0, import_runtime.useContext)(RouteContext);
|
|
469
|
+
}
|
|
470
|
+
var defaultBeforeLeaveContext = {
|
|
471
|
+
addHandler: () => () => {
|
|
472
|
+
},
|
|
473
|
+
confirm: async () => true
|
|
474
|
+
};
|
|
475
|
+
var BeforeLeaveContext = (0, import_runtime.createContext)(defaultBeforeLeaveContext);
|
|
476
|
+
BeforeLeaveContext.displayName = "BeforeLeaveContext";
|
|
477
|
+
function useBeforeLeaveContext() {
|
|
478
|
+
return (0, import_runtime.useContext)(BeforeLeaveContext);
|
|
479
|
+
}
|
|
480
|
+
var defaultRouteErrorContext = {
|
|
481
|
+
error: void 0,
|
|
482
|
+
reset: void 0
|
|
483
|
+
};
|
|
484
|
+
var RouteErrorContext = (0, import_runtime.createContext)(defaultRouteErrorContext);
|
|
485
|
+
RouteErrorContext.displayName = "RouteErrorContext";
|
|
486
|
+
function useNavigate() {
|
|
487
|
+
const router = useRouter();
|
|
488
|
+
return router.navigate;
|
|
489
|
+
}
|
|
490
|
+
function useLocation() {
|
|
491
|
+
const router = useRouter();
|
|
492
|
+
return router.location;
|
|
493
|
+
}
|
|
494
|
+
function useParams() {
|
|
495
|
+
const router = useRouter();
|
|
496
|
+
return router.params;
|
|
497
|
+
}
|
|
498
|
+
function useSearchParams() {
|
|
499
|
+
const router = useRouter();
|
|
500
|
+
const getSearchParams = () => {
|
|
501
|
+
const location = router.location();
|
|
502
|
+
return new URLSearchParams(location.search);
|
|
503
|
+
};
|
|
504
|
+
const setSearchParams = (params, options) => {
|
|
505
|
+
const searchParams = params instanceof URLSearchParams ? params : new URLSearchParams(params);
|
|
506
|
+
const search = searchParams.toString();
|
|
507
|
+
const location = router.location();
|
|
508
|
+
router.navigate(
|
|
509
|
+
{
|
|
510
|
+
pathname: location.pathname,
|
|
511
|
+
search: search ? "?" + search : "",
|
|
512
|
+
hash: location.hash
|
|
513
|
+
},
|
|
514
|
+
{ replace: options?.replace }
|
|
515
|
+
);
|
|
516
|
+
};
|
|
517
|
+
return [getSearchParams, setSearchParams];
|
|
518
|
+
}
|
|
519
|
+
function useMatches() {
|
|
520
|
+
const router = useRouter();
|
|
521
|
+
return router.matches;
|
|
522
|
+
}
|
|
523
|
+
function useIsRouting() {
|
|
524
|
+
const router = useRouter();
|
|
525
|
+
return router.isRouting;
|
|
526
|
+
}
|
|
527
|
+
function usePendingLocation() {
|
|
528
|
+
const router = useRouter();
|
|
529
|
+
return router.pendingLocation;
|
|
530
|
+
}
|
|
531
|
+
function useRouteData() {
|
|
532
|
+
const route = useRoute();
|
|
533
|
+
return route.data;
|
|
534
|
+
}
|
|
535
|
+
function useRouteError() {
|
|
536
|
+
const errorContext = (0, import_runtime.useContext)(RouteErrorContext);
|
|
537
|
+
if (errorContext.error !== void 0) {
|
|
538
|
+
return errorContext.error;
|
|
539
|
+
}
|
|
540
|
+
const route = useRoute();
|
|
541
|
+
return route.error?.();
|
|
542
|
+
}
|
|
543
|
+
function useResolvedPath(to) {
|
|
544
|
+
const route = useRoute();
|
|
545
|
+
return () => {
|
|
546
|
+
const target = typeof to === "function" ? to() : to;
|
|
547
|
+
return route.resolvePath(target);
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
function useMatch(path) {
|
|
551
|
+
const router = useRouter();
|
|
552
|
+
return () => {
|
|
553
|
+
const targetPath = typeof path === "function" ? path() : path;
|
|
554
|
+
const matches = router.matches();
|
|
555
|
+
for (const match of matches) {
|
|
556
|
+
if (match.pattern === targetPath || match.pathname === targetPath) {
|
|
557
|
+
return match;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return null;
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
function useHref(to) {
|
|
564
|
+
const router = useRouter();
|
|
565
|
+
return () => {
|
|
566
|
+
const target = typeof to === "function" ? to() : to;
|
|
567
|
+
let pathname;
|
|
568
|
+
let search = "";
|
|
569
|
+
let hash = "";
|
|
570
|
+
if (typeof target === "string") {
|
|
571
|
+
let remaining = target;
|
|
572
|
+
const hashIndex = remaining.indexOf("#");
|
|
573
|
+
if (hashIndex >= 0) {
|
|
574
|
+
hash = remaining.slice(hashIndex);
|
|
575
|
+
remaining = remaining.slice(0, hashIndex);
|
|
576
|
+
}
|
|
577
|
+
const searchIndex = remaining.indexOf("?");
|
|
578
|
+
if (searchIndex >= 0) {
|
|
579
|
+
search = remaining.slice(searchIndex);
|
|
580
|
+
remaining = remaining.slice(0, searchIndex);
|
|
581
|
+
}
|
|
582
|
+
pathname = remaining;
|
|
583
|
+
} else {
|
|
584
|
+
pathname = target.pathname || "";
|
|
585
|
+
search = target.search || "";
|
|
586
|
+
hash = target.hash || "";
|
|
587
|
+
}
|
|
588
|
+
let resolved;
|
|
589
|
+
if (pathname === "") {
|
|
590
|
+
const currentPathname = router.location().pathname;
|
|
591
|
+
const normalizedBase = router.base === "/" || router.base === "" ? "" : router.base;
|
|
592
|
+
if (normalizedBase && !currentPathname.startsWith(normalizedBase)) {
|
|
593
|
+
return currentPathname + search + hash;
|
|
594
|
+
}
|
|
595
|
+
resolved = stripBasePath(currentPathname, router.base);
|
|
596
|
+
} else {
|
|
597
|
+
resolved = router.resolvePath(pathname);
|
|
598
|
+
}
|
|
599
|
+
const baseHref = prependBasePath(resolved, router.base);
|
|
600
|
+
return baseHref + search + hash;
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
function useIsActive(to, options) {
|
|
604
|
+
const router = useRouter();
|
|
605
|
+
return () => {
|
|
606
|
+
const target = typeof to === "function" ? to() : to;
|
|
607
|
+
const resolvedTargetPath = router.resolvePath(target);
|
|
608
|
+
const currentPath = router.location().pathname;
|
|
609
|
+
if (router.base && currentPath !== router.base && !currentPath.startsWith(router.base + "/")) {
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
const currentPathWithoutBase = stripBasePath(currentPath, router.base);
|
|
613
|
+
if (options?.end) {
|
|
614
|
+
return currentPathWithoutBase === resolvedTargetPath;
|
|
615
|
+
}
|
|
616
|
+
return currentPathWithoutBase === resolvedTargetPath || currentPathWithoutBase.startsWith(resolvedTargetPath + "/");
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
function useBeforeLeave(handler) {
|
|
620
|
+
const context = useBeforeLeaveContext();
|
|
621
|
+
const _cleanup = context.addHandler(handler);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// src/history.ts
|
|
625
|
+
function createHistoryState(location, index) {
|
|
626
|
+
return {
|
|
627
|
+
usr: location.state,
|
|
628
|
+
key: location.key,
|
|
629
|
+
idx: index
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
function readLocation(state, url) {
|
|
633
|
+
const { pathname, search, hash } = parseURL(url);
|
|
634
|
+
return {
|
|
635
|
+
pathname,
|
|
636
|
+
search,
|
|
637
|
+
hash,
|
|
638
|
+
state: state?.usr ?? null,
|
|
639
|
+
key: state?.key ?? createKey()
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
function createBrowserHistory() {
|
|
643
|
+
if (typeof window === "undefined") {
|
|
644
|
+
throw new Error(
|
|
645
|
+
"[fict-router] createBrowserHistory cannot be used in a server environment. Use createMemoryHistory or createStaticHistory for SSR."
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
649
|
+
const blockers = /* @__PURE__ */ new Set();
|
|
650
|
+
let action2 = "POP";
|
|
651
|
+
let location = readLocation(
|
|
652
|
+
window.history.state,
|
|
653
|
+
window.location.pathname + window.location.search + window.location.hash
|
|
654
|
+
);
|
|
655
|
+
let index = window.history.state?.idx ?? 0;
|
|
656
|
+
function handlePopState(event) {
|
|
657
|
+
const nextLocation = readLocation(
|
|
658
|
+
event.state,
|
|
659
|
+
window.location.pathname + window.location.search + window.location.hash
|
|
660
|
+
);
|
|
661
|
+
const nextAction = "POP";
|
|
662
|
+
const nextIndex = event.state?.idx ?? 0;
|
|
663
|
+
if (blockers.size > 0) {
|
|
664
|
+
let blocked = false;
|
|
665
|
+
const retry = () => {
|
|
666
|
+
window.history.go(nextIndex - index);
|
|
667
|
+
};
|
|
668
|
+
for (const blocker of blockers) {
|
|
669
|
+
blocker({
|
|
670
|
+
action: nextAction,
|
|
671
|
+
location: nextLocation,
|
|
672
|
+
retry
|
|
673
|
+
});
|
|
674
|
+
blocked = true;
|
|
675
|
+
break;
|
|
676
|
+
}
|
|
677
|
+
if (blocked) {
|
|
678
|
+
window.history.go(index - nextIndex);
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
action2 = nextAction;
|
|
683
|
+
location = nextLocation;
|
|
684
|
+
index = nextIndex;
|
|
685
|
+
notifyListeners();
|
|
686
|
+
}
|
|
687
|
+
window.addEventListener("popstate", handlePopState);
|
|
688
|
+
function notifyListeners() {
|
|
689
|
+
for (const listener of listeners) {
|
|
690
|
+
listener({ action: action2, location });
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
function push(to, state) {
|
|
694
|
+
const nextLocation = createLocation(to, state);
|
|
695
|
+
const nextAction = "PUSH";
|
|
696
|
+
if (blockers.size > 0) {
|
|
697
|
+
let blocked = false;
|
|
698
|
+
const retry = () => push(to, state);
|
|
699
|
+
for (const blocker of blockers) {
|
|
700
|
+
blocker({
|
|
701
|
+
action: nextAction,
|
|
702
|
+
location: nextLocation,
|
|
703
|
+
retry
|
|
704
|
+
});
|
|
705
|
+
blocked = true;
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
if (blocked) return;
|
|
709
|
+
}
|
|
710
|
+
action2 = nextAction;
|
|
711
|
+
location = nextLocation;
|
|
712
|
+
index++;
|
|
713
|
+
const historyState = createHistoryState(location, index);
|
|
714
|
+
window.history.pushState(historyState, "", createURL(location));
|
|
715
|
+
notifyListeners();
|
|
716
|
+
}
|
|
717
|
+
function replace(to, state) {
|
|
718
|
+
const nextLocation = createLocation(to, state);
|
|
719
|
+
const nextAction = "REPLACE";
|
|
720
|
+
if (blockers.size > 0) {
|
|
721
|
+
let blocked = false;
|
|
722
|
+
const retry = () => replace(to, state);
|
|
723
|
+
for (const blocker of blockers) {
|
|
724
|
+
blocker({
|
|
725
|
+
action: nextAction,
|
|
726
|
+
location: nextLocation,
|
|
727
|
+
retry
|
|
728
|
+
});
|
|
729
|
+
blocked = true;
|
|
730
|
+
break;
|
|
731
|
+
}
|
|
732
|
+
if (blocked) return;
|
|
733
|
+
}
|
|
734
|
+
action2 = nextAction;
|
|
735
|
+
location = nextLocation;
|
|
736
|
+
const historyState = createHistoryState(location, index);
|
|
737
|
+
window.history.replaceState(historyState, "", createURL(location));
|
|
738
|
+
notifyListeners();
|
|
739
|
+
}
|
|
740
|
+
function go(delta) {
|
|
741
|
+
window.history.go(delta);
|
|
742
|
+
}
|
|
743
|
+
if (window.history.state === null) {
|
|
744
|
+
const historyState = createHistoryState(location, index);
|
|
745
|
+
window.history.replaceState(historyState, "", createURL(location));
|
|
746
|
+
}
|
|
747
|
+
return {
|
|
748
|
+
get action() {
|
|
749
|
+
return action2;
|
|
750
|
+
},
|
|
751
|
+
get location() {
|
|
752
|
+
return location;
|
|
753
|
+
},
|
|
754
|
+
push,
|
|
755
|
+
replace,
|
|
756
|
+
go,
|
|
757
|
+
back() {
|
|
758
|
+
go(-1);
|
|
759
|
+
},
|
|
760
|
+
forward() {
|
|
761
|
+
go(1);
|
|
762
|
+
},
|
|
763
|
+
listen(listener) {
|
|
764
|
+
listeners.add(listener);
|
|
765
|
+
return () => listeners.delete(listener);
|
|
766
|
+
},
|
|
767
|
+
createHref(to) {
|
|
768
|
+
const loc = typeof to === "string" ? parseURL(to) : to;
|
|
769
|
+
return createURL(loc);
|
|
770
|
+
},
|
|
771
|
+
block(blocker) {
|
|
772
|
+
blockers.add(blocker);
|
|
773
|
+
if (blockers.size === 1) {
|
|
774
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
775
|
+
}
|
|
776
|
+
return () => {
|
|
777
|
+
blockers.delete(blocker);
|
|
778
|
+
if (blockers.size === 0) {
|
|
779
|
+
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
function handleBeforeUnload(event) {
|
|
786
|
+
event.preventDefault();
|
|
787
|
+
event.returnValue = "";
|
|
788
|
+
}
|
|
789
|
+
function createHashHistory(options = {}) {
|
|
790
|
+
if (typeof window === "undefined") {
|
|
791
|
+
throw new Error(
|
|
792
|
+
"[fict-router] createHashHistory cannot be used in a server environment. Use createMemoryHistory or createStaticHistory for SSR."
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
const { hashType = "slash" } = options;
|
|
796
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
797
|
+
const blockers = /* @__PURE__ */ new Set();
|
|
798
|
+
let action2 = "POP";
|
|
799
|
+
let location = readHashLocation();
|
|
800
|
+
let index = 0;
|
|
801
|
+
function readHashLocation() {
|
|
802
|
+
let hash = window.location.hash.slice(1);
|
|
803
|
+
if (hashType === "slash" && !hash.startsWith("/")) {
|
|
804
|
+
hash = "/" + hash;
|
|
805
|
+
} else if (hashType === "noslash" && hash.startsWith("/")) {
|
|
806
|
+
hash = hash.slice(1);
|
|
807
|
+
}
|
|
808
|
+
const { pathname, search, hash: innerHash } = parseURL(hash || "/");
|
|
809
|
+
return {
|
|
810
|
+
pathname: normalizePath(pathname),
|
|
811
|
+
search,
|
|
812
|
+
hash: innerHash,
|
|
813
|
+
state: window.history.state?.usr ?? null,
|
|
814
|
+
key: window.history.state?.key ?? createKey()
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
function createHashHref(location2) {
|
|
818
|
+
const url = createURL(location2);
|
|
819
|
+
if (hashType === "noslash") {
|
|
820
|
+
return "#" + url.slice(1);
|
|
821
|
+
}
|
|
822
|
+
return "#" + url;
|
|
823
|
+
}
|
|
824
|
+
function handleHashChange() {
|
|
825
|
+
const nextLocation = readHashLocation();
|
|
826
|
+
const nextAction = "POP";
|
|
827
|
+
if (blockers.size > 0) {
|
|
828
|
+
let blocked = false;
|
|
829
|
+
const retry = () => {
|
|
830
|
+
window.location.hash = createHashHref(nextLocation);
|
|
831
|
+
};
|
|
832
|
+
for (const blocker of blockers) {
|
|
833
|
+
blocker({
|
|
834
|
+
action: nextAction,
|
|
835
|
+
location: nextLocation,
|
|
836
|
+
retry
|
|
837
|
+
});
|
|
838
|
+
blocked = true;
|
|
839
|
+
break;
|
|
840
|
+
}
|
|
841
|
+
if (blocked) {
|
|
842
|
+
window.location.hash = createHashHref(location);
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
action2 = nextAction;
|
|
847
|
+
location = nextLocation;
|
|
848
|
+
notifyListeners();
|
|
849
|
+
}
|
|
850
|
+
window.addEventListener("hashchange", handleHashChange);
|
|
851
|
+
function notifyListeners() {
|
|
852
|
+
for (const listener of listeners) {
|
|
853
|
+
listener({ action: action2, location });
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
function push(to, state) {
|
|
857
|
+
const nextLocation = createLocation(to, state);
|
|
858
|
+
const nextAction = "PUSH";
|
|
859
|
+
if (blockers.size > 0) {
|
|
860
|
+
let blocked = false;
|
|
861
|
+
const retry = () => push(to, state);
|
|
862
|
+
for (const blocker of blockers) {
|
|
863
|
+
blocker({
|
|
864
|
+
action: nextAction,
|
|
865
|
+
location: nextLocation,
|
|
866
|
+
retry
|
|
867
|
+
});
|
|
868
|
+
blocked = true;
|
|
869
|
+
break;
|
|
870
|
+
}
|
|
871
|
+
if (blocked) return;
|
|
872
|
+
}
|
|
873
|
+
action2 = nextAction;
|
|
874
|
+
location = nextLocation;
|
|
875
|
+
index++;
|
|
876
|
+
const historyState = createHistoryState(location, index);
|
|
877
|
+
window.history.pushState(historyState, "", createHashHref(location));
|
|
878
|
+
notifyListeners();
|
|
879
|
+
}
|
|
880
|
+
function replace(to, state) {
|
|
881
|
+
const nextLocation = createLocation(to, state);
|
|
882
|
+
const nextAction = "REPLACE";
|
|
883
|
+
if (blockers.size > 0) {
|
|
884
|
+
let blocked = false;
|
|
885
|
+
const retry = () => replace(to, state);
|
|
886
|
+
for (const blocker of blockers) {
|
|
887
|
+
blocker({
|
|
888
|
+
action: nextAction,
|
|
889
|
+
location: nextLocation,
|
|
890
|
+
retry
|
|
891
|
+
});
|
|
892
|
+
blocked = true;
|
|
893
|
+
break;
|
|
894
|
+
}
|
|
895
|
+
if (blocked) return;
|
|
896
|
+
}
|
|
897
|
+
action2 = nextAction;
|
|
898
|
+
location = nextLocation;
|
|
899
|
+
const historyState = createHistoryState(location, index);
|
|
900
|
+
window.history.replaceState(historyState, "", createHashHref(location));
|
|
901
|
+
notifyListeners();
|
|
902
|
+
}
|
|
903
|
+
function go(delta) {
|
|
904
|
+
window.history.go(delta);
|
|
905
|
+
}
|
|
906
|
+
return {
|
|
907
|
+
get action() {
|
|
908
|
+
return action2;
|
|
909
|
+
},
|
|
910
|
+
get location() {
|
|
911
|
+
return location;
|
|
912
|
+
},
|
|
913
|
+
push,
|
|
914
|
+
replace,
|
|
915
|
+
go,
|
|
916
|
+
back() {
|
|
917
|
+
go(-1);
|
|
918
|
+
},
|
|
919
|
+
forward() {
|
|
920
|
+
go(1);
|
|
921
|
+
},
|
|
922
|
+
listen(listener) {
|
|
923
|
+
listeners.add(listener);
|
|
924
|
+
return () => listeners.delete(listener);
|
|
925
|
+
},
|
|
926
|
+
createHref(to) {
|
|
927
|
+
const loc = createLocation(to);
|
|
928
|
+
return createHashHref(loc);
|
|
929
|
+
},
|
|
930
|
+
block(blocker) {
|
|
931
|
+
blockers.add(blocker);
|
|
932
|
+
if (blockers.size === 1) {
|
|
933
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
934
|
+
}
|
|
935
|
+
return () => {
|
|
936
|
+
blockers.delete(blocker);
|
|
937
|
+
if (blockers.size === 0) {
|
|
938
|
+
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
function createMemoryHistory(options = {}) {
|
|
945
|
+
const { initialEntries = ["/"], initialIndex } = options;
|
|
946
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
947
|
+
const blockers = /* @__PURE__ */ new Set();
|
|
948
|
+
const entries = initialEntries.map((entry, i) => createLocation(entry, null, `${i}`));
|
|
949
|
+
let index = initialIndex ?? entries.length - 1;
|
|
950
|
+
let action2 = "POP";
|
|
951
|
+
index = Math.max(0, Math.min(index, entries.length - 1));
|
|
952
|
+
function notifyListeners() {
|
|
953
|
+
const location = entries[index];
|
|
954
|
+
for (const listener of listeners) {
|
|
955
|
+
listener({ action: action2, location });
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
function push(to, state) {
|
|
959
|
+
const nextLocation = createLocation(to, state);
|
|
960
|
+
const nextAction = "PUSH";
|
|
961
|
+
if (blockers.size > 0) {
|
|
962
|
+
let blocked = false;
|
|
963
|
+
const retry = () => push(to, state);
|
|
964
|
+
for (const blocker of blockers) {
|
|
965
|
+
blocker({
|
|
966
|
+
action: nextAction,
|
|
967
|
+
location: nextLocation,
|
|
968
|
+
retry
|
|
969
|
+
});
|
|
970
|
+
blocked = true;
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
if (blocked) return;
|
|
974
|
+
}
|
|
975
|
+
action2 = nextAction;
|
|
976
|
+
entries.splice(index + 1);
|
|
977
|
+
entries.push(nextLocation);
|
|
978
|
+
index = entries.length - 1;
|
|
979
|
+
notifyListeners();
|
|
980
|
+
}
|
|
981
|
+
function replace(to, state) {
|
|
982
|
+
const nextLocation = createLocation(to, state);
|
|
983
|
+
const nextAction = "REPLACE";
|
|
984
|
+
if (blockers.size > 0) {
|
|
985
|
+
let blocked = false;
|
|
986
|
+
const retry = () => replace(to, state);
|
|
987
|
+
for (const blocker of blockers) {
|
|
988
|
+
blocker({
|
|
989
|
+
action: nextAction,
|
|
990
|
+
location: nextLocation,
|
|
991
|
+
retry
|
|
992
|
+
});
|
|
993
|
+
blocked = true;
|
|
994
|
+
break;
|
|
995
|
+
}
|
|
996
|
+
if (blocked) return;
|
|
997
|
+
}
|
|
998
|
+
action2 = nextAction;
|
|
999
|
+
entries[index] = nextLocation;
|
|
1000
|
+
notifyListeners();
|
|
1001
|
+
}
|
|
1002
|
+
function go(delta) {
|
|
1003
|
+
const nextIndex = Math.max(0, Math.min(index + delta, entries.length - 1));
|
|
1004
|
+
if (nextIndex === index) return;
|
|
1005
|
+
const nextLocation = entries[nextIndex];
|
|
1006
|
+
const nextAction = "POP";
|
|
1007
|
+
if (blockers.size > 0) {
|
|
1008
|
+
let blocked = false;
|
|
1009
|
+
const retry = () => go(delta);
|
|
1010
|
+
for (const blocker of blockers) {
|
|
1011
|
+
blocker({
|
|
1012
|
+
action: nextAction,
|
|
1013
|
+
location: nextLocation,
|
|
1014
|
+
retry
|
|
1015
|
+
});
|
|
1016
|
+
blocked = true;
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
1019
|
+
if (blocked) return;
|
|
1020
|
+
}
|
|
1021
|
+
action2 = nextAction;
|
|
1022
|
+
index = nextIndex;
|
|
1023
|
+
notifyListeners();
|
|
1024
|
+
}
|
|
1025
|
+
return {
|
|
1026
|
+
get action() {
|
|
1027
|
+
return action2;
|
|
1028
|
+
},
|
|
1029
|
+
get location() {
|
|
1030
|
+
return entries[index];
|
|
1031
|
+
},
|
|
1032
|
+
push,
|
|
1033
|
+
replace,
|
|
1034
|
+
go,
|
|
1035
|
+
back() {
|
|
1036
|
+
go(-1);
|
|
1037
|
+
},
|
|
1038
|
+
forward() {
|
|
1039
|
+
go(1);
|
|
1040
|
+
},
|
|
1041
|
+
listen(listener) {
|
|
1042
|
+
listeners.add(listener);
|
|
1043
|
+
return () => listeners.delete(listener);
|
|
1044
|
+
},
|
|
1045
|
+
createHref(to) {
|
|
1046
|
+
const loc = typeof to === "string" ? parseURL(to) : to;
|
|
1047
|
+
return createURL(loc);
|
|
1048
|
+
},
|
|
1049
|
+
block(blocker) {
|
|
1050
|
+
blockers.add(blocker);
|
|
1051
|
+
return () => blockers.delete(blocker);
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
1055
|
+
function createStaticHistory(url) {
|
|
1056
|
+
const location = createLocation(url);
|
|
1057
|
+
return {
|
|
1058
|
+
get action() {
|
|
1059
|
+
return "POP";
|
|
1060
|
+
},
|
|
1061
|
+
get location() {
|
|
1062
|
+
return location;
|
|
1063
|
+
},
|
|
1064
|
+
push() {
|
|
1065
|
+
console.warn("[fict-router] Cannot push on static history (SSR)");
|
|
1066
|
+
},
|
|
1067
|
+
replace() {
|
|
1068
|
+
console.warn("[fict-router] Cannot replace on static history (SSR)");
|
|
1069
|
+
},
|
|
1070
|
+
go() {
|
|
1071
|
+
console.warn("[fict-router] Cannot go on static history (SSR)");
|
|
1072
|
+
},
|
|
1073
|
+
back() {
|
|
1074
|
+
},
|
|
1075
|
+
forward() {
|
|
1076
|
+
},
|
|
1077
|
+
listen() {
|
|
1078
|
+
return () => {
|
|
1079
|
+
};
|
|
1080
|
+
},
|
|
1081
|
+
createHref(to) {
|
|
1082
|
+
const loc = typeof to === "string" ? parseURL(to) : to;
|
|
1083
|
+
return createURL(loc);
|
|
1084
|
+
},
|
|
1085
|
+
block() {
|
|
1086
|
+
return () => {
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
// src/scroll.ts
|
|
1093
|
+
var scrollPositions = /* @__PURE__ */ new Map();
|
|
1094
|
+
var MAX_STORED_POSITIONS = 100;
|
|
1095
|
+
function saveScrollPosition(key) {
|
|
1096
|
+
if (!isBrowser()) return;
|
|
1097
|
+
scrollPositions.set(key, {
|
|
1098
|
+
x: window.scrollX,
|
|
1099
|
+
y: window.scrollY
|
|
1100
|
+
});
|
|
1101
|
+
if (scrollPositions.size > MAX_STORED_POSITIONS) {
|
|
1102
|
+
const firstKey = scrollPositions.keys().next().value;
|
|
1103
|
+
if (firstKey) {
|
|
1104
|
+
scrollPositions.delete(firstKey);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
function clearScrollPosition(key) {
|
|
1109
|
+
scrollPositions.delete(key);
|
|
1110
|
+
}
|
|
1111
|
+
function clearAllScrollPositions() {
|
|
1112
|
+
scrollPositions.clear();
|
|
1113
|
+
}
|
|
1114
|
+
function scrollTo(x, y, behavior = "auto") {
|
|
1115
|
+
if (!isBrowser()) return;
|
|
1116
|
+
window.scrollTo({
|
|
1117
|
+
left: x,
|
|
1118
|
+
top: y,
|
|
1119
|
+
behavior
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
function scrollToTop(behavior = "auto") {
|
|
1123
|
+
scrollTo(0, 0, behavior);
|
|
1124
|
+
}
|
|
1125
|
+
function scrollToHash(hash, behavior = "auto") {
|
|
1126
|
+
if (!isBrowser() || !hash) return false;
|
|
1127
|
+
const id = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
1128
|
+
if (!id) return false;
|
|
1129
|
+
const element = document.getElementById(id);
|
|
1130
|
+
if (element) {
|
|
1131
|
+
element.scrollIntoView({ behavior });
|
|
1132
|
+
return true;
|
|
1133
|
+
}
|
|
1134
|
+
return false;
|
|
1135
|
+
}
|
|
1136
|
+
function restoreScrollPosition(key) {
|
|
1137
|
+
if (!isBrowser()) return false;
|
|
1138
|
+
const position = scrollPositions.get(key);
|
|
1139
|
+
if (position) {
|
|
1140
|
+
requestAnimationFrame(() => {
|
|
1141
|
+
scrollTo(position.x, position.y);
|
|
1142
|
+
});
|
|
1143
|
+
return true;
|
|
1144
|
+
}
|
|
1145
|
+
return false;
|
|
1146
|
+
}
|
|
1147
|
+
var defaultOptions = {
|
|
1148
|
+
enabled: true,
|
|
1149
|
+
restoreOnPop: true,
|
|
1150
|
+
scrollToTopOnPush: true,
|
|
1151
|
+
behavior: "auto"
|
|
27
1152
|
};
|
|
1153
|
+
function createScrollRestoration(options = {}) {
|
|
1154
|
+
const config = { ...defaultOptions, ...options };
|
|
1155
|
+
if (isBrowser() && "scrollRestoration" in history) {
|
|
1156
|
+
history.scrollRestoration = "manual";
|
|
1157
|
+
}
|
|
1158
|
+
function handleNavigation(from, to, action2) {
|
|
1159
|
+
if (!config.enabled || !isBrowser()) return;
|
|
1160
|
+
if (from?.key) {
|
|
1161
|
+
saveScrollPosition(from.key);
|
|
1162
|
+
}
|
|
1163
|
+
if (action2 === "POP" && config.restoreOnPop) {
|
|
1164
|
+
if (!restoreScrollPosition(to.key)) {
|
|
1165
|
+
if (to.hash) {
|
|
1166
|
+
requestAnimationFrame(() => {
|
|
1167
|
+
if (!scrollToHash(to.hash, config.behavior)) {
|
|
1168
|
+
scrollToTop(config.behavior);
|
|
1169
|
+
}
|
|
1170
|
+
});
|
|
1171
|
+
} else {
|
|
1172
|
+
scrollToTop(config.behavior);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
} else if ((action2 === "PUSH" || action2 === "REPLACE") && config.scrollToTopOnPush) {
|
|
1176
|
+
requestAnimationFrame(() => {
|
|
1177
|
+
if (to.hash) {
|
|
1178
|
+
if (!scrollToHash(to.hash, config.behavior)) {
|
|
1179
|
+
scrollToTop(config.behavior);
|
|
1180
|
+
}
|
|
1181
|
+
} else {
|
|
1182
|
+
scrollToTop(config.behavior);
|
|
1183
|
+
}
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
function reset() {
|
|
1188
|
+
if (isBrowser() && "scrollRestoration" in history) {
|
|
1189
|
+
history.scrollRestoration = "auto";
|
|
1190
|
+
}
|
|
1191
|
+
clearAllScrollPositions();
|
|
1192
|
+
}
|
|
1193
|
+
return {
|
|
1194
|
+
handleNavigation,
|
|
1195
|
+
saveScrollPosition,
|
|
1196
|
+
restoreScrollPosition,
|
|
1197
|
+
scrollToTop: () => scrollToTop(config.behavior),
|
|
1198
|
+
scrollToHash: (hash) => scrollToHash(hash, config.behavior),
|
|
1199
|
+
reset,
|
|
1200
|
+
config
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
var defaultScrollRestoration = null;
|
|
1204
|
+
function getScrollRestoration() {
|
|
1205
|
+
if (!defaultScrollRestoration) {
|
|
1206
|
+
defaultScrollRestoration = createScrollRestoration();
|
|
1207
|
+
}
|
|
1208
|
+
return defaultScrollRestoration;
|
|
1209
|
+
}
|
|
1210
|
+
function configureScrollRestoration(options) {
|
|
1211
|
+
defaultScrollRestoration = createScrollRestoration(options);
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
// src/components.tsx
|
|
1215
|
+
var import_jsx_runtime = require("fict/jsx-runtime");
|
|
1216
|
+
var import_meta = {};
|
|
1217
|
+
var isDevEnv = typeof import_meta !== "undefined" && import_meta.env?.DEV === true || typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
1218
|
+
var didWarnBaseMismatch = false;
|
|
1219
|
+
function hasBasePrefix(pathname, base) {
|
|
1220
|
+
if (!base) return true;
|
|
1221
|
+
return pathname === base || pathname.startsWith(base + "/");
|
|
1222
|
+
}
|
|
1223
|
+
function stripBaseOrWarn(pathname, base) {
|
|
1224
|
+
if (!base) return pathname;
|
|
1225
|
+
if (!hasBasePrefix(pathname, base)) {
|
|
1226
|
+
if (isDevEnv && !didWarnBaseMismatch) {
|
|
1227
|
+
didWarnBaseMismatch = true;
|
|
1228
|
+
console.warn(
|
|
1229
|
+
`[fict-router] Location "${pathname}" does not start with base "${base}". No routes matched.`
|
|
1230
|
+
);
|
|
1231
|
+
}
|
|
1232
|
+
return null;
|
|
1233
|
+
}
|
|
1234
|
+
return stripBasePath(pathname, base);
|
|
1235
|
+
}
|
|
1236
|
+
function stripBaseIfPresent(pathname, base) {
|
|
1237
|
+
if (!base) return pathname;
|
|
1238
|
+
if (hasBasePrefix(pathname, base)) {
|
|
1239
|
+
return stripBasePath(pathname, base);
|
|
1240
|
+
}
|
|
1241
|
+
return pathname;
|
|
1242
|
+
}
|
|
1243
|
+
function createRouterState(history2, routes, base = "") {
|
|
1244
|
+
const normalizedBase = normalizePath(base);
|
|
1245
|
+
const baseForStrip = normalizedBase === "/" ? "" : normalizedBase;
|
|
1246
|
+
const compiledRoutes = routes.map((r) => compileRoute(r));
|
|
1247
|
+
const branches = createBranches(compiledRoutes);
|
|
1248
|
+
const matchWithBase = (pathname) => {
|
|
1249
|
+
const strippedPath = stripBaseOrWarn(pathname, baseForStrip);
|
|
1250
|
+
if (strippedPath == null) return [];
|
|
1251
|
+
return matchRoutes(branches, strippedPath) || [];
|
|
1252
|
+
};
|
|
1253
|
+
const initialLocation = history2.location;
|
|
1254
|
+
const initialMatches = matchWithBase(initialLocation.pathname);
|
|
1255
|
+
const locationSignal = (0, import_advanced.createSignal)(initialLocation);
|
|
1256
|
+
const matchesSignal = (0, import_advanced.createSignal)(initialMatches);
|
|
1257
|
+
const isRoutingSignal = (0, import_advanced.createSignal)(false);
|
|
1258
|
+
const pendingLocationSignal = (0, import_advanced.createSignal)(null);
|
|
1259
|
+
const beforeLeaveHandlers = /* @__PURE__ */ new Set();
|
|
1260
|
+
let navigationToken = 0;
|
|
1261
|
+
const beforeLeave = {
|
|
1262
|
+
addHandler(handler) {
|
|
1263
|
+
beforeLeaveHandlers.add(handler);
|
|
1264
|
+
return () => beforeLeaveHandlers.delete(handler);
|
|
1265
|
+
},
|
|
1266
|
+
async confirm(to, from) {
|
|
1267
|
+
if (beforeLeaveHandlers.size === 0) return true;
|
|
1268
|
+
const currentToken = ++navigationToken;
|
|
1269
|
+
let defaultPrevented = false;
|
|
1270
|
+
let retryRequested = false;
|
|
1271
|
+
let forceRetry = false;
|
|
1272
|
+
const event = {
|
|
1273
|
+
to,
|
|
1274
|
+
from,
|
|
1275
|
+
get defaultPrevented() {
|
|
1276
|
+
return defaultPrevented;
|
|
1277
|
+
},
|
|
1278
|
+
preventDefault() {
|
|
1279
|
+
defaultPrevented = true;
|
|
1280
|
+
},
|
|
1281
|
+
retry(force) {
|
|
1282
|
+
retryRequested = true;
|
|
1283
|
+
forceRetry = force ?? false;
|
|
1284
|
+
}
|
|
1285
|
+
};
|
|
1286
|
+
for (const handler of beforeLeaveHandlers) {
|
|
1287
|
+
await handler(event);
|
|
1288
|
+
if (currentToken !== navigationToken) {
|
|
1289
|
+
return false;
|
|
1290
|
+
}
|
|
1291
|
+
if (defaultPrevented && !retryRequested) {
|
|
1292
|
+
return false;
|
|
1293
|
+
}
|
|
1294
|
+
if (retryRequested && forceRetry) {
|
|
1295
|
+
return true;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
if (currentToken !== navigationToken) {
|
|
1299
|
+
return false;
|
|
1300
|
+
}
|
|
1301
|
+
return !defaultPrevented || retryRequested;
|
|
1302
|
+
}
|
|
1303
|
+
};
|
|
1304
|
+
const navigate = (toOrDelta, options) => {
|
|
1305
|
+
if (typeof toOrDelta === "number") {
|
|
1306
|
+
history2.go(toOrDelta);
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
const currentLocation = locationSignal();
|
|
1310
|
+
const to = toOrDelta;
|
|
1311
|
+
let toPathname;
|
|
1312
|
+
let toSearch = "";
|
|
1313
|
+
let toHash = "";
|
|
1314
|
+
if (typeof to === "string") {
|
|
1315
|
+
let remaining = to;
|
|
1316
|
+
const hashIndex = remaining.indexOf("#");
|
|
1317
|
+
if (hashIndex >= 0) {
|
|
1318
|
+
toHash = remaining.slice(hashIndex);
|
|
1319
|
+
remaining = remaining.slice(0, hashIndex);
|
|
1320
|
+
}
|
|
1321
|
+
const searchIndex = remaining.indexOf("?");
|
|
1322
|
+
if (searchIndex >= 0) {
|
|
1323
|
+
toSearch = remaining.slice(searchIndex);
|
|
1324
|
+
remaining = remaining.slice(0, searchIndex);
|
|
1325
|
+
}
|
|
1326
|
+
toPathname = remaining;
|
|
1327
|
+
} else {
|
|
1328
|
+
toPathname = to.pathname || "";
|
|
1329
|
+
toSearch = to.search || "";
|
|
1330
|
+
toHash = to.hash || "";
|
|
1331
|
+
}
|
|
1332
|
+
let targetPath;
|
|
1333
|
+
const currentPathWithoutBase = stripBaseOrWarn(currentLocation.pathname, baseForStrip) || "/";
|
|
1334
|
+
if (typeof to === "string") {
|
|
1335
|
+
if (toPathname === "") {
|
|
1336
|
+
targetPath = currentPathWithoutBase;
|
|
1337
|
+
} else if (options?.relative === "route") {
|
|
1338
|
+
const matches = matchesSignal();
|
|
1339
|
+
const currentMatch = matches[matches.length - 1];
|
|
1340
|
+
const currentRoutePath = currentMatch?.pathname || currentPathWithoutBase;
|
|
1341
|
+
targetPath = resolvePath(currentRoutePath, toPathname);
|
|
1342
|
+
} else {
|
|
1343
|
+
targetPath = toPathname.startsWith("/") ? stripBaseIfPresent(toPathname, baseForStrip) : resolvePath(currentPathWithoutBase, toPathname);
|
|
1344
|
+
}
|
|
1345
|
+
} else {
|
|
1346
|
+
const rawTargetPath = toPathname || currentPathWithoutBase;
|
|
1347
|
+
targetPath = stripBaseIfPresent(rawTargetPath, baseForStrip);
|
|
1348
|
+
}
|
|
1349
|
+
const toState = typeof to === "object" ? to.state : void 0;
|
|
1350
|
+
const toKey = typeof to === "object" ? to.key : void 0;
|
|
1351
|
+
const finalState = options?.state !== void 0 ? options.state : toState;
|
|
1352
|
+
const targetPathWithBase = prependBasePath(targetPath, baseForStrip);
|
|
1353
|
+
const locationSpec = {
|
|
1354
|
+
pathname: targetPathWithBase,
|
|
1355
|
+
search: toSearch,
|
|
1356
|
+
hash: toHash
|
|
1357
|
+
};
|
|
1358
|
+
if (finalState !== void 0) {
|
|
1359
|
+
locationSpec.state = finalState;
|
|
1360
|
+
}
|
|
1361
|
+
if (toKey !== void 0) {
|
|
1362
|
+
locationSpec.key = toKey;
|
|
1363
|
+
}
|
|
1364
|
+
const targetLocation = createLocation(locationSpec, finalState, toKey);
|
|
1365
|
+
(0, import_runtime2.untrack)(async () => {
|
|
1366
|
+
const canNavigate = await beforeLeave.confirm(targetLocation, currentLocation);
|
|
1367
|
+
if (!canNavigate) {
|
|
1368
|
+
pendingLocationSignal(null);
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
(0, import_runtime2.batch)(() => {
|
|
1372
|
+
isRoutingSignal(true);
|
|
1373
|
+
pendingLocationSignal(targetLocation);
|
|
1374
|
+
});
|
|
1375
|
+
(0, import_runtime2.startTransition)(() => {
|
|
1376
|
+
const prevLocation = history2.location;
|
|
1377
|
+
if (options?.replace) {
|
|
1378
|
+
history2.replace(targetLocation, finalState);
|
|
1379
|
+
} else {
|
|
1380
|
+
history2.push(targetLocation, finalState);
|
|
1381
|
+
}
|
|
1382
|
+
if (options?.scroll !== false && isBrowser()) {
|
|
1383
|
+
const scrollRestoration = getScrollRestoration();
|
|
1384
|
+
scrollRestoration.handleNavigation(
|
|
1385
|
+
prevLocation,
|
|
1386
|
+
history2.location,
|
|
1387
|
+
options?.replace ? "REPLACE" : "PUSH"
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
if (locationsAreEqual(prevLocation, history2.location)) {
|
|
1391
|
+
(0, import_runtime2.batch)(() => {
|
|
1392
|
+
isRoutingSignal(false);
|
|
1393
|
+
pendingLocationSignal(null);
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
});
|
|
1397
|
+
});
|
|
1398
|
+
};
|
|
1399
|
+
const unlisten = history2.listen(({ action: action2, location: newLocation }) => {
|
|
1400
|
+
const prevLocation = locationSignal();
|
|
1401
|
+
(0, import_runtime2.batch)(() => {
|
|
1402
|
+
locationSignal(newLocation);
|
|
1403
|
+
const newMatches = matchWithBase(newLocation.pathname);
|
|
1404
|
+
matchesSignal(newMatches);
|
|
1405
|
+
isRoutingSignal(false);
|
|
1406
|
+
pendingLocationSignal(null);
|
|
1407
|
+
});
|
|
1408
|
+
if (action2 === "POP" && isBrowser()) {
|
|
1409
|
+
const scrollRestoration = getScrollRestoration();
|
|
1410
|
+
scrollRestoration.handleNavigation(prevLocation, newLocation, "POP");
|
|
1411
|
+
}
|
|
1412
|
+
});
|
|
1413
|
+
const state = () => ({
|
|
1414
|
+
location: locationSignal(),
|
|
1415
|
+
matches: matchesSignal(),
|
|
1416
|
+
isRouting: isRoutingSignal(),
|
|
1417
|
+
pendingLocation: pendingLocationSignal()
|
|
1418
|
+
});
|
|
1419
|
+
return {
|
|
1420
|
+
state,
|
|
1421
|
+
navigate,
|
|
1422
|
+
beforeLeave,
|
|
1423
|
+
cleanup: unlisten,
|
|
1424
|
+
normalizedBase: baseForStrip
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
function RouterProvider(props) {
|
|
1428
|
+
const { state, navigate, beforeLeave, cleanup, normalizedBase } = createRouterState(
|
|
1429
|
+
props.history,
|
|
1430
|
+
props.routes,
|
|
1431
|
+
props.base
|
|
1432
|
+
);
|
|
1433
|
+
(0, import_runtime2.onCleanup)(cleanup);
|
|
1434
|
+
const routerContext = {
|
|
1435
|
+
location: () => state().location,
|
|
1436
|
+
params: () => {
|
|
1437
|
+
const matches = state().matches;
|
|
1438
|
+
const allParams = {};
|
|
1439
|
+
for (const match of matches) {
|
|
1440
|
+
Object.assign(allParams, match.params);
|
|
1441
|
+
}
|
|
1442
|
+
return allParams;
|
|
1443
|
+
},
|
|
1444
|
+
matches: () => state().matches,
|
|
1445
|
+
navigate,
|
|
1446
|
+
isRouting: () => state().isRouting,
|
|
1447
|
+
pendingLocation: () => state().pendingLocation,
|
|
1448
|
+
base: normalizedBase,
|
|
1449
|
+
resolvePath: (to) => {
|
|
1450
|
+
const location = state().location;
|
|
1451
|
+
const currentPathWithoutBase = stripBaseOrWarn(location.pathname, normalizedBase) || "/";
|
|
1452
|
+
const rawTargetPath = typeof to === "string" ? to : to.pathname || "/";
|
|
1453
|
+
const targetPath = rawTargetPath.startsWith("/") ? stripBaseIfPresent(rawTargetPath, normalizedBase) : rawTargetPath;
|
|
1454
|
+
return resolvePath(currentPathWithoutBase, targetPath);
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouterContext.Provider, { value: routerContext, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BeforeLeaveContext.Provider, { value: beforeLeave, children: props.children }) });
|
|
1458
|
+
}
|
|
1459
|
+
function Router(props) {
|
|
1460
|
+
const history2 = props.history || createBrowserHistory();
|
|
1461
|
+
const routes = extractRoutes(props.children);
|
|
1462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouterProvider, { history: history2, routes, base: props.base, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Routes, { children: props.children }) });
|
|
1463
|
+
}
|
|
1464
|
+
function HashRouter(props) {
|
|
1465
|
+
const hashOptions = props.hashType ? { hashType: props.hashType } : void 0;
|
|
1466
|
+
const history2 = createHashHistory(hashOptions);
|
|
1467
|
+
const routes = extractRoutes(props.children);
|
|
1468
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouterProvider, { history: history2, routes, base: props.base, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Routes, { children: props.children }) });
|
|
1469
|
+
}
|
|
1470
|
+
function MemoryRouter(props) {
|
|
1471
|
+
const memoryOptions = {};
|
|
1472
|
+
if (props.initialEntries !== void 0) {
|
|
1473
|
+
memoryOptions.initialEntries = props.initialEntries;
|
|
1474
|
+
}
|
|
1475
|
+
if (props.initialIndex !== void 0) {
|
|
1476
|
+
memoryOptions.initialIndex = props.initialIndex;
|
|
1477
|
+
}
|
|
1478
|
+
const history2 = createMemoryHistory(
|
|
1479
|
+
Object.keys(memoryOptions).length > 0 ? memoryOptions : void 0
|
|
1480
|
+
);
|
|
1481
|
+
const routes = extractRoutes(props.children);
|
|
1482
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouterProvider, { history: history2, routes, base: props.base, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Routes, { children: props.children }) });
|
|
1483
|
+
}
|
|
1484
|
+
function StaticRouter(props) {
|
|
1485
|
+
const history2 = createStaticHistory(props.url);
|
|
1486
|
+
const routes = extractRoutes(props.children);
|
|
1487
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouterProvider, { history: history2, routes, base: props.base, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Routes, { children: props.children }) });
|
|
1488
|
+
}
|
|
1489
|
+
function Routes(props) {
|
|
1490
|
+
const router = useRouter();
|
|
1491
|
+
const parentRoute = useRoute();
|
|
1492
|
+
const routes = extractRoutes(props.children);
|
|
1493
|
+
const compiledRoutes = routes.map((r) => compileRoute(r));
|
|
1494
|
+
const branches = createBranches(compiledRoutes);
|
|
1495
|
+
const currentMatches = (0, import_runtime2.createMemo)(() => {
|
|
1496
|
+
const location = router.location();
|
|
1497
|
+
const parentMatch = parentRoute.match();
|
|
1498
|
+
const locationPath = stripBaseOrWarn(location.pathname, router.base);
|
|
1499
|
+
if (locationPath == null) return [];
|
|
1500
|
+
let basePath = "/";
|
|
1501
|
+
if (parentMatch) {
|
|
1502
|
+
basePath = parentMatch.pathname;
|
|
1503
|
+
}
|
|
1504
|
+
const relativePath = locationPath.startsWith(basePath) ? locationPath.slice(basePath.length) || "/" : locationPath;
|
|
1505
|
+
return matchRoutes(branches, relativePath) || [];
|
|
1506
|
+
});
|
|
1507
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: renderMatches(currentMatches(), 0) });
|
|
1508
|
+
}
|
|
1509
|
+
function renderMatches(matches, index) {
|
|
1510
|
+
if (index >= matches.length) {
|
|
1511
|
+
return null;
|
|
1512
|
+
}
|
|
1513
|
+
const match = matches[index];
|
|
1514
|
+
const route = match.route;
|
|
1515
|
+
const router = useRouter();
|
|
1516
|
+
const dataState = (0, import_advanced.createSignal)({
|
|
1517
|
+
data: void 0,
|
|
1518
|
+
error: void 0,
|
|
1519
|
+
loading: !!route.preload
|
|
1520
|
+
});
|
|
1521
|
+
let preloadToken = 0;
|
|
1522
|
+
if (route.preload) {
|
|
1523
|
+
(0, import_runtime2.createEffect)(() => {
|
|
1524
|
+
const location = router.location();
|
|
1525
|
+
const preloadArgs = {
|
|
1526
|
+
params: match.params,
|
|
1527
|
+
location,
|
|
1528
|
+
intent: "navigate"
|
|
1529
|
+
};
|
|
1530
|
+
const currentToken = ++preloadToken;
|
|
1531
|
+
dataState({ data: void 0, error: void 0, loading: true });
|
|
1532
|
+
Promise.resolve(route.preload(preloadArgs)).then((result) => {
|
|
1533
|
+
if (currentToken === preloadToken) {
|
|
1534
|
+
dataState({ data: result, error: void 0, loading: false });
|
|
1535
|
+
}
|
|
1536
|
+
}).catch((error) => {
|
|
1537
|
+
if (currentToken === preloadToken) {
|
|
1538
|
+
dataState({ data: void 0, error, loading: false });
|
|
1539
|
+
}
|
|
1540
|
+
});
|
|
1541
|
+
});
|
|
1542
|
+
}
|
|
1543
|
+
const routeContext = {
|
|
1544
|
+
match: () => match,
|
|
1545
|
+
data: () => dataState().data,
|
|
1546
|
+
error: () => dataState().error,
|
|
1547
|
+
outlet: () => renderMatches(matches, index + 1),
|
|
1548
|
+
resolvePath: (to) => {
|
|
1549
|
+
const basePath = match.pathname;
|
|
1550
|
+
const targetPath = typeof to === "string" ? to : to.pathname || "/";
|
|
1551
|
+
return resolvePath(basePath, targetPath);
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
const renderContent = () => {
|
|
1555
|
+
const state = dataState();
|
|
1556
|
+
if (state.error !== void 0 && route.errorElement) {
|
|
1557
|
+
return route.errorElement;
|
|
1558
|
+
}
|
|
1559
|
+
if (state.loading && route.loadingElement) {
|
|
1560
|
+
return route.loadingElement;
|
|
1561
|
+
}
|
|
1562
|
+
if (route.component) {
|
|
1563
|
+
const Component = route.component;
|
|
1564
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { params: match.params, location: router.location(), data: state.data, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Outlet, {}) });
|
|
1565
|
+
} else if (route.element) {
|
|
1566
|
+
return route.element;
|
|
1567
|
+
} else if (route.children) {
|
|
1568
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Outlet, {});
|
|
1569
|
+
}
|
|
1570
|
+
return null;
|
|
1571
|
+
};
|
|
1572
|
+
let content = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouteContext.Provider, { value: routeContext, children: renderContent() });
|
|
1573
|
+
if (route.errorElement) {
|
|
1574
|
+
content = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1575
|
+
import_runtime2.ErrorBoundary,
|
|
1576
|
+
{
|
|
1577
|
+
fallback: (err, reset) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouteErrorContext.Provider, { value: { error: err, reset }, children: route.errorElement }),
|
|
1578
|
+
children: content
|
|
1579
|
+
}
|
|
1580
|
+
);
|
|
1581
|
+
}
|
|
1582
|
+
if (route.loadingElement) {
|
|
1583
|
+
content = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_runtime2.Suspense, { fallback: route.loadingElement, children: content });
|
|
1584
|
+
}
|
|
1585
|
+
return content;
|
|
1586
|
+
}
|
|
1587
|
+
function Route(_props) {
|
|
1588
|
+
return null;
|
|
1589
|
+
}
|
|
1590
|
+
function Outlet() {
|
|
1591
|
+
const route = useRoute();
|
|
1592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: route.outlet() });
|
|
1593
|
+
}
|
|
1594
|
+
function Navigate(props) {
|
|
1595
|
+
const router = useRouter();
|
|
1596
|
+
(0, import_runtime2.createEffect)(() => {
|
|
1597
|
+
router.navigate(props.to, {
|
|
1598
|
+
replace: props.replace ?? true,
|
|
1599
|
+
state: props.state
|
|
1600
|
+
});
|
|
1601
|
+
});
|
|
1602
|
+
return null;
|
|
1603
|
+
}
|
|
1604
|
+
function Redirect(props) {
|
|
1605
|
+
const router = useRouter();
|
|
1606
|
+
(0, import_runtime2.createEffect)(() => {
|
|
1607
|
+
router.navigate(props.to, {
|
|
1608
|
+
replace: props.push !== true,
|
|
1609
|
+
// Replace by default, push only if explicitly requested
|
|
1610
|
+
state: props.state
|
|
1611
|
+
});
|
|
1612
|
+
});
|
|
1613
|
+
return null;
|
|
1614
|
+
}
|
|
1615
|
+
function extractRoutes(children) {
|
|
1616
|
+
const routes = [];
|
|
1617
|
+
if (children == null) return routes;
|
|
1618
|
+
const childArray = Array.isArray(children) ? children : [children];
|
|
1619
|
+
for (const child of childArray) {
|
|
1620
|
+
if (child == null || typeof child !== "object") continue;
|
|
1621
|
+
const vnode = child;
|
|
1622
|
+
if (vnode.type === Route) {
|
|
1623
|
+
const props = vnode.props || {};
|
|
1624
|
+
const routeDef = {};
|
|
1625
|
+
if (props.path !== void 0) routeDef.path = props.path;
|
|
1626
|
+
if (props.component !== void 0) routeDef.component = props.component;
|
|
1627
|
+
if (props.element !== void 0) routeDef.element = props.element;
|
|
1628
|
+
if (props.index !== void 0) routeDef.index = props.index;
|
|
1629
|
+
if (props.preload !== void 0)
|
|
1630
|
+
routeDef.preload = props.preload;
|
|
1631
|
+
if (props.errorElement !== void 0) routeDef.errorElement = props.errorElement;
|
|
1632
|
+
if (props.loadingElement !== void 0)
|
|
1633
|
+
routeDef.loadingElement = props.loadingElement;
|
|
1634
|
+
if (props.children) routeDef.children = extractRoutes(props.children);
|
|
1635
|
+
routes.push(routeDef);
|
|
1636
|
+
} else if (vnode.type === import_runtime2.Fragment && vnode.props?.children) {
|
|
1637
|
+
routes.push(...extractRoutes(vnode.props.children));
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
return routes;
|
|
1641
|
+
}
|
|
1642
|
+
function createRoutes(routes) {
|
|
1643
|
+
return routes;
|
|
1644
|
+
}
|
|
1645
|
+
function createRouter(routes, options) {
|
|
1646
|
+
return {
|
|
1647
|
+
Router: (props) => {
|
|
1648
|
+
const history2 = options?.history || createBrowserHistory();
|
|
1649
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouterProvider, { history: history2, routes, base: options?.base, children: props.children || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Routes, { children: routesToElements(routes) }) });
|
|
1650
|
+
}
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
function routesToElements(routes) {
|
|
1654
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: routes.map((route, i) => {
|
|
1655
|
+
const routeProps = { key: route.key || `route-${i}` };
|
|
1656
|
+
if (route.path !== void 0) routeProps.path = route.path;
|
|
1657
|
+
if (route.component !== void 0) routeProps.component = route.component;
|
|
1658
|
+
if (route.element !== void 0) routeProps.element = route.element;
|
|
1659
|
+
if (route.index !== void 0) routeProps.index = route.index;
|
|
1660
|
+
if (route.children) routeProps.children = routesToElements(route.children);
|
|
1661
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Route, { ...routeProps });
|
|
1662
|
+
}) });
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// src/link.tsx
|
|
1666
|
+
var import_runtime3 = require("@fictjs/runtime");
|
|
1667
|
+
var import_jsx_runtime2 = require("fict/jsx-runtime");
|
|
1668
|
+
function Link(props) {
|
|
1669
|
+
const router = useRouter();
|
|
1670
|
+
const href = useHref(() => props.to);
|
|
1671
|
+
let preloadTriggered = false;
|
|
1672
|
+
const handleClick = (event) => {
|
|
1673
|
+
if (props.onClick) {
|
|
1674
|
+
props.onClick(event);
|
|
1675
|
+
}
|
|
1676
|
+
if (event.defaultPrevented) return;
|
|
1677
|
+
if (event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) return;
|
|
1678
|
+
if (event.button !== 0) return;
|
|
1679
|
+
if (props.reloadDocument) return;
|
|
1680
|
+
if (props.disabled) return;
|
|
1681
|
+
const target = event.currentTarget.target;
|
|
1682
|
+
if (target && target !== "_self") return;
|
|
1683
|
+
event.preventDefault();
|
|
1684
|
+
const options = {
|
|
1685
|
+
replace: props.replace,
|
|
1686
|
+
state: props.state,
|
|
1687
|
+
scroll: props.scroll,
|
|
1688
|
+
relative: props.relative
|
|
1689
|
+
};
|
|
1690
|
+
router.navigate(props.to, options);
|
|
1691
|
+
};
|
|
1692
|
+
const triggerPreload = () => {
|
|
1693
|
+
if (preloadTriggered || props.disabled || props.prefetch === "none") return;
|
|
1694
|
+
preloadTriggered = true;
|
|
1695
|
+
const hrefValue = href();
|
|
1696
|
+
if (typeof window !== "undefined" && window.dispatchEvent) {
|
|
1697
|
+
window.dispatchEvent(
|
|
1698
|
+
new CustomEvent("fict-router:preload", {
|
|
1699
|
+
detail: { href: hrefValue, to: props.to }
|
|
1700
|
+
})
|
|
1701
|
+
);
|
|
1702
|
+
}
|
|
1703
|
+
};
|
|
1704
|
+
const handleMouseEnter = (event) => {
|
|
1705
|
+
if (props.prefetch === "intent" || props.prefetch === void 0) {
|
|
1706
|
+
triggerPreload();
|
|
1707
|
+
}
|
|
1708
|
+
const onMouseEnter = props.onMouseEnter;
|
|
1709
|
+
if (onMouseEnter) onMouseEnter(event);
|
|
1710
|
+
};
|
|
1711
|
+
const handleFocus = (event) => {
|
|
1712
|
+
if (props.prefetch === "intent" || props.prefetch === void 0) {
|
|
1713
|
+
triggerPreload();
|
|
1714
|
+
}
|
|
1715
|
+
const onFocus = props.onFocus;
|
|
1716
|
+
if (onFocus) onFocus(event);
|
|
1717
|
+
};
|
|
1718
|
+
const {
|
|
1719
|
+
to: _to,
|
|
1720
|
+
replace: _replace,
|
|
1721
|
+
state: _state,
|
|
1722
|
+
scroll: _scroll,
|
|
1723
|
+
relative: _relative,
|
|
1724
|
+
reloadDocument: _reloadDocument,
|
|
1725
|
+
prefetch,
|
|
1726
|
+
disabled,
|
|
1727
|
+
onClick: _onClick,
|
|
1728
|
+
children,
|
|
1729
|
+
...anchorProps
|
|
1730
|
+
} = props;
|
|
1731
|
+
if (disabled) {
|
|
1732
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { ...anchorProps, children });
|
|
1733
|
+
}
|
|
1734
|
+
if (prefetch === "render") {
|
|
1735
|
+
triggerPreload();
|
|
1736
|
+
}
|
|
1737
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1738
|
+
"a",
|
|
1739
|
+
{
|
|
1740
|
+
...anchorProps,
|
|
1741
|
+
href: href(),
|
|
1742
|
+
onClick: handleClick,
|
|
1743
|
+
onMouseEnter: handleMouseEnter,
|
|
1744
|
+
onFocus: handleFocus,
|
|
1745
|
+
children
|
|
1746
|
+
}
|
|
1747
|
+
);
|
|
1748
|
+
}
|
|
1749
|
+
function NavLink(props) {
|
|
1750
|
+
const router = useRouter();
|
|
1751
|
+
const isActive = useIsActive(() => props.to, { end: props.end });
|
|
1752
|
+
const href = useHref(() => props.to);
|
|
1753
|
+
const pendingLocation = usePendingLocation();
|
|
1754
|
+
const computeIsPending = () => {
|
|
1755
|
+
const pending = pendingLocation();
|
|
1756
|
+
if (!pending) return false;
|
|
1757
|
+
const resolvedHref = href();
|
|
1758
|
+
const baseToStrip = router.base === "/" ? "" : router.base;
|
|
1759
|
+
const pendingPathWithoutBase = stripBasePath(pending.pathname, baseToStrip);
|
|
1760
|
+
const parsed = parseURL(resolvedHref);
|
|
1761
|
+
const targetPathWithoutBase = stripBasePath(parsed.pathname, baseToStrip);
|
|
1762
|
+
if (props.end) {
|
|
1763
|
+
return pendingPathWithoutBase === targetPathWithoutBase;
|
|
1764
|
+
}
|
|
1765
|
+
return pendingPathWithoutBase === targetPathWithoutBase || pendingPathWithoutBase.startsWith(targetPathWithoutBase + "/");
|
|
1766
|
+
};
|
|
1767
|
+
const getRenderProps = () => ({
|
|
1768
|
+
isActive: isActive(),
|
|
1769
|
+
isPending: computeIsPending(),
|
|
1770
|
+
isTransitioning: router.isRouting()
|
|
1771
|
+
});
|
|
1772
|
+
const computedClassName = (0, import_runtime3.createMemo)(() => {
|
|
1773
|
+
const renderProps = getRenderProps();
|
|
1774
|
+
const classes = [];
|
|
1775
|
+
if (typeof props.className === "function") {
|
|
1776
|
+
const result = props.className(renderProps);
|
|
1777
|
+
if (result) classes.push(result);
|
|
1778
|
+
} else if (props.className) {
|
|
1779
|
+
classes.push(props.className);
|
|
1780
|
+
}
|
|
1781
|
+
if (renderProps.isActive && props.activeClassName) {
|
|
1782
|
+
classes.push(props.activeClassName);
|
|
1783
|
+
}
|
|
1784
|
+
if (renderProps.isPending && props.pendingClassName) {
|
|
1785
|
+
classes.push(props.pendingClassName);
|
|
1786
|
+
}
|
|
1787
|
+
return classes.join(" ") || void 0;
|
|
1788
|
+
});
|
|
1789
|
+
const computedStyle = (0, import_runtime3.createMemo)(() => {
|
|
1790
|
+
const renderProps = getRenderProps();
|
|
1791
|
+
const style = {};
|
|
1792
|
+
if (typeof props.style === "function") {
|
|
1793
|
+
const result = props.style(renderProps);
|
|
1794
|
+
if (result) Object.assign(style, result);
|
|
1795
|
+
} else if (props.style) {
|
|
1796
|
+
Object.assign(style, props.style);
|
|
1797
|
+
}
|
|
1798
|
+
if (renderProps.isActive && props.activeStyle) {
|
|
1799
|
+
Object.assign(style, props.activeStyle);
|
|
1800
|
+
}
|
|
1801
|
+
if (renderProps.isPending && props.pendingStyle) {
|
|
1802
|
+
Object.assign(style, props.pendingStyle);
|
|
1803
|
+
}
|
|
1804
|
+
return Object.keys(style).length > 0 ? style : void 0;
|
|
1805
|
+
});
|
|
1806
|
+
const computedChildren = (0, import_runtime3.createMemo)(() => {
|
|
1807
|
+
const renderProps = getRenderProps();
|
|
1808
|
+
if (typeof props.children === "function") {
|
|
1809
|
+
return props.children(renderProps);
|
|
1810
|
+
}
|
|
1811
|
+
return props.children;
|
|
1812
|
+
});
|
|
1813
|
+
const ariaCurrent = (0, import_runtime3.createMemo)(() => {
|
|
1814
|
+
const renderProps = getRenderProps();
|
|
1815
|
+
if (!renderProps.isActive) return void 0;
|
|
1816
|
+
return props["aria-current"] || "page";
|
|
1817
|
+
});
|
|
1818
|
+
const handleClick = (event) => {
|
|
1819
|
+
if (props.onClick) {
|
|
1820
|
+
props.onClick(event);
|
|
1821
|
+
}
|
|
1822
|
+
if (event.defaultPrevented) return;
|
|
1823
|
+
if (event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) return;
|
|
1824
|
+
if (event.button !== 0) return;
|
|
1825
|
+
if (props.reloadDocument) return;
|
|
1826
|
+
if (props.disabled) return;
|
|
1827
|
+
const target = event.currentTarget.target;
|
|
1828
|
+
if (target && target !== "_self") return;
|
|
1829
|
+
event.preventDefault();
|
|
1830
|
+
router.navigate(props.to, {
|
|
1831
|
+
replace: props.replace,
|
|
1832
|
+
state: props.state,
|
|
1833
|
+
scroll: props.scroll,
|
|
1834
|
+
relative: props.relative
|
|
1835
|
+
});
|
|
1836
|
+
};
|
|
1837
|
+
const {
|
|
1838
|
+
to: _to,
|
|
1839
|
+
replace: _replace,
|
|
1840
|
+
state: _state,
|
|
1841
|
+
scroll: _scroll,
|
|
1842
|
+
relative: _relative,
|
|
1843
|
+
reloadDocument: _reloadDocument,
|
|
1844
|
+
prefetch: _prefetch,
|
|
1845
|
+
disabled,
|
|
1846
|
+
onClick: _onClick,
|
|
1847
|
+
children: _children,
|
|
1848
|
+
className: _className,
|
|
1849
|
+
style: _style,
|
|
1850
|
+
end: _end,
|
|
1851
|
+
caseSensitive: _caseSensitive,
|
|
1852
|
+
activeClassName: _activeClassName,
|
|
1853
|
+
pendingClassName: _pendingClassName,
|
|
1854
|
+
activeStyle: _activeStyle,
|
|
1855
|
+
pendingStyle: _pendingStyle,
|
|
1856
|
+
"aria-current": _ariaCurrent,
|
|
1857
|
+
...anchorProps
|
|
1858
|
+
} = props;
|
|
1859
|
+
if (disabled) {
|
|
1860
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { ...anchorProps, className: computedClassName(), style: computedStyle(), children: computedChildren() });
|
|
1861
|
+
}
|
|
1862
|
+
const finalClassName = computedClassName();
|
|
1863
|
+
const finalStyle = computedStyle();
|
|
1864
|
+
const finalAriaCurrent = ariaCurrent();
|
|
1865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1866
|
+
"a",
|
|
1867
|
+
{
|
|
1868
|
+
...anchorProps,
|
|
1869
|
+
href: href(),
|
|
1870
|
+
...finalClassName !== void 0 ? { className: finalClassName } : {},
|
|
1871
|
+
...finalStyle !== void 0 ? { style: finalStyle } : {},
|
|
1872
|
+
...finalAriaCurrent !== void 0 ? { "aria-current": finalAriaCurrent } : {},
|
|
1873
|
+
onClick: handleClick,
|
|
1874
|
+
children: computedChildren()
|
|
1875
|
+
}
|
|
1876
|
+
);
|
|
1877
|
+
}
|
|
1878
|
+
function Form(props) {
|
|
1879
|
+
const router = useRouter();
|
|
1880
|
+
const handleSubmit = (event) => {
|
|
1881
|
+
if (props.onSubmit) {
|
|
1882
|
+
props.onSubmit(event);
|
|
1883
|
+
}
|
|
1884
|
+
if (event.defaultPrevented) return;
|
|
1885
|
+
const form = event.currentTarget;
|
|
1886
|
+
const target = form.target;
|
|
1887
|
+
if (target && target !== "_self") return;
|
|
1888
|
+
event.preventDefault();
|
|
1889
|
+
const formData = new FormData(form);
|
|
1890
|
+
const method2 = props.method?.toUpperCase() || "GET";
|
|
1891
|
+
const actionUrl = props.action || router.location().pathname;
|
|
1892
|
+
if (method2 === "GET") {
|
|
1893
|
+
const searchParams = new URLSearchParams();
|
|
1894
|
+
formData.forEach((value, key) => {
|
|
1895
|
+
if (typeof value === "string") {
|
|
1896
|
+
searchParams.append(key, value);
|
|
1897
|
+
}
|
|
1898
|
+
});
|
|
1899
|
+
router.navigate(
|
|
1900
|
+
{
|
|
1901
|
+
pathname: actionUrl,
|
|
1902
|
+
search: "?" + searchParams.toString()
|
|
1903
|
+
},
|
|
1904
|
+
{ replace: props.replace }
|
|
1905
|
+
);
|
|
1906
|
+
} else {
|
|
1907
|
+
submitFormAction(form, actionUrl, method2, formData, {
|
|
1908
|
+
navigate: props.navigate !== false,
|
|
1909
|
+
replace: props.replace ?? false,
|
|
1910
|
+
router
|
|
1911
|
+
});
|
|
1912
|
+
}
|
|
1913
|
+
};
|
|
1914
|
+
async function submitFormAction(formElement, url, method2, formData, options) {
|
|
1915
|
+
try {
|
|
1916
|
+
const response = await fetch(url, {
|
|
1917
|
+
method: method2,
|
|
1918
|
+
body: formData,
|
|
1919
|
+
headers: {
|
|
1920
|
+
// Let the browser set Content-Type for FormData (includes boundary)
|
|
1921
|
+
Accept: "application/json"
|
|
1922
|
+
}
|
|
1923
|
+
});
|
|
1924
|
+
if (!response.ok) {
|
|
1925
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1926
|
+
}
|
|
1927
|
+
const contentType = response.headers.get("Content-Type");
|
|
1928
|
+
let data = null;
|
|
1929
|
+
if (contentType?.includes("application/json")) {
|
|
1930
|
+
data = await response.json();
|
|
1931
|
+
}
|
|
1932
|
+
const redirectUrl = response.headers.get("X-Redirect") || response.headers.get("Location");
|
|
1933
|
+
if (options.navigate && redirectUrl) {
|
|
1934
|
+
options.router.navigate(redirectUrl, { replace: options.replace });
|
|
1935
|
+
}
|
|
1936
|
+
formElement.dispatchEvent(
|
|
1937
|
+
new CustomEvent("formsubmit", {
|
|
1938
|
+
bubbles: true,
|
|
1939
|
+
detail: { data, response }
|
|
1940
|
+
})
|
|
1941
|
+
);
|
|
1942
|
+
return { data, response };
|
|
1943
|
+
} catch (error) {
|
|
1944
|
+
formElement.dispatchEvent(
|
|
1945
|
+
new CustomEvent("formerror", {
|
|
1946
|
+
bubbles: true,
|
|
1947
|
+
detail: { error }
|
|
1948
|
+
})
|
|
1949
|
+
);
|
|
1950
|
+
console.error("[fict-router] Form submission failed:", error);
|
|
1951
|
+
throw error;
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
const {
|
|
1955
|
+
action: action2,
|
|
1956
|
+
method,
|
|
1957
|
+
replace: _replace,
|
|
1958
|
+
relative: _relative,
|
|
1959
|
+
preventScrollReset: _preventScrollReset,
|
|
1960
|
+
navigate: _navigate,
|
|
1961
|
+
fetcherKey: _fetcherKey,
|
|
1962
|
+
children,
|
|
1963
|
+
onSubmit: _onSubmit,
|
|
1964
|
+
...formProps
|
|
1965
|
+
} = props;
|
|
1966
|
+
const htmlMethod = method && ["get", "post"].includes(method) ? method : void 0;
|
|
1967
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1968
|
+
"form",
|
|
1969
|
+
{
|
|
1970
|
+
...formProps,
|
|
1971
|
+
...action2 !== void 0 ? { action: action2 } : {},
|
|
1972
|
+
...htmlMethod !== void 0 ? { method: htmlMethod } : {},
|
|
1973
|
+
onSubmit: handleSubmit,
|
|
1974
|
+
children
|
|
1975
|
+
}
|
|
1976
|
+
);
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
// src/data.ts
|
|
1980
|
+
var import_runtime4 = require("@fictjs/runtime");
|
|
1981
|
+
var import_advanced2 = require("@fictjs/runtime/advanced");
|
|
1982
|
+
var CACHE_DURATION = 3 * 60 * 1e3;
|
|
1983
|
+
var PRELOAD_CACHE_DURATION = 5 * 1e3;
|
|
1984
|
+
var MAX_CACHE_SIZE = 500;
|
|
1985
|
+
var NORMAL_CLEANUP_INTERVAL = 60 * 1e3;
|
|
1986
|
+
var FAST_CLEANUP_INTERVAL = 10 * 1e3;
|
|
1987
|
+
var queryCache = /* @__PURE__ */ new Map();
|
|
1988
|
+
var cacheCleanupTimer;
|
|
1989
|
+
var currentCleanupInterval = NORMAL_CLEANUP_INTERVAL;
|
|
1990
|
+
function evictOldestEntries() {
|
|
1991
|
+
if (queryCache.size <= MAX_CACHE_SIZE) return;
|
|
1992
|
+
const entries = Array.from(queryCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
|
|
1993
|
+
const toRemove = queryCache.size - MAX_CACHE_SIZE;
|
|
1994
|
+
for (let i = 0; i < toRemove && i < entries.length; i++) {
|
|
1995
|
+
queryCache.delete(entries[i][0]);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
function runCacheCleanup() {
|
|
1999
|
+
const now = Date.now();
|
|
2000
|
+
for (const [key, entry] of queryCache) {
|
|
2001
|
+
const maxAge = entry.intent === "preload" ? PRELOAD_CACHE_DURATION : CACHE_DURATION;
|
|
2002
|
+
if (now - entry.timestamp > maxAge) {
|
|
2003
|
+
queryCache.delete(key);
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
const newInterval = queryCache.size > MAX_CACHE_SIZE / 2 ? FAST_CLEANUP_INTERVAL : NORMAL_CLEANUP_INTERVAL;
|
|
2007
|
+
if (newInterval !== currentCleanupInterval) {
|
|
2008
|
+
currentCleanupInterval = newInterval;
|
|
2009
|
+
stopCacheCleanup();
|
|
2010
|
+
startCacheCleanup();
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
function startCacheCleanup() {
|
|
2014
|
+
if (cacheCleanupTimer) return;
|
|
2015
|
+
cacheCleanupTimer = setInterval(runCacheCleanup, currentCleanupInterval);
|
|
2016
|
+
}
|
|
2017
|
+
function stopCacheCleanup() {
|
|
2018
|
+
if (cacheCleanupTimer) {
|
|
2019
|
+
clearInterval(cacheCleanupTimer);
|
|
2020
|
+
cacheCleanupTimer = void 0;
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
function query(fn, name) {
|
|
2024
|
+
startCacheCleanup();
|
|
2025
|
+
return (...args) => {
|
|
2026
|
+
const cacheKey = `${name}:${hashParams(args)}`;
|
|
2027
|
+
const cached = queryCache.get(cacheKey);
|
|
2028
|
+
if (cached && cached.result !== void 0) {
|
|
2029
|
+
const maxAge = cached.intent === "preload" ? PRELOAD_CACHE_DURATION : CACHE_DURATION;
|
|
2030
|
+
if (Date.now() - cached.timestamp < maxAge) {
|
|
2031
|
+
return () => cached.result;
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
const resultSignal = (0, import_advanced2.createSignal)(cached?.result);
|
|
2035
|
+
const errorSignal = (0, import_advanced2.createSignal)(void 0);
|
|
2036
|
+
const loadingSignal = (0, import_advanced2.createSignal)(true);
|
|
2037
|
+
const promise = Promise.resolve(fn(...args)).then((result) => {
|
|
2038
|
+
const entry = {
|
|
2039
|
+
timestamp: Date.now(),
|
|
2040
|
+
promise,
|
|
2041
|
+
result,
|
|
2042
|
+
intent: "navigate"
|
|
2043
|
+
};
|
|
2044
|
+
queryCache.set(cacheKey, entry);
|
|
2045
|
+
evictOldestEntries();
|
|
2046
|
+
(0, import_runtime4.batch)(() => {
|
|
2047
|
+
resultSignal(result);
|
|
2048
|
+
loadingSignal(false);
|
|
2049
|
+
});
|
|
2050
|
+
return result;
|
|
2051
|
+
}).catch((error) => {
|
|
2052
|
+
(0, import_runtime4.batch)(() => {
|
|
2053
|
+
errorSignal(error);
|
|
2054
|
+
loadingSignal(false);
|
|
2055
|
+
});
|
|
2056
|
+
throw error;
|
|
2057
|
+
});
|
|
2058
|
+
if (!cached) {
|
|
2059
|
+
queryCache.set(cacheKey, {
|
|
2060
|
+
timestamp: Date.now(),
|
|
2061
|
+
promise,
|
|
2062
|
+
intent: "navigate"
|
|
2063
|
+
});
|
|
2064
|
+
}
|
|
2065
|
+
return () => resultSignal();
|
|
2066
|
+
};
|
|
2067
|
+
}
|
|
2068
|
+
function revalidate(keys) {
|
|
2069
|
+
if (!keys) {
|
|
2070
|
+
queryCache.clear();
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
if (typeof keys === "string") {
|
|
2074
|
+
for (const cacheKey of queryCache.keys()) {
|
|
2075
|
+
if (cacheKey.startsWith(keys)) {
|
|
2076
|
+
queryCache.delete(cacheKey);
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
if (Array.isArray(keys)) {
|
|
2082
|
+
for (const key of keys) {
|
|
2083
|
+
for (const cacheKey of queryCache.keys()) {
|
|
2084
|
+
if (cacheKey.startsWith(key)) {
|
|
2085
|
+
queryCache.delete(cacheKey);
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
return;
|
|
2090
|
+
}
|
|
2091
|
+
if (keys instanceof RegExp) {
|
|
2092
|
+
for (const cacheKey of queryCache.keys()) {
|
|
2093
|
+
if (keys.test(cacheKey)) {
|
|
2094
|
+
queryCache.delete(cacheKey);
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
var actionRegistry = /* @__PURE__ */ new Map();
|
|
2100
|
+
var submissionCounter = 0;
|
|
2101
|
+
function action(fn, name) {
|
|
2102
|
+
const actionName = name || `action-${++submissionCounter}`;
|
|
2103
|
+
const actionUrl = `/_action/${actionName}`;
|
|
2104
|
+
actionRegistry.set(actionUrl, fn);
|
|
2105
|
+
return {
|
|
2106
|
+
url: actionUrl,
|
|
2107
|
+
name: actionName,
|
|
2108
|
+
submit: async (formData) => {
|
|
2109
|
+
const baseUrl = typeof window !== "undefined" && window.location ? window.location.origin : "http://localhost";
|
|
2110
|
+
const request = new Request(new URL(actionUrl, baseUrl).href, {
|
|
2111
|
+
method: "POST",
|
|
2112
|
+
body: formData
|
|
2113
|
+
});
|
|
2114
|
+
return fn(formData, { params: {}, request });
|
|
2115
|
+
}
|
|
2116
|
+
};
|
|
2117
|
+
}
|
|
2118
|
+
function getAction(url) {
|
|
2119
|
+
return actionRegistry.get(url);
|
|
2120
|
+
}
|
|
2121
|
+
var activeSubmissions = (0, import_advanced2.createSignal)(/* @__PURE__ */ new Map());
|
|
2122
|
+
function useSubmission(actionOrUrl) {
|
|
2123
|
+
const url = typeof actionOrUrl === "string" ? actionOrUrl : actionOrUrl.url;
|
|
2124
|
+
return () => {
|
|
2125
|
+
const submissions = activeSubmissions();
|
|
2126
|
+
return submissions.get(url);
|
|
2127
|
+
};
|
|
2128
|
+
}
|
|
2129
|
+
function useSubmissions() {
|
|
2130
|
+
return () => Array.from(activeSubmissions().values());
|
|
2131
|
+
}
|
|
2132
|
+
async function submitAction(action2, formData, params = {}) {
|
|
2133
|
+
const key = `submission-${++submissionCounter}`;
|
|
2134
|
+
const submission = {
|
|
2135
|
+
key,
|
|
2136
|
+
formData,
|
|
2137
|
+
state: "submitting",
|
|
2138
|
+
clear: () => {
|
|
2139
|
+
const submissions2 = new Map(activeSubmissions());
|
|
2140
|
+
submissions2.delete(action2.url);
|
|
2141
|
+
activeSubmissions(submissions2);
|
|
2142
|
+
},
|
|
2143
|
+
retry: () => {
|
|
2144
|
+
submitAction(action2, formData, params);
|
|
2145
|
+
}
|
|
2146
|
+
};
|
|
2147
|
+
const submissions = new Map(activeSubmissions());
|
|
2148
|
+
submissions.set(action2.url, submission);
|
|
2149
|
+
activeSubmissions(submissions);
|
|
2150
|
+
try {
|
|
2151
|
+
const result = await action2.submit(formData);
|
|
2152
|
+
submission.result = result;
|
|
2153
|
+
submission.state = "idle";
|
|
2154
|
+
const updatedSubmissions = new Map(activeSubmissions());
|
|
2155
|
+
updatedSubmissions.set(action2.url, submission);
|
|
2156
|
+
activeSubmissions(updatedSubmissions);
|
|
2157
|
+
return result;
|
|
2158
|
+
} catch (error) {
|
|
2159
|
+
submission.error = error;
|
|
2160
|
+
submission.state = "idle";
|
|
2161
|
+
const updatedSubmissions = new Map(activeSubmissions());
|
|
2162
|
+
updatedSubmissions.set(action2.url, submission);
|
|
2163
|
+
activeSubmissions(updatedSubmissions);
|
|
2164
|
+
throw error;
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
function preloadQuery(queryFn, ...args) {
|
|
2168
|
+
queryFn(...args);
|
|
2169
|
+
}
|
|
2170
|
+
function createPreload(fn) {
|
|
2171
|
+
return async (args) => {
|
|
2172
|
+
return fn(args);
|
|
2173
|
+
};
|
|
2174
|
+
}
|
|
2175
|
+
function createResource(source, fetcher) {
|
|
2176
|
+
const dataSignal = (0, import_advanced2.createSignal)(void 0);
|
|
2177
|
+
const loadingSignal = (0, import_advanced2.createSignal)(true);
|
|
2178
|
+
const errorSignal = (0, import_advanced2.createSignal)(void 0);
|
|
2179
|
+
const latestSignal = (0, import_advanced2.createSignal)(void 0);
|
|
2180
|
+
let currentSource;
|
|
2181
|
+
let fetchId = 0;
|
|
2182
|
+
const doFetch = async (s, id) => {
|
|
2183
|
+
loadingSignal(true);
|
|
2184
|
+
errorSignal(void 0);
|
|
2185
|
+
try {
|
|
2186
|
+
const result = await fetcher(s);
|
|
2187
|
+
if (id === fetchId) {
|
|
2188
|
+
(0, import_runtime4.batch)(() => {
|
|
2189
|
+
dataSignal(result);
|
|
2190
|
+
latestSignal(result);
|
|
2191
|
+
loadingSignal(false);
|
|
2192
|
+
});
|
|
2193
|
+
return result;
|
|
2194
|
+
}
|
|
2195
|
+
return void 0;
|
|
2196
|
+
} catch (err) {
|
|
2197
|
+
if (id === fetchId) {
|
|
2198
|
+
(0, import_runtime4.batch)(() => {
|
|
2199
|
+
errorSignal(err);
|
|
2200
|
+
loadingSignal(false);
|
|
2201
|
+
});
|
|
2202
|
+
}
|
|
2203
|
+
return void 0;
|
|
2204
|
+
}
|
|
2205
|
+
};
|
|
2206
|
+
(0, import_runtime4.createEffect)(() => {
|
|
2207
|
+
const s = source();
|
|
2208
|
+
if (s !== currentSource) {
|
|
2209
|
+
currentSource = s;
|
|
2210
|
+
const currentFetchId = ++fetchId;
|
|
2211
|
+
doFetch(s, currentFetchId);
|
|
2212
|
+
}
|
|
2213
|
+
});
|
|
2214
|
+
const resource = (() => dataSignal());
|
|
2215
|
+
resource.loading = () => loadingSignal();
|
|
2216
|
+
resource.error = () => errorSignal();
|
|
2217
|
+
resource.latest = () => latestSignal();
|
|
2218
|
+
resource.refetch = () => {
|
|
2219
|
+
const currentFetchId = ++fetchId;
|
|
2220
|
+
return doFetch(currentSource, currentFetchId);
|
|
2221
|
+
};
|
|
2222
|
+
return resource;
|
|
2223
|
+
}
|
|
2224
|
+
function cleanupDataUtilities() {
|
|
2225
|
+
stopCacheCleanup();
|
|
2226
|
+
queryCache.clear();
|
|
2227
|
+
actionRegistry.clear();
|
|
2228
|
+
activeSubmissions(/* @__PURE__ */ new Map());
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
// src/lazy.tsx
|
|
2232
|
+
var import_runtime5 = require("@fictjs/runtime");
|
|
2233
|
+
var import_advanced3 = require("@fictjs/runtime/advanced");
|
|
2234
|
+
var import_jsx_runtime3 = require("fict/jsx-runtime");
|
|
2235
|
+
function lazy(loader) {
|
|
2236
|
+
let cachedComponent = null;
|
|
2237
|
+
let loadPromise = null;
|
|
2238
|
+
const LazyComponent = (props) => {
|
|
2239
|
+
const state = (0, import_advanced3.createSignal)({
|
|
2240
|
+
component: cachedComponent,
|
|
2241
|
+
error: null,
|
|
2242
|
+
loading: !cachedComponent
|
|
2243
|
+
});
|
|
2244
|
+
if (cachedComponent) {
|
|
2245
|
+
const CachedComponent = cachedComponent;
|
|
2246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CachedComponent, { ...props });
|
|
2247
|
+
}
|
|
2248
|
+
if (!loadPromise) {
|
|
2249
|
+
loadPromise = loader().then((module2) => {
|
|
2250
|
+
const component = "default" in module2 ? module2.default : module2;
|
|
2251
|
+
cachedComponent = component;
|
|
2252
|
+
return component;
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
loadPromise.then((component) => {
|
|
2256
|
+
state({ component, error: null, loading: false });
|
|
2257
|
+
}).catch((error) => {
|
|
2258
|
+
state({ component: null, error, loading: false });
|
|
2259
|
+
});
|
|
2260
|
+
const currentState = state();
|
|
2261
|
+
if (currentState.error) {
|
|
2262
|
+
throw currentState.error;
|
|
2263
|
+
}
|
|
2264
|
+
if (currentState.loading || !currentState.component) {
|
|
2265
|
+
throw loadPromise;
|
|
2266
|
+
}
|
|
2267
|
+
const LoadedComponent = currentState.component;
|
|
2268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LoadedComponent, { ...props });
|
|
2269
|
+
};
|
|
2270
|
+
LazyComponent.__lazy = true;
|
|
2271
|
+
LazyComponent.__preload = () => {
|
|
2272
|
+
if (!loadPromise) {
|
|
2273
|
+
loadPromise = loader().then((module2) => {
|
|
2274
|
+
const component = "default" in module2 ? module2.default : module2;
|
|
2275
|
+
cachedComponent = component;
|
|
2276
|
+
return component;
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
2279
|
+
return loadPromise;
|
|
2280
|
+
};
|
|
2281
|
+
return LazyComponent;
|
|
2282
|
+
}
|
|
2283
|
+
function preloadLazy(component) {
|
|
2284
|
+
const lazyComp = component;
|
|
2285
|
+
if (lazyComp.__lazy && lazyComp.__preload) {
|
|
2286
|
+
return lazyComp.__preload();
|
|
2287
|
+
}
|
|
2288
|
+
return Promise.resolve();
|
|
2289
|
+
}
|
|
2290
|
+
function isLazyComponent(component) {
|
|
2291
|
+
return !!(component && typeof component === "function" && component.__lazy);
|
|
2292
|
+
}
|
|
2293
|
+
function lazyRoute(config) {
|
|
2294
|
+
const LazyComponent = lazy(config.component);
|
|
2295
|
+
const routeDef = {
|
|
2296
|
+
component: LazyComponent
|
|
2297
|
+
};
|
|
2298
|
+
if (config.path !== void 0) routeDef.path = config.path;
|
|
2299
|
+
if (config.loadingElement !== void 0) routeDef.loadingElement = config.loadingElement;
|
|
2300
|
+
if (config.errorElement !== void 0) routeDef.errorElement = config.errorElement;
|
|
2301
|
+
if (config.preload !== void 0) routeDef.preload = config.preload;
|
|
2302
|
+
if (config.children !== void 0) routeDef.children = config.children;
|
|
2303
|
+
if (config.index !== void 0) routeDef.index = config.index;
|
|
2304
|
+
if (config.key !== void 0) routeDef.key = config.key;
|
|
2305
|
+
return routeDef;
|
|
2306
|
+
}
|
|
2307
|
+
function createLazyRoutes(modules, options = {}) {
|
|
2308
|
+
const routes = [];
|
|
2309
|
+
for (const [filePath, loader] of Object.entries(modules)) {
|
|
2310
|
+
const path = options.pathTransform ? options.pathTransform(filePath) : filePath.replace(/^\.\/pages/, "").replace(/\.(tsx?|jsx?)$/, "").toLowerCase();
|
|
2311
|
+
routes.push(
|
|
2312
|
+
lazyRoute({
|
|
2313
|
+
path,
|
|
2314
|
+
component: loader,
|
|
2315
|
+
loadingElement: options.loadingElement,
|
|
2316
|
+
errorElement: options.errorElement
|
|
2317
|
+
})
|
|
2318
|
+
);
|
|
2319
|
+
}
|
|
2320
|
+
return routes;
|
|
2321
|
+
}
|
|
28
2322
|
// Annotate the CommonJS export names for ESM import in node:
|
|
29
2323
|
0 && (module.exports = {
|
|
30
|
-
|
|
2324
|
+
Form,
|
|
2325
|
+
HashRouter,
|
|
2326
|
+
Link,
|
|
2327
|
+
MemoryRouter,
|
|
2328
|
+
NavLink,
|
|
2329
|
+
Navigate,
|
|
2330
|
+
Outlet,
|
|
2331
|
+
Redirect,
|
|
2332
|
+
Route,
|
|
2333
|
+
Router,
|
|
2334
|
+
Routes,
|
|
2335
|
+
StaticRouter,
|
|
2336
|
+
action,
|
|
2337
|
+
cleanupDataUtilities,
|
|
2338
|
+
clearAllScrollPositions,
|
|
2339
|
+
clearScrollPosition,
|
|
2340
|
+
compileRoute,
|
|
2341
|
+
configureScrollRestoration,
|
|
2342
|
+
createBranches,
|
|
2343
|
+
createBrowserHistory,
|
|
2344
|
+
createHashHistory,
|
|
2345
|
+
createLazyRoutes,
|
|
2346
|
+
createLocation,
|
|
2347
|
+
createMemoryHistory,
|
|
2348
|
+
createPreload,
|
|
2349
|
+
createResource,
|
|
2350
|
+
createRouter,
|
|
2351
|
+
createRoutes,
|
|
2352
|
+
createScrollRestoration,
|
|
2353
|
+
createStaticHistory,
|
|
2354
|
+
createURL,
|
|
2355
|
+
getAction,
|
|
2356
|
+
getScrollRestoration,
|
|
2357
|
+
isBrowser,
|
|
2358
|
+
isLazyComponent,
|
|
2359
|
+
isServer,
|
|
2360
|
+
joinPaths,
|
|
2361
|
+
lazy,
|
|
2362
|
+
lazyRoute,
|
|
2363
|
+
locationsAreEqual,
|
|
2364
|
+
matchRoutes,
|
|
2365
|
+
normalizePath,
|
|
2366
|
+
parseSearchParams,
|
|
2367
|
+
parseURL,
|
|
2368
|
+
preloadLazy,
|
|
2369
|
+
preloadQuery,
|
|
2370
|
+
prependBasePath,
|
|
2371
|
+
query,
|
|
2372
|
+
resolvePath,
|
|
2373
|
+
restoreScrollPosition,
|
|
2374
|
+
revalidate,
|
|
2375
|
+
saveScrollPosition,
|
|
2376
|
+
scoreRoute,
|
|
2377
|
+
scrollToHash,
|
|
2378
|
+
scrollToTop,
|
|
2379
|
+
stringifySearchParams,
|
|
2380
|
+
stripBasePath,
|
|
2381
|
+
submitAction,
|
|
2382
|
+
useBeforeLeave,
|
|
2383
|
+
useHref,
|
|
2384
|
+
useIsActive,
|
|
2385
|
+
useIsRouting,
|
|
2386
|
+
useLocation,
|
|
2387
|
+
useMatch,
|
|
2388
|
+
useMatches,
|
|
2389
|
+
useNavigate,
|
|
2390
|
+
useParams,
|
|
2391
|
+
usePendingLocation,
|
|
2392
|
+
useResolvedPath,
|
|
2393
|
+
useRoute,
|
|
2394
|
+
useRouteData,
|
|
2395
|
+
useRouteError,
|
|
2396
|
+
useRouter,
|
|
2397
|
+
useSearchParams,
|
|
2398
|
+
useSubmission,
|
|
2399
|
+
useSubmissions
|
|
31
2400
|
});
|
|
2401
|
+
//# sourceMappingURL=index.cjs.map
|