Skip to content

Commit 7e90d16

Browse files
authored
Merge pull request #48 from 7span/local
Initialize documentation site with VitePress.
2 parents 7a06afa + 9b84298 commit 7e90d16

File tree

10 files changed

+4539
-2499
lines changed

10 files changed

+4539
-2499
lines changed

apps/docs/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.vitepress/cache
2+
.vitepress/dist
3+
.vitepress/temp

apps/docs/.vitepress/config.mjs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { defineConfig } from "vitepress";
2+
3+
export default defineConfig({
4+
title: "Vue Form",
5+
description: "Dynamic forms for Vue 2 & 3",
6+
base: "/open-source/vue-form/",
7+
themeConfig: {
8+
nav: [{ text: "Introduction", link: "/" }],
9+
sidebar: [
10+
{
11+
text: "Introduction",
12+
items: [{ text: "What is Vue Form?", link: "/" }],
13+
},
14+
{
15+
text: "Configurations",
16+
items: [{ text: "Plugin Options", link: "/configurations" }],
17+
},
18+
{
19+
text: "Components",
20+
items: [{ text: "Component Guide", link: "/components" }],
21+
},
22+
],
23+
socialLinks: [
24+
{ icon: "github", link: "https://github.com/7span/vue-form" },
25+
],
26+
},
27+
});

apps/docs/components.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Components
2+
3+
## Vue 3 / Vue 2 (options & slots)
4+
5+
Both builds expose a single global component using the configured prefix (`VForm` by default).
6+
7+
### Props
8+
9+
- `fields` (Array, required): field definitions. Strings become `{ name, value: null }`; objects merge with defaults. Supports `in` and `out` transforms for coercion.
10+
- `id` (String|Number): primary key; when present the form enters `edit` mode and runs `get`.
11+
- `nativeId` (String): applied to the root div.
12+
- `get(id)`, `save(id, values)`, `delete(id, values)`, `archive(id, values)`: async callbacks for CRUD.
13+
- `formState`, `formValues` (sync v-model style): emitted via `update:formState` and `update:formValues`.
14+
15+
### Slot scope
16+
17+
`VForm` renders no UI. Everything is exposed through the default slot:
18+
19+
- `mode`, `isCreating`, `isEditing`
20+
- `state` (raw in-state), `values` (after `out()` transform)
21+
- Actions: `getItem`, `saveItem`, `deleteItem`, `archiveItem`, `setValue`, `reset`
22+
- Flags: `isSaving`, `isGetting`, `isDeleting`, `isArchiving`, `isLoading`, `isArchived`
23+
- Errors: `errors`, `error`, `hasError`, `fieldErrors`, `nonFieldErrors`
24+
25+
Example (Vue 3 options):
26+
27+
```vue
28+
<VForm
29+
:fields="[{ name: 'title', value: '' }, 'description']"
30+
:get="fetchPost"
31+
:save="savePost"
32+
:id="postId"
33+
v-slot="{ values, saveItem, isSaving, errors }"
34+
>
35+
<input v-model="values.title" placeholder="Title" />
36+
<textarea v-model="values.description" />
37+
<p v-if="errors?.title">{{ errors.title }}</p>
38+
<button :disabled="isSaving" @click="saveItem">Save</button>
39+
</VForm>
40+
```
41+
42+
Vue 2 usage is identical; reactivity uses `this.$set` internally.
43+
44+
## Vue 3 (composition bundle)
45+
46+
The composition build offers granular components and shared state via provide/inject.
47+
48+
### Core component
49+
50+
`VueForm` (or prefixed) accepts:
51+
52+
- `fields` (Array, required)
53+
- `itemId` (String|Number)
54+
- CRUD callbacks: `create(context)`, `read(itemId, context)`, `update(itemId, context)`, `delete(itemId, context)`, `archive(itemId, context)`, `unarchive(itemId, context)`
55+
56+
It exposes slot props:
57+
58+
- `context`: `isNewItem`, `normalizedFields`, `values`, `dirtyValues`, `error`, `itemId`, loading flags, `isArchived`, `touched`, `dirty`
59+
- Actions: `readItem`, `createItem`, `updateItem`, `deleteItem`, `archiveItem`, `unarchiveItem`
60+
61+
### Field helpers
62+
63+
- `VueFormFields`: slot props `{ values, dirtyValues, fieldErrors, hasError }`.
64+
- `VueFormField name="fieldName"`: slot props `{ error, label, name, value, updateValue, field, nativeField }`. Use `field` for Vue component v-model bindings, `nativeField` for plain inputs.
65+
66+
### Action helpers
67+
68+
Buttons with sensible loading labels; each exposes action and flags in its slot:
69+
70+
- `VueFormCreate`, `VueFormUpdate`, `VueFormDelete`, `VueFormArchive`, `VueFormUnarchive`
71+
- `VueFormError`: renders nothing by default but surfaces normalized `error`.
72+
73+
### Example
74+
75+
```vue
76+
<VueForm
77+
:fields="['name', { name: 'email', value: '' }]"
78+
:read="(id) => api.read(id)"
79+
:create="(ctx) => api.create(ctx.values)"
80+
:update="(id, ctx) => api.update(id, ctx.dirtyValues)"
81+
>
82+
<template #default>
83+
<VueFormFields v-slot="{ values, fieldErrors }">
84+
<VueFormField name="name" v-slot="{ label, nativeField, error }">
85+
<label>{{ label }}</label>
86+
<input v-bind="nativeField" />
87+
<small v-if="error">{{ error }}</small>
88+
</VueFormField>
89+
<VueFormField name="email" v-slot="{ nativeField, error }">
90+
<input type="email" v-bind="nativeField" />
91+
<small v-if="error">{{ error }}</small>
92+
</VueFormField>
93+
</VueFormFields>
94+
<VueFormCreate />
95+
<VueFormUpdate />
96+
</template>
97+
</VueForm>
98+
```
99+

apps/docs/configurations.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Configurations
2+
3+
Vue Form exposes lightweight plugin options so you can match component prefixes and error handling to your app. Each package has its own defaults.
4+
5+
## Vue 3 (options / slots)
6+
7+
Default options come from `packages/vue3/src/options.js`.
8+
9+
| Option | Default | Description |
10+
| --- | --- | --- |
11+
| `componentPrefix` | `"V"` | Prefix used when registering the global component (exposes `VForm` by default). |
12+
| `errorAdapter` | `(errors) => errors` | Map your backend error shape to `{ fields, message }`. Used by `setErrors` inside the form. |
13+
14+
Configure on install:
15+
16+
```js
17+
import VueForm from '@7span/vue-form'
18+
19+
app.use(VueForm, {
20+
componentPrefix: 'V',
21+
errorAdapter: (err) => ({
22+
fields: err?.errors || {},
23+
message: err?.message || 'Unable to save form',
24+
}),
25+
})
26+
```
27+
28+
## Vue 2 (options / slots)
29+
30+
Defaults mirror the Vue 3 options build (`packages/vue2/src/options.js`).
31+
32+
| Option | Default | Description |
33+
| --- | --- | --- |
34+
| `componentPrefix` | `"V"` | Registers `VForm` globally. |
35+
| `errorAdapter` | `(errors) => errors` | Normalize backend errors to `{ fields, message }`. |
36+
37+
Install with options:
38+
39+
```js
40+
import Vue from 'vue'
41+
import VueForm from '@7span/vue-form'
42+
43+
Vue.use(VueForm, {
44+
componentPrefix: 'V',
45+
errorAdapter: (err) => ({
46+
fields: err?.errors || {},
47+
message: err?.message,
48+
}),
49+
})
50+
```
51+
52+
## Vue 3 (composition bundle)
53+
54+
Defaults from `packages/vue3-composition/src/options.js`.
55+
56+
| Option | Default | Description |
57+
| --- | --- | --- |
58+
| `componentPrefix` | `""` | Registers `VueForm`, `VueFormField`, etc., without a prefix. |
59+
| `isNewItemCheck` | `({ itemId }) => itemId === '+'` | Decide whether the current record is in “create” mode. |
60+
| `isArchivedItemCheck` | `(response) => response.isArchived == true` | Detect archived records after read/create/update. |
61+
| `errorAdapter` | `(error) => ({ name, message, fieldErrors })` | Normalize errors surfaced to `VueFormError` and slot props. |
62+
63+
Install with overrides:
64+
65+
```js
66+
import VueForm from '@7span/vue-form'
67+
68+
app.use(VueForm, {
69+
componentPrefix: 'My',
70+
isNewItemCheck: ({ itemId }) => !itemId,
71+
errorAdapter: (error) => ({
72+
name: error?.name || 'RequestError',
73+
message: error?.message || 'Request failed',
74+
fieldErrors: error?.errors || {},
75+
}),
76+
})
77+
```
78+
79+
## Field configuration (all builds)
80+
81+
`fields` accepts an array of strings or objects:
82+
83+
- String: `"email"``{ name: 'email', value: null }`
84+
- Object: `{ name: 'email', value: '[email protected]', label: 'Email' }`
85+
86+
In the options/slots builds, you can also provide field-level transforms:
87+
88+
- `in(value)` runs before setting local state.
89+
- `out(value)` runs before exposing values to the parent.
90+
91+
Use these to coerce numbers, trim text, or map select values without mutating the original payloads.
92+

apps/docs/index.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Introduction
2+
3+
Vue Form is a lightweight form helper that turns JSON-like field definitions into working CRUD-friendly forms. It ships in two flavors:
4+
5+
- Vue 3 options/slots package (v1.x) — registers a single `VForm` component with slot-driven rendering.
6+
- Vue 2 options/slots package (v0.x) — API mirrors the Vue 3 options version for legacy apps.
7+
- Vue 3 composition package (v3.x) — granular components (`VueForm`, `VueFormField`, etc.) with provide/inject state and action helpers.
8+
9+
## Installation
10+
11+
Use any package manager (npm shown here). All packages publish under `@7span/vue-form`; use version ranges to target the framework you need.
12+
13+
```bash
14+
# Vue 3 (options API, slots)
15+
npm install @7span/vue-form@^1
16+
17+
# Vue 2
18+
npm install @7span/vue-form@^0
19+
20+
# Vue 3 (composition API bundle)
21+
npm install @7span/vue-form@^3
22+
```
23+
24+
## Quick start (Vue 3 options / slots)
25+
26+
```js
27+
// main.js
28+
import { createApp } from 'vue'
29+
import VueForm from '@7span/vue-form'
30+
import App from './App.vue'
31+
32+
createApp(App).use(VueForm).mount('#app')
33+
```
34+
35+
```vue
36+
<template>
37+
<VForm
38+
v-slot="{ values, saveItem, isSaving, errors }"
39+
:fields="['name', { name: 'email', value: '[email protected]' }]"
40+
:save="saveUser"
41+
>
42+
<input v-model="values.name" placeholder="Name" />
43+
<input v-model="values.email" placeholder="Email" />
44+
<p v-if="errors?.email">{{ errors.email }}</p>
45+
<button :disabled="isSaving" @click="saveItem">Save</button>
46+
</VForm>
47+
</template>
48+
```
49+
50+
## Quick start (Vue 2 options / slots)
51+
52+
```js
53+
// main.js
54+
import Vue from 'vue'
55+
import VueForm from '@7span/vue-form'
56+
57+
Vue.use(VueForm)
58+
```
59+
60+
```vue
61+
<template>
62+
<VForm
63+
v-slot="{ values, saveItem, isSaving, errors }"
64+
:fields="['name', 'email']"
65+
:save="saveUser"
66+
>
67+
<input v-model="values.name" placeholder="Name" />
68+
<input v-model="values.email" placeholder="Email" />
69+
<p v-if="errors?.email">{{ errors.email }}</p>
70+
<button :disabled="isSaving" @click="saveItem">Save</button>
71+
</VForm>
72+
</template>
73+
```
74+
75+
## Quick start (Vue 3 composition bundle)
76+
77+
```js
78+
// main.js
79+
import { createApp } from 'vue'
80+
import VueForm from '@7span/vue-form'
81+
import App from './App.vue'
82+
83+
createApp(App).use(VueForm).mount('#app')
84+
```
85+
86+
```vue
87+
<template>
88+
<VueForm
89+
:fields="['name', { name: 'email', value: '[email protected]' }]"
90+
:read="readUser"
91+
:create="createUser"
92+
:update="updateUser"
93+
>
94+
<template #default="{ context }">
95+
<VueFormFields v-slot="{ values }">
96+
<label>Name</label>
97+
<input v-model="values.name" />
98+
<label>Email</label>
99+
<input v-model="values.email" />
100+
</VueFormFields>
101+
<VueFormCreate />
102+
<VueFormUpdate />
103+
</template>
104+
</VueForm>
105+
</template>
106+
```
107+
108+
## Package mapping
109+
110+
- Vue 3 options/slots: uses `componentPrefix` to expose `VForm` by default and provides `OPTIONS` via dependency injection.
111+
- Vue 2 options/slots: same slot contract as Vue 3 options; uses `this.$set` internally for reactivity.
112+
- Vue 3 composition bundle: exposes granular components and injects shared state/actions so you can compose any UI library.
113+
114+
Next, see **Configurations** for plugin options and **Components** for slot props and action helpers.

0 commit comments

Comments
 (0)