@void/vue 0.0.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 +113 -0
- package/dist/index-C0fE29Kv.d.mts +79 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +2 -0
- package/dist/plugin.d.mts +11 -0
- package/dist/plugin.mjs +729 -0
- package/dist/runtime/index.d.mts +2 -0
- package/dist/runtime/index.mjs +2 -0
- package/dist/runtime/prefetch.d.mts +2 -0
- package/dist/runtime/prefetch.mjs +2 -0
- package/dist/runtime/use-deferred.d.mts +19 -0
- package/dist/runtime/use-deferred.mjs +21 -0
- package/dist/runtime-DL_B0L_H.mjs +462 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# @void/vue
|
|
2
|
+
|
|
3
|
+
Vue adapter for Void Pages mode.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { defineConfig } from 'vite';
|
|
9
|
+
import { voidPlugin } from 'void';
|
|
10
|
+
import { voidVue } from '@void/vue/plugin';
|
|
11
|
+
|
|
12
|
+
export default defineConfig({
|
|
13
|
+
plugins: [voidPlugin(), voidVue()],
|
|
14
|
+
});
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Plugin
|
|
18
|
+
|
|
19
|
+
`voidVue(options?)` returns:
|
|
20
|
+
|
|
21
|
+
- `@vitejs/plugin-vue`
|
|
22
|
+
- the Vue pages plugin
|
|
23
|
+
- the Vue islands plugin
|
|
24
|
+
|
|
25
|
+
Options:
|
|
26
|
+
|
|
27
|
+
- `vue?` — forwarded to `@vitejs/plugin-vue`
|
|
28
|
+
- `viewTransitions?` — enable View Transitions for SPA navigation
|
|
29
|
+
|
|
30
|
+
## Runtime
|
|
31
|
+
|
|
32
|
+
Main runtime APIs live at `@void/vue`:
|
|
33
|
+
|
|
34
|
+
- `Link`
|
|
35
|
+
- `useRouter()`
|
|
36
|
+
- `useNavigation()`
|
|
37
|
+
- `useShared()`
|
|
38
|
+
- `useForm()`
|
|
39
|
+
- `useIslandForm()`
|
|
40
|
+
- `action()`
|
|
41
|
+
|
|
42
|
+
Deferred helpers are exported from `@void/vue/deferred`.
|
|
43
|
+
|
|
44
|
+
### Link
|
|
45
|
+
|
|
46
|
+
`Link` renders an `<a>` for GET navigation and a `<button>` for mutation methods:
|
|
47
|
+
|
|
48
|
+
```vue
|
|
49
|
+
<Link href="/users" :data="{ page: 2, tag: ['active', 'new'] }">Filtered users</Link>
|
|
50
|
+
<Link href="/users" replace>Users</Link>
|
|
51
|
+
<Link href="/logout" reload-document>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 Vue async error handling or explicit `catch` handlers.
|
|
64
|
+
|
|
65
|
+
```vue
|
|
66
|
+
<script setup lang="ts">
|
|
67
|
+
import { useForm } from '@void/vue';
|
|
68
|
+
|
|
69
|
+
const form = useForm('/users', { name: '', email: '' });
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<template>
|
|
73
|
+
<form @submit.prevent="form.post()">
|
|
74
|
+
<input v-model="form.data.name" name="name" />
|
|
75
|
+
<p v-if="form.errors.name">{{ form.errors.name }}</p>
|
|
76
|
+
<p v-if="form.error">{{ form.error.message }}</p>
|
|
77
|
+
<button :disabled="form.pending">Save</button>
|
|
78
|
+
</form>
|
|
79
|
+
</template>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Use `action()` for the awaitable imperative escape hatch. It returns
|
|
83
|
+
`{ ok: true, pageData }` or `{ ok: false, error }` for call-site action errors,
|
|
84
|
+
while boundary-class failures are thrown. `action()` uses `POST` by default and
|
|
85
|
+
accepts `{ method: "PUT" | "PATCH" | "DELETE" }`.
|
|
86
|
+
|
|
87
|
+
## Pages
|
|
88
|
+
|
|
89
|
+
Pages are `.vue` files in `pages/` with companion `.server.ts` files:
|
|
90
|
+
|
|
91
|
+
```vue
|
|
92
|
+
<script setup lang="ts">
|
|
93
|
+
defineProps<{ title: string }>();
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
<template>
|
|
97
|
+
<h1>{{ title }}</h1>
|
|
98
|
+
</template>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import { defineHandler } from 'void';
|
|
103
|
+
|
|
104
|
+
export const loader = defineHandler(() => ({ title: 'Home' }));
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Tests
|
|
108
|
+
|
|
109
|
+
- `test/unit/use-form.test.ts`
|
|
110
|
+
- `test/unit/prefetch.test.ts`
|
|
111
|
+
- `test/integration/vue-pages-client.test.ts`
|
|
112
|
+
|
|
113
|
+
Cross-package SSR/protocol coverage for Vue pages mode also lives in `framework/packages/void/test/integration/*`.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Component } from "vue";
|
|
2
|
+
import { ActionResult, NavigationState, VisitOptions, VoidActionError, VoidRouter } from "void/pages-client";
|
|
3
|
+
import { CloudContextVariables, DeferredState as Deferred, InferProps } from "void";
|
|
4
|
+
import { ActionFormOptions, ActionUrl, ResolveActionBody, ResolveActionParams } from "void/routes";
|
|
5
|
+
|
|
6
|
+
//#region src/runtime/link.d.ts
|
|
7
|
+
declare const Link: Component;
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/runtime/use-router.d.ts
|
|
10
|
+
declare function useRouter(): VoidRouter;
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/runtime/use-shared.d.ts
|
|
13
|
+
declare function useShared<T = CloudContextVariables["shared"]>(): T;
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/runtime/use-form.d.ts
|
|
16
|
+
type FormSubmitOptions = Omit<VisitOptions, "method" | "data"> & {
|
|
17
|
+
data?: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
declare function useForm<U extends ActionUrl & string>(url: U, defaults: ResolveActionBody<U>, options?: ActionFormOptions<U>): {
|
|
20
|
+
data: ResolveActionBody<U>;
|
|
21
|
+
errors: Partial<Record<keyof ResolveActionBody<U> & string, string>>;
|
|
22
|
+
error: VoidActionError | null;
|
|
23
|
+
pending: boolean;
|
|
24
|
+
hasChanges: boolean;
|
|
25
|
+
wasSuccessful: boolean;
|
|
26
|
+
recentlySuccessful: boolean;
|
|
27
|
+
post(opts?: FormSubmitOptions): Promise<void>;
|
|
28
|
+
put(opts?: FormSubmitOptions): Promise<void>;
|
|
29
|
+
patch(opts?: FormSubmitOptions): Promise<void>;
|
|
30
|
+
delete(opts?: FormSubmitOptions): Promise<void>;
|
|
31
|
+
reset(...fields: Array<keyof ResolveActionBody<U> & string>): void;
|
|
32
|
+
clearErrors(...fields: Array<keyof ResolveActionBody<U> & string>): void;
|
|
33
|
+
clearError(): void;
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/runtime/use-navigation.d.ts
|
|
37
|
+
declare function useNavigation(): NavigationState;
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/runtime/use-island-form.d.ts
|
|
40
|
+
interface IslandFormReturn<T extends Record<string, unknown>> {
|
|
41
|
+
data: T;
|
|
42
|
+
errors: Record<string, string>;
|
|
43
|
+
error: VoidActionError | null;
|
|
44
|
+
pending: boolean;
|
|
45
|
+
hasChanges: boolean;
|
|
46
|
+
wasSuccessful: boolean;
|
|
47
|
+
recentlySuccessful: boolean;
|
|
48
|
+
submit(url: string, method: string): Promise<void>;
|
|
49
|
+
post(url: string): Promise<void>;
|
|
50
|
+
put(url: string): Promise<void>;
|
|
51
|
+
patch(url: string): Promise<void>;
|
|
52
|
+
delete(url: string): Promise<void>;
|
|
53
|
+
reset(...fields: Array<keyof T & string>): void;
|
|
54
|
+
clearErrors(...fields: Array<string>): void;
|
|
55
|
+
clearError(): void;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Form composable for island pages. Uses fetch + page reload instead of the
|
|
59
|
+
* Void Router (which is not available in island mode).
|
|
60
|
+
*/
|
|
61
|
+
declare function useIslandForm<T extends Record<string, unknown>>(defaults: T): IslandFormReturn<T>;
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/runtime/action.d.ts
|
|
64
|
+
type ActionMethod = "POST" | "PUT" | "PATCH" | "DELETE";
|
|
65
|
+
type HasParams<U extends string> = [ResolveActionParams<U>] extends [never] ? false : true;
|
|
66
|
+
type ActionOptions<U extends string> = {
|
|
67
|
+
data?: ResolveActionBody<U>;
|
|
68
|
+
method?: ActionMethod;
|
|
69
|
+
} & (HasParams<U> extends true ? {
|
|
70
|
+
params: ResolveActionParams<U>;
|
|
71
|
+
} : {
|
|
72
|
+
params?: never;
|
|
73
|
+
});
|
|
74
|
+
/** Called during app initialization to store the router instance */
|
|
75
|
+
declare function setActionRouter(router: VoidRouter): void;
|
|
76
|
+
/** Programmatic one-shot page action call with Inertia page update */
|
|
77
|
+
declare function action<U extends ActionUrl & string>(url: U, ...args: HasParams<U> extends true ? [options: ActionOptions<U>] : [options?: ActionOptions<U>]): Promise<ActionResult>;
|
|
78
|
+
//#endregion
|
|
79
|
+
export { useIslandForm as a, useShared as c, setActionRouter as i, useRouter as l, InferProps as n, useNavigation as o, action as r, useForm as s, Deferred as t, Link as u };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as useIslandForm, c as useShared, i as setActionRouter, l as useRouter, n as InferProps, o as useNavigation, r as action, s as useForm, t as Deferred, u as Link } from "./index-C0fE29Kv.mjs";
|
|
2
|
+
export { Deferred, InferProps, Link, action, setActionRouter, useForm, useIslandForm, useNavigation, useRouter, useShared };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import vue from "@vitejs/plugin-vue";
|
|
2
|
+
import { Plugin } from "vite";
|
|
3
|
+
|
|
4
|
+
//#region src/plugin.d.ts
|
|
5
|
+
interface VoidVueOptions {
|
|
6
|
+
vue?: Parameters<typeof vue>[0];
|
|
7
|
+
viewTransitions?: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare function voidVue(options?: VoidVueOptions): Array<Plugin>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { VoidVueOptions, voidVue };
|