@fluixi/core 1.0.0-alpha.94 → 1.0.0-alpha.95
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/LICENSE +1 -1
- package/dist/cdn/core.global.js +2 -2
- package/dist/src/cdn/{chunk-7XM7Q5VR.mjs → chunk-IFONZJWJ.mjs} +93 -2
- package/dist/src/cdn/core.cjs +99 -3
- package/dist/src/cdn/core.mjs +3 -3
- package/dist/src/cdn/{router-VOY43YNM.mjs → router-TU5CPI54.mjs} +1 -1
- package/dist/src/index.cjs +95 -4
- package/dist/src/index.mjs +95 -4
- package/dist/src/lib/client/{chunk-TSXM2PNY.mjs → chunk-AHNP3IWU.mjs} +1 -1
- package/dist/src/lib/client/index.cjs +100 -4
- package/dist/src/lib/client/index.mjs +4 -4
- package/dist/src/lib/client/{router-BDVPLLYX.mjs → router-5C6FQJQ4.mjs} +95 -4
- package/dist/src/lib/core.cjs +94 -3
- package/dist/src/lib/core.mjs +94 -3
- package/dist/src/lib/i18n/index.cjs +1 -1
- package/dist/src/lib/i18n/index.mjs +1 -1
- package/dist/src/lib/index.cjs +1 -1
- package/dist/src/lib/index.mjs +1 -1
- package/dist/src/lib/jsx-runtime/index.cjs +1 -1
- package/dist/src/lib/jsx-runtime/index.mjs +1 -1
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.cjs +1 -1
- package/dist/src/lib/jsx-runtime/jsx-dev-runtime.mjs +1 -1
- package/dist/src/lib/plugins/index.cjs +1 -1
- package/dist/src/lib/plugins/index.mjs +1 -1
- package/dist/src/lib/render/index.cjs +1 -1
- package/dist/src/lib/render/index.mjs +1 -1
- package/dist/src/lib/render/versions.cjs +1 -1
- package/dist/src/lib/render/versions.mjs +1 -1
- package/dist/src/lib/router/index.cjs +94 -3
- package/dist/src/lib/router/index.d.ts.map +1 -1
- package/dist/src/lib/router/index.js +55 -0
- package/dist/src/lib/router/index.mjs +94 -3
- package/dist/src/lib/router/scroll.cjs +79 -0
- package/dist/src/lib/router/scroll.d.ts +19 -0
- package/dist/src/lib/router/scroll.d.ts.map +1 -0
- package/dist/src/lib/router/scroll.js +68 -0
- package/dist/src/lib/router/scroll.mjs +58 -0
- package/dist/src/lib/server/index.cjs +1 -1
- package/dist/src/lib/server/index.mjs +1 -1
- package/dist/src/lib/storage/index.cjs +1 -1
- package/dist/src/lib/storage/index.mjs +1 -1
- package/dist/src/routes.cjs +1 -1
- package/dist/src/routes.mjs +1 -1
- package/dist/src/utils.cjs +1 -1
- package/dist/src/utils.mjs +1 -1
- package/dist/src/version.generated.cjs +1 -1
- package/dist/src/version.generated.d.ts +1 -1
- package/dist/src/version.generated.js +1 -1
- package/dist/src/version.generated.mjs +1 -1
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +16 -16
|
@@ -84,6 +84,64 @@ import {
|
|
|
84
84
|
import { createContext as createContext2, useContext as useContext2 } from "@fluixi/reactive/signal";
|
|
85
85
|
import { get } from "@fluixi/utils/object";
|
|
86
86
|
import { deepEqual } from "@fluixi/utils/compare";
|
|
87
|
+
|
|
88
|
+
// src/lib/router/scroll.ts
|
|
89
|
+
var STORE = "fx:scroll";
|
|
90
|
+
var KEEP = 100;
|
|
91
|
+
function keepScroll(initial) {
|
|
92
|
+
const read2 = () => {
|
|
93
|
+
try {
|
|
94
|
+
return JSON.parse(sessionStorage.getItem(STORE) ?? "{}");
|
|
95
|
+
} catch {
|
|
96
|
+
return {};
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const positions = read2();
|
|
100
|
+
const write = () => {
|
|
101
|
+
const keys = Object.keys(positions);
|
|
102
|
+
for (const key of keys.slice(0, Math.max(0, keys.length - KEEP))) delete positions[key];
|
|
103
|
+
try {
|
|
104
|
+
sessionStorage.setItem(STORE, JSON.stringify(positions));
|
|
105
|
+
} catch {
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
let current = initial.key;
|
|
109
|
+
const save = () => {
|
|
110
|
+
if (current === void 0) return;
|
|
111
|
+
delete positions[current];
|
|
112
|
+
positions[current] = window.scrollY;
|
|
113
|
+
write();
|
|
114
|
+
};
|
|
115
|
+
const restoration = history.scrollRestoration;
|
|
116
|
+
history.scrollRestoration = "manual";
|
|
117
|
+
window.addEventListener("pagehide", save);
|
|
118
|
+
const to = (top) => window.scrollTo({ top, left: 0, behavior: "instant" });
|
|
119
|
+
const toHash = (hash) => {
|
|
120
|
+
if (!hash || hash === "#") return false;
|
|
121
|
+
const target = document.getElementById(decodeURIComponent(hash.slice(1)));
|
|
122
|
+
target?.scrollIntoView({ behavior: "instant" });
|
|
123
|
+
return target !== null;
|
|
124
|
+
};
|
|
125
|
+
return {
|
|
126
|
+
leave: save,
|
|
127
|
+
arrive(location, from) {
|
|
128
|
+
current = location.key;
|
|
129
|
+
if (location.action === "pop" || from === void 0) {
|
|
130
|
+
const y = location.key === void 0 ? void 0 : positions[location.key];
|
|
131
|
+
if (y !== void 0) to(y);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (location.action === "replace" && location.pathname === from.pathname) return;
|
|
135
|
+
if (!toHash(location.hash)) to(0);
|
|
136
|
+
},
|
|
137
|
+
dispose() {
|
|
138
|
+
window.removeEventListener("pagehide", save);
|
|
139
|
+
history.scrollRestoration = restoration;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/lib/router/index.ts
|
|
87
145
|
import {
|
|
88
146
|
createRouter as createCoreRouter,
|
|
89
147
|
createBrowserHistory,
|
|
@@ -405,9 +463,20 @@ function renderLayer(m, depth, base) {
|
|
|
405
463
|
return router ? router.trackLoad(result) : result;
|
|
406
464
|
});
|
|
407
465
|
onCleanup(onRevalidate(() => void refetch()));
|
|
466
|
+
let loadedFor = untrack2(() => JSON.stringify(base.matched()[depth]?.params ?? {}));
|
|
467
|
+
createEffect(() => {
|
|
468
|
+
const now = base.matched()[depth];
|
|
469
|
+
if (now?.route !== m.route) return;
|
|
470
|
+
const params = JSON.stringify(now.params ?? {});
|
|
471
|
+
if (params === loadedFor) return;
|
|
472
|
+
loadedFor = params;
|
|
473
|
+
untrack2(() => void refetch());
|
|
474
|
+
});
|
|
408
475
|
data = () => {
|
|
409
476
|
const error = resource.error;
|
|
410
477
|
if (error !== void 0 && error !== null) throw error;
|
|
478
|
+
const r = resource;
|
|
479
|
+
if (r.state === "refreshing") return r.latest;
|
|
411
480
|
return resource();
|
|
412
481
|
};
|
|
413
482
|
Object.defineProperty(data, "loading", { get: () => resource.loading });
|
|
@@ -512,16 +581,19 @@ function buildDefaultNotFound() {
|
|
|
512
581
|
}
|
|
513
582
|
var pendingTransitionMode;
|
|
514
583
|
function Router(props) {
|
|
515
|
-
const
|
|
584
|
+
const history2 = props.history ?? createBrowserHistory();
|
|
516
585
|
const router = createCoreRouter({
|
|
517
586
|
routes: props.routes,
|
|
518
587
|
base: props.base,
|
|
519
|
-
history
|
|
588
|
+
history: history2
|
|
520
589
|
});
|
|
521
590
|
const [state, setState] = createSignal2(router.state());
|
|
522
591
|
const [navigating, setNavigating] = createSignal2(false);
|
|
523
592
|
const [loads, setLoads] = createSignal2(0);
|
|
524
593
|
let navigationId = 0;
|
|
594
|
+
const scroll = history2.window ? keepScroll(router.state().location) : void 0;
|
|
595
|
+
let arriving = scroll ? { id: 0, location: router.state().location, from: void 0 } : null;
|
|
596
|
+
const [arrived, setArrived] = createSignal2(0);
|
|
525
597
|
const takeMode = () => {
|
|
526
598
|
const mode = pendingTransitionMode ?? (props.transition ?? "auto");
|
|
527
599
|
pendingTransitionMode = void 0;
|
|
@@ -531,6 +603,10 @@ function Router(props) {
|
|
|
531
603
|
const id = ++navigationId;
|
|
532
604
|
const mode = takeMode();
|
|
533
605
|
setNavigating(true);
|
|
606
|
+
if (scroll) {
|
|
607
|
+
scroll.leave();
|
|
608
|
+
arriving = { id, location: next.location, from: untrack2(state).location };
|
|
609
|
+
}
|
|
534
610
|
const prepared = prepareComponents(
|
|
535
611
|
(next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
|
|
536
612
|
);
|
|
@@ -538,6 +614,7 @@ function Router(props) {
|
|
|
538
614
|
setState(next);
|
|
539
615
|
const flushed = flush();
|
|
540
616
|
if (id === navigationId) setNavigating(false);
|
|
617
|
+
if (scroll) setArrived(id);
|
|
541
618
|
return flushed;
|
|
542
619
|
};
|
|
543
620
|
if (!prepared) {
|
|
@@ -551,6 +628,7 @@ function Router(props) {
|
|
|
551
628
|
});
|
|
552
629
|
onCleanup(() => {
|
|
553
630
|
unsub();
|
|
631
|
+
scroll?.dispose();
|
|
554
632
|
router.destroy();
|
|
555
633
|
navigationId++;
|
|
556
634
|
});
|
|
@@ -573,6 +651,19 @@ function Router(props) {
|
|
|
573
651
|
return result;
|
|
574
652
|
}
|
|
575
653
|
};
|
|
654
|
+
if (scroll) {
|
|
655
|
+
const nextFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (fn) => setTimeout(fn, 0);
|
|
656
|
+
createEffect(() => {
|
|
657
|
+
const id = arrived();
|
|
658
|
+
if (ctx.isRouting()) return;
|
|
659
|
+
const next = arriving;
|
|
660
|
+
if (!next || next.id !== id || id !== navigationId) return;
|
|
661
|
+
arriving = null;
|
|
662
|
+
nextFrame(() => {
|
|
663
|
+
if (id === navigationId) scroll.arrive(next.location, next.from);
|
|
664
|
+
});
|
|
665
|
+
});
|
|
666
|
+
}
|
|
576
667
|
const root = {
|
|
577
668
|
depth: -1,
|
|
578
669
|
matched,
|
package/dist/src/cdn/core.cjs
CHANGED
|
@@ -184,6 +184,68 @@ var init_transition = __esm({
|
|
|
184
184
|
}
|
|
185
185
|
});
|
|
186
186
|
|
|
187
|
+
// src/lib/router/scroll.ts
|
|
188
|
+
function keepScroll(initial) {
|
|
189
|
+
const read2 = () => {
|
|
190
|
+
try {
|
|
191
|
+
return JSON.parse(sessionStorage.getItem(STORE) ?? "{}");
|
|
192
|
+
} catch {
|
|
193
|
+
return {};
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
const positions = read2();
|
|
197
|
+
const write = () => {
|
|
198
|
+
const keys = Object.keys(positions);
|
|
199
|
+
for (const key of keys.slice(0, Math.max(0, keys.length - KEEP))) delete positions[key];
|
|
200
|
+
try {
|
|
201
|
+
sessionStorage.setItem(STORE, JSON.stringify(positions));
|
|
202
|
+
} catch {
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
let current = initial.key;
|
|
206
|
+
const save = () => {
|
|
207
|
+
if (current === void 0) return;
|
|
208
|
+
delete positions[current];
|
|
209
|
+
positions[current] = window.scrollY;
|
|
210
|
+
write();
|
|
211
|
+
};
|
|
212
|
+
const restoration = history.scrollRestoration;
|
|
213
|
+
history.scrollRestoration = "manual";
|
|
214
|
+
window.addEventListener("pagehide", save);
|
|
215
|
+
const to = (top) => window.scrollTo({ top, left: 0, behavior: "instant" });
|
|
216
|
+
const toHash = (hash) => {
|
|
217
|
+
if (!hash || hash === "#") return false;
|
|
218
|
+
const target = document.getElementById(decodeURIComponent(hash.slice(1)));
|
|
219
|
+
target?.scrollIntoView({ behavior: "instant" });
|
|
220
|
+
return target !== null;
|
|
221
|
+
};
|
|
222
|
+
return {
|
|
223
|
+
leave: save,
|
|
224
|
+
arrive(location, from) {
|
|
225
|
+
current = location.key;
|
|
226
|
+
if (location.action === "pop" || from === void 0) {
|
|
227
|
+
const y = location.key === void 0 ? void 0 : positions[location.key];
|
|
228
|
+
if (y !== void 0) to(y);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (location.action === "replace" && location.pathname === from.pathname) return;
|
|
232
|
+
if (!toHash(location.hash)) to(0);
|
|
233
|
+
},
|
|
234
|
+
dispose() {
|
|
235
|
+
window.removeEventListener("pagehide", save);
|
|
236
|
+
history.scrollRestoration = restoration;
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
var STORE, KEEP;
|
|
241
|
+
var init_scroll = __esm({
|
|
242
|
+
"src/lib/router/scroll.ts"() {
|
|
243
|
+
"use strict";
|
|
244
|
+
STORE = "fx:scroll";
|
|
245
|
+
KEEP = 100;
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
187
249
|
// src/lib/router/data.ts
|
|
188
250
|
function onRevalidate(listener) {
|
|
189
251
|
revalidationListeners.add(listener);
|
|
@@ -419,9 +481,20 @@ function renderLayer(m, depth, base) {
|
|
|
419
481
|
return router ? router.trackLoad(result) : result;
|
|
420
482
|
});
|
|
421
483
|
(0, import_signal14.onCleanup)(onRevalidate(() => void refetch()));
|
|
484
|
+
let loadedFor = (0, import_signal14.untrack)(() => JSON.stringify(base.matched()[depth]?.params ?? {}));
|
|
485
|
+
(0, import_signal14.createEffect)(() => {
|
|
486
|
+
const now = base.matched()[depth];
|
|
487
|
+
if (now?.route !== m.route) return;
|
|
488
|
+
const params = JSON.stringify(now.params ?? {});
|
|
489
|
+
if (params === loadedFor) return;
|
|
490
|
+
loadedFor = params;
|
|
491
|
+
(0, import_signal14.untrack)(() => void refetch());
|
|
492
|
+
});
|
|
422
493
|
data = () => {
|
|
423
494
|
const error = resource.error;
|
|
424
495
|
if (error !== void 0 && error !== null) throw error;
|
|
496
|
+
const r = resource;
|
|
497
|
+
if (r.state === "refreshing") return r.latest;
|
|
425
498
|
return resource();
|
|
426
499
|
};
|
|
427
500
|
Object.defineProperty(data, "loading", { get: () => resource.loading });
|
|
@@ -525,16 +598,19 @@ function buildDefaultNotFound() {
|
|
|
525
598
|
return el;
|
|
526
599
|
}
|
|
527
600
|
function Router(props) {
|
|
528
|
-
const
|
|
601
|
+
const history2 = props.history ?? (0, import_router.createBrowserHistory)();
|
|
529
602
|
const router = (0, import_router.createRouter)({
|
|
530
603
|
routes: props.routes,
|
|
531
604
|
base: props.base,
|
|
532
|
-
history
|
|
605
|
+
history: history2
|
|
533
606
|
});
|
|
534
607
|
const [state, setState] = (0, import_signal14.createSignal)(router.state());
|
|
535
608
|
const [navigating, setNavigating] = (0, import_signal14.createSignal)(false);
|
|
536
609
|
const [loads, setLoads] = (0, import_signal14.createSignal)(0);
|
|
537
610
|
let navigationId = 0;
|
|
611
|
+
const scroll = history2.window ? keepScroll(router.state().location) : void 0;
|
|
612
|
+
let arriving = scroll ? { id: 0, location: router.state().location, from: void 0 } : null;
|
|
613
|
+
const [arrived, setArrived] = (0, import_signal14.createSignal)(0);
|
|
538
614
|
const takeMode = () => {
|
|
539
615
|
const mode = pendingTransitionMode ?? (props.transition ?? "auto");
|
|
540
616
|
pendingTransitionMode = void 0;
|
|
@@ -544,6 +620,10 @@ function Router(props) {
|
|
|
544
620
|
const id = ++navigationId;
|
|
545
621
|
const mode = takeMode();
|
|
546
622
|
setNavigating(true);
|
|
623
|
+
if (scroll) {
|
|
624
|
+
scroll.leave();
|
|
625
|
+
arriving = { id, location: next.location, from: (0, import_signal14.untrack)(state).location };
|
|
626
|
+
}
|
|
547
627
|
const prepared = prepareComponents(
|
|
548
628
|
(next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
|
|
549
629
|
);
|
|
@@ -551,6 +631,7 @@ function Router(props) {
|
|
|
551
631
|
setState(next);
|
|
552
632
|
const flushed = (0, import_signal14.flush)();
|
|
553
633
|
if (id === navigationId) setNavigating(false);
|
|
634
|
+
if (scroll) setArrived(id);
|
|
554
635
|
return flushed;
|
|
555
636
|
};
|
|
556
637
|
if (!prepared) {
|
|
@@ -564,6 +645,7 @@ function Router(props) {
|
|
|
564
645
|
});
|
|
565
646
|
(0, import_signal14.onCleanup)(() => {
|
|
566
647
|
unsub();
|
|
648
|
+
scroll?.dispose();
|
|
567
649
|
router.destroy();
|
|
568
650
|
navigationId++;
|
|
569
651
|
});
|
|
@@ -586,6 +668,19 @@ function Router(props) {
|
|
|
586
668
|
return result;
|
|
587
669
|
}
|
|
588
670
|
};
|
|
671
|
+
if (scroll) {
|
|
672
|
+
const nextFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (fn) => setTimeout(fn, 0);
|
|
673
|
+
(0, import_signal14.createEffect)(() => {
|
|
674
|
+
const id = arrived();
|
|
675
|
+
if (ctx.isRouting()) return;
|
|
676
|
+
const next = arriving;
|
|
677
|
+
if (!next || next.id !== id || id !== navigationId) return;
|
|
678
|
+
arriving = null;
|
|
679
|
+
nextFrame(() => {
|
|
680
|
+
if (id === navigationId) scroll.arrive(next.location, next.from);
|
|
681
|
+
});
|
|
682
|
+
});
|
|
683
|
+
}
|
|
589
684
|
const root = {
|
|
590
685
|
depth: -1,
|
|
591
686
|
matched,
|
|
@@ -829,6 +924,7 @@ var init_router = __esm({
|
|
|
829
924
|
import_signal15 = require("@fluixi/reactive/signal");
|
|
830
925
|
import_object = require("@fluixi/utils/object");
|
|
831
926
|
import_compare = require("@fluixi/utils/compare");
|
|
927
|
+
init_scroll();
|
|
832
928
|
import_router = require("@fluixi/router");
|
|
833
929
|
init_data();
|
|
834
930
|
import_router2 = require("@fluixi/router");
|
|
@@ -976,7 +1072,7 @@ var import_signal6 = require("@fluixi/reactive/signal");
|
|
|
976
1072
|
var import_dom = require("@fluixi/dom");
|
|
977
1073
|
|
|
978
1074
|
// src/version.generated.ts
|
|
979
|
-
var VERSION = "1.0.0-alpha.
|
|
1075
|
+
var VERSION = "1.0.0-alpha.95";
|
|
980
1076
|
|
|
981
1077
|
// src/lib/render/versions.ts
|
|
982
1078
|
var import_dom2 = require("@fluixi/dom");
|
package/dist/src/cdn/core.mjs
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
useParams,
|
|
21
21
|
useRouter,
|
|
22
22
|
useSearchParams
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-IFONZJWJ.mjs";
|
|
24
24
|
|
|
25
25
|
// src/lib/index.ts
|
|
26
26
|
import {
|
|
@@ -54,7 +54,7 @@ import { createRoot as createRoot2 } from "@fluixi/reactive/signal";
|
|
|
54
54
|
import { registerCoreVersion } from "@fluixi/dom";
|
|
55
55
|
|
|
56
56
|
// src/version.generated.ts
|
|
57
|
-
var VERSION = "1.0.0-alpha.
|
|
57
|
+
var VERSION = "1.0.0-alpha.95";
|
|
58
58
|
|
|
59
59
|
// src/lib/render/versions.ts
|
|
60
60
|
import { stampVersions, warnOnVersionSkew, versions } from "@fluixi/dom";
|
|
@@ -574,7 +574,7 @@ async function startClient(App, options = {}) {
|
|
|
574
574
|
beginAppHydration();
|
|
575
575
|
try {
|
|
576
576
|
if (options.routes && options.routes.length) {
|
|
577
|
-
const { preloadRoutes } = await import("./router-
|
|
577
|
+
const { preloadRoutes } = await import("./router-TU5CPI54.mjs");
|
|
578
578
|
await preloadRoutes(options.routes, window.location.pathname);
|
|
579
579
|
}
|
|
580
580
|
deserializeHydrationData();
|
package/dist/src/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @fluixi/core v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/core v1.0.0-alpha.95 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -143,7 +143,7 @@ __export(index_exports, {
|
|
|
143
143
|
module.exports = __toCommonJS(index_exports);
|
|
144
144
|
|
|
145
145
|
// src/version.generated.ts
|
|
146
|
-
var VERSION = "1.0.0-alpha.
|
|
146
|
+
var VERSION = "1.0.0-alpha.95";
|
|
147
147
|
|
|
148
148
|
// src/lib/core.ts
|
|
149
149
|
var import_signal18 = require("@fluixi/reactive/signal");
|
|
@@ -1178,6 +1178,64 @@ var import_dom15 = require("@fluixi/dom");
|
|
|
1178
1178
|
var import_signal16 = require("@fluixi/reactive/signal");
|
|
1179
1179
|
var import_object = require("@fluixi/utils/object");
|
|
1180
1180
|
var import_compare = require("@fluixi/utils/compare");
|
|
1181
|
+
|
|
1182
|
+
// src/lib/router/scroll.ts
|
|
1183
|
+
var STORE = "fx:scroll";
|
|
1184
|
+
var KEEP = 100;
|
|
1185
|
+
function keepScroll(initial) {
|
|
1186
|
+
const read3 = () => {
|
|
1187
|
+
try {
|
|
1188
|
+
return JSON.parse(sessionStorage.getItem(STORE) ?? "{}");
|
|
1189
|
+
} catch {
|
|
1190
|
+
return {};
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
const positions = read3();
|
|
1194
|
+
const write = () => {
|
|
1195
|
+
const keys = Object.keys(positions);
|
|
1196
|
+
for (const key of keys.slice(0, Math.max(0, keys.length - KEEP))) delete positions[key];
|
|
1197
|
+
try {
|
|
1198
|
+
sessionStorage.setItem(STORE, JSON.stringify(positions));
|
|
1199
|
+
} catch {
|
|
1200
|
+
}
|
|
1201
|
+
};
|
|
1202
|
+
let current = initial.key;
|
|
1203
|
+
const save = () => {
|
|
1204
|
+
if (current === void 0) return;
|
|
1205
|
+
delete positions[current];
|
|
1206
|
+
positions[current] = window.scrollY;
|
|
1207
|
+
write();
|
|
1208
|
+
};
|
|
1209
|
+
const restoration = history.scrollRestoration;
|
|
1210
|
+
history.scrollRestoration = "manual";
|
|
1211
|
+
window.addEventListener("pagehide", save);
|
|
1212
|
+
const to = (top) => window.scrollTo({ top, left: 0, behavior: "instant" });
|
|
1213
|
+
const toHash = (hash) => {
|
|
1214
|
+
if (!hash || hash === "#") return false;
|
|
1215
|
+
const target = document.getElementById(decodeURIComponent(hash.slice(1)));
|
|
1216
|
+
target?.scrollIntoView({ behavior: "instant" });
|
|
1217
|
+
return target !== null;
|
|
1218
|
+
};
|
|
1219
|
+
return {
|
|
1220
|
+
leave: save,
|
|
1221
|
+
arrive(location, from) {
|
|
1222
|
+
current = location.key;
|
|
1223
|
+
if (location.action === "pop" || from === void 0) {
|
|
1224
|
+
const y = location.key === void 0 ? void 0 : positions[location.key];
|
|
1225
|
+
if (y !== void 0) to(y);
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1228
|
+
if (location.action === "replace" && location.pathname === from.pathname) return;
|
|
1229
|
+
if (!toHash(location.hash)) to(0);
|
|
1230
|
+
},
|
|
1231
|
+
dispose() {
|
|
1232
|
+
window.removeEventListener("pagehide", save);
|
|
1233
|
+
history.scrollRestoration = restoration;
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
// src/lib/router/index.ts
|
|
1181
1239
|
var import_router = require("@fluixi/router");
|
|
1182
1240
|
|
|
1183
1241
|
// src/lib/router/data.ts
|
|
@@ -1257,9 +1315,20 @@ function renderLayer(m, depth, base) {
|
|
|
1257
1315
|
return router ? router.trackLoad(result) : result;
|
|
1258
1316
|
});
|
|
1259
1317
|
(0, import_signal15.onCleanup)(onRevalidate(() => void refetch()));
|
|
1318
|
+
let loadedFor = (0, import_signal15.untrack)(() => JSON.stringify(base.matched()[depth]?.params ?? {}));
|
|
1319
|
+
(0, import_signal15.createEffect)(() => {
|
|
1320
|
+
const now = base.matched()[depth];
|
|
1321
|
+
if (now?.route !== m.route) return;
|
|
1322
|
+
const params = JSON.stringify(now.params ?? {});
|
|
1323
|
+
if (params === loadedFor) return;
|
|
1324
|
+
loadedFor = params;
|
|
1325
|
+
(0, import_signal15.untrack)(() => void refetch());
|
|
1326
|
+
});
|
|
1260
1327
|
data = () => {
|
|
1261
1328
|
const error = resource2.error;
|
|
1262
1329
|
if (error !== void 0 && error !== null) throw error;
|
|
1330
|
+
const r = resource2;
|
|
1331
|
+
if (r.state === "refreshing") return r.latest;
|
|
1263
1332
|
return resource2();
|
|
1264
1333
|
};
|
|
1265
1334
|
Object.defineProperty(data, "loading", { get: () => resource2.loading });
|
|
@@ -1364,16 +1433,19 @@ function buildDefaultNotFound() {
|
|
|
1364
1433
|
}
|
|
1365
1434
|
var pendingTransitionMode;
|
|
1366
1435
|
function Router(props) {
|
|
1367
|
-
const
|
|
1436
|
+
const history2 = props.history ?? (0, import_router.createBrowserHistory)();
|
|
1368
1437
|
const router = (0, import_router.createRouter)({
|
|
1369
1438
|
routes: props.routes,
|
|
1370
1439
|
base: props.base,
|
|
1371
|
-
history
|
|
1440
|
+
history: history2
|
|
1372
1441
|
});
|
|
1373
1442
|
const [state, setState] = (0, import_signal15.createSignal)(router.state());
|
|
1374
1443
|
const [navigating, setNavigating] = (0, import_signal15.createSignal)(false);
|
|
1375
1444
|
const [loads, setLoads] = (0, import_signal15.createSignal)(0);
|
|
1376
1445
|
let navigationId = 0;
|
|
1446
|
+
const scroll = history2.window ? keepScroll(router.state().location) : void 0;
|
|
1447
|
+
let arriving = scroll ? { id: 0, location: router.state().location, from: void 0 } : null;
|
|
1448
|
+
const [arrived, setArrived] = (0, import_signal15.createSignal)(0);
|
|
1377
1449
|
const takeMode = () => {
|
|
1378
1450
|
const mode = pendingTransitionMode ?? (props.transition ?? "auto");
|
|
1379
1451
|
pendingTransitionMode = void 0;
|
|
@@ -1383,6 +1455,10 @@ function Router(props) {
|
|
|
1383
1455
|
const id = ++navigationId;
|
|
1384
1456
|
const mode = takeMode();
|
|
1385
1457
|
setNavigating(true);
|
|
1458
|
+
if (scroll) {
|
|
1459
|
+
scroll.leave();
|
|
1460
|
+
arriving = { id, location: next.location, from: (0, import_signal15.untrack)(state).location };
|
|
1461
|
+
}
|
|
1386
1462
|
const prepared = prepareComponents(
|
|
1387
1463
|
(next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
|
|
1388
1464
|
);
|
|
@@ -1390,6 +1466,7 @@ function Router(props) {
|
|
|
1390
1466
|
setState(next);
|
|
1391
1467
|
const flushed = (0, import_signal15.flush)();
|
|
1392
1468
|
if (id === navigationId) setNavigating(false);
|
|
1469
|
+
if (scroll) setArrived(id);
|
|
1393
1470
|
return flushed;
|
|
1394
1471
|
};
|
|
1395
1472
|
if (!prepared) {
|
|
@@ -1403,6 +1480,7 @@ function Router(props) {
|
|
|
1403
1480
|
});
|
|
1404
1481
|
(0, import_signal15.onCleanup)(() => {
|
|
1405
1482
|
unsub();
|
|
1483
|
+
scroll?.dispose();
|
|
1406
1484
|
router.destroy();
|
|
1407
1485
|
navigationId++;
|
|
1408
1486
|
});
|
|
@@ -1425,6 +1503,19 @@ function Router(props) {
|
|
|
1425
1503
|
return result;
|
|
1426
1504
|
}
|
|
1427
1505
|
};
|
|
1506
|
+
if (scroll) {
|
|
1507
|
+
const nextFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (fn) => setTimeout(fn, 0);
|
|
1508
|
+
(0, import_signal15.createEffect)(() => {
|
|
1509
|
+
const id = arrived();
|
|
1510
|
+
if (ctx.isRouting()) return;
|
|
1511
|
+
const next = arriving;
|
|
1512
|
+
if (!next || next.id !== id || id !== navigationId) return;
|
|
1513
|
+
arriving = null;
|
|
1514
|
+
nextFrame(() => {
|
|
1515
|
+
if (id === navigationId) scroll.arrive(next.location, next.from);
|
|
1516
|
+
});
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1428
1519
|
const root = {
|
|
1429
1520
|
depth: -1,
|
|
1430
1521
|
matched,
|
package/dist/src/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/*! @fluixi/core v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/core v1.0.0-alpha.95 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
|
|
3
3
|
// src/version.generated.ts
|
|
4
|
-
var VERSION = "1.0.0-alpha.
|
|
4
|
+
var VERSION = "1.0.0-alpha.95";
|
|
5
5
|
|
|
6
6
|
// src/lib/core.ts
|
|
7
7
|
import {
|
|
@@ -1126,6 +1126,64 @@ import {
|
|
|
1126
1126
|
import { createContext as createContext5, useContext as useContext5 } from "@fluixi/reactive/signal";
|
|
1127
1127
|
import { get } from "@fluixi/utils/object";
|
|
1128
1128
|
import { deepEqual } from "@fluixi/utils/compare";
|
|
1129
|
+
|
|
1130
|
+
// src/lib/router/scroll.ts
|
|
1131
|
+
var STORE = "fx:scroll";
|
|
1132
|
+
var KEEP = 100;
|
|
1133
|
+
function keepScroll(initial) {
|
|
1134
|
+
const read3 = () => {
|
|
1135
|
+
try {
|
|
1136
|
+
return JSON.parse(sessionStorage.getItem(STORE) ?? "{}");
|
|
1137
|
+
} catch {
|
|
1138
|
+
return {};
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
const positions = read3();
|
|
1142
|
+
const write = () => {
|
|
1143
|
+
const keys = Object.keys(positions);
|
|
1144
|
+
for (const key of keys.slice(0, Math.max(0, keys.length - KEEP))) delete positions[key];
|
|
1145
|
+
try {
|
|
1146
|
+
sessionStorage.setItem(STORE, JSON.stringify(positions));
|
|
1147
|
+
} catch {
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
let current = initial.key;
|
|
1151
|
+
const save = () => {
|
|
1152
|
+
if (current === void 0) return;
|
|
1153
|
+
delete positions[current];
|
|
1154
|
+
positions[current] = window.scrollY;
|
|
1155
|
+
write();
|
|
1156
|
+
};
|
|
1157
|
+
const restoration = history.scrollRestoration;
|
|
1158
|
+
history.scrollRestoration = "manual";
|
|
1159
|
+
window.addEventListener("pagehide", save);
|
|
1160
|
+
const to = (top) => window.scrollTo({ top, left: 0, behavior: "instant" });
|
|
1161
|
+
const toHash = (hash) => {
|
|
1162
|
+
if (!hash || hash === "#") return false;
|
|
1163
|
+
const target = document.getElementById(decodeURIComponent(hash.slice(1)));
|
|
1164
|
+
target?.scrollIntoView({ behavior: "instant" });
|
|
1165
|
+
return target !== null;
|
|
1166
|
+
};
|
|
1167
|
+
return {
|
|
1168
|
+
leave: save,
|
|
1169
|
+
arrive(location, from) {
|
|
1170
|
+
current = location.key;
|
|
1171
|
+
if (location.action === "pop" || from === void 0) {
|
|
1172
|
+
const y = location.key === void 0 ? void 0 : positions[location.key];
|
|
1173
|
+
if (y !== void 0) to(y);
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
if (location.action === "replace" && location.pathname === from.pathname) return;
|
|
1177
|
+
if (!toHash(location.hash)) to(0);
|
|
1178
|
+
},
|
|
1179
|
+
dispose() {
|
|
1180
|
+
window.removeEventListener("pagehide", save);
|
|
1181
|
+
history.scrollRestoration = restoration;
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// src/lib/router/index.ts
|
|
1129
1187
|
import {
|
|
1130
1188
|
createRouter as createCoreRouter,
|
|
1131
1189
|
createBrowserHistory,
|
|
@@ -1218,9 +1276,20 @@ function renderLayer(m, depth, base) {
|
|
|
1218
1276
|
return router ? router.trackLoad(result) : result;
|
|
1219
1277
|
});
|
|
1220
1278
|
onCleanup4(onRevalidate(() => void refetch()));
|
|
1279
|
+
let loadedFor = untrack4(() => JSON.stringify(base.matched()[depth]?.params ?? {}));
|
|
1280
|
+
createEffect4(() => {
|
|
1281
|
+
const now = base.matched()[depth];
|
|
1282
|
+
if (now?.route !== m.route) return;
|
|
1283
|
+
const params = JSON.stringify(now.params ?? {});
|
|
1284
|
+
if (params === loadedFor) return;
|
|
1285
|
+
loadedFor = params;
|
|
1286
|
+
untrack4(() => void refetch());
|
|
1287
|
+
});
|
|
1221
1288
|
data = () => {
|
|
1222
1289
|
const error = resource2.error;
|
|
1223
1290
|
if (error !== void 0 && error !== null) throw error;
|
|
1291
|
+
const r = resource2;
|
|
1292
|
+
if (r.state === "refreshing") return r.latest;
|
|
1224
1293
|
return resource2();
|
|
1225
1294
|
};
|
|
1226
1295
|
Object.defineProperty(data, "loading", { get: () => resource2.loading });
|
|
@@ -1325,16 +1394,19 @@ function buildDefaultNotFound() {
|
|
|
1325
1394
|
}
|
|
1326
1395
|
var pendingTransitionMode;
|
|
1327
1396
|
function Router(props) {
|
|
1328
|
-
const
|
|
1397
|
+
const history2 = props.history ?? createBrowserHistory();
|
|
1329
1398
|
const router = createCoreRouter({
|
|
1330
1399
|
routes: props.routes,
|
|
1331
1400
|
base: props.base,
|
|
1332
|
-
history
|
|
1401
|
+
history: history2
|
|
1333
1402
|
});
|
|
1334
1403
|
const [state, setState] = createSignal8(router.state());
|
|
1335
1404
|
const [navigating, setNavigating] = createSignal8(false);
|
|
1336
1405
|
const [loads, setLoads] = createSignal8(0);
|
|
1337
1406
|
let navigationId = 0;
|
|
1407
|
+
const scroll = history2.window ? keepScroll(router.state().location) : void 0;
|
|
1408
|
+
let arriving = scroll ? { id: 0, location: router.state().location, from: void 0 } : null;
|
|
1409
|
+
const [arrived, setArrived] = createSignal8(0);
|
|
1338
1410
|
const takeMode = () => {
|
|
1339
1411
|
const mode = pendingTransitionMode ?? (props.transition ?? "auto");
|
|
1340
1412
|
pendingTransitionMode = void 0;
|
|
@@ -1344,6 +1416,10 @@ function Router(props) {
|
|
|
1344
1416
|
const id = ++navigationId;
|
|
1345
1417
|
const mode = takeMode();
|
|
1346
1418
|
setNavigating(true);
|
|
1419
|
+
if (scroll) {
|
|
1420
|
+
scroll.leave();
|
|
1421
|
+
arriving = { id, location: next.location, from: untrack4(state).location };
|
|
1422
|
+
}
|
|
1347
1423
|
const prepared = prepareComponents(
|
|
1348
1424
|
(next.match?.matched ?? []).map((m) => m.component).filter(Boolean)
|
|
1349
1425
|
);
|
|
@@ -1351,6 +1427,7 @@ function Router(props) {
|
|
|
1351
1427
|
setState(next);
|
|
1352
1428
|
const flushed = flush();
|
|
1353
1429
|
if (id === navigationId) setNavigating(false);
|
|
1430
|
+
if (scroll) setArrived(id);
|
|
1354
1431
|
return flushed;
|
|
1355
1432
|
};
|
|
1356
1433
|
if (!prepared) {
|
|
@@ -1364,6 +1441,7 @@ function Router(props) {
|
|
|
1364
1441
|
});
|
|
1365
1442
|
onCleanup4(() => {
|
|
1366
1443
|
unsub();
|
|
1444
|
+
scroll?.dispose();
|
|
1367
1445
|
router.destroy();
|
|
1368
1446
|
navigationId++;
|
|
1369
1447
|
});
|
|
@@ -1386,6 +1464,19 @@ function Router(props) {
|
|
|
1386
1464
|
return result;
|
|
1387
1465
|
}
|
|
1388
1466
|
};
|
|
1467
|
+
if (scroll) {
|
|
1468
|
+
const nextFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (fn) => setTimeout(fn, 0);
|
|
1469
|
+
createEffect4(() => {
|
|
1470
|
+
const id = arrived();
|
|
1471
|
+
if (ctx.isRouting()) return;
|
|
1472
|
+
const next = arriving;
|
|
1473
|
+
if (!next || next.id !== id || id !== navigationId) return;
|
|
1474
|
+
arriving = null;
|
|
1475
|
+
nextFrame(() => {
|
|
1476
|
+
if (id === navigationId) scroll.arrive(next.location, next.from);
|
|
1477
|
+
});
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1389
1480
|
const root = {
|
|
1390
1481
|
depth: -1,
|
|
1391
1482
|
matched,
|