@vertz/ui 0.2.0 → 0.2.2
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 +339 -857
- package/dist/css/public.d.ts +24 -27
- package/dist/css/public.js +5 -1
- package/dist/form/public.d.ts +94 -38
- package/dist/form/public.js +5 -3
- package/dist/index.d.ts +754 -167
- package/dist/index.js +606 -84
- package/dist/internals.d.ts +192 -23
- package/dist/internals.js +151 -102
- package/dist/jsx-runtime/index.d.ts +44 -17
- package/dist/jsx-runtime/index.js +26 -7
- package/dist/query/public.d.ts +73 -7
- package/dist/query/public.js +12 -4
- package/dist/router/public.d.ts +199 -26
- package/dist/router/public.js +22 -7
- package/dist/shared/chunk-0xcmwgdb.js +288 -0
- package/dist/shared/{chunk-j8vzvne3.js → chunk-9e92w0wt.js} +4 -1
- package/dist/shared/chunk-g4rch80a.js +33 -0
- package/dist/shared/chunk-hh0dhmb4.js +528 -0
- package/dist/shared/{chunk-pgymxpn1.js → chunk-hrd0mft1.js} +136 -34
- package/dist/shared/chunk-jrtrk5z4.js +125 -0
- package/dist/shared/chunk-ka5ked7n.js +188 -0
- package/dist/shared/chunk-n91rwj2r.js +483 -0
- package/dist/shared/chunk-prj7nm08.js +67 -0
- package/dist/shared/chunk-q6cpe5k7.js +230 -0
- package/dist/shared/{chunk-f1ynwam4.js → chunk-qacth5ah.js} +162 -36
- package/dist/shared/chunk-ryb49346.js +374 -0
- package/dist/shared/chunk-v3yyf79g.js +48 -0
- package/dist/test/index.d.ts +67 -6
- package/dist/test/index.js +4 -3
- package/package.json +14 -9
- package/dist/shared/chunk-bp3v6s9j.js +0 -62
- package/dist/shared/chunk-d8h2eh8d.js +0 -141
- package/dist/shared/chunk-tsdpgmks.js +0 -98
- package/dist/shared/chunk-xd9d7q5p.js +0 -115
- package/dist/shared/chunk-zbbvx05f.js +0 -202
|
@@ -1,11 +1,76 @@
|
|
|
1
1
|
// src/component/context.ts
|
|
2
2
|
var currentScope = null;
|
|
3
|
+
function isSignalLike(value) {
|
|
4
|
+
return value != null && typeof value === "object" && "peek" in value && typeof value.peek === "function";
|
|
5
|
+
}
|
|
6
|
+
function wrapSignalProps(value) {
|
|
7
|
+
if (value == null || typeof value !== "object" || Array.isArray(value)) {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
const source = value;
|
|
11
|
+
const keys = Object.keys(source);
|
|
12
|
+
let hasSignal = false;
|
|
13
|
+
for (const key of keys) {
|
|
14
|
+
if (isSignalLike(source[key])) {
|
|
15
|
+
hasSignal = true;
|
|
16
|
+
break;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (!hasSignal)
|
|
20
|
+
return value;
|
|
21
|
+
const wrapped = {};
|
|
22
|
+
for (const key of keys) {
|
|
23
|
+
const propValue = source[key];
|
|
24
|
+
if (isSignalLike(propValue)) {
|
|
25
|
+
Object.defineProperty(wrapped, key, {
|
|
26
|
+
get() {
|
|
27
|
+
return propValue.value;
|
|
28
|
+
},
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true
|
|
31
|
+
});
|
|
32
|
+
} else {
|
|
33
|
+
wrapped[key] = propValue;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return wrapped;
|
|
37
|
+
}
|
|
3
38
|
function asKey(ctx) {
|
|
4
39
|
return ctx;
|
|
5
40
|
}
|
|
6
|
-
|
|
41
|
+
var REGISTRY_KEY = "__VERTZ_CTX_REG__";
|
|
42
|
+
var contextRegistry = globalThis[REGISTRY_KEY] ?? (() => {
|
|
43
|
+
const m = new Map;
|
|
44
|
+
globalThis[REGISTRY_KEY] = m;
|
|
45
|
+
return m;
|
|
46
|
+
})();
|
|
47
|
+
function createContext(defaultValue, __stableId) {
|
|
48
|
+
if (__stableId) {
|
|
49
|
+
const existing = contextRegistry.get(__stableId);
|
|
50
|
+
if (existing)
|
|
51
|
+
return existing;
|
|
52
|
+
}
|
|
7
53
|
const ctx = {
|
|
8
|
-
Provider(
|
|
54
|
+
Provider(valueOrProps, fn) {
|
|
55
|
+
if (fn !== undefined) {
|
|
56
|
+
const value2 = wrapSignalProps(valueOrProps);
|
|
57
|
+
const parentScope2 = currentScope;
|
|
58
|
+
const scope2 = parentScope2 ? new Map(parentScope2) : new Map;
|
|
59
|
+
scope2.set(asKey(ctx), value2);
|
|
60
|
+
ctx._stack.push(value2);
|
|
61
|
+
const prevScope2 = currentScope;
|
|
62
|
+
currentScope = scope2;
|
|
63
|
+
try {
|
|
64
|
+
fn();
|
|
65
|
+
} finally {
|
|
66
|
+
ctx._stack.pop();
|
|
67
|
+
currentScope = prevScope2;
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const props = valueOrProps;
|
|
72
|
+
const { value: rawValue, children } = props;
|
|
73
|
+
const value = wrapSignalProps(rawValue);
|
|
9
74
|
const parentScope = currentScope;
|
|
10
75
|
const scope = parentScope ? new Map(parentScope) : new Map;
|
|
11
76
|
scope.set(asKey(ctx), value);
|
|
@@ -13,7 +78,11 @@ function createContext(defaultValue) {
|
|
|
13
78
|
const prevScope = currentScope;
|
|
14
79
|
currentScope = scope;
|
|
15
80
|
try {
|
|
16
|
-
|
|
81
|
+
const result = typeof children === "function" ? children() : children;
|
|
82
|
+
if (typeof process !== "undefined" && true && Array.isArray(result)) {
|
|
83
|
+
throw new Error("Context.Provider JSX children must have a single root element. " + "Wrap multiple children in a fragment: <><Child1 /><Child2 /></>");
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
17
86
|
} finally {
|
|
18
87
|
ctx._stack.pop();
|
|
19
88
|
currentScope = prevScope;
|
|
@@ -22,6 +91,9 @@ function createContext(defaultValue) {
|
|
|
22
91
|
_default: defaultValue,
|
|
23
92
|
_stack: []
|
|
24
93
|
};
|
|
94
|
+
if (__stableId) {
|
|
95
|
+
contextRegistry.set(__stableId, ctx);
|
|
96
|
+
}
|
|
25
97
|
return ctx;
|
|
26
98
|
}
|
|
27
99
|
function useContext(ctx) {
|
|
@@ -46,7 +118,7 @@ function setContextScope(scope) {
|
|
|
46
118
|
// src/runtime/disposal.ts
|
|
47
119
|
class DisposalScopeError extends Error {
|
|
48
120
|
constructor() {
|
|
49
|
-
super("onCleanup() must be called within a disposal scope (e.g., inside
|
|
121
|
+
super("onCleanup() must be called within a disposal scope (e.g., inside domEffect(), lifecycleEffect(), onMount(), or a pushScope()/popScope() block). " + "Called outside a scope, the cleanup callback would be silently discarded.");
|
|
50
122
|
this.name = "DisposalScopeError";
|
|
51
123
|
}
|
|
52
124
|
}
|
|
@@ -79,6 +151,35 @@ function runCleanups(cleanups) {
|
|
|
79
151
|
cleanups.length = 0;
|
|
80
152
|
}
|
|
81
153
|
|
|
154
|
+
// src/runtime/tracking.ts
|
|
155
|
+
var currentSubscriber = null;
|
|
156
|
+
var readValueCallback = null;
|
|
157
|
+
function getSubscriber() {
|
|
158
|
+
return currentSubscriber;
|
|
159
|
+
}
|
|
160
|
+
function setSubscriber(sub) {
|
|
161
|
+
const prev = currentSubscriber;
|
|
162
|
+
currentSubscriber = sub;
|
|
163
|
+
return prev;
|
|
164
|
+
}
|
|
165
|
+
function getReadValueCallback() {
|
|
166
|
+
return readValueCallback;
|
|
167
|
+
}
|
|
168
|
+
function setReadValueCallback(cb) {
|
|
169
|
+
const prev = readValueCallback;
|
|
170
|
+
readValueCallback = cb;
|
|
171
|
+
return prev;
|
|
172
|
+
}
|
|
173
|
+
function untrack(fn) {
|
|
174
|
+
const prev = currentSubscriber;
|
|
175
|
+
currentSubscriber = null;
|
|
176
|
+
try {
|
|
177
|
+
return fn();
|
|
178
|
+
} finally {
|
|
179
|
+
currentSubscriber = prev;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
82
183
|
// src/runtime/scheduler.ts
|
|
83
184
|
var batchDepth = 0;
|
|
84
185
|
var pendingEffects = new Map;
|
|
@@ -114,36 +215,18 @@ function batch(fn) {
|
|
|
114
215
|
}
|
|
115
216
|
}
|
|
116
217
|
|
|
117
|
-
// src/runtime/
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
function
|
|
121
|
-
return currentSubscriber;
|
|
122
|
-
}
|
|
123
|
-
function setSubscriber(sub) {
|
|
124
|
-
const prev = currentSubscriber;
|
|
125
|
-
currentSubscriber = sub;
|
|
126
|
-
return prev;
|
|
218
|
+
// src/runtime/signal.ts
|
|
219
|
+
function isSSR() {
|
|
220
|
+
const check = typeof globalThis !== "undefined" && globalThis.__VERTZ_IS_SSR__;
|
|
221
|
+
return typeof check === "function" ? check() : false;
|
|
127
222
|
}
|
|
128
|
-
|
|
129
|
-
|
|
223
|
+
var signalCollectorStack = [];
|
|
224
|
+
function startSignalCollection() {
|
|
225
|
+
signalCollectorStack.push([]);
|
|
130
226
|
}
|
|
131
|
-
function
|
|
132
|
-
|
|
133
|
-
readValueCallback = cb;
|
|
134
|
-
return prev;
|
|
135
|
-
}
|
|
136
|
-
function untrack(fn) {
|
|
137
|
-
const prev = currentSubscriber;
|
|
138
|
-
currentSubscriber = null;
|
|
139
|
-
try {
|
|
140
|
-
return fn();
|
|
141
|
-
} finally {
|
|
142
|
-
currentSubscriber = prev;
|
|
143
|
-
}
|
|
227
|
+
function stopSignalCollection() {
|
|
228
|
+
return signalCollectorStack.pop() ?? [];
|
|
144
229
|
}
|
|
145
|
-
|
|
146
|
-
// src/runtime/signal.ts
|
|
147
230
|
var nextId = 0;
|
|
148
231
|
|
|
149
232
|
class SignalImpl {
|
|
@@ -185,7 +268,12 @@ class SignalImpl {
|
|
|
185
268
|
}
|
|
186
269
|
}
|
|
187
270
|
function signal(initial) {
|
|
188
|
-
|
|
271
|
+
const s = new SignalImpl(initial);
|
|
272
|
+
const collector = signalCollectorStack[signalCollectorStack.length - 1];
|
|
273
|
+
if (collector) {
|
|
274
|
+
collector.push(s);
|
|
275
|
+
}
|
|
276
|
+
return s;
|
|
189
277
|
}
|
|
190
278
|
class ComputedImpl {
|
|
191
279
|
_id;
|
|
@@ -297,7 +385,21 @@ class EffectImpl {
|
|
|
297
385
|
this._contextScope = null;
|
|
298
386
|
}
|
|
299
387
|
}
|
|
300
|
-
function
|
|
388
|
+
function domEffect(fn) {
|
|
389
|
+
if (isSSR()) {
|
|
390
|
+
fn();
|
|
391
|
+
return () => {};
|
|
392
|
+
}
|
|
393
|
+
const eff = new EffectImpl(fn);
|
|
394
|
+
eff._run();
|
|
395
|
+
const dispose = () => eff._dispose();
|
|
396
|
+
_tryOnCleanup(dispose);
|
|
397
|
+
return dispose;
|
|
398
|
+
}
|
|
399
|
+
function lifecycleEffect(fn) {
|
|
400
|
+
if (isSSR()) {
|
|
401
|
+
return () => {};
|
|
402
|
+
}
|
|
301
403
|
const eff = new EffectImpl(fn);
|
|
302
404
|
eff._run();
|
|
303
405
|
const dispose = () => eff._dispose();
|
|
@@ -305,4 +407,4 @@ function effect(fn) {
|
|
|
305
407
|
return dispose;
|
|
306
408
|
}
|
|
307
409
|
|
|
308
|
-
export { createContext, useContext, DisposalScopeError, onCleanup, _tryOnCleanup, pushScope, popScope, runCleanups, batch,
|
|
410
|
+
export { createContext, useContext, getContextScope, setContextScope, DisposalScopeError, onCleanup, _tryOnCleanup, pushScope, popScope, runCleanups, setReadValueCallback, untrack, batch, startSignalCollection, stopSignalCollection, signal, computed, domEffect, lifecycleEffect };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// src/router/server-nav.ts
|
|
2
|
+
function parseSSE(buffer) {
|
|
3
|
+
const events = [];
|
|
4
|
+
const blocks = buffer.split(`
|
|
5
|
+
|
|
6
|
+
`);
|
|
7
|
+
const remaining = blocks.pop() ?? "";
|
|
8
|
+
for (const block of blocks) {
|
|
9
|
+
if (block.trim() === "")
|
|
10
|
+
continue;
|
|
11
|
+
let type = "";
|
|
12
|
+
let data = "";
|
|
13
|
+
for (const line of block.split(`
|
|
14
|
+
`)) {
|
|
15
|
+
if (line.startsWith("event: ")) {
|
|
16
|
+
type = line.slice(7).trim();
|
|
17
|
+
} else if (line.startsWith("data: ")) {
|
|
18
|
+
data = line.slice(6);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (type) {
|
|
22
|
+
events.push({ type, data });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return { events, remaining };
|
|
26
|
+
}
|
|
27
|
+
function ensureSSRDataBus() {
|
|
28
|
+
const g = globalThis;
|
|
29
|
+
g.__VERTZ_SSR_DATA__ = [];
|
|
30
|
+
g.__VERTZ_SSR_PUSH__ = (key, data) => {
|
|
31
|
+
g.__VERTZ_SSR_DATA__.push({ key, data });
|
|
32
|
+
document.dispatchEvent(new CustomEvent("vertz:ssr-data", { detail: { key, data } }));
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function pushNavData(key, data) {
|
|
36
|
+
const push = globalThis.__VERTZ_SSR_PUSH__;
|
|
37
|
+
if (typeof push === "function") {
|
|
38
|
+
push(key, data);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function isNavPrefetchActive() {
|
|
42
|
+
return globalThis.__VERTZ_NAV_PREFETCH_ACTIVE__ === true;
|
|
43
|
+
}
|
|
44
|
+
function setNavPrefetchActive(active) {
|
|
45
|
+
globalThis.__VERTZ_NAV_PREFETCH_ACTIVE__ = active;
|
|
46
|
+
}
|
|
47
|
+
function dispatchPrefetchDone() {
|
|
48
|
+
setNavPrefetchActive(false);
|
|
49
|
+
document.dispatchEvent(new CustomEvent("vertz:nav-prefetch-done"));
|
|
50
|
+
}
|
|
51
|
+
var prefetchGen = 0;
|
|
52
|
+
function prefetchNavData(url, options) {
|
|
53
|
+
const controller = new AbortController;
|
|
54
|
+
const timeout = options?.timeout ?? 5000;
|
|
55
|
+
const gen = ++prefetchGen;
|
|
56
|
+
ensureSSRDataBus();
|
|
57
|
+
setNavPrefetchActive(true);
|
|
58
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
59
|
+
let resolveFirstEvent = null;
|
|
60
|
+
const firstEvent = new Promise((r) => {
|
|
61
|
+
resolveFirstEvent = r;
|
|
62
|
+
});
|
|
63
|
+
function onFirstEvent() {
|
|
64
|
+
if (resolveFirstEvent) {
|
|
65
|
+
resolveFirstEvent();
|
|
66
|
+
resolveFirstEvent = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function finishIfCurrent() {
|
|
70
|
+
if (gen === prefetchGen) {
|
|
71
|
+
dispatchPrefetchDone();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const done = fetch(url, {
|
|
75
|
+
headers: { "X-Vertz-Nav": "1" },
|
|
76
|
+
signal: controller.signal
|
|
77
|
+
}).then(async (response) => {
|
|
78
|
+
if (!response.body) {
|
|
79
|
+
onFirstEvent();
|
|
80
|
+
finishIfCurrent();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const reader = response.body.getReader();
|
|
84
|
+
const decoder = new TextDecoder;
|
|
85
|
+
let buffer = "";
|
|
86
|
+
while (true) {
|
|
87
|
+
const { done: streamDone, value } = await reader.read();
|
|
88
|
+
if (streamDone)
|
|
89
|
+
break;
|
|
90
|
+
buffer += decoder.decode(value, { stream: true });
|
|
91
|
+
const parsed = parseSSE(buffer);
|
|
92
|
+
buffer = parsed.remaining;
|
|
93
|
+
for (const event of parsed.events) {
|
|
94
|
+
onFirstEvent();
|
|
95
|
+
if (event.type === "data") {
|
|
96
|
+
try {
|
|
97
|
+
const { key, data } = JSON.parse(event.data);
|
|
98
|
+
pushNavData(key, data);
|
|
99
|
+
} catch {}
|
|
100
|
+
} else if (event.type === "done") {
|
|
101
|
+
finishIfCurrent();
|
|
102
|
+
clearTimeout(timeoutId);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
onFirstEvent();
|
|
108
|
+
finishIfCurrent();
|
|
109
|
+
}).catch(() => {
|
|
110
|
+
onFirstEvent();
|
|
111
|
+
finishIfCurrent();
|
|
112
|
+
}).finally(() => {
|
|
113
|
+
clearTimeout(timeoutId);
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
abort: () => {
|
|
117
|
+
controller.abort();
|
|
118
|
+
clearTimeout(timeoutId);
|
|
119
|
+
},
|
|
120
|
+
done,
|
|
121
|
+
firstEvent
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export { isNavPrefetchActive, prefetchNavData };
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import {
|
|
2
|
+
executeLoaders,
|
|
3
|
+
matchRoute
|
|
4
|
+
} from "./chunk-9e92w0wt.js";
|
|
5
|
+
import {
|
|
6
|
+
prefetchNavData
|
|
7
|
+
} from "./chunk-jrtrk5z4.js";
|
|
8
|
+
import {
|
|
9
|
+
signal
|
|
10
|
+
} from "./chunk-hrd0mft1.js";
|
|
11
|
+
|
|
12
|
+
// src/router/navigate.ts
|
|
13
|
+
var DEFAULT_NAV_THRESHOLD_MS = 500;
|
|
14
|
+
function createRouter(routes, initialUrl, options) {
|
|
15
|
+
const isSSR = typeof window === "undefined" || typeof globalThis.__SSR_URL__ !== "undefined";
|
|
16
|
+
let url;
|
|
17
|
+
if (initialUrl) {
|
|
18
|
+
url = initialUrl;
|
|
19
|
+
} else if (isSSR) {
|
|
20
|
+
url = globalThis.__SSR_URL__ || "/";
|
|
21
|
+
} else {
|
|
22
|
+
url = window.location.pathname + window.location.search;
|
|
23
|
+
}
|
|
24
|
+
const initialMatch = matchRoute(routes, url);
|
|
25
|
+
function normalizeUrl(rawUrl) {
|
|
26
|
+
const qIdx = rawUrl.indexOf("?");
|
|
27
|
+
if (qIdx === -1)
|
|
28
|
+
return rawUrl;
|
|
29
|
+
const pathname = rawUrl.slice(0, qIdx);
|
|
30
|
+
const params = new URLSearchParams(rawUrl.slice(qIdx + 1));
|
|
31
|
+
params.sort();
|
|
32
|
+
const sorted = params.toString();
|
|
33
|
+
return sorted ? `${pathname}?${sorted}` : pathname;
|
|
34
|
+
}
|
|
35
|
+
const visitedUrls = new Set;
|
|
36
|
+
if (initialMatch)
|
|
37
|
+
visitedUrls.add(normalizeUrl(url));
|
|
38
|
+
const current = signal(initialMatch);
|
|
39
|
+
const loaderData = signal([]);
|
|
40
|
+
const loaderError = signal(null);
|
|
41
|
+
const searchParams = signal(initialMatch?.search ?? {});
|
|
42
|
+
let navigationGen = 0;
|
|
43
|
+
let navigateGen = 0;
|
|
44
|
+
let currentAbort = null;
|
|
45
|
+
const serverNavEnabled = !!options?.serverNav;
|
|
46
|
+
const serverNavTimeout = typeof options?.serverNav === "object" ? options.serverNav.timeout : undefined;
|
|
47
|
+
const prefetchFn = options?._prefetchNavData ?? (serverNavEnabled ? prefetchNavData : null);
|
|
48
|
+
let activePrefetch = null;
|
|
49
|
+
let activePrefetchUrl = null;
|
|
50
|
+
function startPrefetch(navUrl) {
|
|
51
|
+
if (!serverNavEnabled || !prefetchFn)
|
|
52
|
+
return null;
|
|
53
|
+
const normalized = normalizeUrl(navUrl);
|
|
54
|
+
if (activePrefetch && activePrefetchUrl === normalized) {
|
|
55
|
+
return activePrefetch;
|
|
56
|
+
}
|
|
57
|
+
if (activePrefetch) {
|
|
58
|
+
activePrefetch.abort();
|
|
59
|
+
}
|
|
60
|
+
const prefetchOpts = {};
|
|
61
|
+
if (serverNavTimeout !== undefined) {
|
|
62
|
+
prefetchOpts.timeout = serverNavTimeout;
|
|
63
|
+
}
|
|
64
|
+
activePrefetch = prefetchFn(navUrl, prefetchOpts);
|
|
65
|
+
activePrefetchUrl = normalized;
|
|
66
|
+
return activePrefetch;
|
|
67
|
+
}
|
|
68
|
+
async function awaitPrefetch(handle) {
|
|
69
|
+
const target = handle?.firstEvent ?? handle?.done;
|
|
70
|
+
if (!target)
|
|
71
|
+
return;
|
|
72
|
+
await Promise.race([target, new Promise((r) => setTimeout(r, DEFAULT_NAV_THRESHOLD_MS))]);
|
|
73
|
+
}
|
|
74
|
+
if (isSSR) {
|
|
75
|
+
const g = globalThis;
|
|
76
|
+
const prev = g.__VERTZ_SSR_SYNC_ROUTER__;
|
|
77
|
+
g.__VERTZ_SSR_SYNC_ROUTER__ = (ssrUrl) => {
|
|
78
|
+
if (typeof prev === "function")
|
|
79
|
+
prev(ssrUrl);
|
|
80
|
+
const match = matchRoute(routes, ssrUrl);
|
|
81
|
+
current.value = match;
|
|
82
|
+
searchParams.value = match?.search ?? {};
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (initialMatch) {
|
|
86
|
+
const gen = ++navigationGen;
|
|
87
|
+
const abort = new AbortController;
|
|
88
|
+
currentAbort = abort;
|
|
89
|
+
runLoaders(initialMatch, gen, abort.signal).catch(() => {});
|
|
90
|
+
}
|
|
91
|
+
async function runLoaders(match, gen, abortSignal) {
|
|
92
|
+
try {
|
|
93
|
+
loaderError.value = null;
|
|
94
|
+
const results = await executeLoaders(match.matched, match.params, abortSignal);
|
|
95
|
+
if (gen === navigationGen) {
|
|
96
|
+
loaderData.value = results;
|
|
97
|
+
}
|
|
98
|
+
} catch (err) {
|
|
99
|
+
if (gen === navigationGen) {
|
|
100
|
+
loaderError.value = err instanceof Error ? err : new Error(String(err));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function applyNavigation(url2) {
|
|
105
|
+
if (currentAbort) {
|
|
106
|
+
currentAbort.abort();
|
|
107
|
+
}
|
|
108
|
+
const gen = ++navigationGen;
|
|
109
|
+
const abort = new AbortController;
|
|
110
|
+
currentAbort = abort;
|
|
111
|
+
const match = matchRoute(routes, url2);
|
|
112
|
+
current.value = match;
|
|
113
|
+
if (match) {
|
|
114
|
+
visitedUrls.add(normalizeUrl(url2));
|
|
115
|
+
searchParams.value = match.search;
|
|
116
|
+
await runLoaders(match, gen, abort.signal);
|
|
117
|
+
} else {
|
|
118
|
+
searchParams.value = {};
|
|
119
|
+
if (gen === navigationGen) {
|
|
120
|
+
loaderData.value = [];
|
|
121
|
+
loaderError.value = null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async function navigate(navUrl, navOptions) {
|
|
126
|
+
const gen = ++navigateGen;
|
|
127
|
+
const handle = startPrefetch(navUrl);
|
|
128
|
+
if (!isSSR) {
|
|
129
|
+
if (navOptions?.replace) {
|
|
130
|
+
window.history.replaceState(null, "", navUrl);
|
|
131
|
+
} else {
|
|
132
|
+
window.history.pushState(null, "", navUrl);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const isCachedNav = visitedUrls.has(normalizeUrl(navUrl));
|
|
136
|
+
if (!isCachedNav && (handle?.firstEvent || handle?.done)) {
|
|
137
|
+
await awaitPrefetch(handle);
|
|
138
|
+
}
|
|
139
|
+
if (gen !== navigateGen)
|
|
140
|
+
return;
|
|
141
|
+
await applyNavigation(navUrl);
|
|
142
|
+
}
|
|
143
|
+
async function revalidate() {
|
|
144
|
+
const match = current.value;
|
|
145
|
+
if (match) {
|
|
146
|
+
if (currentAbort) {
|
|
147
|
+
currentAbort.abort();
|
|
148
|
+
}
|
|
149
|
+
const gen = ++navigationGen;
|
|
150
|
+
const abort = new AbortController;
|
|
151
|
+
currentAbort = abort;
|
|
152
|
+
await runLoaders(match, gen, abort.signal);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
let onPopState = null;
|
|
156
|
+
if (!isSSR) {
|
|
157
|
+
onPopState = () => {
|
|
158
|
+
const popUrl = window.location.pathname + window.location.search;
|
|
159
|
+
startPrefetch(popUrl);
|
|
160
|
+
applyNavigation(popUrl).catch(() => {});
|
|
161
|
+
};
|
|
162
|
+
window.addEventListener("popstate", onPopState);
|
|
163
|
+
}
|
|
164
|
+
function dispose() {
|
|
165
|
+
if (onPopState) {
|
|
166
|
+
window.removeEventListener("popstate", onPopState);
|
|
167
|
+
}
|
|
168
|
+
if (currentAbort) {
|
|
169
|
+
currentAbort.abort();
|
|
170
|
+
}
|
|
171
|
+
if (activePrefetch) {
|
|
172
|
+
activePrefetch.abort();
|
|
173
|
+
activePrefetch = null;
|
|
174
|
+
activePrefetchUrl = null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
current,
|
|
179
|
+
dispose,
|
|
180
|
+
loaderData,
|
|
181
|
+
loaderError,
|
|
182
|
+
navigate,
|
|
183
|
+
revalidate,
|
|
184
|
+
searchParams
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export { createRouter };
|