@fictjs/router 0.4.0 → 0.5.1
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/README.md +1 -1
- package/dist/index.cjs +370 -181
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -8
- package/dist/index.d.ts +15 -8
- package/dist/index.js +360 -175
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/src/accessor-utils.ts +22 -0
- package/src/components.tsx +50 -451
- package/src/context.ts +161 -42
- package/src/lazy.tsx +29 -14
- package/src/link.tsx +58 -17
- package/src/router-internals.ts +33 -0
- package/src/router-provider.ts +388 -0
package/dist/index.js
CHANGED
|
@@ -1,19 +1,34 @@
|
|
|
1
1
|
// src/components.tsx
|
|
2
2
|
import {
|
|
3
3
|
createEffect,
|
|
4
|
-
onCleanup,
|
|
5
4
|
createMemo,
|
|
6
|
-
batch,
|
|
7
|
-
untrack,
|
|
8
|
-
startTransition,
|
|
9
5
|
Fragment,
|
|
10
6
|
Suspense,
|
|
11
7
|
ErrorBoundary
|
|
12
8
|
} from "@fictjs/runtime";
|
|
13
|
-
import { createSignal } from "@fictjs/runtime/advanced";
|
|
9
|
+
import { createSignal as createSignal3 } from "@fictjs/runtime/advanced";
|
|
10
|
+
|
|
11
|
+
// src/accessor-utils.ts
|
|
12
|
+
function wrapAccessor(fn) {
|
|
13
|
+
const wrapped = ((...args) => {
|
|
14
|
+
if (args.length === 0) return wrapped;
|
|
15
|
+
return fn(...args);
|
|
16
|
+
});
|
|
17
|
+
return wrapped;
|
|
18
|
+
}
|
|
19
|
+
function wrapValue(value) {
|
|
20
|
+
const wrapped = (() => value);
|
|
21
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
22
|
+
const primitive = value;
|
|
23
|
+
wrapped.toString = () => String(primitive);
|
|
24
|
+
wrapped.valueOf = () => primitive;
|
|
25
|
+
}
|
|
26
|
+
return wrapped;
|
|
27
|
+
}
|
|
14
28
|
|
|
15
29
|
// src/context.ts
|
|
16
|
-
import { createContext, useContext } from "@fictjs/runtime";
|
|
30
|
+
import { batch, createContext, useContext } from "@fictjs/runtime";
|
|
31
|
+
import { createSignal } from "@fictjs/runtime/advanced";
|
|
17
32
|
|
|
18
33
|
// src/utils.ts
|
|
19
34
|
function normalizePath(path) {
|
|
@@ -342,23 +357,76 @@ function isBrowser() {
|
|
|
342
357
|
}
|
|
343
358
|
|
|
344
359
|
// src/context.ts
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
360
|
+
function readAccessor(value) {
|
|
361
|
+
return typeof value === "function" ? value() : value;
|
|
362
|
+
}
|
|
363
|
+
var activeRouter = createSignal(null);
|
|
364
|
+
var activeRouterStack = [];
|
|
365
|
+
function pushActiveRouter(router) {
|
|
366
|
+
activeRouterStack.push(router);
|
|
367
|
+
batch(() => {
|
|
368
|
+
activeRouter(router);
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
function popActiveRouter(router) {
|
|
372
|
+
const index = activeRouterStack.lastIndexOf(router);
|
|
373
|
+
if (index >= 0) {
|
|
374
|
+
activeRouterStack.splice(index, 1);
|
|
375
|
+
}
|
|
376
|
+
batch(() => {
|
|
377
|
+
activeRouter(activeRouterStack[activeRouterStack.length - 1] ?? null);
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
var defaultLocation = {
|
|
381
|
+
pathname: "/",
|
|
382
|
+
search: "",
|
|
383
|
+
hash: "",
|
|
384
|
+
state: null,
|
|
385
|
+
key: "default"
|
|
386
|
+
};
|
|
387
|
+
var defaultNavigate = wrapAccessor(((toOrDelta) => {
|
|
388
|
+
const router = activeRouter();
|
|
389
|
+
if (!router) {
|
|
356
390
|
console.warn("[fict-router] No router found. Wrap your app in a <Router>");
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const navigate = readAccessor(router.navigate);
|
|
394
|
+
if (typeof toOrDelta === "number") {
|
|
395
|
+
return navigate(toOrDelta);
|
|
396
|
+
}
|
|
397
|
+
return navigate(toOrDelta);
|
|
398
|
+
}));
|
|
399
|
+
var defaultResolvePath = wrapAccessor((to) => {
|
|
400
|
+
const router = activeRouter();
|
|
401
|
+
if (router) {
|
|
402
|
+
return readAccessor(router.resolvePath)(to);
|
|
403
|
+
}
|
|
404
|
+
return typeof to === "string" ? to : to.pathname || "/";
|
|
405
|
+
});
|
|
406
|
+
var defaultRouterContext = {
|
|
407
|
+
location: () => {
|
|
408
|
+
const router = activeRouter();
|
|
409
|
+
return router ? readAccessor(router.location) : defaultLocation;
|
|
410
|
+
},
|
|
411
|
+
params: () => {
|
|
412
|
+
const router = activeRouter();
|
|
413
|
+
return router ? readAccessor(router.params) : {};
|
|
414
|
+
},
|
|
415
|
+
matches: () => {
|
|
416
|
+
const router = activeRouter();
|
|
417
|
+
return router ? readAccessor(router.matches) : [];
|
|
418
|
+
},
|
|
419
|
+
navigate: defaultNavigate,
|
|
420
|
+
isRouting: () => {
|
|
421
|
+
const router = activeRouter();
|
|
422
|
+
return router ? readAccessor(router.isRouting) : false;
|
|
423
|
+
},
|
|
424
|
+
pendingLocation: () => {
|
|
425
|
+
const router = activeRouter();
|
|
426
|
+
return router ? readAccessor(router.pendingLocation) : null;
|
|
357
427
|
},
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
base: "",
|
|
361
|
-
resolvePath: (to) => typeof to === "string" ? to : to.pathname || "/"
|
|
428
|
+
base: wrapValue(""),
|
|
429
|
+
resolvePath: defaultResolvePath
|
|
362
430
|
};
|
|
363
431
|
var RouterContext = createContext(defaultRouterContext);
|
|
364
432
|
RouterContext.displayName = "RouterContext";
|
|
@@ -369,17 +437,50 @@ var defaultRouteContext = {
|
|
|
369
437
|
match: () => void 0,
|
|
370
438
|
data: () => void 0,
|
|
371
439
|
outlet: () => null,
|
|
372
|
-
resolvePath: (to) => typeof to === "string" ? to : to.pathname || "/"
|
|
440
|
+
resolvePath: wrapAccessor((to) => typeof to === "string" ? to : to.pathname || "/")
|
|
373
441
|
};
|
|
374
442
|
var RouteContext = createContext(defaultRouteContext);
|
|
375
443
|
RouteContext.displayName = "RouteContext";
|
|
376
444
|
function useRoute() {
|
|
377
445
|
return useContext(RouteContext);
|
|
378
446
|
}
|
|
447
|
+
var activeBeforeLeave = createSignal(null);
|
|
448
|
+
var activeBeforeLeaveStack = [];
|
|
449
|
+
function pushActiveBeforeLeave(context) {
|
|
450
|
+
activeBeforeLeaveStack.push(context);
|
|
451
|
+
batch(() => {
|
|
452
|
+
activeBeforeLeave(context);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
function popActiveBeforeLeave(context) {
|
|
456
|
+
const index = activeBeforeLeaveStack.lastIndexOf(context);
|
|
457
|
+
if (index >= 0) {
|
|
458
|
+
activeBeforeLeaveStack.splice(index, 1);
|
|
459
|
+
}
|
|
460
|
+
batch(() => {
|
|
461
|
+
activeBeforeLeave(activeBeforeLeaveStack[activeBeforeLeaveStack.length - 1] ?? null);
|
|
462
|
+
});
|
|
463
|
+
}
|
|
379
464
|
var defaultBeforeLeaveContext = {
|
|
380
|
-
addHandler: (
|
|
381
|
-
|
|
382
|
-
|
|
465
|
+
addHandler: wrapAccessor((handler) => {
|
|
466
|
+
const context = activeBeforeLeave();
|
|
467
|
+
if (context) {
|
|
468
|
+
return readAccessor(
|
|
469
|
+
context.addHandler
|
|
470
|
+
)(handler);
|
|
471
|
+
}
|
|
472
|
+
return () => {
|
|
473
|
+
};
|
|
474
|
+
}),
|
|
475
|
+
confirm: wrapAccessor((to, from) => {
|
|
476
|
+
const context = activeBeforeLeave();
|
|
477
|
+
if (context) {
|
|
478
|
+
return readAccessor(
|
|
479
|
+
context.confirm
|
|
480
|
+
)(to, from);
|
|
481
|
+
}
|
|
482
|
+
return Promise.resolve(true);
|
|
483
|
+
})
|
|
383
484
|
};
|
|
384
485
|
var BeforeLeaveContext = createContext(defaultBeforeLeaveContext);
|
|
385
486
|
BeforeLeaveContext.displayName = "BeforeLeaveContext";
|
|
@@ -394,27 +495,28 @@ var RouteErrorContext = createContext(defaultRouteErrorContext);
|
|
|
394
495
|
RouteErrorContext.displayName = "RouteErrorContext";
|
|
395
496
|
function useNavigate() {
|
|
396
497
|
const router = useRouter();
|
|
397
|
-
return router.navigate;
|
|
498
|
+
return readAccessor(router.navigate);
|
|
398
499
|
}
|
|
399
500
|
function useLocation() {
|
|
400
501
|
const router = useRouter();
|
|
401
|
-
return router.location;
|
|
502
|
+
return () => readAccessor(router.location);
|
|
402
503
|
}
|
|
403
504
|
function useParams() {
|
|
404
505
|
const router = useRouter();
|
|
405
|
-
return router.params;
|
|
506
|
+
return () => readAccessor(router.params);
|
|
406
507
|
}
|
|
407
508
|
function useSearchParams() {
|
|
408
509
|
const router = useRouter();
|
|
409
510
|
const getSearchParams = () => {
|
|
410
|
-
const location = router.location
|
|
511
|
+
const location = readAccessor(router.location);
|
|
411
512
|
return new URLSearchParams(location.search);
|
|
412
513
|
};
|
|
413
514
|
const setSearchParams = (params, options) => {
|
|
414
515
|
const searchParams = params instanceof URLSearchParams ? params : new URLSearchParams(params);
|
|
415
516
|
const search = searchParams.toString();
|
|
416
|
-
const location = router.location
|
|
417
|
-
router.navigate
|
|
517
|
+
const location = readAccessor(router.location);
|
|
518
|
+
const navigate = readAccessor(router.navigate);
|
|
519
|
+
navigate(
|
|
418
520
|
{
|
|
419
521
|
pathname: location.pathname,
|
|
420
522
|
search: search ? "?" + search : "",
|
|
@@ -423,23 +525,23 @@ function useSearchParams() {
|
|
|
423
525
|
{ replace: options?.replace }
|
|
424
526
|
);
|
|
425
527
|
};
|
|
426
|
-
return [getSearchParams, setSearchParams];
|
|
528
|
+
return [getSearchParams, wrapAccessor(setSearchParams)];
|
|
427
529
|
}
|
|
428
530
|
function useMatches() {
|
|
429
531
|
const router = useRouter();
|
|
430
|
-
return router.matches;
|
|
532
|
+
return () => readAccessor(router.matches);
|
|
431
533
|
}
|
|
432
534
|
function useIsRouting() {
|
|
433
535
|
const router = useRouter();
|
|
434
|
-
return router.isRouting;
|
|
536
|
+
return () => readAccessor(router.isRouting);
|
|
435
537
|
}
|
|
436
538
|
function usePendingLocation() {
|
|
437
539
|
const router = useRouter();
|
|
438
|
-
return router.pendingLocation;
|
|
540
|
+
return () => readAccessor(router.pendingLocation);
|
|
439
541
|
}
|
|
440
542
|
function useRouteData() {
|
|
441
543
|
const route = useRoute();
|
|
442
|
-
return route.data;
|
|
544
|
+
return () => readAccessor(route.data);
|
|
443
545
|
}
|
|
444
546
|
function useRouteError() {
|
|
445
547
|
const errorContext = useContext(RouteErrorContext);
|
|
@@ -447,20 +549,23 @@ function useRouteError() {
|
|
|
447
549
|
return errorContext.error;
|
|
448
550
|
}
|
|
449
551
|
const route = useRoute();
|
|
450
|
-
|
|
552
|
+
const routeError = route.error;
|
|
553
|
+
if (routeError === void 0) return void 0;
|
|
554
|
+
return readAccessor(routeError);
|
|
451
555
|
}
|
|
452
556
|
function useResolvedPath(to) {
|
|
453
557
|
const route = useRoute();
|
|
454
558
|
return () => {
|
|
455
559
|
const target = typeof to === "function" ? to() : to;
|
|
456
|
-
|
|
560
|
+
const resolvePath2 = readAccessor(route.resolvePath);
|
|
561
|
+
return resolvePath2(target);
|
|
457
562
|
};
|
|
458
563
|
}
|
|
459
564
|
function useMatch(path) {
|
|
460
565
|
const router = useRouter();
|
|
461
566
|
return () => {
|
|
462
567
|
const targetPath = typeof path === "function" ? path() : path;
|
|
463
|
-
const matches = router.matches
|
|
568
|
+
const matches = readAccessor(router.matches);
|
|
464
569
|
for (const match of matches) {
|
|
465
570
|
if (match.pattern === targetPath || match.pathname === targetPath) {
|
|
466
571
|
return match;
|
|
@@ -473,6 +578,7 @@ function useHref(to) {
|
|
|
473
578
|
const router = useRouter();
|
|
474
579
|
return () => {
|
|
475
580
|
const target = typeof to === "function" ? to() : to;
|
|
581
|
+
const base = readAccessor(router.base);
|
|
476
582
|
let pathname;
|
|
477
583
|
let search = "";
|
|
478
584
|
let hash = "";
|
|
@@ -496,16 +602,17 @@ function useHref(to) {
|
|
|
496
602
|
}
|
|
497
603
|
let resolved;
|
|
498
604
|
if (pathname === "") {
|
|
499
|
-
const currentPathname = router.location
|
|
500
|
-
const normalizedBase =
|
|
605
|
+
const currentPathname = readAccessor(router.location).pathname;
|
|
606
|
+
const normalizedBase = base === "/" || base === "" ? "" : base;
|
|
501
607
|
if (normalizedBase && !currentPathname.startsWith(normalizedBase)) {
|
|
502
608
|
return currentPathname + search + hash;
|
|
503
609
|
}
|
|
504
|
-
resolved = stripBasePath(currentPathname,
|
|
610
|
+
resolved = stripBasePath(currentPathname, base);
|
|
505
611
|
} else {
|
|
506
|
-
|
|
612
|
+
const resolvePath2 = readAccessor(router.resolvePath);
|
|
613
|
+
resolved = resolvePath2(pathname);
|
|
507
614
|
}
|
|
508
|
-
const baseHref = prependBasePath(resolved,
|
|
615
|
+
const baseHref = prependBasePath(resolved, base);
|
|
509
616
|
return baseHref + search + hash;
|
|
510
617
|
};
|
|
511
618
|
}
|
|
@@ -513,12 +620,14 @@ function useIsActive(to, options) {
|
|
|
513
620
|
const router = useRouter();
|
|
514
621
|
return () => {
|
|
515
622
|
const target = typeof to === "function" ? to() : to;
|
|
516
|
-
const
|
|
517
|
-
const
|
|
518
|
-
|
|
623
|
+
const resolvePath2 = readAccessor(router.resolvePath);
|
|
624
|
+
const resolvedTargetPath = resolvePath2(target);
|
|
625
|
+
const currentPath = readAccessor(router.location).pathname;
|
|
626
|
+
const base = readAccessor(router.base);
|
|
627
|
+
if (base && currentPath !== base && !currentPath.startsWith(base + "/")) {
|
|
519
628
|
return false;
|
|
520
629
|
}
|
|
521
|
-
const currentPathWithoutBase = stripBasePath(currentPath,
|
|
630
|
+
const currentPathWithoutBase = stripBasePath(currentPath, base);
|
|
522
631
|
if (options?.end) {
|
|
523
632
|
return currentPathWithoutBase === resolvedTargetPath;
|
|
524
633
|
}
|
|
@@ -998,6 +1107,37 @@ function createStaticHistory(url) {
|
|
|
998
1107
|
};
|
|
999
1108
|
}
|
|
1000
1109
|
|
|
1110
|
+
// src/router-internals.ts
|
|
1111
|
+
var isDevEnv = typeof import.meta !== "undefined" && import.meta.env?.DEV === true || typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
1112
|
+
var didWarnBaseMismatch = false;
|
|
1113
|
+
function hasBasePrefix(pathname, base) {
|
|
1114
|
+
if (!base) return true;
|
|
1115
|
+
return pathname === base || pathname.startsWith(base + "/");
|
|
1116
|
+
}
|
|
1117
|
+
function stripBaseOrWarn(pathname, base) {
|
|
1118
|
+
if (!base) return pathname;
|
|
1119
|
+
if (!hasBasePrefix(pathname, base)) {
|
|
1120
|
+
if (isDevEnv && !didWarnBaseMismatch) {
|
|
1121
|
+
didWarnBaseMismatch = true;
|
|
1122
|
+
console.warn(
|
|
1123
|
+
`[fict-router] Location "${pathname}" does not start with base "${base}". No routes matched.`
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
return null;
|
|
1127
|
+
}
|
|
1128
|
+
return stripBasePath(pathname, base);
|
|
1129
|
+
}
|
|
1130
|
+
function stripBaseIfPresent(pathname, base) {
|
|
1131
|
+
if (!base) return pathname;
|
|
1132
|
+
if (!hasBasePrefix(pathname, base)) return pathname;
|
|
1133
|
+
return stripBasePath(pathname, base);
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
// src/router-provider.ts
|
|
1137
|
+
import { batch as batch2, onCleanup, startTransition, untrack } from "@fictjs/runtime";
|
|
1138
|
+
import { createSignal as createSignal2 } from "@fictjs/runtime/advanced";
|
|
1139
|
+
import { jsx } from "@fictjs/runtime/jsx-runtime";
|
|
1140
|
+
|
|
1001
1141
|
// src/scroll.ts
|
|
1002
1142
|
var scrollPositions = /* @__PURE__ */ new Map();
|
|
1003
1143
|
var MAX_STORED_POSITIONS = 100;
|
|
@@ -1120,34 +1260,7 @@ function configureScrollRestoration(options) {
|
|
|
1120
1260
|
defaultScrollRestoration = createScrollRestoration(options);
|
|
1121
1261
|
}
|
|
1122
1262
|
|
|
1123
|
-
// src/
|
|
1124
|
-
import { Fragment as Fragment2, jsx } from "fict/jsx-runtime";
|
|
1125
|
-
var isDevEnv = typeof import.meta !== "undefined" && import.meta.env?.DEV === true || typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
1126
|
-
var didWarnBaseMismatch = false;
|
|
1127
|
-
function hasBasePrefix(pathname, base) {
|
|
1128
|
-
if (!base) return true;
|
|
1129
|
-
return pathname === base || pathname.startsWith(base + "/");
|
|
1130
|
-
}
|
|
1131
|
-
function stripBaseOrWarn(pathname, base) {
|
|
1132
|
-
if (!base) return pathname;
|
|
1133
|
-
if (!hasBasePrefix(pathname, base)) {
|
|
1134
|
-
if (isDevEnv && !didWarnBaseMismatch) {
|
|
1135
|
-
didWarnBaseMismatch = true;
|
|
1136
|
-
console.warn(
|
|
1137
|
-
`[fict-router] Location "${pathname}" does not start with base "${base}". No routes matched.`
|
|
1138
|
-
);
|
|
1139
|
-
}
|
|
1140
|
-
return null;
|
|
1141
|
-
}
|
|
1142
|
-
return stripBasePath(pathname, base);
|
|
1143
|
-
}
|
|
1144
|
-
function stripBaseIfPresent(pathname, base) {
|
|
1145
|
-
if (!base) return pathname;
|
|
1146
|
-
if (hasBasePrefix(pathname, base)) {
|
|
1147
|
-
return stripBasePath(pathname, base);
|
|
1148
|
-
}
|
|
1149
|
-
return pathname;
|
|
1150
|
-
}
|
|
1263
|
+
// src/router-provider.ts
|
|
1151
1264
|
function createRouterState(history2, routes, base = "") {
|
|
1152
1265
|
const normalizedBase = normalizePath(base);
|
|
1153
1266
|
const baseForStrip = normalizedBase === "/" ? "" : normalizedBase;
|
|
@@ -1160,10 +1273,10 @@ function createRouterState(history2, routes, base = "") {
|
|
|
1160
1273
|
};
|
|
1161
1274
|
const initialLocation = history2.location;
|
|
1162
1275
|
const initialMatches = matchWithBase(initialLocation.pathname);
|
|
1163
|
-
const locationSignal =
|
|
1164
|
-
const matchesSignal =
|
|
1165
|
-
const isRoutingSignal =
|
|
1166
|
-
const pendingLocationSignal =
|
|
1276
|
+
const locationSignal = createSignal2(initialLocation);
|
|
1277
|
+
const matchesSignal = createSignal2(initialMatches);
|
|
1278
|
+
const isRoutingSignal = createSignal2(false);
|
|
1279
|
+
const pendingLocationSignal = createSignal2(null);
|
|
1167
1280
|
const beforeLeaveHandlers = /* @__PURE__ */ new Set();
|
|
1168
1281
|
let navigationToken = 0;
|
|
1169
1282
|
const beforeLeave = {
|
|
@@ -1174,7 +1287,7 @@ function createRouterState(history2, routes, base = "") {
|
|
|
1174
1287
|
async confirm(to, from) {
|
|
1175
1288
|
if (beforeLeaveHandlers.size === 0) return true;
|
|
1176
1289
|
const currentToken = ++navigationToken;
|
|
1177
|
-
let defaultPrevented =
|
|
1290
|
+
let defaultPrevented = true;
|
|
1178
1291
|
let retryRequested = false;
|
|
1179
1292
|
let forceRetry = false;
|
|
1180
1293
|
const event = {
|
|
@@ -1271,12 +1384,14 @@ function createRouterState(history2, routes, base = "") {
|
|
|
1271
1384
|
}
|
|
1272
1385
|
const targetLocation = createLocation(locationSpec, finalState, toKey);
|
|
1273
1386
|
untrack(async () => {
|
|
1387
|
+
if (beforeLeaveHandlers.size > 0) {
|
|
1388
|
+
pendingLocationSignal(targetLocation);
|
|
1389
|
+
}
|
|
1274
1390
|
const canNavigate = await beforeLeave.confirm(targetLocation, currentLocation);
|
|
1275
1391
|
if (!canNavigate) {
|
|
1276
|
-
pendingLocationSignal(null);
|
|
1277
1392
|
return;
|
|
1278
1393
|
}
|
|
1279
|
-
|
|
1394
|
+
batch2(() => {
|
|
1280
1395
|
isRoutingSignal(true);
|
|
1281
1396
|
pendingLocationSignal(targetLocation);
|
|
1282
1397
|
});
|
|
@@ -1296,7 +1411,7 @@ function createRouterState(history2, routes, base = "") {
|
|
|
1296
1411
|
);
|
|
1297
1412
|
}
|
|
1298
1413
|
if (locationsAreEqual(prevLocation, history2.location)) {
|
|
1299
|
-
|
|
1414
|
+
batch2(() => {
|
|
1300
1415
|
isRoutingSignal(false);
|
|
1301
1416
|
pendingLocationSignal(null);
|
|
1302
1417
|
});
|
|
@@ -1306,7 +1421,7 @@ function createRouterState(history2, routes, base = "") {
|
|
|
1306
1421
|
};
|
|
1307
1422
|
const unlisten = history2.listen(({ action: action2, location: newLocation }) => {
|
|
1308
1423
|
const prevLocation = locationSignal();
|
|
1309
|
-
|
|
1424
|
+
batch2(() => {
|
|
1310
1425
|
locationSignal(newLocation);
|
|
1311
1426
|
const newMatches = matchWithBase(newLocation.pathname);
|
|
1312
1427
|
matchesSignal(newMatches);
|
|
@@ -1339,6 +1454,17 @@ function RouterProvider(props) {
|
|
|
1339
1454
|
props.base
|
|
1340
1455
|
);
|
|
1341
1456
|
onCleanup(cleanup);
|
|
1457
|
+
const beforeLeaveContext = {
|
|
1458
|
+
addHandler: wrapAccessor(beforeLeave.addHandler),
|
|
1459
|
+
confirm: wrapAccessor(beforeLeave.confirm)
|
|
1460
|
+
};
|
|
1461
|
+
const resolvePathFn = (to) => {
|
|
1462
|
+
const location = state().location;
|
|
1463
|
+
const currentPathWithoutBase = stripBaseOrWarn(location.pathname, normalizedBase) || "/";
|
|
1464
|
+
const rawTargetPath = typeof to === "string" ? to : to.pathname || "/";
|
|
1465
|
+
const targetPath = rawTargetPath.startsWith("/") ? stripBaseIfPresent(rawTargetPath, normalizedBase) : rawTargetPath;
|
|
1466
|
+
return resolvePath(currentPathWithoutBase, targetPath);
|
|
1467
|
+
};
|
|
1342
1468
|
const routerContext = {
|
|
1343
1469
|
location: () => state().location,
|
|
1344
1470
|
params: () => {
|
|
@@ -1350,30 +1476,41 @@ function RouterProvider(props) {
|
|
|
1350
1476
|
return allParams;
|
|
1351
1477
|
},
|
|
1352
1478
|
matches: () => state().matches,
|
|
1353
|
-
navigate,
|
|
1479
|
+
navigate: wrapAccessor(navigate),
|
|
1354
1480
|
isRouting: () => state().isRouting,
|
|
1355
1481
|
pendingLocation: () => state().pendingLocation,
|
|
1356
|
-
base: normalizedBase,
|
|
1357
|
-
resolvePath: (
|
|
1358
|
-
const location = state().location;
|
|
1359
|
-
const currentPathWithoutBase = stripBaseOrWarn(location.pathname, normalizedBase) || "/";
|
|
1360
|
-
const rawTargetPath = typeof to === "string" ? to : to.pathname || "/";
|
|
1361
|
-
const targetPath = rawTargetPath.startsWith("/") ? stripBaseIfPresent(rawTargetPath, normalizedBase) : rawTargetPath;
|
|
1362
|
-
return resolvePath(currentPathWithoutBase, targetPath);
|
|
1363
|
-
}
|
|
1482
|
+
base: wrapValue(normalizedBase),
|
|
1483
|
+
resolvePath: wrapAccessor(resolvePathFn)
|
|
1364
1484
|
};
|
|
1365
|
-
|
|
1485
|
+
pushActiveRouter(routerContext);
|
|
1486
|
+
pushActiveBeforeLeave(beforeLeaveContext);
|
|
1487
|
+
onCleanup(() => {
|
|
1488
|
+
popActiveBeforeLeave(beforeLeaveContext);
|
|
1489
|
+
popActiveRouter(routerContext);
|
|
1490
|
+
});
|
|
1491
|
+
const RouterContextProvider = RouterContext.Provider;
|
|
1492
|
+
const BeforeLeaveProvider = BeforeLeaveContext.Provider;
|
|
1493
|
+
return jsx(RouterContextProvider, {
|
|
1494
|
+
value: routerContext,
|
|
1495
|
+
children: jsx(BeforeLeaveProvider, {
|
|
1496
|
+
value: beforeLeaveContext,
|
|
1497
|
+
children: props.children
|
|
1498
|
+
})
|
|
1499
|
+
});
|
|
1366
1500
|
}
|
|
1501
|
+
|
|
1502
|
+
// src/components.tsx
|
|
1503
|
+
import { Fragment as Fragment2, jsx as jsx2 } from "fict/jsx-runtime";
|
|
1367
1504
|
function Router(props) {
|
|
1368
1505
|
const history2 = props.history || createBrowserHistory();
|
|
1369
1506
|
const routes = extractRoutes(props.children);
|
|
1370
|
-
return /* @__PURE__ */
|
|
1507
|
+
return /* @__PURE__ */ jsx2(RouterProvider, { history: history2, routes, base: props.base, children: /* @__PURE__ */ jsx2(Routes, { children: props.children }) });
|
|
1371
1508
|
}
|
|
1372
1509
|
function HashRouter(props) {
|
|
1373
1510
|
const hashOptions = props.hashType ? { hashType: props.hashType } : void 0;
|
|
1374
1511
|
const history2 = createHashHistory(hashOptions);
|
|
1375
1512
|
const routes = extractRoutes(props.children);
|
|
1376
|
-
return /* @__PURE__ */
|
|
1513
|
+
return /* @__PURE__ */ jsx2(RouterProvider, { history: history2, routes, base: props.base, children: /* @__PURE__ */ jsx2(Routes, { children: props.children }) });
|
|
1377
1514
|
}
|
|
1378
1515
|
function MemoryRouter(props) {
|
|
1379
1516
|
const memoryOptions = {};
|
|
@@ -1387,12 +1524,12 @@ function MemoryRouter(props) {
|
|
|
1387
1524
|
Object.keys(memoryOptions).length > 0 ? memoryOptions : void 0
|
|
1388
1525
|
);
|
|
1389
1526
|
const routes = extractRoutes(props.children);
|
|
1390
|
-
return /* @__PURE__ */
|
|
1527
|
+
return /* @__PURE__ */ jsx2(RouterProvider, { history: history2, routes, base: props.base, children: /* @__PURE__ */ jsx2(Routes, { children: props.children }) });
|
|
1391
1528
|
}
|
|
1392
1529
|
function StaticRouter(props) {
|
|
1393
1530
|
const history2 = createStaticHistory(props.url);
|
|
1394
1531
|
const routes = extractRoutes(props.children);
|
|
1395
|
-
return /* @__PURE__ */
|
|
1532
|
+
return /* @__PURE__ */ jsx2(RouterProvider, { history: history2, routes, base: props.base, children: /* @__PURE__ */ jsx2(Routes, { children: props.children }) });
|
|
1396
1533
|
}
|
|
1397
1534
|
function Routes(props) {
|
|
1398
1535
|
const router = useRouter();
|
|
@@ -1401,9 +1538,11 @@ function Routes(props) {
|
|
|
1401
1538
|
const compiledRoutes = routes.map((r) => compileRoute(r));
|
|
1402
1539
|
const branches = createBranches(compiledRoutes);
|
|
1403
1540
|
const currentMatches = createMemo(() => {
|
|
1404
|
-
const
|
|
1405
|
-
const
|
|
1406
|
-
const
|
|
1541
|
+
const pendingLocation = readAccessor(router.pendingLocation);
|
|
1542
|
+
const location = pendingLocation ?? readAccessor(router.location);
|
|
1543
|
+
const parentMatch = readAccessor(parentRoute.match);
|
|
1544
|
+
const base = readAccessor(router.base);
|
|
1545
|
+
const locationPath = stripBaseOrWarn(location.pathname, base);
|
|
1407
1546
|
if (locationPath == null) return [];
|
|
1408
1547
|
let basePath = "/";
|
|
1409
1548
|
if (parentMatch) {
|
|
@@ -1412,16 +1551,14 @@ function Routes(props) {
|
|
|
1412
1551
|
const relativePath = locationPath.startsWith(basePath) ? locationPath.slice(basePath.length) || "/" : locationPath;
|
|
1413
1552
|
return matchRoutes(branches, relativePath) || [];
|
|
1414
1553
|
});
|
|
1415
|
-
|
|
1554
|
+
const matches = currentMatches();
|
|
1555
|
+
return /* @__PURE__ */ jsx2(Fragment2, { children: matches.length > 0 ? renderMatches(matches, 0) : null });
|
|
1416
1556
|
}
|
|
1417
1557
|
function renderMatches(matches, index) {
|
|
1418
|
-
if (index >= matches.length) {
|
|
1419
|
-
return null;
|
|
1420
|
-
}
|
|
1421
1558
|
const match = matches[index];
|
|
1422
1559
|
const route = match.route;
|
|
1423
1560
|
const router = useRouter();
|
|
1424
|
-
const dataState =
|
|
1561
|
+
const dataState = createSignal3({
|
|
1425
1562
|
data: void 0,
|
|
1426
1563
|
error: void 0,
|
|
1427
1564
|
loading: !!route.preload
|
|
@@ -1429,7 +1566,7 @@ function renderMatches(matches, index) {
|
|
|
1429
1566
|
let preloadToken = 0;
|
|
1430
1567
|
if (route.preload) {
|
|
1431
1568
|
createEffect(() => {
|
|
1432
|
-
const location = router.location
|
|
1569
|
+
const location = readAccessor(router.location);
|
|
1433
1570
|
const preloadArgs = {
|
|
1434
1571
|
params: match.params,
|
|
1435
1572
|
location,
|
|
@@ -1448,17 +1585,7 @@ function renderMatches(matches, index) {
|
|
|
1448
1585
|
});
|
|
1449
1586
|
});
|
|
1450
1587
|
}
|
|
1451
|
-
const
|
|
1452
|
-
match: () => match,
|
|
1453
|
-
data: () => dataState().data,
|
|
1454
|
-
error: () => dataState().error,
|
|
1455
|
-
outlet: () => renderMatches(matches, index + 1),
|
|
1456
|
-
resolvePath: (to) => {
|
|
1457
|
-
const basePath = match.pathname;
|
|
1458
|
-
const targetPath = typeof to === "string" ? to : to.pathname || "/";
|
|
1459
|
-
return resolvePath(basePath, targetPath);
|
|
1460
|
-
}
|
|
1461
|
-
};
|
|
1588
|
+
const outletNode = /* @__PURE__ */ jsx2(Outlet, {});
|
|
1462
1589
|
const renderContent = () => {
|
|
1463
1590
|
const state = dataState();
|
|
1464
1591
|
if (state.error !== void 0 && route.errorElement) {
|
|
@@ -1469,26 +1596,39 @@ function renderMatches(matches, index) {
|
|
|
1469
1596
|
}
|
|
1470
1597
|
if (route.component) {
|
|
1471
1598
|
const Component = route.component;
|
|
1472
|
-
return /* @__PURE__ */
|
|
1473
|
-
}
|
|
1599
|
+
return /* @__PURE__ */ jsx2(Component, { params: match.params, location: readAccessor(router.location), data: state.data, children: outletNode });
|
|
1600
|
+
}
|
|
1601
|
+
if (route.element) {
|
|
1474
1602
|
return route.element;
|
|
1475
|
-
}
|
|
1476
|
-
|
|
1603
|
+
}
|
|
1604
|
+
if (route.children) {
|
|
1605
|
+
return outletNode;
|
|
1477
1606
|
}
|
|
1478
1607
|
return null;
|
|
1479
1608
|
};
|
|
1480
|
-
|
|
1609
|
+
const routeContext = {
|
|
1610
|
+
match: () => match,
|
|
1611
|
+
data: () => dataState().data,
|
|
1612
|
+
error: () => dataState().error,
|
|
1613
|
+
outlet: () => index + 1 < matches.length ? renderMatches(matches, index + 1) : null,
|
|
1614
|
+
resolvePath: wrapAccessor((to) => {
|
|
1615
|
+
const basePath = match.pathname;
|
|
1616
|
+
const targetPath = typeof to === "string" ? to : to.pathname || "/";
|
|
1617
|
+
return resolvePath(basePath, targetPath);
|
|
1618
|
+
})
|
|
1619
|
+
};
|
|
1620
|
+
let content = /* @__PURE__ */ jsx2(RouteContext.Provider, { value: routeContext, children: renderContent() });
|
|
1481
1621
|
if (route.errorElement) {
|
|
1482
|
-
content = /* @__PURE__ */
|
|
1622
|
+
content = /* @__PURE__ */ jsx2(
|
|
1483
1623
|
ErrorBoundary,
|
|
1484
1624
|
{
|
|
1485
|
-
fallback: (err, reset) => /* @__PURE__ */
|
|
1625
|
+
fallback: (err, reset) => /* @__PURE__ */ jsx2(RouteErrorContext.Provider, { value: { error: err, reset }, children: route.errorElement }),
|
|
1486
1626
|
children: content
|
|
1487
1627
|
}
|
|
1488
1628
|
);
|
|
1489
1629
|
}
|
|
1490
1630
|
if (route.loadingElement) {
|
|
1491
|
-
content = /* @__PURE__ */
|
|
1631
|
+
content = /* @__PURE__ */ jsx2(Suspense, { fallback: route.loadingElement, children: content });
|
|
1492
1632
|
}
|
|
1493
1633
|
return content;
|
|
1494
1634
|
}
|
|
@@ -1497,7 +1637,7 @@ function Route(_props) {
|
|
|
1497
1637
|
}
|
|
1498
1638
|
function Outlet() {
|
|
1499
1639
|
const route = useRoute();
|
|
1500
|
-
return
|
|
1640
|
+
return readAccessor(route.outlet);
|
|
1501
1641
|
}
|
|
1502
1642
|
function Navigate(props) {
|
|
1503
1643
|
const router = useRouter();
|
|
@@ -1554,28 +1694,42 @@ function createRouter(routes, options) {
|
|
|
1554
1694
|
return {
|
|
1555
1695
|
Router: (props) => {
|
|
1556
1696
|
const history2 = options?.history || createBrowserHistory();
|
|
1557
|
-
return /* @__PURE__ */
|
|
1697
|
+
return /* @__PURE__ */ jsx2(RouterProvider, { history: history2, routes, base: options?.base, children: props.children || /* @__PURE__ */ jsx2(Routes, { children: routesToElements(routes) }) });
|
|
1558
1698
|
}
|
|
1559
1699
|
};
|
|
1560
1700
|
}
|
|
1561
1701
|
function routesToElements(routes) {
|
|
1562
|
-
return /* @__PURE__ */
|
|
1702
|
+
return /* @__PURE__ */ jsx2(Fragment2, { children: routes.map((route, i) => {
|
|
1563
1703
|
const routeProps = { key: route.key || `route-${i}` };
|
|
1564
1704
|
if (route.path !== void 0) routeProps.path = route.path;
|
|
1565
1705
|
if (route.component !== void 0) routeProps.component = route.component;
|
|
1566
1706
|
if (route.element !== void 0) routeProps.element = route.element;
|
|
1567
1707
|
if (route.index !== void 0) routeProps.index = route.index;
|
|
1568
1708
|
if (route.children) routeProps.children = routesToElements(route.children);
|
|
1569
|
-
return /* @__PURE__ */
|
|
1709
|
+
return /* @__PURE__ */ jsx2(Route, { ...routeProps });
|
|
1570
1710
|
}) });
|
|
1571
1711
|
}
|
|
1572
1712
|
|
|
1573
1713
|
// src/link.tsx
|
|
1574
1714
|
import { createMemo as createMemo2 } from "@fictjs/runtime";
|
|
1575
|
-
import {
|
|
1715
|
+
import { spread } from "@fictjs/runtime/internal";
|
|
1716
|
+
import { jsx as jsx3 } from "fict/jsx-runtime";
|
|
1717
|
+
var createSpreadRef = (props) => {
|
|
1718
|
+
let current = null;
|
|
1719
|
+
return (el) => {
|
|
1720
|
+
if (!el) {
|
|
1721
|
+
current = null;
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
if (el === current) return;
|
|
1725
|
+
current = el;
|
|
1726
|
+
spread(el, props, false, true);
|
|
1727
|
+
};
|
|
1728
|
+
};
|
|
1576
1729
|
function Link(props) {
|
|
1577
1730
|
const router = useRouter();
|
|
1578
1731
|
const href = useHref(() => props.to);
|
|
1732
|
+
const getHrefValue = () => readAccessor(readAccessor(href));
|
|
1579
1733
|
let preloadTriggered = false;
|
|
1580
1734
|
const handleClick = (event) => {
|
|
1581
1735
|
if (props.onClick) {
|
|
@@ -1600,7 +1754,7 @@ function Link(props) {
|
|
|
1600
1754
|
const triggerPreload = () => {
|
|
1601
1755
|
if (preloadTriggered || props.disabled || props.prefetch === "none") return;
|
|
1602
1756
|
preloadTriggered = true;
|
|
1603
|
-
const hrefValue =
|
|
1757
|
+
const hrefValue = getHrefValue();
|
|
1604
1758
|
if (typeof window !== "undefined" && window.dispatchEvent) {
|
|
1605
1759
|
window.dispatchEvent(
|
|
1606
1760
|
new CustomEvent("fict-router:preload", {
|
|
@@ -1613,14 +1767,16 @@ function Link(props) {
|
|
|
1613
1767
|
if (props.prefetch === "intent" || props.prefetch === void 0) {
|
|
1614
1768
|
triggerPreload();
|
|
1615
1769
|
}
|
|
1616
|
-
const
|
|
1770
|
+
const propsRecord = props;
|
|
1771
|
+
const onMouseEnter = propsRecord.onMouseEnter;
|
|
1617
1772
|
if (onMouseEnter) onMouseEnter(event);
|
|
1618
1773
|
};
|
|
1619
1774
|
const handleFocus = (event) => {
|
|
1620
1775
|
if (props.prefetch === "intent" || props.prefetch === void 0) {
|
|
1621
1776
|
triggerPreload();
|
|
1622
1777
|
}
|
|
1623
|
-
const
|
|
1778
|
+
const propsRecord = props;
|
|
1779
|
+
const onFocus = propsRecord.onFocus;
|
|
1624
1780
|
if (onFocus) onFocus(event);
|
|
1625
1781
|
};
|
|
1626
1782
|
const {
|
|
@@ -1633,20 +1789,24 @@ function Link(props) {
|
|
|
1633
1789
|
prefetch,
|
|
1634
1790
|
disabled,
|
|
1635
1791
|
onClick: _onClick,
|
|
1792
|
+
onMouseEnter: _onMouseEnter,
|
|
1793
|
+
onFocus: _onFocus,
|
|
1636
1794
|
children,
|
|
1637
1795
|
...anchorProps
|
|
1638
1796
|
} = props;
|
|
1797
|
+
const anchorRef = createSpreadRef(anchorProps);
|
|
1798
|
+
const spanRef = createSpreadRef(anchorProps);
|
|
1639
1799
|
if (disabled) {
|
|
1640
|
-
return /* @__PURE__ */
|
|
1800
|
+
return /* @__PURE__ */ jsx3("span", { ref: spanRef, children });
|
|
1641
1801
|
}
|
|
1642
1802
|
if (prefetch === "render") {
|
|
1643
1803
|
triggerPreload();
|
|
1644
1804
|
}
|
|
1645
|
-
return /* @__PURE__ */
|
|
1805
|
+
return /* @__PURE__ */ jsx3(
|
|
1646
1806
|
"a",
|
|
1647
1807
|
{
|
|
1648
|
-
|
|
1649
|
-
href:
|
|
1808
|
+
ref: anchorRef,
|
|
1809
|
+
href: getHrefValue(),
|
|
1650
1810
|
onClick: handleClick,
|
|
1651
1811
|
onMouseEnter: handleMouseEnter,
|
|
1652
1812
|
onFocus: handleFocus,
|
|
@@ -1658,12 +1818,14 @@ function NavLink(props) {
|
|
|
1658
1818
|
const router = useRouter();
|
|
1659
1819
|
const isActive = useIsActive(() => props.to, { end: props.end });
|
|
1660
1820
|
const href = useHref(() => props.to);
|
|
1821
|
+
const getHrefValue = () => readAccessor(readAccessor(href));
|
|
1661
1822
|
const pendingLocation = usePendingLocation();
|
|
1662
1823
|
const computeIsPending = () => {
|
|
1663
1824
|
const pending = pendingLocation();
|
|
1664
1825
|
if (!pending) return false;
|
|
1665
|
-
const resolvedHref =
|
|
1666
|
-
const
|
|
1826
|
+
const resolvedHref = getHrefValue();
|
|
1827
|
+
const base = readAccessor(router.base);
|
|
1828
|
+
const baseToStrip = base === "/" ? "" : base;
|
|
1667
1829
|
const pendingPathWithoutBase = stripBasePath(pending.pathname, baseToStrip);
|
|
1668
1830
|
const parsed = parseURL(resolvedHref);
|
|
1669
1831
|
const targetPathWithoutBase = stripBasePath(parsed.pathname, baseToStrip);
|
|
@@ -1675,7 +1837,7 @@ function NavLink(props) {
|
|
|
1675
1837
|
const getRenderProps = () => ({
|
|
1676
1838
|
isActive: isActive(),
|
|
1677
1839
|
isPending: computeIsPending(),
|
|
1678
|
-
isTransitioning: router.isRouting
|
|
1840
|
+
isTransitioning: readAccessor(router.isRouting)
|
|
1679
1841
|
});
|
|
1680
1842
|
const computedClassName = createMemo2(() => {
|
|
1681
1843
|
const renderProps = getRenderProps();
|
|
@@ -1764,18 +1926,30 @@ function NavLink(props) {
|
|
|
1764
1926
|
"aria-current": _ariaCurrent,
|
|
1765
1927
|
...anchorProps
|
|
1766
1928
|
} = props;
|
|
1929
|
+
const anchorRef = createSpreadRef(anchorProps);
|
|
1930
|
+
const spanRef = createSpreadRef(anchorProps);
|
|
1767
1931
|
if (disabled) {
|
|
1768
|
-
|
|
1932
|
+
const disabledClassName = computedClassName();
|
|
1933
|
+
const disabledStyle = computedStyle();
|
|
1934
|
+
return /* @__PURE__ */ jsx3(
|
|
1935
|
+
"span",
|
|
1936
|
+
{
|
|
1937
|
+
ref: spanRef,
|
|
1938
|
+
...disabledClassName !== void 0 ? { class: disabledClassName } : {},
|
|
1939
|
+
...disabledStyle !== void 0 ? { style: disabledStyle } : {},
|
|
1940
|
+
children: computedChildren()
|
|
1941
|
+
}
|
|
1942
|
+
);
|
|
1769
1943
|
}
|
|
1770
1944
|
const finalClassName = computedClassName();
|
|
1771
1945
|
const finalStyle = computedStyle();
|
|
1772
1946
|
const finalAriaCurrent = ariaCurrent();
|
|
1773
|
-
return /* @__PURE__ */
|
|
1947
|
+
return /* @__PURE__ */ jsx3(
|
|
1774
1948
|
"a",
|
|
1775
1949
|
{
|
|
1776
|
-
|
|
1777
|
-
href:
|
|
1778
|
-
...finalClassName !== void 0 ? {
|
|
1950
|
+
ref: anchorRef,
|
|
1951
|
+
href: getHrefValue(),
|
|
1952
|
+
...finalClassName !== void 0 ? { class: finalClassName } : {},
|
|
1779
1953
|
...finalStyle !== void 0 ? { style: finalStyle } : {},
|
|
1780
1954
|
...finalAriaCurrent !== void 0 ? { "aria-current": finalAriaCurrent } : {},
|
|
1781
1955
|
onClick: handleClick,
|
|
@@ -1796,7 +1970,7 @@ function Form(props) {
|
|
|
1796
1970
|
event.preventDefault();
|
|
1797
1971
|
const formData = new FormData(form);
|
|
1798
1972
|
const method2 = props.method?.toUpperCase() || "GET";
|
|
1799
|
-
const actionUrl = props.action || router.location
|
|
1973
|
+
const actionUrl = props.action || readAccessor(router.location).pathname;
|
|
1800
1974
|
if (method2 === "GET") {
|
|
1801
1975
|
const searchParams = new URLSearchParams();
|
|
1802
1976
|
formData.forEach((value, key) => {
|
|
@@ -1871,11 +2045,12 @@ function Form(props) {
|
|
|
1871
2045
|
onSubmit: _onSubmit,
|
|
1872
2046
|
...formProps
|
|
1873
2047
|
} = props;
|
|
2048
|
+
const formRef = createSpreadRef(formProps);
|
|
1874
2049
|
const htmlMethod = method && ["get", "post"].includes(method) ? method : void 0;
|
|
1875
|
-
return /* @__PURE__ */
|
|
2050
|
+
return /* @__PURE__ */ jsx3(
|
|
1876
2051
|
"form",
|
|
1877
2052
|
{
|
|
1878
|
-
|
|
2053
|
+
ref: formRef,
|
|
1879
2054
|
...action2 !== void 0 ? { action: action2 } : {},
|
|
1880
2055
|
...htmlMethod !== void 0 ? { method: htmlMethod } : {},
|
|
1881
2056
|
onSubmit: handleSubmit,
|
|
@@ -1885,8 +2060,8 @@ function Form(props) {
|
|
|
1885
2060
|
}
|
|
1886
2061
|
|
|
1887
2062
|
// src/data.ts
|
|
1888
|
-
import { createEffect as createEffect2, batch as
|
|
1889
|
-
import { createSignal as
|
|
2063
|
+
import { createEffect as createEffect2, batch as batch3 } from "@fictjs/runtime";
|
|
2064
|
+
import { createSignal as createSignal4 } from "@fictjs/runtime/advanced";
|
|
1890
2065
|
var CACHE_DURATION = 3 * 60 * 1e3;
|
|
1891
2066
|
var PRELOAD_CACHE_DURATION = 5 * 1e3;
|
|
1892
2067
|
var MAX_CACHE_SIZE = 500;
|
|
@@ -1939,9 +2114,9 @@ function query(fn, name) {
|
|
|
1939
2114
|
return () => cached.result;
|
|
1940
2115
|
}
|
|
1941
2116
|
}
|
|
1942
|
-
const resultSignal =
|
|
1943
|
-
const errorSignal =
|
|
1944
|
-
const loadingSignal =
|
|
2117
|
+
const resultSignal = createSignal4(cached?.result);
|
|
2118
|
+
const errorSignal = createSignal4(void 0);
|
|
2119
|
+
const loadingSignal = createSignal4(true);
|
|
1945
2120
|
const promise = Promise.resolve(fn(...args)).then((result) => {
|
|
1946
2121
|
const entry = {
|
|
1947
2122
|
timestamp: Date.now(),
|
|
@@ -1951,13 +2126,13 @@ function query(fn, name) {
|
|
|
1951
2126
|
};
|
|
1952
2127
|
queryCache.set(cacheKey, entry);
|
|
1953
2128
|
evictOldestEntries();
|
|
1954
|
-
|
|
2129
|
+
batch3(() => {
|
|
1955
2130
|
resultSignal(result);
|
|
1956
2131
|
loadingSignal(false);
|
|
1957
2132
|
});
|
|
1958
2133
|
return result;
|
|
1959
2134
|
}).catch((error) => {
|
|
1960
|
-
|
|
2135
|
+
batch3(() => {
|
|
1961
2136
|
errorSignal(error);
|
|
1962
2137
|
loadingSignal(false);
|
|
1963
2138
|
});
|
|
@@ -2026,7 +2201,7 @@ function action(fn, name) {
|
|
|
2026
2201
|
function getAction(url) {
|
|
2027
2202
|
return actionRegistry.get(url);
|
|
2028
2203
|
}
|
|
2029
|
-
var activeSubmissions =
|
|
2204
|
+
var activeSubmissions = createSignal4(/* @__PURE__ */ new Map());
|
|
2030
2205
|
function useSubmission(actionOrUrl) {
|
|
2031
2206
|
const url = typeof actionOrUrl === "string" ? actionOrUrl : actionOrUrl.url;
|
|
2032
2207
|
return () => {
|
|
@@ -2081,10 +2256,10 @@ function createPreload(fn) {
|
|
|
2081
2256
|
};
|
|
2082
2257
|
}
|
|
2083
2258
|
function createResource(source, fetcher) {
|
|
2084
|
-
const dataSignal =
|
|
2085
|
-
const loadingSignal =
|
|
2086
|
-
const errorSignal =
|
|
2087
|
-
const latestSignal =
|
|
2259
|
+
const dataSignal = createSignal4(void 0);
|
|
2260
|
+
const loadingSignal = createSignal4(true);
|
|
2261
|
+
const errorSignal = createSignal4(void 0);
|
|
2262
|
+
const latestSignal = createSignal4(void 0);
|
|
2088
2263
|
let currentSource;
|
|
2089
2264
|
let fetchId = 0;
|
|
2090
2265
|
const doFetch = async (s, id) => {
|
|
@@ -2093,7 +2268,7 @@ function createResource(source, fetcher) {
|
|
|
2093
2268
|
try {
|
|
2094
2269
|
const result = await fetcher(s);
|
|
2095
2270
|
if (id === fetchId) {
|
|
2096
|
-
|
|
2271
|
+
batch3(() => {
|
|
2097
2272
|
dataSignal(result);
|
|
2098
2273
|
latestSignal(result);
|
|
2099
2274
|
loadingSignal(false);
|
|
@@ -2103,7 +2278,7 @@ function createResource(source, fetcher) {
|
|
|
2103
2278
|
return void 0;
|
|
2104
2279
|
} catch (err) {
|
|
2105
2280
|
if (id === fetchId) {
|
|
2106
|
-
|
|
2281
|
+
batch3(() => {
|
|
2107
2282
|
errorSignal(err);
|
|
2108
2283
|
loadingSignal(false);
|
|
2109
2284
|
});
|
|
@@ -2137,21 +2312,25 @@ function cleanupDataUtilities() {
|
|
|
2137
2312
|
}
|
|
2138
2313
|
|
|
2139
2314
|
// src/lazy.tsx
|
|
2140
|
-
import "@fictjs/runtime";
|
|
2141
|
-
import { createSignal as
|
|
2142
|
-
import { jsx as
|
|
2315
|
+
import { onCleanup as onCleanup2 } from "@fictjs/runtime";
|
|
2316
|
+
import { createSignal as createSignal5 } from "@fictjs/runtime/advanced";
|
|
2317
|
+
import { jsx as jsx4 } from "fict/jsx-runtime";
|
|
2143
2318
|
function lazy(loader) {
|
|
2144
2319
|
let cachedComponent = null;
|
|
2145
2320
|
let loadPromise = null;
|
|
2146
2321
|
const LazyComponent = (props) => {
|
|
2147
|
-
|
|
2322
|
+
let isMounted = true;
|
|
2323
|
+
onCleanup2(() => {
|
|
2324
|
+
isMounted = false;
|
|
2325
|
+
});
|
|
2326
|
+
const state = createSignal5({
|
|
2148
2327
|
component: cachedComponent,
|
|
2149
2328
|
error: null,
|
|
2150
2329
|
loading: !cachedComponent
|
|
2151
2330
|
});
|
|
2152
2331
|
if (cachedComponent) {
|
|
2153
2332
|
const CachedComponent = cachedComponent;
|
|
2154
|
-
return /* @__PURE__ */
|
|
2333
|
+
return /* @__PURE__ */ jsx4(CachedComponent, { ...props });
|
|
2155
2334
|
}
|
|
2156
2335
|
if (!loadPromise) {
|
|
2157
2336
|
loadPromise = loader().then((module) => {
|
|
@@ -2161,9 +2340,13 @@ function lazy(loader) {
|
|
|
2161
2340
|
});
|
|
2162
2341
|
}
|
|
2163
2342
|
loadPromise.then((component) => {
|
|
2164
|
-
|
|
2343
|
+
if (isMounted) {
|
|
2344
|
+
state({ component, error: null, loading: false });
|
|
2345
|
+
}
|
|
2165
2346
|
}).catch((error) => {
|
|
2166
|
-
|
|
2347
|
+
if (isMounted) {
|
|
2348
|
+
state({ component: null, error, loading: false });
|
|
2349
|
+
}
|
|
2167
2350
|
});
|
|
2168
2351
|
const currentState = state();
|
|
2169
2352
|
if (currentState.error) {
|
|
@@ -2173,10 +2356,11 @@ function lazy(loader) {
|
|
|
2173
2356
|
throw loadPromise;
|
|
2174
2357
|
}
|
|
2175
2358
|
const LoadedComponent = currentState.component;
|
|
2176
|
-
return /* @__PURE__ */
|
|
2359
|
+
return /* @__PURE__ */ jsx4(LoadedComponent, { ...props });
|
|
2177
2360
|
};
|
|
2178
|
-
|
|
2179
|
-
|
|
2361
|
+
const lazyComp = LazyComponent;
|
|
2362
|
+
lazyComp.__lazy = true;
|
|
2363
|
+
lazyComp.__preload = () => {
|
|
2180
2364
|
if (!loadPromise) {
|
|
2181
2365
|
loadPromise = loader().then((module) => {
|
|
2182
2366
|
const component = "default" in module ? module.default : module;
|
|
@@ -2196,7 +2380,8 @@ function preloadLazy(component) {
|
|
|
2196
2380
|
return Promise.resolve();
|
|
2197
2381
|
}
|
|
2198
2382
|
function isLazyComponent(component) {
|
|
2199
|
-
|
|
2383
|
+
const comp = component;
|
|
2384
|
+
return !!(comp && typeof comp === "function" && comp.__lazy);
|
|
2200
2385
|
}
|
|
2201
2386
|
function lazyRoute(config) {
|
|
2202
2387
|
const LazyComponent = lazy(config.component);
|