@netrojs/fnetro 0.1.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/dist/client.js ADDED
@@ -0,0 +1,673 @@
1
+ // client.ts
2
+ import { render } from "hono/jsx/dom";
3
+ import { jsx } from "hono/jsx";
4
+ import {
5
+ useState,
6
+ useEffect,
7
+ useMemo,
8
+ useRef as useHonoRef,
9
+ useSyncExternalStore
10
+ } from "hono/jsx";
11
+
12
+ // core.ts
13
+ var RAW = /* @__PURE__ */ Symbol("raw");
14
+ var IS_REACTIVE = /* @__PURE__ */ Symbol("isReactive");
15
+ var IS_READONLY = /* @__PURE__ */ Symbol("isReadonly");
16
+ var IS_REF = /* @__PURE__ */ Symbol("isRef");
17
+ var MARK_RAW = /* @__PURE__ */ Symbol("markRaw");
18
+ var targetMap = /* @__PURE__ */ new WeakMap();
19
+ var activeEffect = null;
20
+ var shouldTrack = true;
21
+ var trackStack = [];
22
+ function pauseTracking() {
23
+ trackStack.push(shouldTrack);
24
+ shouldTrack = false;
25
+ }
26
+ function resetTracking() {
27
+ shouldTrack = trackStack.pop() ?? true;
28
+ }
29
+ function track(target, key) {
30
+ if (!shouldTrack || !activeEffect) return;
31
+ let depsMap = targetMap.get(target);
32
+ if (!depsMap) targetMap.set(target, depsMap = /* @__PURE__ */ new Map());
33
+ let dep = depsMap.get(key);
34
+ if (!dep) depsMap.set(key, dep = /* @__PURE__ */ new Set());
35
+ trackEffect(activeEffect, dep);
36
+ }
37
+ function trackEffect(effect2, dep) {
38
+ if (!dep.has(effect2)) {
39
+ dep.add(effect2);
40
+ effect2.deps.push(dep);
41
+ }
42
+ }
43
+ function trigger(target, key, newVal, oldVal) {
44
+ const depsMap = targetMap.get(target);
45
+ if (!depsMap) return;
46
+ const effects = [];
47
+ const computedEffects = [];
48
+ depsMap.get(key)?.forEach((e) => {
49
+ if (e !== activeEffect) {
50
+ e.computed ? computedEffects.push(e) : effects.push(e);
51
+ }
52
+ });
53
+ [...computedEffects, ...effects].forEach((e) => {
54
+ if (e.active) e.scheduler ? e.scheduler() : e.run();
55
+ });
56
+ }
57
+ var ReactiveEffect = class {
58
+ constructor(fn, scheduler, scope) {
59
+ this.fn = fn;
60
+ this.scheduler = scheduler;
61
+ this.scope = scope;
62
+ scope?.effects.push(this);
63
+ }
64
+ deps = [];
65
+ active = true;
66
+ cleanup;
67
+ computed = false;
68
+ run() {
69
+ if (!this.active) return this.fn();
70
+ const prevEffect = activeEffect;
71
+ const prevShouldTrack = shouldTrack;
72
+ shouldTrack = true;
73
+ activeEffect = this;
74
+ this.cleanup?.();
75
+ this.cleanup = void 0;
76
+ this.deps.length = 0;
77
+ try {
78
+ const result = this.fn();
79
+ if (typeof result === "function") this.cleanup = result;
80
+ return result;
81
+ } finally {
82
+ activeEffect = prevEffect;
83
+ shouldTrack = prevShouldTrack;
84
+ }
85
+ }
86
+ stop() {
87
+ if (this.active) {
88
+ cleanupEffect(this);
89
+ this.active = false;
90
+ }
91
+ }
92
+ };
93
+ function cleanupEffect(e) {
94
+ e.deps.forEach((dep) => dep.delete(e));
95
+ e.deps.length = 0;
96
+ }
97
+ var activeScope;
98
+ var EffectScope = class {
99
+ effects = [];
100
+ cleanups = [];
101
+ active = true;
102
+ run(fn) {
103
+ const prev = activeScope;
104
+ activeScope = this;
105
+ try {
106
+ return fn();
107
+ } finally {
108
+ activeScope = prev;
109
+ }
110
+ }
111
+ stop() {
112
+ if (this.active) {
113
+ this.effects.forEach((e) => e.stop());
114
+ this.cleanups.forEach((fn) => fn());
115
+ this.active = false;
116
+ }
117
+ }
118
+ onCleanup(fn) {
119
+ this.cleanups.push(fn);
120
+ }
121
+ };
122
+ function effectScope() {
123
+ return new EffectScope();
124
+ }
125
+ function effect(fn) {
126
+ const e = new ReactiveEffect(fn, void 0, activeScope);
127
+ e.run();
128
+ return () => e.stop();
129
+ }
130
+ function watchEffect(fn, opts) {
131
+ const e = new ReactiveEffect(fn, void 0, activeScope);
132
+ e.run();
133
+ return () => e.stop();
134
+ }
135
+ var refTarget = /* @__PURE__ */ Symbol("refTarget");
136
+ var RefImpl = class {
137
+ constructor(value, shallow = false) {
138
+ this.shallow = shallow;
139
+ this._value = shallow ? value : toReactive(value);
140
+ }
141
+ [IS_REF] = true;
142
+ _value;
143
+ _subscribers = /* @__PURE__ */ new Set();
144
+ get value() {
145
+ track(this, refTarget);
146
+ this._subscribers.forEach((fn) => {
147
+ });
148
+ return this._value;
149
+ }
150
+ set value(next) {
151
+ const newVal = this.shallow ? next : toReactive(next);
152
+ if (!hasChanged(newVal, this._value)) return;
153
+ this._value = newVal;
154
+ trigger(this, refTarget, newVal, this._value);
155
+ this._subscribers.forEach((fn) => fn());
156
+ }
157
+ /** Subscribe for useSyncExternalStore */
158
+ subscribe(fn) {
159
+ this._subscribers.add(fn);
160
+ return () => this._subscribers.delete(fn);
161
+ }
162
+ peek() {
163
+ return this._value;
164
+ }
165
+ };
166
+ function ref(value) {
167
+ return isRef(value) ? value : new RefImpl(value);
168
+ }
169
+ function shallowRef(value) {
170
+ return new RefImpl(value, true);
171
+ }
172
+ function triggerRef(r) {
173
+ if (r instanceof RefImpl) {
174
+ trigger(r, refTarget);
175
+ r._subscribers.forEach((fn) => fn());
176
+ }
177
+ }
178
+ function isRef(r) {
179
+ return !!r && typeof r === "object" && r[IS_REF] === true;
180
+ }
181
+ function unref(r) {
182
+ return isRef(r) ? r.value : r;
183
+ }
184
+ function toRef(obj, key) {
185
+ const r = new RefImpl(void 0, false);
186
+ Object.defineProperty(r, "value", {
187
+ get() {
188
+ track(r, refTarget);
189
+ return obj[key];
190
+ },
191
+ set(v) {
192
+ obj[key] = v;
193
+ trigger(r, refTarget, v, obj[key]);
194
+ }
195
+ });
196
+ return r;
197
+ }
198
+ function toRefs(obj) {
199
+ const result = {};
200
+ for (const key in obj) result[key] = toRef(obj, key);
201
+ return result;
202
+ }
203
+ var ComputedRefImpl = class {
204
+ constructor(getter, setter) {
205
+ this.setter = setter;
206
+ this.effect = new ReactiveEffect(getter, () => {
207
+ if (!this._dirty) {
208
+ this._dirty = true;
209
+ trigger(this, refTarget);
210
+ this._subscribers.forEach((fn) => fn());
211
+ }
212
+ }, activeScope);
213
+ this.effect.computed = true;
214
+ }
215
+ [IS_REF] = true;
216
+ effect;
217
+ _value;
218
+ _dirty = true;
219
+ _subscribers = /* @__PURE__ */ new Set();
220
+ get value() {
221
+ track(this, refTarget);
222
+ if (this._dirty) {
223
+ this._dirty = false;
224
+ this._value = this.effect.run();
225
+ }
226
+ return this._value;
227
+ }
228
+ set value(v) {
229
+ this.setter?.(v);
230
+ }
231
+ subscribe(fn) {
232
+ this._subscribers.add(fn);
233
+ return () => this._subscribers.delete(fn);
234
+ }
235
+ peek() {
236
+ return this._value;
237
+ }
238
+ };
239
+ function computed(arg) {
240
+ if (typeof arg === "function") {
241
+ return new ComputedRefImpl(arg);
242
+ }
243
+ return new ComputedRefImpl(arg.get, arg.set);
244
+ }
245
+ var reactiveMap = /* @__PURE__ */ new WeakMap();
246
+ var readonlyMap = /* @__PURE__ */ new WeakMap();
247
+ var shallowReactiveMap = /* @__PURE__ */ new WeakMap();
248
+ function toReactive(value) {
249
+ return value !== null && typeof value === "object" ? reactive(value) : value;
250
+ }
251
+ var arrayInstrumentations = {};
252
+ ["includes", "indexOf", "lastIndexOf"].forEach((method) => {
253
+ arrayInstrumentations[method] = function(...args) {
254
+ const arr = toRaw(this);
255
+ for (let i = 0; i < this.length; i++) track(arr, i);
256
+ let res = arr[method](...args);
257
+ if (res === -1 || res === false) res = arr[method](...args.map(toRaw));
258
+ return res;
259
+ };
260
+ });
261
+ ["push", "pop", "shift", "unshift", "splice"].forEach((method) => {
262
+ arrayInstrumentations[method] = function(...args) {
263
+ pauseTracking();
264
+ const res = toRaw(this)[method].apply(this, args);
265
+ resetTracking();
266
+ return res;
267
+ };
268
+ });
269
+ function createHandler(shallow = false, readonly2 = false) {
270
+ return {
271
+ get(target, key, receiver) {
272
+ if (key === RAW) return target;
273
+ if (key === IS_REACTIVE) return !readonly2;
274
+ if (key === IS_READONLY) return readonly2;
275
+ if (key === MARK_RAW) return target[MARK_RAW];
276
+ const isArray = Array.isArray(target);
277
+ if (!readonly2 && isArray && hasOwn(arrayInstrumentations, key)) {
278
+ return Reflect.get(arrayInstrumentations, key, receiver);
279
+ }
280
+ const res = Reflect.get(target, key, receiver);
281
+ if (typeof key === "symbol" || key === "__proto__") return res;
282
+ if (!readonly2) track(target, key);
283
+ if (shallow) return res;
284
+ if (isRef(res)) return isArray ? res : res.value;
285
+ return res !== null && typeof res === "object" && !res[MARK_RAW] ? readonly2 ? readonlyProxy(res) : reactive(res) : res;
286
+ },
287
+ set(target, key, value, receiver) {
288
+ if (readonly2) {
289
+ console.warn(`[fnetro] Cannot set "${String(key)}" on readonly object`);
290
+ return true;
291
+ }
292
+ const oldVal = target[key];
293
+ const result = Reflect.set(target, key, value, receiver);
294
+ if (hasChanged(value, oldVal)) trigger(target, key, value, oldVal);
295
+ return result;
296
+ },
297
+ deleteProperty(target, key) {
298
+ if (readonly2) return true;
299
+ const hadKey = hasOwn(target, key);
300
+ const result = Reflect.deleteProperty(target, key);
301
+ if (hadKey && result) trigger(target, key);
302
+ return result;
303
+ },
304
+ has(target, key) {
305
+ const res = Reflect.has(target, key);
306
+ track(target, key);
307
+ return res;
308
+ },
309
+ ownKeys(target) {
310
+ track(target, Array.isArray(target) ? "length" : "__iterate__");
311
+ return Reflect.ownKeys(target);
312
+ }
313
+ };
314
+ }
315
+ function reactive(target) {
316
+ if (isReadonly(target)) return target;
317
+ if (target[MARK_RAW]) return target;
318
+ if (reactiveMap.has(target)) return reactiveMap.get(target);
319
+ const proxy = new Proxy(target, createHandler());
320
+ reactiveMap.set(target, proxy);
321
+ return proxy;
322
+ }
323
+ function shallowReactive(target) {
324
+ if (shallowReactiveMap.has(target)) return shallowReactiveMap.get(target);
325
+ const proxy = new Proxy(target, createHandler(true));
326
+ shallowReactiveMap.set(target, proxy);
327
+ return proxy;
328
+ }
329
+ function readonlyProxy(target) {
330
+ if (readonlyMap.has(target)) return readonlyMap.get(target);
331
+ const proxy = new Proxy(target, createHandler(false, true));
332
+ readonlyMap.set(target, proxy);
333
+ return proxy;
334
+ }
335
+ function readonly(target) {
336
+ return readonlyProxy(target);
337
+ }
338
+ function markRaw(value) {
339
+ ;
340
+ value[MARK_RAW] = true;
341
+ return value;
342
+ }
343
+ function toRaw(observed) {
344
+ const raw = observed?.[RAW];
345
+ return raw ? toRaw(raw) : observed;
346
+ }
347
+ function isReactive(value) {
348
+ if (isReadonly(value)) return isReactive(value[RAW]);
349
+ return !!(value && value[IS_REACTIVE]);
350
+ }
351
+ function isReadonly(value) {
352
+ return !!(value && value[IS_READONLY]);
353
+ }
354
+ function traverse(value, seen = /* @__PURE__ */ new Set()) {
355
+ if (!value || typeof value !== "object" || seen.has(value)) return value;
356
+ seen.add(value);
357
+ if (isRef(value)) {
358
+ traverse(value.value, seen);
359
+ return value;
360
+ }
361
+ if (Array.isArray(value)) {
362
+ value.forEach((v) => traverse(v, seen));
363
+ return value;
364
+ }
365
+ for (const key in value) traverse(value[key], seen);
366
+ return value;
367
+ }
368
+ function normalizeSource(src) {
369
+ if (Array.isArray(src)) return () => src.map((s) => isRef(s) ? s.value : s());
370
+ if (isRef(src)) return () => src.value;
371
+ return src;
372
+ }
373
+ function watch(source, cb, opts = {}) {
374
+ const getter = opts.deep ? () => traverse(normalizeSource(source)()) : normalizeSource(source);
375
+ let oldVal = void 0;
376
+ let cleanupFn;
377
+ const cleanup = (fn) => {
378
+ cleanupFn = fn;
379
+ };
380
+ const job = () => {
381
+ if (!effect2.active) return;
382
+ cleanupFn?.();
383
+ cleanupFn = void 0;
384
+ const newVal = effect2.run();
385
+ if (opts.deep || hasChanged(newVal, oldVal)) {
386
+ cb(newVal, oldVal, cleanup);
387
+ oldVal = newVal;
388
+ }
389
+ if (opts.once) effect2.stop();
390
+ };
391
+ const effect2 = new ReactiveEffect(getter, job, activeScope);
392
+ if (opts.immediate) {
393
+ cleanupFn?.();
394
+ cleanupFn = void 0;
395
+ const val = effect2.run();
396
+ cb(val, oldVal, cleanup);
397
+ oldVal = val;
398
+ } else {
399
+ oldVal = effect2.run();
400
+ }
401
+ return () => effect2.stop();
402
+ }
403
+ var __hooks = {
404
+ useValue: (r) => isRef(r) ? r.value : r(),
405
+ useLocalRef: (init) => ref(init),
406
+ useLocalReactive: (init) => reactive(init)
407
+ };
408
+ function use(source) {
409
+ return __hooks.useValue(source);
410
+ }
411
+ function useLocalRef(init) {
412
+ return __hooks.useLocalRef(init);
413
+ }
414
+ function useLocalReactive(init) {
415
+ return __hooks.useLocalReactive(init);
416
+ }
417
+ function definePage(def) {
418
+ return { __type: "page", ...def };
419
+ }
420
+ function defineGroup(def) {
421
+ return { __type: "group", ...def };
422
+ }
423
+ function defineLayout(Component) {
424
+ return { __type: "layout", Component };
425
+ }
426
+ function defineMiddleware(handler) {
427
+ return { __type: "middleware", handler };
428
+ }
429
+ function defineApiRoute(path, register) {
430
+ return { __type: "api", path, register };
431
+ }
432
+ function resolveRoutes(routes, options = {}) {
433
+ const pages = [];
434
+ const apis = [];
435
+ for (const route of routes) {
436
+ if (route.__type === "api") {
437
+ apis.push({ ...route, path: (options.prefix ?? "") + route.path });
438
+ } else if (route.__type === "group") {
439
+ const prefix = (options.prefix ?? "") + route.prefix;
440
+ const mw = [...options.middleware ?? [], ...route.middleware ?? []];
441
+ const layout = route.layout !== void 0 ? route.layout : options.layout;
442
+ const sub = resolveRoutes(route.routes, { prefix, middleware: mw, layout });
443
+ pages.push(...sub.pages);
444
+ apis.push(...sub.apis);
445
+ } else {
446
+ const fullPath = (options.prefix ?? "") + route.path;
447
+ const layout = route.layout !== void 0 ? route.layout : options.layout;
448
+ const middleware = [...options.middleware ?? [], ...route.middleware ?? []];
449
+ pages.push({ fullPath, page: route, layout, middleware });
450
+ }
451
+ }
452
+ return { pages, apis };
453
+ }
454
+ var SPA_HEADER = "x-fnetro-spa";
455
+ var STATE_KEY = "__FNETRO_STATE__";
456
+ var PARAMS_KEY = "__FNETRO_PARAMS__";
457
+ function hasChanged(a, b) {
458
+ return !Object.is(a, b);
459
+ }
460
+ function hasOwn(obj, key) {
461
+ return Object.prototype.hasOwnProperty.call(obj, key);
462
+ }
463
+
464
+ // client.ts
465
+ function clientUseValue(source) {
466
+ if (isRef(source)) {
467
+ return useSyncExternalStore(
468
+ (notify) => source.subscribe(notify),
469
+ () => source.peek?.() ?? source.value
470
+ );
471
+ }
472
+ const c = useMemo(() => computed(source), [source]);
473
+ return useSyncExternalStore(
474
+ (notify) => c.subscribe(notify),
475
+ () => c.peek?.() ?? c.value
476
+ );
477
+ }
478
+ function clientUseLocalRef(init) {
479
+ const stableRef = useHonoRef(null);
480
+ if (stableRef.current === null) stableRef.current = ref(init);
481
+ const r = stableRef.current;
482
+ useSyncExternalStore(
483
+ (notify) => r.subscribe(notify),
484
+ () => r.peek?.() ?? r.value
485
+ );
486
+ return r;
487
+ }
488
+ function clientUseLocalReactive(init) {
489
+ const stableRef = useHonoRef(null);
490
+ if (stableRef.current === null) stableRef.current = reactive(init);
491
+ const proxy = stableRef.current;
492
+ const [tick, setTick] = useState(0);
493
+ useEffect(() => {
494
+ return watchEffect(() => {
495
+ JSON.stringify(proxy);
496
+ setTick((t) => t + 1);
497
+ });
498
+ }, []);
499
+ return proxy;
500
+ }
501
+ Object.assign(__hooks, {
502
+ useValue: clientUseValue,
503
+ useLocalRef: clientUseLocalRef,
504
+ useLocalReactive: clientUseLocalReactive
505
+ });
506
+ function compileRoute(r) {
507
+ const keys = [];
508
+ const src = r.fullPath.replace(/\[\.\.\.([^\]]+)\]/g, (_, k) => {
509
+ keys.push(k);
510
+ return "(.*)";
511
+ }).replace(/\[([^\]]+)\]/g, (_, k) => {
512
+ keys.push(k);
513
+ return "([^/]+)";
514
+ }).replace(/\*/g, "(.*)");
515
+ return { route: r, re: new RegExp(`^${src}$`), keys };
516
+ }
517
+ function matchRoute(compiled2, pathname) {
518
+ for (const c of compiled2) {
519
+ const m = pathname.match(c.re);
520
+ if (m) {
521
+ const params = {};
522
+ c.keys.forEach((k, i) => {
523
+ params[k] = decodeURIComponent(m[i + 1]);
524
+ });
525
+ return { route: c.route, params };
526
+ }
527
+ }
528
+ return null;
529
+ }
530
+ var beforeNavListeners = [];
531
+ var afterNavListeners = [];
532
+ function onBeforeNavigate(fn) {
533
+ beforeNavListeners.push(fn);
534
+ return () => beforeNavListeners.splice(beforeNavListeners.indexOf(fn), 1);
535
+ }
536
+ function onAfterNavigate(fn) {
537
+ afterNavListeners.push(fn);
538
+ return () => afterNavListeners.splice(afterNavListeners.indexOf(fn), 1);
539
+ }
540
+ var compiled = [];
541
+ var currentConfig;
542
+ var currentLayout;
543
+ var prefetchCache = /* @__PURE__ */ new Map();
544
+ function fetchPage(url) {
545
+ if (!prefetchCache.has(url)) {
546
+ prefetchCache.set(url, fetch(url, {
547
+ headers: { [SPA_HEADER]: "1" }
548
+ }).then((r) => r.json()));
549
+ }
550
+ return prefetchCache.get(url);
551
+ }
552
+ async function renderPage(route, data, url, params) {
553
+ const container = document.getElementById("fnetro-app");
554
+ const pageNode = jsx(route.page.Page, { ...data, url, params });
555
+ const layout = route.layout !== void 0 ? route.layout : currentLayout;
556
+ const tree = layout ? jsx(layout.Component, { url, params, children: pageNode }) : pageNode;
557
+ render(tree, container);
558
+ }
559
+ async function navigate(to, opts = {}) {
560
+ const u = new URL(to, location.origin);
561
+ if (u.origin !== location.origin) {
562
+ location.href = to;
563
+ return;
564
+ }
565
+ for (const fn of beforeNavListeners) await fn(u.pathname);
566
+ const match = matchRoute(compiled, u.pathname);
567
+ if (!match) {
568
+ location.href = to;
569
+ return;
570
+ }
571
+ try {
572
+ const payload = await fetchPage(u.toString());
573
+ const method = opts.replace ? "replaceState" : "pushState";
574
+ history[method]({ url: u.pathname }, "", u.pathname);
575
+ if (opts.scroll !== false) window.scrollTo(0, 0);
576
+ await renderPage(match.route, payload.state ?? {}, u.pathname, payload.params ?? {});
577
+ window[STATE_KEY] = {
578
+ ...window[STATE_KEY],
579
+ [u.pathname]: payload.state ?? {}
580
+ };
581
+ for (const fn of afterNavListeners) await fn(u.pathname);
582
+ } catch (e) {
583
+ console.error("[fnetro] Navigation failed:", e);
584
+ location.href = to;
585
+ }
586
+ }
587
+ function prefetch(url) {
588
+ const u = new URL(url, location.origin);
589
+ if (u.origin !== location.origin) return;
590
+ if (!matchRoute(compiled, u.pathname)) return;
591
+ fetchPage(u.toString());
592
+ }
593
+ function interceptClicks(e) {
594
+ if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
595
+ const a = e.composedPath().find(
596
+ (el) => el instanceof HTMLAnchorElement
597
+ );
598
+ if (!a?.href) return;
599
+ if (a.target && a.target !== "_self") return;
600
+ if (a.hasAttribute("data-no-spa") || a.rel?.includes("external")) return;
601
+ const u = new URL(a.href);
602
+ if (u.origin !== location.origin) return;
603
+ e.preventDefault();
604
+ navigate(a.href);
605
+ }
606
+ function interceptHover(e) {
607
+ const a = e.composedPath().find(
608
+ (el) => el instanceof HTMLAnchorElement
609
+ );
610
+ if (a?.href) prefetch(a.href);
611
+ }
612
+ function onPopState() {
613
+ navigate(location.href, { replace: true, scroll: false });
614
+ }
615
+ async function boot(options) {
616
+ const { pages } = resolveRoutes(options.routes, {
617
+ layout: options.layout,
618
+ middleware: []
619
+ });
620
+ compiled = pages.map(compileRoute);
621
+ currentConfig = options;
622
+ currentLayout = options.layout;
623
+ const pathname = location.pathname;
624
+ const match = matchRoute(compiled, pathname);
625
+ if (!match) {
626
+ console.warn(`[fnetro] No route matched "${pathname}" \u2014 not hydrating`);
627
+ return;
628
+ }
629
+ const stateMap = window[STATE_KEY] ?? {};
630
+ const paramsMap = window[PARAMS_KEY] ?? {};
631
+ const data = stateMap[pathname] ?? {};
632
+ await renderPage(match.route, data, pathname, paramsMap);
633
+ document.addEventListener("click", interceptClicks);
634
+ if (options.prefetchOnHover !== false) {
635
+ document.addEventListener("mouseover", interceptHover);
636
+ }
637
+ window.addEventListener("popstate", onPopState);
638
+ for (const fn of afterNavListeners) await fn(pathname);
639
+ }
640
+ export {
641
+ boot,
642
+ computed,
643
+ defineApiRoute,
644
+ defineGroup,
645
+ defineLayout,
646
+ defineMiddleware,
647
+ definePage,
648
+ effect,
649
+ effectScope,
650
+ isReactive,
651
+ isReadonly,
652
+ isRef,
653
+ markRaw,
654
+ navigate,
655
+ onAfterNavigate,
656
+ onBeforeNavigate,
657
+ prefetch,
658
+ reactive,
659
+ readonly,
660
+ ref,
661
+ shallowReactive,
662
+ shallowRef,
663
+ toRaw,
664
+ toRef,
665
+ toRefs,
666
+ triggerRef,
667
+ unref,
668
+ use,
669
+ useLocalReactive,
670
+ useLocalRef,
671
+ watch,
672
+ watchEffect
673
+ };