@void/react 0.10.13 → 0.20.1
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 +21 -0
- package/README.md +3 -2
- package/dist/{index-5JoQg_-q.d.mts → index-Cx2A1XEu.d.mts} +4 -26
- package/dist/index.d.mts +1 -1
- package/dist/plugin.d.mts +3 -5
- package/dist/plugin.mjs +4 -3
- package/dist/runtime/index.d.mts +1 -1
- package/dist/runtime/pages-client.d.mts +4 -6
- package/dist/runtime/pages-client.mjs +21 -20
- package/dist/runtime/pages-server.d.mts +3 -11
- package/dist/runtime/pages-server.mjs +2 -1
- package/package.json +12 -20
- package/dist/runtime/prefetch.d.mts +0 -2
- package/dist/runtime/prefetch.mjs +0 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026-present, Cloudflare, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -219,8 +219,9 @@ export const loader = defineHandler(() => ({ title: 'Home' }));
|
|
|
219
219
|
|
|
220
220
|
## Tests
|
|
221
221
|
|
|
222
|
-
- `test/unit/use-form.test.ts`
|
|
223
222
|
- `test/unit/link.test.ts`
|
|
224
223
|
- `test/integration/react-pages-client.test.ts`
|
|
225
224
|
|
|
226
|
-
Cross-package SSR/protocol coverage for React pages mode also lives in `
|
|
225
|
+
Cross-package SSR/protocol coverage for React pages mode also lives in `packages/void/test/integration/*`.
|
|
226
|
+
|
|
227
|
+
The [shared client](../../test/pages-client-contract.ts) and [island](../../test/pages-island-contract.ts) contracts run against this adapter in both dev and preview. Shared form equality is tested directly in [Void](../void/test/unit/form-value-equality.test.ts); tests do not copy the hook implementation.
|
|
@@ -2,7 +2,6 @@ import { AnchorHTMLAttributes, ButtonHTMLAttributes, Context, JSX } from "react"
|
|
|
2
2
|
import { ActionResult, NavigationState, VoidActionError, VoidRouter } from "void/pages-client";
|
|
3
3
|
import { CloudContextVariables, InferProps } from "void";
|
|
4
4
|
import { ActionFormOptions, ActionUrl, ResolveActionBody, ResolveActionParams } from "void/routes";
|
|
5
|
-
|
|
6
5
|
//#region src/runtime/link.d.ts
|
|
7
6
|
type PrefetchStrategy = "hover" | "click" | "mount" | "visible";
|
|
8
7
|
type LinkMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
@@ -22,28 +21,7 @@ type CommonProps = {
|
|
|
22
21
|
}) => void;
|
|
23
22
|
};
|
|
24
23
|
type LinkProps = CommonProps & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof CommonProps> & Omit<ButtonHTMLAttributes<HTMLButtonElement>, keyof CommonProps>;
|
|
25
|
-
declare function Link({
|
|
26
|
-
href,
|
|
27
|
-
method,
|
|
28
|
-
data,
|
|
29
|
-
preserveScroll,
|
|
30
|
-
preserveState,
|
|
31
|
-
replace,
|
|
32
|
-
reloadDocument,
|
|
33
|
-
viewTransition,
|
|
34
|
-
prefetch: prefetchProp,
|
|
35
|
-
cacheFor,
|
|
36
|
-
onNavigate,
|
|
37
|
-
children,
|
|
38
|
-
style,
|
|
39
|
-
onClick: onClickProp,
|
|
40
|
-
onMouseEnter: onMouseEnterProp,
|
|
41
|
-
onMouseLeave: onMouseLeaveProp,
|
|
42
|
-
onFocus: onFocusProp,
|
|
43
|
-
onMouseDown: onMouseDownProp,
|
|
44
|
-
onTouchStart: onTouchStartProp,
|
|
45
|
-
...rest
|
|
46
|
-
}: LinkProps): JSX.Element;
|
|
24
|
+
declare function Link({ href, method, data, preserveScroll, preserveState, replace, reloadDocument, viewTransition, prefetch: prefetchProp, cacheFor, onNavigate, children, style, onClick: onClickProp, onMouseEnter: onMouseEnterProp, onMouseLeave: onMouseLeaveProp, onFocus: onFocusProp, onMouseDown: onMouseDownProp, onTouchStart: onTouchStartProp, ...rest }: LinkProps): JSX.Element;
|
|
47
25
|
//#endregion
|
|
48
26
|
//#region src/runtime/use-router.d.ts
|
|
49
27
|
declare function useRouter(): VoidRouter;
|
|
@@ -95,9 +73,9 @@ type IslandFormReturn<T extends Record<string, unknown>> = Readonly<{
|
|
|
95
73
|
delete: (url: string) => Promise<void>;
|
|
96
74
|
}>;
|
|
97
75
|
/**
|
|
98
|
-
* Form hook for island pages. Uses fetch + page reload instead of the
|
|
99
|
-
* Void Router (which is not available in island mode).
|
|
100
|
-
*/
|
|
76
|
+
* Form hook for island pages. Uses fetch + page reload instead of the
|
|
77
|
+
* Void Router (which is not available in island mode).
|
|
78
|
+
*/
|
|
101
79
|
declare function useIslandForm<T extends Record<string, unknown>>(defaults: T): IslandFormReturn<T>;
|
|
102
80
|
//#endregion
|
|
103
81
|
//#region src/runtime/action.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ParamsContext, c as action, d as useNavigation, f as useForm, g as Link, h as useRouter, i as NavigationContext, l as setActionRouter, m as useParams, n as InferProps, o as RouterContext, p as useShared, r as ErrorsContext, s as SharedContext, t as Deferred, u as useIslandForm } from "./index-
|
|
1
|
+
import { a as ParamsContext, c as action, d as useNavigation, f as useForm, g as Link, h as useRouter, i as NavigationContext, l as setActionRouter, m as useParams, n as InferProps, o as RouterContext, p as useShared, r as ErrorsContext, s as SharedContext, t as Deferred, u as useIslandForm } from "./index-Cx2A1XEu.mjs";
|
|
2
2
|
export { Deferred, ErrorsContext, type InferProps, Link, NavigationContext, ParamsContext, RouterContext, SharedContext, action, setActionRouter, useForm, useIslandForm, useNavigation, useParams, useRouter, useShared };
|
package/dist/plugin.d.mts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import react from "@vitejs/plugin-react";
|
|
2
2
|
import { Plugin } from "vite";
|
|
3
|
-
|
|
4
3
|
//#region src/plugin.d.ts
|
|
5
4
|
type PrefetchConfig = {
|
|
6
5
|
hoverDelay?: number;
|
|
7
6
|
cacheFor?: number | string | [string, string];
|
|
8
7
|
};
|
|
9
|
-
type VoidReactOptions = Readonly<{
|
|
8
|
+
export type VoidReactOptions = Readonly<{
|
|
10
9
|
react?: Parameters<typeof react>[0];
|
|
11
10
|
viewTransitions?: boolean;
|
|
12
11
|
prefetch?: PrefetchConfig;
|
|
13
12
|
}>;
|
|
14
|
-
declare function voidReact(options?: VoidReactOptions): Array<Plugin>;
|
|
15
|
-
//#endregion
|
|
16
|
-
export { VoidReactOptions, voidReact };
|
|
13
|
+
export declare function voidReact(options?: VoidReactOptions): Array<Plugin>;
|
|
14
|
+
//#endregion
|
package/dist/plugin.mjs
CHANGED
|
@@ -319,6 +319,7 @@ initIslands(islands, hydrateIsland);
|
|
|
319
319
|
}
|
|
320
320
|
//#endregion
|
|
321
321
|
//#region src/plugin-pages.ts
|
|
322
|
+
const RENDERER_ID = "virtual:void-pages-renderer";
|
|
322
323
|
const CLIENT_ENTRY_ID = "virtual:void-pages-client";
|
|
323
324
|
const WORKER_ENVIRONMENT_NAME = "void_worker";
|
|
324
325
|
const REACT_DEDUPE = ["react", "react-dom"];
|
|
@@ -364,7 +365,7 @@ function pagesPlugin(pagesDir, options) {
|
|
|
364
365
|
return pendingRescan;
|
|
365
366
|
};
|
|
366
367
|
const invalidatePageModules = (server) => {
|
|
367
|
-
for (const env of Object.values(server.environments)) for (const id of ["\
|
|
368
|
+
for (const env of Object.values(server.environments)) for (const id of ["\0" + RENDERER_ID, "\0" + CLIENT_ENTRY_ID]) {
|
|
368
369
|
const mod = env.moduleGraph.getModuleById(id);
|
|
369
370
|
if (mod) env.moduleGraph.invalidateModule(mod);
|
|
370
371
|
}
|
|
@@ -385,11 +386,11 @@ function pagesPlugin(pagesDir, options) {
|
|
|
385
386
|
async handler(id) {
|
|
386
387
|
if (isDev && pendingRescan) await pendingRescan;
|
|
387
388
|
if (!pageScan && existsSync(pagesDir)) await runRescan();
|
|
388
|
-
if (id === "\
|
|
389
|
+
if (id === "\0" + RENDERER_ID) {
|
|
389
390
|
if (!pageScan) return "export function renderPage() { throw new Error('No pages found'); }";
|
|
390
391
|
return generateRendererModule(pageScan, pagesDir, isDev);
|
|
391
392
|
}
|
|
392
|
-
if (id === "\
|
|
393
|
+
if (id === "\0" + CLIENT_ENTRY_ID) {
|
|
393
394
|
if (!pageScan) return "";
|
|
394
395
|
return generateClientEntry(pageScan, pagesDir, options?.viewTransitions, options?.prefetch, resolveStaticPageDataBuildOptions(root, { publicDir: viteConfig?.publicDir }));
|
|
395
396
|
}
|
package/dist/runtime/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ParamsContext, c as action, d as useNavigation, f as useForm, g as Link, h as useRouter, i as NavigationContext, l as setActionRouter, m as useParams, n as InferProps, o as RouterContext, p as useShared, r as ErrorsContext, s as SharedContext, t as Deferred, u as useIslandForm } from "../index-
|
|
1
|
+
import { a as ParamsContext, c as action, d as useNavigation, f as useForm, g as Link, h as useRouter, i as NavigationContext, l as setActionRouter, m as useParams, n as InferProps, o as RouterContext, p as useShared, r as ErrorsContext, s as SharedContext, t as Deferred, u as useIslandForm } from "../index-Cx2A1XEu.mjs";
|
|
2
2
|
export { Deferred, ErrorsContext, type InferProps, Link, NavigationContext, ParamsContext, RouterContext, SharedContext, action, setActionRouter, useForm, useIslandForm, useNavigation, useParams, useRouter, useShared };
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { ComponentType } from "react";
|
|
2
2
|
import { VoidRouter } from "void/pages-client";
|
|
3
3
|
import { CacheForResult } from "void/pages-prefetch";
|
|
4
|
-
|
|
5
4
|
//#region src/runtime/pages-client.d.ts
|
|
6
5
|
type ComponentModule = {
|
|
7
6
|
default: ComponentType<any>;
|
|
8
7
|
};
|
|
9
|
-
type ReactPagesConfig = Readonly<{
|
|
8
|
+
export type ReactPagesConfig = Readonly<{
|
|
10
9
|
components: Record<string, () => Promise<ComponentModule>>;
|
|
11
10
|
layoutTree: Record<string, Array<string>>;
|
|
12
11
|
routeMeta: Record<string, {
|
|
@@ -19,9 +18,8 @@ type ReactPagesConfig = Readonly<{
|
|
|
19
18
|
prefetchHoverDelay: number;
|
|
20
19
|
prefetchDefaultCacheFor: CacheForResult;
|
|
21
20
|
}>;
|
|
22
|
-
type ReactPagesClient = Readonly<{
|
|
21
|
+
export type ReactPagesClient = Readonly<{
|
|
23
22
|
router: VoidRouter;
|
|
24
23
|
}>;
|
|
25
|
-
declare function startReactPages(config: ReactPagesConfig): Promise<ReactPagesClient>;
|
|
26
|
-
//#endregion
|
|
27
|
-
export { ReactPagesClient, ReactPagesConfig, startReactPages };
|
|
24
|
+
export declare function startReactPages(config: ReactPagesConfig): Promise<ReactPagesClient>;
|
|
25
|
+
//#endregion
|
|
@@ -193,27 +193,28 @@ function startViewTransition(resource, reveal, enabled) {
|
|
|
193
193
|
function App({ engine, router, viewTransitions }) {
|
|
194
194
|
const initialPageData = engine.initialPageData;
|
|
195
195
|
const sharedStateRef = useRef(initialPageData.shared);
|
|
196
|
+
const initialResource = useMemo(() => ({
|
|
197
|
+
id: 0,
|
|
198
|
+
url: initialPageData.url || currentUrl(),
|
|
199
|
+
fetchUrl: initialPageData.url || currentUrl(),
|
|
200
|
+
hash: window.location.hash,
|
|
201
|
+
method: "GET",
|
|
202
|
+
options: {},
|
|
203
|
+
immediate: false,
|
|
204
|
+
shell: Promise.resolve({
|
|
205
|
+
pageData: {
|
|
206
|
+
...initialPageData,
|
|
207
|
+
shared: initialPageData.shared
|
|
208
|
+
},
|
|
209
|
+
component: engine.initialComponent,
|
|
210
|
+
layouts: engine.initialLayouts
|
|
211
|
+
}),
|
|
212
|
+
abort() {},
|
|
213
|
+
async commit() {},
|
|
214
|
+
dispose() {}
|
|
215
|
+
}), [engine, initialPageData]);
|
|
196
216
|
const [state, dispatch] = useReducer(appReducer, {
|
|
197
|
-
resource:
|
|
198
|
-
id: 0,
|
|
199
|
-
url: initialPageData.url || currentUrl(),
|
|
200
|
-
fetchUrl: initialPageData.url || currentUrl(),
|
|
201
|
-
hash: window.location.hash,
|
|
202
|
-
method: "GET",
|
|
203
|
-
options: {},
|
|
204
|
-
immediate: false,
|
|
205
|
-
shell: Promise.resolve({
|
|
206
|
-
pageData: {
|
|
207
|
-
...initialPageData,
|
|
208
|
-
shared: initialPageData.shared
|
|
209
|
-
},
|
|
210
|
-
component: engine.initialComponent,
|
|
211
|
-
layouts: engine.initialLayouts
|
|
212
|
-
}),
|
|
213
|
-
abort() {},
|
|
214
|
-
async commit() {},
|
|
215
|
-
dispose() {}
|
|
216
|
-
}), [engine, initialPageData]),
|
|
217
|
+
resource: initialResource,
|
|
217
218
|
rollbackResource: null,
|
|
218
219
|
pendingId: null,
|
|
219
220
|
routeUrl: currentUrl(),
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { ComponentType } from "react";
|
|
2
2
|
import { PageObject } from "void/pages-protocol";
|
|
3
|
-
|
|
4
3
|
//#region src/runtime/pages-server.d.ts
|
|
5
4
|
type ComponentModule = {
|
|
6
5
|
default: ComponentType<any>;
|
|
7
6
|
};
|
|
8
|
-
type ReactPagesServerConfig = Readonly<{
|
|
7
|
+
export type ReactPagesServerConfig = Readonly<{
|
|
9
8
|
pageObj: PageObject;
|
|
10
9
|
assetTags: {
|
|
11
10
|
css: string;
|
|
@@ -16,12 +15,5 @@ type ReactPagesServerConfig = Readonly<{
|
|
|
16
15
|
layoutTree: Record<string, Array<string>>;
|
|
17
16
|
preambleScript?: string;
|
|
18
17
|
}>;
|
|
19
|
-
declare function renderReactPage({
|
|
20
|
-
|
|
21
|
-
assetTags,
|
|
22
|
-
components,
|
|
23
|
-
layoutTree,
|
|
24
|
-
preambleScript
|
|
25
|
-
}: ReactPagesServerConfig): Promise<ReadableStream<Uint8Array>>;
|
|
26
|
-
//#endregion
|
|
27
|
-
export { ReactPagesServerConfig, renderReactPage };
|
|
18
|
+
export declare function renderReactPage({ pageObj, assetTags, components, layoutTree, preambleScript }: ReactPagesServerConfig): Promise<ReadableStream<Uint8Array>>;
|
|
19
|
+
//#endregion
|
|
@@ -84,7 +84,8 @@ async function renderReactPage({ pageObj, assetTags, components, layoutTree, pre
|
|
|
84
84
|
let element = React.createElement(PageComponent, renderProps);
|
|
85
85
|
for (let i = layoutComponents.length - 1; i >= 0; i--) element = React.createElement(layoutComponents[i], null, element);
|
|
86
86
|
element = React.createElement(RouterContext.Provider, { value: createSsrRouter(pageObj.url || "/", pageObj.params ?? {}) }, React.createElement(NavigationContext.Provider, { value: idleNavigationState() }, React.createElement(React.Suspense, { fallback: null }, React.createElement(SharedContext.Provider, { value: pageObj.shared || {} }, React.createElement(ParamsContext.Provider, { value: pageObj.params ?? {} }, React.createElement(ErrorsContext.Provider, { value: pageObj.errors || {} }, element))))));
|
|
87
|
-
const
|
|
87
|
+
const renderElement = pageObj.deferredKeys ? React.createElement(React.Fragment, null, element, React.createElement("template", { id: DEFERRED_SHELL_END_ID })) : element;
|
|
88
|
+
const appStream = await renderToReadableStream(renderElement, { onError(error) {
|
|
88
89
|
if (error === DEFERRED_SHELL_CANCEL_REASON) return;
|
|
89
90
|
throw error;
|
|
90
91
|
} });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@void/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/voidzero-dev/void.git",
|
|
@@ -19,14 +19,6 @@
|
|
|
19
19
|
"types": "./dist/plugin.d.mts",
|
|
20
20
|
"import": "./dist/plugin.mjs"
|
|
21
21
|
},
|
|
22
|
-
"./runtime": {
|
|
23
|
-
"types": "./dist/runtime/index.d.mts",
|
|
24
|
-
"import": "./dist/runtime/index.mjs"
|
|
25
|
-
},
|
|
26
|
-
"./prefetch": {
|
|
27
|
-
"types": "./dist/runtime/prefetch.d.mts",
|
|
28
|
-
"import": "./dist/runtime/prefetch.mjs"
|
|
29
|
-
},
|
|
30
22
|
"./pages-client": {
|
|
31
23
|
"types": "./dist/runtime/pages-client.d.mts",
|
|
32
24
|
"import": "./dist/runtime/pages-client.mjs"
|
|
@@ -40,28 +32,28 @@
|
|
|
40
32
|
"access": "public"
|
|
41
33
|
},
|
|
42
34
|
"dependencies": {
|
|
43
|
-
"@vitejs/plugin-react": "^6.
|
|
35
|
+
"@vitejs/plugin-react": "^6.1.1"
|
|
44
36
|
},
|
|
45
37
|
"devDependencies": {
|
|
46
|
-
"@types/node": "^26.1
|
|
47
|
-
"@types/react": "^19.
|
|
48
|
-
"@types/react-dom": "^19.
|
|
38
|
+
"@types/node": "^26.5.1",
|
|
39
|
+
"@types/react": "^19.3.0",
|
|
40
|
+
"@types/react-dom": "^19.3.0",
|
|
49
41
|
"pathslash": "^0.1.0",
|
|
50
|
-
"react": "^19.
|
|
51
|
-
"react-dom": "^19.
|
|
52
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@0.
|
|
53
|
-
"vite-plus": "
|
|
54
|
-
"void": "0.
|
|
42
|
+
"react": "^19.3.0",
|
|
43
|
+
"react-dom": "^19.3.0",
|
|
44
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.3.1",
|
|
45
|
+
"vite-plus": "0.3.1",
|
|
46
|
+
"void": "0.20.1"
|
|
55
47
|
},
|
|
56
48
|
"peerDependencies": {
|
|
57
49
|
"react": "^19.0.0",
|
|
58
50
|
"react-dom": "^19.0.0",
|
|
59
51
|
"vite": "^8.0.0",
|
|
60
|
-
"void": "0.
|
|
52
|
+
"void": "0.20.1"
|
|
61
53
|
},
|
|
62
54
|
"scripts": {
|
|
63
55
|
"build": "vp pack",
|
|
64
56
|
"dev": "vp pack --watch",
|
|
65
|
-
"typecheck": "
|
|
57
|
+
"typecheck": "tsc --noEmit --rootDir ../.."
|
|
66
58
|
}
|
|
67
59
|
}
|