@ilha/router 0.8.6 → 0.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/{src-_T1q_MN5.js → src-Dfq3JPRz.js} +186 -32
- package/dist/ssr.js +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { A as wrapLayout, C as routePath, D as src_default, E as serializeHead, M as setHistoryMode, O as useRoute, S as routeParams, T as router, _ as navigating, a as RouterView, b as redirect, c as composeLoaders, d as error, f as head, g as navigate, h as loader, i as RouterLink, j as getHistoryMode, k as wrapError, l as defineLayout, m as isActive, n as LoaderError, o as afterNavigate, p as invalidate, r as Redirect, s as beforeNavigate, t as LOADER_ENDPOINT, u as enableLinkInterception, v as prefetch, w as routeSearch, x as routeHash, y as prime } from "./src-
|
|
1
|
+
import { A as wrapLayout, C as routePath, D as src_default, E as serializeHead, M as setHistoryMode, O as useRoute, S as routeParams, T as router, _ as navigating, a as RouterView, b as redirect, c as composeLoaders, d as error, f as head, g as navigate, h as loader, i as RouterLink, j as getHistoryMode, k as wrapError, l as defineLayout, m as isActive, n as LoaderError, o as afterNavigate, p as invalidate, r as Redirect, s as beforeNavigate, t as LOADER_ENDPOINT, u as enableLinkInterception, v as prefetch, w as routeSearch, x as routeHash, y as prime } from "./src-Dfq3JPRz.js";
|
|
2
2
|
|
|
3
3
|
export { LOADER_ENDPOINT, LoaderError, Redirect, RouterLink, RouterView, afterNavigate, beforeNavigate, composeLoaders, src_default as default, defineLayout, enableLinkInterception, error, getHistoryMode, head, invalidate, isActive, loader, navigate, navigating, prefetch, prime, redirect, routeHash, routeParams, routePath, routeSearch, router, serializeHead, setHistoryMode, useRoute, wrapError, wrapLayout };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import ilha, { ISLAND_MOUNT_INTERNAL, context, html, mount } from "ilha";
|
|
1
|
+
import ilha, { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, context, html, mount } from "ilha";
|
|
2
2
|
import { addRoute, createRouter, findRoute } from "rou3";
|
|
3
3
|
|
|
4
4
|
//#region src/hash.ts
|
|
@@ -310,7 +310,6 @@ function injectKPageSlot(layoutHtml, slotInnerHtml, which) {
|
|
|
310
310
|
const target = which === "innermost" ? spans[spans.length - 1] : spans[0];
|
|
311
311
|
return layoutHtml.slice(0, target.openEnd) + slotInnerHtml + layoutHtml.slice(target.closeStart);
|
|
312
312
|
}
|
|
313
|
-
/** Layout shell HTML with an empty `k:page` — avoids scanning MDX/twoslash inside `Wrapped.toString()`. */
|
|
314
313
|
function layoutHtmlWithEmptyKPage(wrappedLayout, props) {
|
|
315
314
|
const handler = wrappedLayout[WRAP_LAYOUT_HANDLER];
|
|
316
315
|
if (!handler) return wrappedLayout.toString(props);
|
|
@@ -397,6 +396,43 @@ function wrapLayout(layout, page) {
|
|
|
397
396
|
};
|
|
398
397
|
}
|
|
399
398
|
wrapLeafPageMountHooks(leafPage);
|
|
399
|
+
const pageHandles = /* @__PURE__ */ new Map();
|
|
400
|
+
const pageInternalBase = page[ISLAND_MOUNT_INTERNAL];
|
|
401
|
+
if (typeof pageInternalBase === "function") page[ISLAND_MOUNT_INTERNAL] = (host, props) => {
|
|
402
|
+
const handle = pageInternalBase(host, props);
|
|
403
|
+
const entry = {
|
|
404
|
+
handle,
|
|
405
|
+
mountProps: props
|
|
406
|
+
};
|
|
407
|
+
pageHandles.set(host, entry);
|
|
408
|
+
return {
|
|
409
|
+
unmount: () => {
|
|
410
|
+
if (pageHandles.get(host) === entry) pageHandles.delete(host);
|
|
411
|
+
return handle.unmount();
|
|
412
|
+
},
|
|
413
|
+
updateProps: (p) => {
|
|
414
|
+
entry.mountProps = p;
|
|
415
|
+
handle.updateProps(p);
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
};
|
|
419
|
+
/**
|
|
420
|
+
* In-place prop update for one mounted layout instance: refresh the
|
|
421
|
+
* merged-input ref (so any layout re-render passes fresh props to `k:page`),
|
|
422
|
+
* push the merged loader props directly into the page mounted under *this*
|
|
423
|
+
* layout host (spread over its latest slot props so layout-provided extras
|
|
424
|
+
* survive), then update the layout island's own input. Page-first ordering
|
|
425
|
+
* lets a layout that *does* read its input re-render afterwards and win with
|
|
426
|
+
* its own fresher slot props.
|
|
427
|
+
*/
|
|
428
|
+
const layoutUpdateProps = (layoutHost, coreUpdate) => (p) => {
|
|
429
|
+
setLayoutMergedInput(p);
|
|
430
|
+
for (const [pageHost, entry] of pageHandles) if (layoutHost.contains(pageHost)) entry.handle.updateProps({
|
|
431
|
+
...entry.mountProps ?? {},
|
|
432
|
+
...p ?? {}
|
|
433
|
+
});
|
|
434
|
+
coreUpdate?.(p);
|
|
435
|
+
};
|
|
400
436
|
const layoutMount = Wrapped.mount.bind(Wrapped);
|
|
401
437
|
const layoutInternal = Wrapped[ISLAND_MOUNT_INTERNAL];
|
|
402
438
|
function prepareLayoutMountHost(host) {
|
|
@@ -405,16 +441,27 @@ function wrapLayout(layout, page) {
|
|
|
405
441
|
Wrapped.mount = (host, props) => {
|
|
406
442
|
setLayoutMergedInput(props);
|
|
407
443
|
prepareLayoutMountHost(host);
|
|
408
|
-
|
|
444
|
+
const unmount = layoutMount(host, props);
|
|
445
|
+
const core = ISLAND_MOUNT_HANDLES.get(host);
|
|
446
|
+
ISLAND_MOUNT_HANDLES.set(host, {
|
|
447
|
+
unmount,
|
|
448
|
+
updateProps: layoutUpdateProps(host, core?.updateProps)
|
|
449
|
+
});
|
|
450
|
+
return unmount;
|
|
409
451
|
};
|
|
410
452
|
Wrapped[ISLAND_MOUNT_INTERNAL] = (host, props) => {
|
|
411
453
|
setLayoutMergedInput(props);
|
|
412
454
|
prepareLayoutMountHost(host);
|
|
413
|
-
|
|
414
|
-
return {
|
|
455
|
+
const base = typeof layoutInternal === "function" ? layoutInternal(host, props) : {
|
|
415
456
|
unmount: layoutMount(host, props),
|
|
416
457
|
updateProps: () => {}
|
|
417
458
|
};
|
|
459
|
+
const enhanced = {
|
|
460
|
+
unmount: base.unmount,
|
|
461
|
+
updateProps: layoutUpdateProps(host, base.updateProps)
|
|
462
|
+
};
|
|
463
|
+
ISLAND_MOUNT_HANDLES.set(host, enhanced);
|
|
464
|
+
return enhanced;
|
|
418
465
|
};
|
|
419
466
|
Wrapped.hydratable = async (props, opts) => {
|
|
420
467
|
if (!opts?.name) throw new Error("wrapLayout: hydratable requires options.name");
|
|
@@ -644,6 +691,51 @@ function prefetch(pathWithSearch) {
|
|
|
644
691
|
expires: Date.now() + PREFETCH_TTL_MS
|
|
645
692
|
});
|
|
646
693
|
}
|
|
694
|
+
const noopRouteHandle = () => ({
|
|
695
|
+
unmount: () => {},
|
|
696
|
+
updateProps: null
|
|
697
|
+
});
|
|
698
|
+
/** Mount an island keeping the full internal handle so later same-island
|
|
699
|
+
* navigations can push new loader props instead of remounting. */
|
|
700
|
+
function mountIslandWithHandle(island, host, props) {
|
|
701
|
+
const internal = island[ISLAND_MOUNT_INTERNAL];
|
|
702
|
+
if (typeof internal === "function") {
|
|
703
|
+
const h = internal(host, props);
|
|
704
|
+
return {
|
|
705
|
+
unmount: () => void h.unmount(),
|
|
706
|
+
updateProps: (p) => h.updateProps(p)
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
return {
|
|
710
|
+
unmount: island.mount(host, props),
|
|
711
|
+
updateProps: null
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Same-island fast path: fetch fresh loader data and push it into the mounted
|
|
716
|
+
* island via `updateProps` — ilha's fine-grained morph reconciles the DOM, so
|
|
717
|
+
* focus, caret, selection, and scroll survive (the reason persistQuery-driven
|
|
718
|
+
* filter inputs don't blur while typing). Returns "updated" when applied (or
|
|
719
|
+
* redirected), "remount" when the caller must run the full teardown + mount
|
|
720
|
+
* path (loader error / not-found need boundary DOM; the full path re-fetches,
|
|
721
|
+
* accepted for these rare cases). Throws AbortError when superseded.
|
|
722
|
+
*/
|
|
723
|
+
async function updateRouteInPlace(handle, pathWithSearch, signal) {
|
|
724
|
+
if (!handle.updateProps) return "remount";
|
|
725
|
+
const result = !!findRoute(_rou3, "GET", pathWithSearch.split("?")[0] ?? "")?.data?.hasLoader ? await fetchLoaderData(pathWithSearch, signal) : {
|
|
726
|
+
kind: "data",
|
|
727
|
+
data: {}
|
|
728
|
+
};
|
|
729
|
+
signal.throwIfAborted();
|
|
730
|
+
if (result.kind === "redirect") {
|
|
731
|
+
clientRedirect(result.to);
|
|
732
|
+
return "updated";
|
|
733
|
+
}
|
|
734
|
+
if (result.kind !== "data") return "remount";
|
|
735
|
+
if (result.headEntries?.length) applyHeadEntriesToDocument([...result.headEntries]);
|
|
736
|
+
handle.updateProps(result.data);
|
|
737
|
+
return "updated";
|
|
738
|
+
}
|
|
647
739
|
/**
|
|
648
740
|
* Mounts a route island with proper hydration for client-side navigation.
|
|
649
741
|
* Looks up the island in the reverse registry, runs the loader (via fetch),
|
|
@@ -656,13 +748,16 @@ async function mountRouteWithHydration(island, host, pathWithSearch, signal, reg
|
|
|
656
748
|
return withViewSwap(() => {
|
|
657
749
|
host.innerHTML = `<div data-router-view data-router-not-found>${nf.toString()}</div>`;
|
|
658
750
|
const nfHost = host.firstElementChild;
|
|
659
|
-
return
|
|
751
|
+
return {
|
|
752
|
+
unmount: nfHost ? nf.mount(nfHost) : () => {},
|
|
753
|
+
updateProps: null
|
|
754
|
+
};
|
|
660
755
|
});
|
|
661
756
|
}
|
|
662
757
|
await withViewSwap(() => {
|
|
663
758
|
host.innerHTML = `<div data-router-empty></div>`;
|
|
664
759
|
});
|
|
665
|
-
return ()
|
|
760
|
+
return noopRouteHandle();
|
|
666
761
|
}
|
|
667
762
|
const clientMatch = findRoute(_rou3, "GET", pathWithSearch.split("?")[0] ?? "");
|
|
668
763
|
const hasLoader = !!clientMatch?.data?.hasLoader;
|
|
@@ -673,22 +768,25 @@ async function mountRouteWithHydration(island, host, pathWithSearch, signal, reg
|
|
|
673
768
|
};
|
|
674
769
|
if (loaderResult.kind === "redirect") {
|
|
675
770
|
clientRedirect(loaderResult.to);
|
|
676
|
-
return ()
|
|
771
|
+
return noopRouteHandle();
|
|
677
772
|
}
|
|
678
773
|
if (loaderResult.kind === "error") {
|
|
679
774
|
const boundary = clientMatch?.data?.errorHandler;
|
|
680
|
-
if (boundary) return withViewSwap(() =>
|
|
775
|
+
if (boundary) return withViewSwap(() => ({
|
|
776
|
+
unmount: mountLoaderErrorBoundary(boundary, host, loaderResult.status, loaderResult.message),
|
|
777
|
+
updateProps: null
|
|
778
|
+
}));
|
|
681
779
|
const escaped = escapeHtml(loaderResult.message);
|
|
682
780
|
await withViewSwap(() => {
|
|
683
781
|
host.innerHTML = `<div data-router-view data-router-error="${loaderResult.status}">${escaped}</div>`;
|
|
684
782
|
});
|
|
685
|
-
return ()
|
|
783
|
+
return noopRouteHandle();
|
|
686
784
|
}
|
|
687
785
|
if (loaderResult.kind === "not-found") {
|
|
688
786
|
await withViewSwap(() => {
|
|
689
787
|
host.innerHTML = `<div data-router-empty></div>`;
|
|
690
788
|
});
|
|
691
|
-
return ()
|
|
789
|
+
return noopRouteHandle();
|
|
692
790
|
}
|
|
693
791
|
props = loaderResult.data;
|
|
694
792
|
const headStore = { entries: [...loaderResult.headEntries ?? []] };
|
|
@@ -699,7 +797,7 @@ async function mountRouteWithHydration(island, host, pathWithSearch, signal, reg
|
|
|
699
797
|
applyHeadEntriesToDocument(headStore.entries);
|
|
700
798
|
host.innerHTML = `<div data-router-view>${html}</div>`;
|
|
701
799
|
});
|
|
702
|
-
return ()
|
|
800
|
+
return noopRouteHandle();
|
|
703
801
|
}
|
|
704
802
|
const name = reverseRegistry?.get(island) ?? Object.entries(registry).find(([, v]) => v === island)?.[0];
|
|
705
803
|
if (!name) {
|
|
@@ -709,7 +807,7 @@ async function mountRouteWithHydration(island, host, pathWithSearch, signal, reg
|
|
|
709
807
|
applyHeadEntriesToDocument(headStore.entries);
|
|
710
808
|
host.innerHTML = `<div data-router-view>${html}</div>`;
|
|
711
809
|
});
|
|
712
|
-
return ()
|
|
810
|
+
return noopRouteHandle();
|
|
713
811
|
}
|
|
714
812
|
const html = await withHeadStore(headStore, () => island.hydratable(props, {
|
|
715
813
|
name,
|
|
@@ -720,7 +818,7 @@ async function mountRouteWithHydration(island, host, pathWithSearch, signal, reg
|
|
|
720
818
|
applyHeadEntriesToDocument(headStore.entries);
|
|
721
819
|
host.innerHTML = `<div data-router-view>${html}</div>`;
|
|
722
820
|
const islandHost = host.querySelector(`[data-ilha="${name}"]`);
|
|
723
|
-
return islandHost ? island
|
|
821
|
+
return islandHost ? mountIslandWithHandle(island, islandHost) : noopRouteHandle();
|
|
724
822
|
});
|
|
725
823
|
}
|
|
726
824
|
/** Render + mount a `+error` boundary island for a failed loader. */
|
|
@@ -964,7 +1062,12 @@ function navigate(to, opts = {}) {
|
|
|
964
1062
|
}
|
|
965
1063
|
_lastNavKey = currentNavKey();
|
|
966
1064
|
syncRouteFromLocation();
|
|
967
|
-
if (opts.scroll !== false)
|
|
1065
|
+
if (opts.scroll !== false) {
|
|
1066
|
+
const dest = adapter.readLocation();
|
|
1067
|
+
const fromMatch = findRoute(_rou3, "GET", cur.pathname);
|
|
1068
|
+
const destMatch = findRoute(_rou3, "GET", dest.pathname);
|
|
1069
|
+
if (!(fromMatch?.data?.island != null && destMatch?.data?.island === fromMatch.data.island) || dest.hash && dest.hash !== "#") scrollAfterNavigate(dest.hash);
|
|
1070
|
+
}
|
|
968
1071
|
runAfterNavigateHooks({
|
|
969
1072
|
from: current,
|
|
970
1073
|
to,
|
|
@@ -1539,6 +1642,16 @@ function router(options = {}) {
|
|
|
1539
1642
|
const viewHost = host.querySelector("[data-router-view]") ?? host;
|
|
1540
1643
|
let currentMountedIsland = activeIsland();
|
|
1541
1644
|
let currentMountedPath = routePath() + routeSearch();
|
|
1645
|
+
let viewHandle = null;
|
|
1646
|
+
const adoptHydratedHandle = () => {
|
|
1647
|
+
const el = viewHost.querySelector("[data-ilha]");
|
|
1648
|
+
if (!el) return null;
|
|
1649
|
+
const h = ISLAND_MOUNT_HANDLES.get(el);
|
|
1650
|
+
return h ? {
|
|
1651
|
+
unmount: () => void h.unmount(),
|
|
1652
|
+
updateProps: (p) => h.updateProps(p)
|
|
1653
|
+
} : null;
|
|
1654
|
+
};
|
|
1542
1655
|
const reverseRegistry = registry ? buildReverseRegistry(registry) : void 0;
|
|
1543
1656
|
let navVersion = 0;
|
|
1544
1657
|
const NavHandler = ilha.render(() => {
|
|
@@ -1552,10 +1665,20 @@ function router(options = {}) {
|
|
|
1552
1665
|
queueMicrotask(async () => {
|
|
1553
1666
|
if (thisNav !== navVersion) return;
|
|
1554
1667
|
const settle = beginNavigation();
|
|
1555
|
-
unmountView?.();
|
|
1556
|
-
unmountView = null;
|
|
1557
1668
|
try {
|
|
1558
|
-
|
|
1669
|
+
if (current !== null && current === currentMountedIsland) {
|
|
1670
|
+
const handle = viewHandle ?? adoptHydratedHandle();
|
|
1671
|
+
if (handle?.updateProps) {
|
|
1672
|
+
if (await updateRouteInPlace(handle, pathWithSearch, signal) === "updated") {
|
|
1673
|
+
viewHandle = handle;
|
|
1674
|
+
currentMountedPath = pathWithSearch;
|
|
1675
|
+
return;
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
viewHandle?.unmount();
|
|
1680
|
+
viewHandle = null;
|
|
1681
|
+
viewHandle = await mountRouteWithHydration(current, viewHost, pathWithSearch, signal, registry, reverseRegistry);
|
|
1559
1682
|
} catch (e) {
|
|
1560
1683
|
if (e?.name === "AbortError") return;
|
|
1561
1684
|
console.error("[ilha-router] navigation failed:", e);
|
|
@@ -1586,8 +1709,8 @@ function router(options = {}) {
|
|
|
1586
1709
|
navAbort = ac;
|
|
1587
1710
|
try {
|
|
1588
1711
|
const um = await mountRouteWithHydration(island, viewHost, pathWithSearch, ac.signal, registry, reverseRegistry);
|
|
1589
|
-
if (thisNav === navVersion)
|
|
1590
|
-
else um();
|
|
1712
|
+
if (thisNav === navVersion) viewHandle = um;
|
|
1713
|
+
else um.unmount();
|
|
1591
1714
|
} catch (e) {
|
|
1592
1715
|
if (e?.name !== "AbortError") console.error("[ilha-router] initial client loader render failed:", e);
|
|
1593
1716
|
}
|
|
@@ -1614,13 +1737,25 @@ function router(options = {}) {
|
|
|
1614
1737
|
try {
|
|
1615
1738
|
const loc = getAdapter().readLocation();
|
|
1616
1739
|
const pathWithSearch = loc.pathname + loc.search;
|
|
1740
|
+
if (island !== null && island === currentMountedIsland) {
|
|
1741
|
+
const handle = viewHandle ?? adoptHydratedHandle();
|
|
1742
|
+
if (handle?.updateProps) {
|
|
1743
|
+
if (await updateRouteInPlace(handle, pathWithSearch, ac.signal) === "updated") {
|
|
1744
|
+
if (thisNav === navVersion) {
|
|
1745
|
+
viewHandle = handle;
|
|
1746
|
+
currentMountedPath = pathWithSearch;
|
|
1747
|
+
}
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1617
1752
|
const um = await mountRouteWithHydration(island, viewHost, pathWithSearch, ac.signal, registry, reverseRegistry);
|
|
1618
1753
|
if (thisNav === navVersion) {
|
|
1619
|
-
|
|
1620
|
-
|
|
1754
|
+
viewHandle?.unmount();
|
|
1755
|
+
viewHandle = um;
|
|
1621
1756
|
currentMountedIsland = island;
|
|
1622
1757
|
currentMountedPath = pathWithSearch;
|
|
1623
|
-
} else um();
|
|
1758
|
+
} else um.unmount();
|
|
1624
1759
|
} catch (e) {
|
|
1625
1760
|
if (e?.name !== "AbortError") console.error("[ilha-router] invalidate failed:", e);
|
|
1626
1761
|
} finally {
|
|
@@ -1634,7 +1769,7 @@ function router(options = {}) {
|
|
|
1634
1769
|
navAbort?.abort();
|
|
1635
1770
|
unmountNavHandler();
|
|
1636
1771
|
navHost.remove();
|
|
1637
|
-
|
|
1772
|
+
viewHandle?.unmount();
|
|
1638
1773
|
_linkCleanup?.();
|
|
1639
1774
|
_navChangeCleanup?.();
|
|
1640
1775
|
_linkCleanup = null;
|
|
@@ -1642,7 +1777,8 @@ function router(options = {}) {
|
|
|
1642
1777
|
if (prevScrollRestoration !== null) history.scrollRestoration = prevScrollRestoration;
|
|
1643
1778
|
};
|
|
1644
1779
|
}
|
|
1645
|
-
let
|
|
1780
|
+
let mountedHandle = null;
|
|
1781
|
+
let mountedHandleIsland = null;
|
|
1646
1782
|
let currentMountedIsland = null;
|
|
1647
1783
|
let currentMountedPath = null;
|
|
1648
1784
|
let navVersion = 0;
|
|
@@ -1653,13 +1789,21 @@ function router(options = {}) {
|
|
|
1653
1789
|
* render would have no access to loader data.
|
|
1654
1790
|
*/
|
|
1655
1791
|
async function mountActiveIsland(island, signal) {
|
|
1656
|
-
|
|
1657
|
-
|
|
1792
|
+
const sameIsland = island !== null && island === mountedHandleIsland && mountedHandle?.updateProps != null;
|
|
1793
|
+
const teardown = () => {
|
|
1794
|
+
mountedHandle?.unmount();
|
|
1795
|
+
mountedHandle = null;
|
|
1796
|
+
mountedHandleIsland = null;
|
|
1797
|
+
};
|
|
1798
|
+
if (!sameIsland) teardown();
|
|
1658
1799
|
currentMountedIsland = island;
|
|
1659
1800
|
currentMountedPath = routePath() + routeSearch();
|
|
1660
1801
|
if (!island) {
|
|
1661
1802
|
const nfHost = host?.querySelector("[data-router-not-found]");
|
|
1662
|
-
if (_notFound && nfHost)
|
|
1803
|
+
if (_notFound && nfHost) mountedHandle = {
|
|
1804
|
+
unmount: _notFound.mount(nfHost),
|
|
1805
|
+
updateProps: null
|
|
1806
|
+
};
|
|
1663
1807
|
return;
|
|
1664
1808
|
}
|
|
1665
1809
|
const viewHost = host?.querySelector("[data-router-view]");
|
|
@@ -1676,9 +1820,13 @@ function router(options = {}) {
|
|
|
1676
1820
|
return;
|
|
1677
1821
|
}
|
|
1678
1822
|
if (result.kind === "error") {
|
|
1823
|
+
if (sameIsland) teardown();
|
|
1679
1824
|
const boundary = clientMatch?.data?.errorHandler;
|
|
1680
1825
|
if (boundary) {
|
|
1681
|
-
|
|
1826
|
+
mountedHandle = await withViewSwap(() => ({
|
|
1827
|
+
unmount: mountLoaderErrorBoundary(boundary, viewHost, result.status, result.message),
|
|
1828
|
+
updateProps: null
|
|
1829
|
+
}));
|
|
1682
1830
|
return;
|
|
1683
1831
|
}
|
|
1684
1832
|
const escaped = escapeHtml(result.message);
|
|
@@ -1688,13 +1836,19 @@ function router(options = {}) {
|
|
|
1688
1836
|
return;
|
|
1689
1837
|
}
|
|
1690
1838
|
const props = result.kind === "data" ? result.data : {};
|
|
1839
|
+
if (sameIsland && mountedHandle?.updateProps) {
|
|
1840
|
+
if (result.kind === "data" && result.headEntries?.length) applyHeadEntriesToDocument([...result.headEntries]);
|
|
1841
|
+
mountedHandle.updateProps(props);
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1691
1844
|
const headStore = { entries: [...result.kind === "data" ? result.headEntries ?? [] : []] };
|
|
1692
1845
|
const html = await withHeadStore(headStore, () => island.toString(props));
|
|
1693
|
-
|
|
1846
|
+
mountedHandle = await withViewSwap(() => {
|
|
1694
1847
|
applyHeadEntriesToDocument(headStore.entries);
|
|
1695
1848
|
viewHost.innerHTML = html;
|
|
1696
|
-
return island
|
|
1849
|
+
return mountIslandWithHandle(island, viewHost, props);
|
|
1697
1850
|
});
|
|
1851
|
+
mountedHandleIsland = island;
|
|
1698
1852
|
}
|
|
1699
1853
|
navAbort = new AbortController();
|
|
1700
1854
|
mountActiveIsland(activeIsland(), navAbort.signal).catch((e) => {
|
|
@@ -1742,7 +1896,7 @@ function router(options = {}) {
|
|
|
1742
1896
|
++navVersion;
|
|
1743
1897
|
_revalidate = null;
|
|
1744
1898
|
navAbort?.abort();
|
|
1745
|
-
|
|
1899
|
+
mountedHandle?.unmount();
|
|
1746
1900
|
unmountNavHandler();
|
|
1747
1901
|
navHost.remove();
|
|
1748
1902
|
unmountView?.();
|
package/dist/ssr.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ilha/router",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.8",
|
|
4
4
|
"description": "A tiny SPA router for Ilha",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"frontend",
|
|
@@ -68,10 +68,10 @@
|
|
|
68
68
|
"unplugin": "3.3.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"ilha": "0.9.
|
|
71
|
+
"ilha": "0.9.4",
|
|
72
72
|
"vite": "^8.1.3"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
|
-
"ilha": ">=0.9.
|
|
75
|
+
"ilha": ">=0.9.4"
|
|
76
76
|
}
|
|
77
77
|
}
|