@void/svelte 0.24.0 → 0.26.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/README.md CHANGED
@@ -1,9 +1,17 @@
1
1
  # @void/svelte
2
2
 
3
- Svelte 5 adapter for Void Pages mode.
3
+ Build server-rendered Void pages with Svelte 5, server loaders, and typed forms.
4
4
 
5
5
  ## Setup
6
6
 
7
+ Install alongside `void`:
8
+
9
+ ```sh
10
+ npm install @void/svelte
11
+ ```
12
+
13
+ Add the adapter to your Vite config. It includes the framework's Vite plugin:
14
+
7
15
  ```ts
8
16
  import { defineConfig } from 'vite';
9
17
  import { voidPlugin } from 'void';
@@ -14,111 +22,6 @@ export default defineConfig({
14
22
  });
15
23
  ```
16
24
 
17
- ## Plugin
18
-
19
- `voidSvelte(options?)` returns:
20
-
21
- - `@sveltejs/vite-plugin-svelte`
22
- - the Svelte pages plugin
23
- - the Svelte islands plugin
24
-
25
- Options:
26
-
27
- - `svelte?` — forwarded to the Svelte Vite plugin
28
- - `viewTransitions?` — enable View Transitions for SPA navigation
29
- - `prefetch?` — link prefetch behavior
30
-
31
- ## Runtime
32
-
33
- Main runtime APIs live at `@void/svelte`:
34
-
35
- - `Link`
36
- - `useRouter()`
37
- - `useParams()`
38
- - `useNavigation()`
39
- - `useShared()`
40
- - `Form` and `useForm()`
41
- - `useIslandForm()`
42
- - `action()`
43
-
44
- ### Link
45
-
46
- `Link` renders an `<a>` for GET navigation and a `<button>` for mutation methods:
47
-
48
- ```svelte
49
- <Link href="/users" data={{ page: 2, tag: ["active", "new"] }}>Filtered users</Link>
50
- <Link href="/users" replace>Users</Link>
51
- <Link href="/logout" reloadDocument>Sign out</Link>
52
- ```
53
-
54
- GET `data` is merged into the rendered `href` query string. Primitive values are serialized with `String(value)`, arrays become repeated keys, `null` and `undefined` are omitted, and nested objects throw.
55
-
56
- `prefetch` and `reloadDocument` are GET-only and throw for mutation links. `onNavigate` can cancel client-side navigation by calling `event.preventDefault()`.
57
-
58
- ### Forms
59
-
60
- `useForm()` tracks form state for Pages actions. Use `pending` for in-flight
61
- state, `errors` for field validation, and `error` for non-validation call-site
62
- failures. The submit helpers return promises so boundary-class failures can
63
- propagate through Svelte async error handling or explicit `catch` handlers.
64
-
65
- ```svelte
66
- <script lang="ts">
67
- import { useForm } from '@void/svelte';
68
-
69
- const form = useForm('/users', { name: '', email: '' });
70
- </script>
71
-
72
- <form
73
- onsubmit={(event) => {
74
- event.preventDefault();
75
- return form.post();
76
- }}
77
- >
78
- <input bind:value={form.data.name} name="name" />
79
- {#if form.errors.name}<p>{form.errors.name}</p>{/if}
80
- {#if form.error}<p>{form.error.message}</p>{/if}
81
- <button disabled={form.pending}>Save</button>
82
- </form>
83
- ```
84
-
85
- Use `action()` for the awaitable imperative escape hatch. It returns
86
- `{ ok: true, pageData }` or `{ ok: false, error }` for call-site action errors,
87
- while boundary-class failures are thrown. `action()` uses `POST` by default and
88
- accepts `{ method: "PUT" | "PATCH" | "DELETE" }`.
89
-
90
- ## Pages
91
-
92
- Pages are `.svelte` files in `pages/` with companion `.server.ts` files:
93
-
94
- ```svelte
95
- <script>
96
- let { title } = $props();
97
- </script>
98
-
99
- <h1>{title}</h1>
100
- ```
101
-
102
- ```ts
103
- import { defineHandler } from 'void';
104
-
105
- export const loader = defineHandler(() => ({ title: 'Home' }));
106
- ```
107
-
108
- Export `ssr = false` from a page's `.server.ts` file to skip server-rendered
109
- component HTML for that route while still running its loader on the first
110
- request.
111
-
112
- ## Form
113
-
114
- Use `Form` with `useForm()` to display action and validation errors automatically. It preserves controlled input after a failed submission and announces errors accessibly. Structured usage-limit responses display the application's message and an optional retry time. Submissions are blocked while pending and before that deadline; inputs remain editable and requests are never retried automatically.
115
-
116
- `method` selects `post` (the default), `put`, `patch`, or `delete`. Use `renderError` to customize action-error presentation (a snippet in Svelte). Native forms remain available when you manage error presentation yourself.
117
-
118
- ## Tests
119
-
120
- - `test/integration/svelte-pages-client.test.ts`
121
-
122
- Cross-package SSR/protocol coverage for Svelte pages mode also lives in `packages/void/test/integration/*`.
25
+ Follow [Pages Routing](https://void.cloud/guide/pages-routing/overview) to add pages, then use [loaders](https://void.cloud/guide/pages-routing/loaders), [forms](https://void.cloud/guide/pages-routing/actions-and-forms), and [layouts](https://void.cloud/guide/pages-routing/layouts).
123
26
 
124
- 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.
27
+ See the [adapter API reference](https://void.cloud/reference/api/pages) for plugin options and runtime helpers, and [TESTING.md](../../TESTING.md) for repository verification.
package/dist/plugin.mjs CHANGED
@@ -490,7 +490,7 @@ export async function renderPage(pageObj, assetTags) {
490
490
  }
491
491
  function generateClientEntry(scan, pagesDir, viewTransitions, prefetch, staticPageData) {
492
492
  return `
493
- import { hydrate, mount } from "svelte";
493
+ import { hydrate, mount, tick } from "svelte";
494
494
  import { writable } from "svelte/store";
495
495
  import App from "@void/svelte/App.svelte";
496
496
  import { setActionRouter } from "@void/svelte";
@@ -510,7 +510,7 @@ let routeParams = {};
510
510
  const routeStore = writable(routeUrl);
511
511
  const navigationStore = writable(idleNavigationState());
512
512
 
513
- const { router, initialPageData, initialComponent, initialLayouts, start } =
513
+ const { router, initialPageData, initialComponent, initialLayouts, start, commitInitialRender } =
514
514
  await createVoidRouter({
515
515
  adapter: {
516
516
  createDeferred: () => ({ value: null, loading: true, error: null }),
@@ -589,9 +589,11 @@ if (appEl.getAttribute("data-void-ssr") === "false") {
589
589
  hydrate(App, appOptions);
590
590
  }
591
591
 
592
- appEl.setAttribute("data-hydrated", "true");
593
592
  export { reactiveRouter as router };
594
593
  start();
594
+ await tick();
595
+ commitInitialRender();
596
+ appEl.setAttribute("data-hydrated", "true");
595
597
  `;
596
598
  }
597
599
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@void/svelte",
3
- "version": "0.24.0",
3
+ "version": "0.26.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/voidzero-dev/void.git",
@@ -32,17 +32,17 @@
32
32
  "@sveltejs/vite-plugin-svelte": "^7.3.1"
33
33
  },
34
34
  "devDependencies": {
35
- "@types/node": "^26.6.3",
35
+ "@types/node": "^26.6.4",
36
36
  "pathslash": "^0.1.0",
37
37
  "svelte": "^5.57.1",
38
38
  "vite": "npm:@voidzero-dev/vite-plus-core@1.0.0",
39
39
  "vite-plus": "1.0.0",
40
- "void": "0.24.0"
40
+ "void": "0.26.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "svelte": "^5.0.0",
44
44
  "vite": "^8.0.0",
45
- "void": "0.24.0"
45
+ "void": "0.26.0"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "vp pack",