@void/react 1.1.11 → 1.2.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.
@@ -6,5 +6,6 @@ const ErrorsContext = createContext(null);
6
6
  const ParamsContext = createContext(null);
7
7
  const RouterContext = createContext(null);
8
8
  const NavigationContext = createContext(idleNavigationState());
9
+ const FrontmatterContext = createContext({});
9
10
  //#endregion
10
- export { SharedContext as a, RouterContext as i, NavigationContext as n, ParamsContext as r, ErrorsContext as t };
11
+ export { RouterContext as a, ParamsContext as i, FrontmatterContext as n, SharedContext as o, NavigationContext as r, ErrorsContext as t };
package/dist/index.d.mts CHANGED
@@ -96,6 +96,7 @@ export declare const ErrorsContext: Context<Record<string, string> | null>;
96
96
  export declare const ParamsContext: Context<Record<string, string> | null>;
97
97
  export declare const RouterContext: Context<VoidRouter | null>;
98
98
  export declare const NavigationContext: Context<NavigationState>;
99
+ export declare const FrontmatterContext: Context<Record<string, unknown>>;
99
100
  //#endregion
100
101
  //#region src/runtime/index.d.ts
101
102
  export type Deferred<T> = Promise<T>;
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as SharedContext, i as RouterContext, n as NavigationContext, r as ParamsContext, t as ErrorsContext } from "./context-B0GL7p5m.mjs";
1
+ import { a as RouterContext, i as ParamsContext, n as FrontmatterContext, o as SharedContext, r as NavigationContext, t as ErrorsContext } from "./context-D2ctU4yT.mjs";
2
2
  import { n as setActionRouter, t as action } from "./action-4EvQppia.mjs";
3
3
  import { useActionState, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
4
4
  import { VoidActionError, categorizeActionError, formErrorMessage, formRetryMessage, formSubmissionBlocked, getValidationErrors, interpolateRouteParams, isAbortError, isEqualFormValue, isModifiedEvent, mergeDataIntoHref, scheduleFormRetry, ssrProxy, submitAction } from "void/pages-client";
@@ -460,4 +460,4 @@ function useIslandForm(defaults) {
460
460
  };
461
461
  }
462
462
  //#endregion
463
- export { ErrorsContext, Form, Link, NavigationContext, ParamsContext, RouterContext, SharedContext, action, setActionRouter, useForm, useIslandForm, useNavigation, useParams, useRouter, useShared };
463
+ export { ErrorsContext, Form, FrontmatterContext, Link, NavigationContext, ParamsContext, RouterContext, SharedContext, action, setActionRouter, useForm, useIslandForm, useNavigation, useParams, useRouter, useShared };
package/dist/plugin.mjs CHANGED
@@ -3,7 +3,7 @@ import { generateComponentManifest, resolveEffectiveLayoutChain, resolvePagesDir
3
3
  import { existsSync, readFileSync, readdirSync } from "node:fs";
4
4
  import nodePath from "node:path";
5
5
  import { normalizePath } from "vite";
6
- import { ISLANDS_CLIENT_ENTRY_ID, ISLANDS_RENDERER_ID, computePagesNeedingClientJS, editIslandSource, findIslandImports, findStaticCssImports, needsIslandClientBundle, resolveSpecifier, rewriteCssImportForVirtualModule, watchPagesForRescan } from "void/pages-islands-plugin";
6
+ import { ISLANDS_CLIENT_ENTRY_ID, ISLANDS_RENDERER_ID, computePagesNeedingClientJS, editIslandSource, findIslandImports, findStaticCssImports, hasIslandPages, islandStylesPlugin, recordIslandStyles, recordedIslandStyles, resolveSpecifier, rewriteCssImportForVirtualModule, watchPagesForRescan } from "void/pages-islands-plugin";
7
7
  //#region ../../node_modules/.pnpm/pathslash@0.1.0/node_modules/pathslash/dist/index.mjs
8
8
  const BACKSLASH_RE = /\\/g;
9
9
  const isWindows = process.platform === "win32";
@@ -52,11 +52,14 @@ const REACT_OPTIMIZE_DEPS = [
52
52
  "react",
53
53
  "react/jsx-runtime",
54
54
  "react/jsx-dev-runtime",
55
- "react-dom",
56
- "react-dom/client",
57
- "react-dom/server"
55
+ "react-dom"
56
+ ];
57
+ const CLIENT_OPTIMIZE_DEPS = [...REACT_OPTIMIZE_DEPS, "react-dom/client"];
58
+ const WORKER_OPTIMIZE_DEPS = [
59
+ ...REACT_OPTIMIZE_DEPS,
60
+ "react-dom/server",
61
+ "void/live/client"
58
62
  ];
59
- const WORKER_OPTIMIZE_DEPS = [...REACT_OPTIMIZE_DEPS, "void/live/client"];
60
63
  const REACT_REFRESH_PREAMBLE = `
61
64
  <script type="module">
62
65
  import RefreshRuntime from "/@react-refresh"
@@ -134,7 +137,15 @@ function pagesPlugin(pagesDir, options) {
134
137
  const normalizedPath = normalizePath(path);
135
138
  if (normalizedPath !== normalizedPagesDir && !normalizedPath.startsWith(normalizedPagesDir + "/")) return;
136
139
  if (event === "change" && !normalizedPath.endsWith(".md")) return;
137
- await runRescan();
140
+ try {
141
+ await runRescan();
142
+ } catch (error) {
143
+ server.config.logger.error(error instanceof Error ? error.message : String(error), {
144
+ error: error instanceof Error ? error : void 0,
145
+ timestamp: true
146
+ });
147
+ return;
148
+ }
138
149
  invalidatePageModules(server);
139
150
  };
140
151
  server.watcher.on("add", (path) => handlePagesChange(path, "add"));
@@ -152,9 +163,9 @@ function pagesPlugin(pagesDir, options) {
152
163
  resolve: { dedupe: REACT_DEDUPE },
153
164
  optimizeDeps: {
154
165
  exclude: ["@void/react"],
155
- include: REACT_OPTIMIZE_DEPS
166
+ include: CLIENT_OPTIMIZE_DEPS
156
167
  },
157
- ssr: { optimizeDeps: { include: REACT_OPTIMIZE_DEPS } },
168
+ ssr: { optimizeDeps: { include: [...CLIENT_OPTIMIZE_DEPS, "react-dom/server"] } },
158
169
  environments: { [WORKER_ENVIRONMENT_NAME]: { optimizeDeps: {
159
170
  exclude: ["@void/react"],
160
171
  entries: [pagesOptimizeEntries],
@@ -291,6 +302,9 @@ function islandsPlugin(pagesDir, options) {
291
302
  }
292
303
  }
293
304
  },
305
+ buildEnd() {
306
+ recordIslandStyles(this, pageScan, pagesDir);
307
+ },
294
308
  resolveId: {
295
309
  filter: { id: /^virtual:void-islands-(renderer|client)$/ },
296
310
  handler(source) {
@@ -309,7 +323,7 @@ function islandsPlugin(pagesDir, options) {
309
323
  }
310
324
  if (id === "\0" + ISLANDS_CLIENT_ENTRY_ID) {
311
325
  if (!pageScan) return "";
312
- return generateIslandClientEntry(islandManifest, islandCssFiles, isDev);
326
+ return generateIslandClientEntry(islandManifest, islandCssFiles, recordedIslandStyles(pagesDir), islandManifest.size > 0 || computePagesNeedingClientJS(pageScan, pagesDir, resolvedConfig).size > 0, isDev);
313
327
  }
314
328
  }
315
329
  },
@@ -342,14 +356,13 @@ function islandsPlugin(pagesDir, options) {
342
356
  });
343
357
  }
344
358
  },
345
- config(_, env) {
346
- if (!existsSync(pagesDir)) return;
347
- if (env.command !== "serve" && needsIslandClientBundle(pagesDir, /\.island\.(tsx|jsx)$/, false)) return { build: {
359
+ async config(_, env) {
360
+ if (env.command !== "serve" && await hasIslandPages(root, pagesDir)) return { environments: { client: { build: {
348
361
  manifest: true,
349
362
  rollupOptions: { input: { "islands-client": ISLANDS_CLIENT_ENTRY_ID } }
350
- } };
363
+ } } } };
351
364
  }
352
- }];
365
+ }, islandStylesPlugin(pagesDir)];
353
366
  }
354
367
  function generateIslandRenderer(scan, pagesDir, isDev, mdScriptIds, pagesNeedingClientJS) {
355
368
  const preambleScript = isDev ? REACT_REFRESH_PREAMBLE : "";
@@ -358,8 +371,9 @@ function generateIslandRenderer(scan, pagesDir, isDev, mdScriptIds, pagesNeeding
358
371
  return `
359
372
  import React from "react";
360
373
  import { renderToString } from "react-dom/server";
361
- import { SharedContext, ErrorsContext, ParamsContext } from "@void/react";
374
+ import { SharedContext, ErrorsContext, ParamsContext, FrontmatterContext } from "@void/react";
362
375
  import { renderHeadToString, renderHtmlAttrs, renderBodyAttrs } from "void/pages-head";
376
+ import { islandFrontmatterScript } from "void/pages-server";
363
377
 
364
378
  ${generateComponentManifest(scan, pagesDir)}
365
379
  ${mdScriptIdsCode}
@@ -372,7 +386,9 @@ function escapeAttr(s) {
372
386
  }
373
387
 
374
388
  export async function renderIslandPage(pageObj, assetTags) {
375
- const PageComponent = (await components[pageObj.component]()).default;
389
+ const __pageModule = await components[pageObj.component]();
390
+ const PageComponent = __pageModule.default;
391
+ const __frontmatter = __pageModule.frontmatter ?? {};
376
392
  const layoutIds = layoutTree[pageObj.component] || [];
377
393
  const layoutComponents = await Promise.all(
378
394
  layoutIds.map(async (id) => (await components[id]()).default)
@@ -383,7 +399,8 @@ export async function renderIslandPage(pageObj, assetTags) {
383
399
  element = React.createElement(layoutComponents[i], null, element);
384
400
  }
385
401
 
386
- // No RouterContext — islands have no Void Router
402
+ // No RouterContext — islands have no Void Router.
403
+ // Frontmatter wraps the layouts so they can read the Markdown page's values.
387
404
  element = React.createElement(
388
405
  SharedContext.Provider,
389
406
  { value: pageObj.shared || {} },
@@ -393,12 +410,17 @@ export async function renderIslandPage(pageObj, assetTags) {
393
410
  React.createElement(
394
411
  ErrorsContext.Provider,
395
412
  { value: pageObj.errors || {} },
396
- element
413
+ React.createElement(FrontmatterContext.Provider, { value: __frontmatter }, element)
397
414
  )
398
415
  )
399
416
  );
400
417
 
401
418
  const html = renderToString(element);
419
+ // Islands hydrate as separate roots. Send the page frontmatter so their
420
+ // useFrontmatter() returns the same value in the browser.
421
+ const __frontmatterScript = __pagesNeedingClientJS.has(pageObj.component) && html.includes("data-island=")
422
+ ? islandFrontmatterScript(__pageModule.frontmatter)
423
+ : "";
402
424
  const __mdScriptAttr = __mdClientScriptIds.has(pageObj.component) ? \` data-md-script="\${escapeAttr(pageObj.component)}"\` : "";
403
425
  const headHtml = pageObj.head ? renderHeadToString(pageObj.head) : "";
404
426
  const htmlAttrs = pageObj.head ? renderHtmlAttrs(pageObj.head) : "";
@@ -409,35 +431,42 @@ export async function renderIslandPage(pageObj, assetTags) {
409
431
  <head>\${headHtml}\${PREAMBLE_SCRIPT}\${assetTags.css}\${__pagesNeedingClientJS.has(pageObj.component) ? assetTags.preloads : ""}</head>
410
432
  <body\${bodyAttrs}>
411
433
  <div id="app"\${__mdScriptAttr}>\${html}</div>
412
- \${__pagesNeedingClientJS.has(pageObj.component) ? assetTags.body : ""}
434
+ \${__frontmatterScript}\${__pagesNeedingClientJS.has(pageObj.component) ? assetTags.body : ""}
413
435
  </body>
414
436
  </html>\`;
415
437
  }
416
438
  `;
417
439
  }
418
- function generateIslandClientEntry(manifest, cssFiles, isDev) {
440
+ function generateIslandClientEntry(manifest, cssFiles, styles, needsRuntime, isDev) {
419
441
  const entries = [...manifest.values()];
420
442
  const uniqueIslands = /* @__PURE__ */ new Map();
421
443
  for (const entry of entries) uniqueIslands.set(entry.islandId, entry.componentPath);
422
444
  const lines = [];
423
- lines.push("import { initIslands } from \"void/pages-client\";");
424
- if (!isDev) for (const file of cssFiles) {
445
+ if (!isDev && styles) for (const id of styles) lines.push(`import ${JSON.stringify(id)};`);
446
+ else if (!isDev) for (const file of cssFiles) {
425
447
  const content = readFileSync(file, "utf-8");
426
448
  for (const item of findStaticCssImports(content, file)) lines.push(rewriteCssImportForVirtualModule(item.statement, item.specifier, file));
427
449
  }
450
+ if (!needsRuntime && !isDev) return lines.join("\n");
451
+ lines.push("import { initIslands } from \"void/pages-client\";");
428
452
  lines.push("const islands = {");
429
453
  for (const [id, path] of uniqueIslands) lines.push(` ${JSON.stringify(id)}: () => import(${JSON.stringify(path)}),`);
430
454
  lines.push("};");
431
455
  lines.push(`
432
- async function hydrateIsland(el, mod, props) {
456
+ async function hydrateIsland(el, mod, props, frontmatter) {
433
457
  const { hydrateRoot } = await import("react-dom/client");
434
458
  const React = await import("react");
435
459
  const Component = mod.default || mod;
460
+ let island = React.createElement(Component, props);
461
+ if (Object.keys(frontmatter).length > 0) {
462
+ const { FrontmatterContext } = await import("@void/react");
463
+ island = React.createElement(FrontmatterContext.Provider, { value: frontmatter }, island);
464
+ }
436
465
  function HydratedIsland() {
437
466
  React.useLayoutEffect(() => {
438
467
  el.setAttribute("data-hydrated", "true");
439
468
  }, []);
440
- return React.createElement(Component, props);
469
+ return island;
441
470
  }
442
471
  hydrateRoot(el, React.createElement(HydratedIsland));
443
472
  }
@@ -1,7 +1,7 @@
1
- import { a as SharedContext, i as RouterContext, n as NavigationContext, r as ParamsContext, t as ErrorsContext } from "../context-B0GL7p5m.mjs";
1
+ import { a as RouterContext, i as ParamsContext, o as SharedContext, r as NavigationContext, t as ErrorsContext } from "../context-D2ctU4yT.mjs";
2
2
  import { n as setActionRouter } from "../action-4EvQppia.mjs";
3
3
  import { n as DEFERRED_SHELL_END_ID } from "../deferred-shell-DOuP2YAo.mjs";
4
- import React, { Suspense, startTransition, use, useCallback, useEffect, useInsertionEffect, useLayoutEffect, useMemo, useReducer, useTransition } from "react";
4
+ import React, { Suspense, startTransition, use, useCallback, useEffect, useInsertionEffect, useLayoutEffect, useMemo, useReducer, useState, useTransition } from "react";
5
5
  import { createPageNavigationEngine, createRouterFacade, idleNavigationState, isAbortError, isCallSiteActionError } from "void/pages-client";
6
6
  import { createRoot, hydrateRoot } from "react-dom/client";
7
7
  //#region src/runtime/pages-client.ts
@@ -11,6 +11,7 @@ const pendingVisitSettlers = /* @__PURE__ */ new Map();
11
11
  const committedResources = /* @__PURE__ */ new Set();
12
12
  const EMPTY_PARAMS = {};
13
13
  let activePendingNavigationId = null;
14
+ let prerenderedUrl = null;
14
15
  let scheduleVisit = null;
15
16
  function createDeferredResource() {
16
17
  let resolve;
@@ -54,6 +55,36 @@ function normalizeUrl(value) {
54
55
  const url = value instanceof URL ? value : new URL(value, window.location.origin);
55
56
  return url.origin === window.location.origin ? url.pathname + url.search + url.hash : url.href;
56
57
  }
58
+ /** Page data holds a decoded path. Compare it with browser URLs in their encoded form. */
59
+ function encodedPageUrl(url) {
60
+ if (!url) return url;
61
+ const parsed = new URL(url, window.location.origin);
62
+ return parsed.pathname + parsed.search;
63
+ }
64
+ /** Static hosts serve one page at `/a`, `/a/`, `/a.html` and `/a/index.html`. */
65
+ function staticPagePath(pathname) {
66
+ let path = pathname;
67
+ if (path.endsWith("/index.html")) path = path.slice(0, -10);
68
+ else if (path.endsWith(".html")) path = path.slice(0, -5);
69
+ return path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
70
+ }
71
+ /**
72
+ * Static page data serves every query of a path, so its url has no query. Returns the query of
73
+ * fetchUrl when the page data is such data for its path, or null.
74
+ */
75
+ function staticVisitQuery(pageUrl, fetchUrl) {
76
+ if (!pageUrl || pageUrl.includes("?")) return null;
77
+ const queryStart = fetchUrl.indexOf("?");
78
+ if (staticPagePath(queryStart === -1 ? fetchUrl : fetchUrl.slice(0, queryStart)) !== staticPagePath(pageUrl)) return null;
79
+ return queryStart === -1 ? "" : fetchUrl.slice(queryStart);
80
+ }
81
+ /**
82
+ * The URL prerendered HTML was rendered with, when it lacks the visitor's query, or null.
83
+ */
84
+ function prerenderedRouteUrl(pageData) {
85
+ const pageUrl = encodedPageUrl(pageData.url);
86
+ return staticVisitQuery(pageUrl, window.location.pathname + window.location.search) ? pageUrl + window.location.hash : null;
87
+ }
57
88
  function navigationForResource(resource) {
58
89
  const method = resource.method.toUpperCase();
59
90
  return {
@@ -159,13 +190,20 @@ function RouteResource({ resource, onCommit }) {
159
190
  const pageData = result.pageData;
160
191
  const PageComponent = result.component;
161
192
  const routeParams = pageData.params ?? EMPTY_PARAMS;
162
- const routeRouter = useMemo(() => createRouterFacade(outerRouter, () => {
163
- const outerUrl = outerRouter.url;
164
- const outerPath = outerUrl.pathname + outerUrl.search;
165
- return outerPath === pageData.url ? outerPath + outerUrl.hash : pageData.url + resource.hash;
166
- }, () => routeParams), [
193
+ const routeRouter = useMemo(() => {
194
+ const pageUrl = encodedPageUrl(pageData.url);
195
+ return createRouterFacade(outerRouter, () => {
196
+ const outerUrl = outerRouter.url;
197
+ const outerPath = outerUrl.pathname + outerUrl.search;
198
+ if (outerPath === pageUrl) return outerPath + outerUrl.hash;
199
+ const query = staticVisitQuery(pageUrl, resource.fetchUrl);
200
+ if (query !== null) return pageUrl + query + (outerPath === resource.fetchUrl ? outerUrl.hash : resource.hash);
201
+ return pageUrl + resource.hash;
202
+ }, () => routeParams);
203
+ }, [
167
204
  outerRouter,
168
205
  pageData.url,
206
+ resource.fetchUrl,
169
207
  resource.hash,
170
208
  routeParams
171
209
  ]);
@@ -193,10 +231,11 @@ function startViewTransition(resource, reveal, enabled) {
193
231
  }
194
232
  function App({ engine, router, viewTransitions, navigationFallback: NavigationFallback }) {
195
233
  const initialPageData = engine.initialPageData;
234
+ const [hydrated, setHydrated] = useState(prerenderedUrl === null);
196
235
  const initialResource = useMemo(() => ({
197
236
  id: 0,
198
237
  url: initialPageData.url || currentUrl(),
199
- fetchUrl: initialPageData.url || currentUrl(),
238
+ fetchUrl: window.location.pathname + window.location.search,
200
239
  hash: window.location.hash,
201
240
  method: "GET",
202
241
  options: {},
@@ -210,6 +249,10 @@ function App({ engine, router, viewTransitions, navigationFallback: NavigationFa
210
249
  async commit() {
211
250
  engine.commitInitialRender();
212
251
  document.getElementById("app").setAttribute("data-hydrated", "true");
252
+ if (prerenderedUrl !== null) {
253
+ prerenderedUrl = null;
254
+ React.startTransition(() => setHydrated(true));
255
+ }
213
256
  },
214
257
  dispose() {}
215
258
  }), [engine, initialPageData]);
@@ -403,7 +446,11 @@ function App({ engine, router, viewTransitions, navigationFallback: NavigationFa
403
446
  method: "GET"
404
447
  };
405
448
  }, [isTransitionPending, state.navigation]);
406
- const routerValue = useMemo(() => createRouterFacade(router, () => state.routeUrl), [router, state.routeUrl]);
449
+ const routerValue = useMemo(() => createRouterFacade(router, () => hydrated ? state.routeUrl : prerenderedUrl ?? state.routeUrl), [
450
+ router,
451
+ state.routeUrl,
452
+ hydrated
453
+ ]);
407
454
  return React.createElement(RouterContext.Provider, { value: routerValue }, React.createElement(NavigationContext.Provider, { value: navigationValue }, React.createElement(Suspense, { fallback: NavigationFallback && state.pendingId !== null ? React.createElement(NavigationFallback, { initialPageData }) : null }, React.createElement(RouteResource, {
408
455
  resource: state.resource,
409
456
  onCommit: finishNavigation
@@ -414,6 +461,7 @@ async function startReactPages(config) {
414
461
  pendingVisitSettlers.clear();
415
462
  committedResources.clear();
416
463
  activePendingNavigationId = null;
464
+ prerenderedUrl = null;
417
465
  const engine = await createPageNavigationEngine({
418
466
  adapter: {
419
467
  createDeferred: createDeferredResource,
@@ -436,13 +484,14 @@ async function startReactPages(config) {
436
484
  setActionRouter(router);
437
485
  const appEl = document.getElementById("app");
438
486
  if (!appEl) throw new Error("pages: Missing #app element for Void React pages hydration.");
487
+ const isSsr = appEl.getAttribute("data-void-ssr") !== "false";
488
+ if (isSsr) prerenderedUrl = prerenderedRouteUrl(engine.initialPageData);
439
489
  const appRoot = React.createElement(App, {
440
490
  engine,
441
491
  router,
442
492
  viewTransitions: config.viewTransitions,
443
493
  navigationFallback: config.navigationFallback
444
494
  });
445
- const isSsr = appEl.getAttribute("data-void-ssr") !== "false";
446
495
  const hasDeferred = Boolean(engine.initialPageData.deferredKeys);
447
496
  const app = isSsr && hasDeferred ? React.createElement(React.Fragment, null, appRoot, React.createElement("template", { id: DEFERRED_SHELL_END_ID })) : appRoot;
448
497
  startTransition(() => {
@@ -1,4 +1,4 @@
1
- import { a as SharedContext, i as RouterContext, n as NavigationContext, r as ParamsContext, t as ErrorsContext } from "../context-B0GL7p5m.mjs";
1
+ import { a as RouterContext, i as ParamsContext, o as SharedContext, r as NavigationContext, t as ErrorsContext } from "../context-D2ctU4yT.mjs";
2
2
  import { n as DEFERRED_SHELL_END_ID, r as DEFERRED_SHELL_END_MARKER, t as DEFERRED_SHELL_CANCEL_REASON } from "../deferred-shell-DOuP2YAo.mjs";
3
3
  import React from "react";
4
4
  import { createSsrRouter, idleNavigationState } from "void/pages-client";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@void/react",
3
- "version": "1.1.11",
3
+ "version": "1.2.0",
4
4
  "description": "React pages, server rendering, forms, and navigation for Void.",
5
5
  "homepage": "https://void.cloud",
6
6
  "bugs": {
@@ -45,17 +45,17 @@
45
45
  "@types/react": "^19.3.0",
46
46
  "@types/react-dom": "^19.3.0",
47
47
  "pathslash": "^0.1.0",
48
- "react": "^19.3.0",
49
- "react-dom": "^19.3.0",
50
- "vite": "npm:@voidzero-dev/vite-plus-core@1.2.0",
51
- "vite-plus": "1.2.0",
52
- "void": "1.1.11"
48
+ "react": "^19.3.1",
49
+ "react-dom": "^19.3.1",
50
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.3.0",
51
+ "vite-plus": "1.3.0",
52
+ "void": "1.2.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "react": "^19.0.0",
56
56
  "react-dom": "^19.0.0",
57
57
  "vite": "^8.0.0",
58
- "void": "1.1.11"
58
+ "void": "1.2.0"
59
59
  },
60
60
  "scripts": {
61
61
  "build": "vp pack",