@voltro/web 0.50.1 → 0.52.0
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/CHANGELOG.md +231 -0
- package/dist/{defaultFallbacks-B4Ak-R6R.js → defaultFallbacks-SQ45vAhz.js} +1 -1
- package/dist/{frameworkBoot-CV_o2tIk.js → frameworkBoot-CnE9vzLQ.js} +2 -2
- package/dist/frameworkBoot.js +1 -1
- package/dist/globalContext-AuflFFmy.js +2 -0
- package/dist/hooks.js +1 -1
- package/dist/index.d.ts +143 -31
- package/dist/index.js +10 -9
- package/dist/islands.d.ts +66 -0
- package/dist/islands.js +60 -0
- package/dist/mount.js +37 -2
- package/dist/{serverContext-38JTbYPa.js → serverContext-CzmZZwuQ.js} +352 -282
- package/dist/ssr.d.ts +6 -10
- package/dist/ssr.js +10 -9
- package/package.json +9 -4
- package/dist/globalContext-d4A-ugDg.js +0 -10
- package/dist/mount-nudb4UCl.js +0 -81
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { t as e } from "./globalContext-
|
|
1
|
+
import { t as e } from "./globalContext-AuflFFmy.js";
|
|
2
2
|
import { AppClientsContext as t, useAppClient as n } from "./hooks.js";
|
|
3
|
-
import { a as r, c as i, i as a, l as o, o as s, r as c, s as l, u } from "./frameworkBoot-
|
|
4
|
-
import { a as d, c as f, i as p, l as m, o as h, u as g } from "./defaultFallbacks-
|
|
5
|
-
import {
|
|
6
|
-
import { c as
|
|
7
|
-
import {
|
|
3
|
+
import { a as r, c as i, i as a, l as o, o as s, r as c, s as l, u } from "./frameworkBoot-CnE9vzLQ.js";
|
|
4
|
+
import { a as d, c as f, i as p, l as m, o as h, u as g } from "./defaultFallbacks-SQ45vAhz.js";
|
|
5
|
+
import { getIslandComponent as _, hydrateIslandsOnPage as ee, island as te } from "./islands.js";
|
|
6
|
+
import { c as ne, d as re, h as ie, l as ae, p as oe, u as se } from "./routerState-DAT472IC.js";
|
|
7
|
+
import { mount as ce, noticeIslandsShipTheFullBundle as le } from "./mount.js";
|
|
8
|
+
import { A as ue, B as de, C as fe, D as pe, E as me, F as he, G as ge, H as _e, I as v, K as y, L as b, M as x, N as S, O as C, P as w, R as T, S as E, T as D, U as O, V as k, W as A, _ as j, a as M, b as N, c as P, d as F, f as I, g as ve, h as ye, i as be, j as xe, k as Se, l as Ce, m as we, n as Te, o as Ee, p as De, q as Oe, r as ke, s as Ae, t as je, u as Me, v as Ne, w as Pe, x as Fe, y as Ie, z as Le } from "./serverContext-CzmZZwuQ.js";
|
|
8
9
|
import { Component as Re, Suspense as ze, createElement as L, use as Be, useCallback as Ve, useContext as He, useSyncExternalStore as Ue } from "react";
|
|
9
10
|
import { Fragment as R, jsx as z, jsxs as B } from "react/jsx-runtime";
|
|
10
11
|
export * from "@voltro/client";
|
|
@@ -21,8 +22,8 @@ var We = ({ value: e, fallback: t, children: n, errorFallback: r }) => /* @__PUR
|
|
|
21
22
|
})
|
|
22
23
|
})
|
|
23
24
|
}), V = ({ body: e }) => /* @__PURE__ */ z("script", { dangerouslySetInnerHTML: { __html: e } }), Ge = ({ value: e, errorFallback: t, children: n }) => {
|
|
24
|
-
let r = Be(e), i =
|
|
25
|
-
return a === void 0 ? /* @__PURE__ */ B(R, { children: [i === void 0 ? null : /* @__PURE__ */ z(V, { body:
|
|
25
|
+
let r = Be(e), i = se(e), a = ie(r);
|
|
26
|
+
return a === void 0 ? /* @__PURE__ */ B(R, { children: [i === void 0 ? null : /* @__PURE__ */ z(V, { body: re(i, r) }), n(r)] }) : /* @__PURE__ */ B(R, { children: [i === void 0 ? null : /* @__PURE__ */ z(V, { body: ae(i, a) }), t] });
|
|
26
27
|
}, Ke = class extends Re {
|
|
27
28
|
state = { error: void 0 };
|
|
28
29
|
static getDerivedStateFromError(e) {
|
|
@@ -231,4 +232,4 @@ var We = ({ value: e, fallback: t, children: n, errorFallback: r }) => /* @__PUR
|
|
|
231
232
|
};
|
|
232
233
|
}, ct = "framework-web";
|
|
233
234
|
//#endregion
|
|
234
|
-
export { t as AppClientsContext, We as Await, $e as BlogLayout, p as FallbackStringsProvider, Ye as Image, qe as ImageConfigProvider,
|
|
235
|
+
export { t as AppClientsContext, We as Await, $e as BlogLayout, p as FallbackStringsProvider, Ye as Image, qe as ImageConfigProvider, ke as Link, be as LoaderCache, M as LoaderDataContext, Ee as NO_LOADER_DATA, i as NavigationIndicator, Le as NotFoundError, Ae as PAGE_SLOT_ATTR, P as PageSlot, Ce as PlainLink, Me as RENDER_MODES, o as ReconnectContext, de as RedirectError, F as Router, I as RouterContext, Y as THEME_COOKIE, ct as WEB_NAME, J as canonicalUrl, De as compileRoute, v as decodeSearchParams, d as defaultFallbackStrings, ne as defer, b as encodeSearchParams, we as externalUrl, ye as findNotFound, c as formatPrintf, _ as getIslandComponent, ge as getRouteSnapshot, f as getStatuses, ee as hydrateIslandsOnPage, a as installBrowserConsoleBridge, r as installServerLogRelay, oe as isDeferredLoaderResult, k as isNotFound, _e as isRedirect, te as island, K as joinUrl, ve as lazyPageRoute, j as loaderCacheKey, q as localizedPath, Ne as matchRoute, ce as mount, G as normalizePath, O as notFound, le as noticeIslandsShipTheFullBundle, Ie as pageRoute, je as parseCookieHeader, H as passthroughImageLoader, N as preloadRouteModule, m as pushStatus, A as redirect, s as registerClientTrace, Fe as renderRouterProviderTree, E as resolveAnchorNavigation, fe as resolveMeta, T as searchParamsToObject, Pe as segmentLoaderKey, et as seoAlternates, y as setRouteSnapshot, D as sortRoutesByPriority, Oe as subscribeRouteSnapshot, g as subscribeStatuses, l as subscribeTraceErrors, n as useAppClient, me as useBlocker, h as useFallbackStrings, pe as useLoaderData, C as useLocation, Se as useNavigate, ue as useOptionalLoaderData, xe as useParams, x as usePrefetch, u as useReconnect, Te as useSearchParams, S as useSetSearchParams, st as useTheme, w as withHash, he as withQuery };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Look up a registered island Component by name. Returns undefined if
|
|
6
|
+
* the name isn't registered (typically means the user forgot to import
|
|
7
|
+
* the island file in this bundle).
|
|
8
|
+
*/
|
|
9
|
+
export declare const getIslandComponent: (name: string) => ComponentType<unknown> | undefined;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Client-side runtime: scan the document for `[data-voltro-island]`
|
|
13
|
+
* markers and schedule each for hydration per its strategy. Called by the
|
|
14
|
+
* per-page islands entry, and by `@voltro/web/mount` when an islands page
|
|
15
|
+
* is reached through the full app bundle (SPA navigation). Idempotent —
|
|
16
|
+
* running twice is a no-op (we mark elements as visited).
|
|
17
|
+
*/
|
|
18
|
+
export declare const hydrateIslandsOnPage: (options?: HydrateIslandsOptions) => void;
|
|
19
|
+
|
|
20
|
+
export declare interface HydrateIslandsOptions {
|
|
21
|
+
/** Wrap every island root — the per-page islands entry of a page whose
|
|
22
|
+
* islands use framework hooks passes a `<VoltroRuntimeProvider>` here so
|
|
23
|
+
* a `useSubscription` island gets a live runtime. Purely presentational
|
|
24
|
+
* entries pass nothing and never load the client core. */
|
|
25
|
+
readonly wrap?: (children: ReactNode) => ReactNode;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export declare type HydrateStrategy =
|
|
29
|
+
/** Hydrate as soon as the client runtime mounts (after main script load). */
|
|
30
|
+
'load'
|
|
31
|
+
/** Hydrate when the browser is idle (via `requestIdleCallback`, with a
|
|
32
|
+
* setTimeout fallback for browsers that lack it). */
|
|
33
|
+
| 'idle'
|
|
34
|
+
/** Hydrate when the element scrolls into the viewport (IntersectionObserver). */
|
|
35
|
+
| 'visible'
|
|
36
|
+
/** Hydrate on the first pointer / keyboard interaction with the element. */
|
|
37
|
+
| 'interaction'
|
|
38
|
+
/** Never hydrate. Useful for fully-static islands (e.g. SSR-only data
|
|
39
|
+
* display that never changes). */
|
|
40
|
+
| 'never'
|
|
41
|
+
/** CLIENT-ONLY: the server renders an empty placeholder (never the
|
|
42
|
+
* component — a browser-only lib touching `window` in render would
|
|
43
|
+
* crash the SSR pass), and the client mounts fresh with `createRoot`
|
|
44
|
+
* instead of hydrating. Astro's `client:only`. */
|
|
45
|
+
| 'only';
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Wrap a Component as an island. The returned Component renders the
|
|
49
|
+
* inner content wrapped in a marker `<div data-voltro-island>` that
|
|
50
|
+
* carries the island's name + props + hydrate strategy. The same
|
|
51
|
+
* call also registers the Component under its name so the client
|
|
52
|
+
* runtime can find it when hydrating.
|
|
53
|
+
*/
|
|
54
|
+
export declare const island: <P extends Record<string, unknown>>(Component: ComponentType<P>, options: IslandOptions) => ComponentType<P>;
|
|
55
|
+
|
|
56
|
+
export declare interface IslandOptions {
|
|
57
|
+
/** Stable id of this island. Must be unique within an app. The framework
|
|
58
|
+
* uses it to match the server-rendered marker with the client-side
|
|
59
|
+
* Component. */
|
|
60
|
+
readonly name: string;
|
|
61
|
+
/** When the client runtime should hydrate this island. Defaults to
|
|
62
|
+
* `visible` — matches Astro's default and is the best perf/UX balance. */
|
|
63
|
+
readonly hydrate?: HydrateStrategy;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { }
|
package/dist/islands.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createElement as e } from "react";
|
|
2
|
+
import { createRoot as t, hydrateRoot as n } from "react-dom/client";
|
|
3
|
+
//#region src/islands.tsx
|
|
4
|
+
var r = /* @__PURE__ */ new Map(), i = (t, n) => {
|
|
5
|
+
r.set(n.name, t);
|
|
6
|
+
let i = n.hydrate ?? "visible", a = (r) => e("div", {
|
|
7
|
+
"data-voltro-island": "",
|
|
8
|
+
"data-island-name": n.name,
|
|
9
|
+
"data-island-hydrate": i,
|
|
10
|
+
"data-island-props": o(r, n.name)
|
|
11
|
+
}, i === "only" ? null : e(t, r));
|
|
12
|
+
return a.displayName = `Island(${n.name})`, a;
|
|
13
|
+
}, a = (e) => r.get(e), o = (e, t) => {
|
|
14
|
+
if (process.env.NODE_ENV !== "production" && typeof e == "object" && e) for (let [n, r] of Object.entries(e)) {
|
|
15
|
+
let e = typeof r == "function" ? "a function" : r instanceof Date ? "a Date (arrives as an ISO string)" : r instanceof Map || r instanceof Set ? "a Map/Set (arrives as {})" : void 0;
|
|
16
|
+
e !== void 0 && console.warn(`[voltro] island "${t}" prop "${n}" is ${e} — island props cross an HTML attribute as JSON. Pass a JSON shape (string/number/boolean/array/plain object) and reconstruct richer types inside the island.`);
|
|
17
|
+
}
|
|
18
|
+
return JSON.stringify(e ?? {}).replace(/</g, "\\u003c");
|
|
19
|
+
}, s = (e) => {
|
|
20
|
+
if (!e) return {};
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(e);
|
|
23
|
+
} catch {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
}, c = (i) => {
|
|
27
|
+
let a = document.querySelectorAll("[data-voltro-island]:not([data-voltro-hydrated])");
|
|
28
|
+
for (let o of a) {
|
|
29
|
+
let a = o.dataset.islandName ?? "", c = r.get(a);
|
|
30
|
+
if (!c) {
|
|
31
|
+
console.warn(`[voltro] island "${a}" referenced in DOM but not registered. Did the island file get imported in this bundle?`);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
let l = s(o.dataset.islandProps ?? null), u = o.dataset.islandHydrate ?? "visible";
|
|
35
|
+
o.setAttribute("data-voltro-hydrated", "pending");
|
|
36
|
+
let d = () => {
|
|
37
|
+
if (o.getAttribute("data-voltro-hydrated") === "done") return;
|
|
38
|
+
o.setAttribute("data-voltro-hydrated", "done");
|
|
39
|
+
let r = i?.wrap === void 0 ? e(c, l) : i.wrap(e(c, l));
|
|
40
|
+
u === "only" ? t(o).render(r) : n(o, r);
|
|
41
|
+
};
|
|
42
|
+
if (u === "load" || u === "only") d();
|
|
43
|
+
else if (u === "idle") {
|
|
44
|
+
let e = globalThis.requestIdleCallback;
|
|
45
|
+
e ? e(d) : setTimeout(d, 0);
|
|
46
|
+
} else if (u === "visible") {
|
|
47
|
+
let e = new IntersectionObserver((t) => {
|
|
48
|
+
t.some((e) => e.isIntersecting) && (e.disconnect(), d());
|
|
49
|
+
}, { rootMargin: "64px" });
|
|
50
|
+
e.observe(o);
|
|
51
|
+
} else if (u === "interaction") {
|
|
52
|
+
let e = () => {
|
|
53
|
+
o.removeEventListener("pointerdown", e), o.removeEventListener("keydown", e), d();
|
|
54
|
+
};
|
|
55
|
+
o.addEventListener("pointerdown", e, { passive: !0 }), o.addEventListener("keydown", e);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
export { a as getIslandComponent, c as hydrateIslandsOnPage, i as island };
|
package/dist/mount.js
CHANGED
|
@@ -1,2 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { t as e } from "./frameworkBoot-CnE9vzLQ.js";
|
|
2
|
+
import { hydrateIslandsOnPage as t } from "./islands.js";
|
|
3
|
+
import { o as n, r, t as i } from "./routerState-DAT472IC.js";
|
|
4
|
+
import { StrictMode as a } from "react";
|
|
5
|
+
import { createRoot as o, hydrateRoot as s } from "react-dom/client";
|
|
6
|
+
import { applyPreloadSeeds as c, applyStoreSeeds as l } from "@voltro/client";
|
|
7
|
+
import { jsx as u } from "react/jsx-runtime";
|
|
8
|
+
//#region src/mount.tsx
|
|
9
|
+
var d = () => !1, f = "__voltroIslandsBundleNoticeShown", p = (e) => {
|
|
10
|
+
if (!e) return;
|
|
11
|
+
let t = globalThis;
|
|
12
|
+
t[f] !== !0 && (t[f] = !0, console.info("[voltro] islands mode: hydration is scoped to this page's islands, but the JS payload is NOT reduced — the full app bundle is still downloaded and evaluated. Islands buy CPU, not bytes, today. See the \"Render modes\" docs page."));
|
|
13
|
+
}, m = (e) => `${window.location.protocol === "https:" ? "wss:" : "ws:"}//${window.location.host}/ws/${e}`, h = (f, h) => {
|
|
14
|
+
let g = document.getElementById(h.rootId ?? "root");
|
|
15
|
+
if (!g) throw Error(`@voltro/web: no #${h.rootId ?? "root"} element in the document`);
|
|
16
|
+
let _ = Object.entries(h.apis).map(([e, t]) => ({
|
|
17
|
+
name: e,
|
|
18
|
+
group: t.group,
|
|
19
|
+
descriptors: t.descriptors ?? {},
|
|
20
|
+
wsUrl: t.wsUrl ?? m(e),
|
|
21
|
+
headers: t.headers
|
|
22
|
+
})), v = document.getElementById(i), y = r(v?.textContent, window.location.pathname), b = y !== null && g.children.length > 0, x = document.querySelector("meta[name=\"voltro-interactive\"]")?.getAttribute("content") ?? "full";
|
|
23
|
+
if (x === "none") return;
|
|
24
|
+
if (x === "islands") {
|
|
25
|
+
p(d()), t();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
b && n(y), l(y?.storeSeeds), c(y?.preloadSeeds);
|
|
29
|
+
let S = /* @__PURE__ */ u(a, { children: /* @__PURE__ */ u(e, {
|
|
30
|
+
App: f,
|
|
31
|
+
apis: _,
|
|
32
|
+
...h.Devtools ? { Devtools: h.Devtools } : {}
|
|
33
|
+
}) });
|
|
34
|
+
b ? s(g, S) : o(g).render(S);
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
export { h as mount, p as noticeIslandsShipTheFullBundle };
|