nuxt-ui-formwerk 0.1.3 → 0.1.4
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 +81 -55
- package/dist/module.json +1 -1
- package/dist/module.mjs +3 -1
- package/dist/runtime/components/Field.d.vue.ts +1 -1
- package/dist/runtime/components/Field.vue +24 -4
- package/dist/runtime/components/Field.vue.d.ts +1 -1
- package/dist/runtime/components/Form.vue +14 -2
- package/package.json +8 -6
package/README.md
CHANGED
|
@@ -31,8 +31,8 @@ Add the module to your `nuxt.config.ts`:
|
|
|
31
31
|
|
|
32
32
|
```ts
|
|
33
33
|
export default defineNuxtConfig({
|
|
34
|
-
modules: [
|
|
35
|
-
})
|
|
34
|
+
modules: ["@nuxt/ui", "nuxt-ui-formwerk"],
|
|
35
|
+
});
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
That's it! You can now use enhanced form components in your Nuxt app ✨
|
|
@@ -47,21 +47,26 @@ The root form component that provides validation context and tracks form state.
|
|
|
47
47
|
|
|
48
48
|
```vue
|
|
49
49
|
<script setup lang="ts">
|
|
50
|
-
import { z } from
|
|
50
|
+
import { z } from "zod";
|
|
51
51
|
|
|
52
52
|
const schema = z.object({
|
|
53
53
|
email: z.string().email(),
|
|
54
|
-
password: z.string().min(8)
|
|
55
|
-
})
|
|
54
|
+
password: z.string().min(8),
|
|
55
|
+
});
|
|
56
56
|
|
|
57
57
|
const state = reactive({
|
|
58
|
-
email:
|
|
59
|
-
password:
|
|
60
|
-
})
|
|
58
|
+
email: "",
|
|
59
|
+
password: "",
|
|
60
|
+
});
|
|
61
61
|
</script>
|
|
62
62
|
|
|
63
63
|
<template>
|
|
64
|
-
<FormwerkForm
|
|
64
|
+
<FormwerkForm
|
|
65
|
+
:schema="schema"
|
|
66
|
+
:state="state"
|
|
67
|
+
validate-on="blur"
|
|
68
|
+
#="{ blurredFields, touchedFields, dirtyFields }"
|
|
69
|
+
>
|
|
65
70
|
<!-- Form content here -->
|
|
66
71
|
<p>Blurred fields: {{ blurredFields.size }}</p>
|
|
67
72
|
</FormwerkForm>
|
|
@@ -70,10 +75,10 @@ const state = reactive({
|
|
|
70
75
|
|
|
71
76
|
#### Props
|
|
72
77
|
|
|
73
|
-
| Prop | Type
|
|
74
|
-
| ------------ |
|
|
75
|
-
| `validateOn` | `'touched' \| 'blur' \| 'dirty'` | `'blur'` | When to trigger validation
|
|
76
|
-
| `disabled` | `boolean`
|
|
78
|
+
| Prop | Type | Default | Description |
|
|
79
|
+
| ------------ | -------------------------------- | -------- | -------------------------- |
|
|
80
|
+
| `validateOn` | `'touched' \| 'blur' \| 'dirty'` | `'blur'` | When to trigger validation |
|
|
81
|
+
| `disabled` | `boolean` | `false` | Disable all form fields |
|
|
77
82
|
|
|
78
83
|
#### Slot Props
|
|
79
84
|
|
|
@@ -137,43 +142,64 @@ Groups related form fields together for nested validation.
|
|
|
137
142
|
|
|
138
143
|
```vue
|
|
139
144
|
<script setup lang="ts">
|
|
140
|
-
import { z } from
|
|
145
|
+
import { z } from "zod";
|
|
141
146
|
|
|
142
147
|
const schema = z.object({
|
|
143
|
-
name: z.string().min(2,
|
|
144
|
-
email: z.string().email(
|
|
145
|
-
password: z.string().min(8,
|
|
146
|
-
})
|
|
148
|
+
name: z.string().min(2, "Name must be at least 2 characters"),
|
|
149
|
+
email: z.string().email("Invalid email address"),
|
|
150
|
+
password: z.string().min(8, "Password must be at least 8 characters"),
|
|
151
|
+
});
|
|
147
152
|
|
|
148
153
|
const state = reactive({
|
|
149
|
-
name:
|
|
150
|
-
email:
|
|
151
|
-
password:
|
|
152
|
-
})
|
|
154
|
+
name: "",
|
|
155
|
+
email: "",
|
|
156
|
+
password: "",
|
|
157
|
+
});
|
|
153
158
|
|
|
154
159
|
const onSubmit = () => {
|
|
155
|
-
console.log(
|
|
156
|
-
}
|
|
160
|
+
console.log("Form submitted:", state);
|
|
161
|
+
};
|
|
157
162
|
</script>
|
|
158
163
|
|
|
159
164
|
<template>
|
|
160
|
-
<FormwerkForm
|
|
165
|
+
<FormwerkForm
|
|
166
|
+
:schema="schema"
|
|
167
|
+
:state="state"
|
|
168
|
+
validate-on="blur"
|
|
169
|
+
#="{ blurredFields }"
|
|
170
|
+
>
|
|
161
171
|
<div class="space-y-4">
|
|
162
172
|
<FormwerkField name="name" label="Name" required #="{ setValue, value }">
|
|
163
173
|
<UInput :model-value="value" @update:model-value="setValue" />
|
|
164
174
|
</FormwerkField>
|
|
165
175
|
|
|
166
|
-
<FormwerkField
|
|
167
|
-
|
|
176
|
+
<FormwerkField
|
|
177
|
+
name="email"
|
|
178
|
+
label="Email"
|
|
179
|
+
required
|
|
180
|
+
#="{ setValue, value }"
|
|
181
|
+
>
|
|
182
|
+
<UInput
|
|
183
|
+
:model-value="value"
|
|
184
|
+
@update:model-value="setValue"
|
|
185
|
+
type="email"
|
|
186
|
+
/>
|
|
168
187
|
</FormwerkField>
|
|
169
188
|
|
|
170
|
-
<FormwerkField
|
|
171
|
-
|
|
189
|
+
<FormwerkField
|
|
190
|
+
name="password"
|
|
191
|
+
label="Password"
|
|
192
|
+
required
|
|
193
|
+
#="{ setValue, value }"
|
|
194
|
+
>
|
|
195
|
+
<UInput
|
|
196
|
+
:model-value="value"
|
|
197
|
+
@update:model-value="setValue"
|
|
198
|
+
type="password"
|
|
199
|
+
/>
|
|
172
200
|
</FormwerkField>
|
|
173
201
|
|
|
174
|
-
<UButton type="submit" @click="onSubmit">
|
|
175
|
-
Submit
|
|
176
|
-
</UButton>
|
|
202
|
+
<UButton type="submit" @click="onSubmit"> Submit </UButton>
|
|
177
203
|
|
|
178
204
|
<p class="text-sm text-gray-500">
|
|
179
205
|
Fields blurred: {{ blurredFields.size }}
|
|
@@ -207,38 +233,38 @@ The integration allows you to use Nuxt UI's beautiful form components while leve
|
|
|
207
233
|
<details>
|
|
208
234
|
<summary>Local development</summary>
|
|
209
235
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
236
|
+
```bash
|
|
237
|
+
# Install dependencies
|
|
238
|
+
pnpm install
|
|
213
239
|
|
|
214
|
-
|
|
215
|
-
|
|
240
|
+
# Generate type stubs and prepare playground
|
|
241
|
+
pnpm dev:prepare
|
|
216
242
|
|
|
217
|
-
|
|
218
|
-
|
|
243
|
+
# Develop with the playground
|
|
244
|
+
pnpm dev
|
|
219
245
|
|
|
220
|
-
|
|
221
|
-
|
|
246
|
+
# Build the playground
|
|
247
|
+
pnpm dev:build
|
|
222
248
|
|
|
223
|
-
|
|
224
|
-
|
|
249
|
+
# Run linter (oxlint)
|
|
250
|
+
pnpm lint
|
|
225
251
|
|
|
226
|
-
|
|
227
|
-
|
|
252
|
+
# Fix linting issues
|
|
253
|
+
pnpm lint:fix
|
|
228
254
|
|
|
229
|
-
|
|
230
|
-
|
|
255
|
+
# Format code (oxfmt)
|
|
256
|
+
pnpm format
|
|
231
257
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
258
|
+
# Run tests
|
|
259
|
+
pnpm test
|
|
260
|
+
pnpm test:watch
|
|
235
261
|
|
|
236
|
-
|
|
237
|
-
|
|
262
|
+
# Type check
|
|
263
|
+
pnpm test:types
|
|
238
264
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
265
|
+
# Release new version
|
|
266
|
+
pnpm release
|
|
267
|
+
```
|
|
242
268
|
|
|
243
269
|
</details>
|
|
244
270
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -10,7 +10,9 @@ const module$1 = defineNuxtModule({
|
|
|
10
10
|
const resolver = createResolver(import.meta.url);
|
|
11
11
|
const logger = useLogger("nuxt-ui-formwerk");
|
|
12
12
|
if (!hasNuxtModule("@nuxt/ui")) {
|
|
13
|
-
logger.error(
|
|
13
|
+
logger.error(
|
|
14
|
+
"[nuxt-ui-formwerk] @nuxt/ui is required. Please install it"
|
|
15
|
+
);
|
|
14
16
|
}
|
|
15
17
|
addComponentsDir({
|
|
16
18
|
path: resolver.resolve("./runtime/components"),
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import {} from "@nuxt/ui";
|
|
2
3
|
import { useCustomControl } from "@formwerk/core";
|
|
3
|
-
import {
|
|
4
|
+
import { formBusInjectionKey } from "@nuxt/ui/composables/useFormField";
|
|
5
|
+
import { inject, watch, computed } from "vue";
|
|
6
|
+
import {
|
|
7
|
+
formwerkOptionsInjectionKey,
|
|
8
|
+
formwerkBusInjectionKey
|
|
9
|
+
} from "./Form.vue";
|
|
4
10
|
const props = defineProps({
|
|
5
11
|
as: { type: null, required: false },
|
|
6
12
|
name: { type: String, required: false },
|
|
@@ -17,8 +23,21 @@ const formBus = inject(formBusInjectionKey, void 0);
|
|
|
17
23
|
const formwerkBus = inject(formwerkBusInjectionKey, void 0);
|
|
18
24
|
const formwerkOptions = inject(formwerkOptionsInjectionKey, void 0);
|
|
19
25
|
const {
|
|
20
|
-
field: {
|
|
21
|
-
|
|
26
|
+
field: {
|
|
27
|
+
errorMessage,
|
|
28
|
+
fieldValue,
|
|
29
|
+
setValue,
|
|
30
|
+
setBlurred,
|
|
31
|
+
setTouched,
|
|
32
|
+
isTouched,
|
|
33
|
+
isBlurred,
|
|
34
|
+
isDirty
|
|
35
|
+
}
|
|
36
|
+
} = useCustomControl({
|
|
37
|
+
name: props.name,
|
|
38
|
+
required: props.required,
|
|
39
|
+
disabled: formwerkOptions?.value?.disabled
|
|
40
|
+
});
|
|
22
41
|
const emitFormEvent = (type, name, payload) => {
|
|
23
42
|
if (formwerkBus && name) formwerkBus.emit(type, { name, payload });
|
|
24
43
|
};
|
|
@@ -26,7 +45,8 @@ watch(isTouched, (newValue) => emitFormEvent("touched", props.name, newValue));
|
|
|
26
45
|
watch(isBlurred, (newValue) => emitFormEvent("blur", props.name, newValue));
|
|
27
46
|
watch(isDirty, (newValue) => emitFormEvent("dirty", props.name, newValue));
|
|
28
47
|
const error = computed(() => {
|
|
29
|
-
if (!formwerkOptions || !formwerkOptions.value)
|
|
48
|
+
if (!formwerkOptions || !formwerkOptions.value)
|
|
49
|
+
return errorMessage.value ? errorMessage.value : void 0;
|
|
30
50
|
switch (formwerkOptions.value.validateOn) {
|
|
31
51
|
case "blur":
|
|
32
52
|
return isBlurred.value && errorMessage.value ? errorMessage.value : void 0;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import { provide, reactive, computed } from "vue";
|
|
3
|
+
import {
|
|
4
|
+
formBusInjectionKey,
|
|
5
|
+
formOptionsInjectionKey
|
|
6
|
+
} from "@nuxt/ui/composables/useFormField";
|
|
7
|
+
import { useEventBus } from "@vueuse/core";
|
|
2
8
|
import { useFormContext } from "@formwerk/core";
|
|
3
9
|
export const formwerkOptionsInjectionKey = /* @__PURE__ */ Symbol("nuxt-ui-formwerk.form-options");
|
|
4
10
|
export const formwerkBusInjectionKey = /* @__PURE__ */ Symbol("nuxt-ui-formwerk.form-events");
|
|
@@ -10,7 +16,9 @@ const { validateOn = "blur", disabled = false } = defineProps({
|
|
|
10
16
|
validateOn: { type: String, required: false },
|
|
11
17
|
disabled: { type: Boolean, required: false }
|
|
12
18
|
});
|
|
13
|
-
const formwerkBus = useEventBus(
|
|
19
|
+
const formwerkBus = useEventBus(
|
|
20
|
+
`formwerk-form-${context.id}`
|
|
21
|
+
);
|
|
14
22
|
const NuxtUiFormBus = useEventBus(`form-${context.id}`);
|
|
15
23
|
const dirtyFields = reactive(/* @__PURE__ */ new Set());
|
|
16
24
|
const touchedFields = reactive(/* @__PURE__ */ new Set());
|
|
@@ -55,6 +63,10 @@ formwerkBus.on(async (event, payload) => {
|
|
|
55
63
|
|
|
56
64
|
<template>
|
|
57
65
|
<div>
|
|
58
|
-
<slot
|
|
66
|
+
<slot
|
|
67
|
+
:blurred-fields="blurredFields"
|
|
68
|
+
:touched-fields="touchedFields"
|
|
69
|
+
:dirty-fields="dirtyFields"
|
|
70
|
+
/>
|
|
59
71
|
</div>
|
|
60
72
|
</template>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-ui-formwerk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "A collection of beautiful, animated UI components for Nuxt applications",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "https://github.com/genu/nuxt-ui-formwerk.git",
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@nuxt/kit": "^4.2.2"
|
|
26
|
+
"@nuxt/kit": "^4.2.2",
|
|
27
|
+
"@vueuse/core": "^14.1.0"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
30
|
"@nuxt/devtools": "^3.1.1",
|
|
@@ -37,13 +38,14 @@
|
|
|
37
38
|
"oxfmt": "^0.20.0",
|
|
38
39
|
"oxlint": "^1.35.0",
|
|
39
40
|
"oxlint-tsgolint": "^0.10.0",
|
|
41
|
+
"prettier": "^3.7.4",
|
|
40
42
|
"typescript": "~5.9.3",
|
|
41
43
|
"vitest": "^4.0.16",
|
|
42
44
|
"vue-tsc": "^3.2.1"
|
|
43
45
|
},
|
|
44
46
|
"peerDependencies": {
|
|
45
|
-
"@
|
|
46
|
-
"@
|
|
47
|
+
"@formwerk/core": "^0.14.4",
|
|
48
|
+
"@nuxt/ui": "^4.0.0"
|
|
47
49
|
},
|
|
48
50
|
"scripts": {
|
|
49
51
|
"dev": "pnpm dev:prepare && nuxi dev playground",
|
|
@@ -51,8 +53,8 @@
|
|
|
51
53
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
52
54
|
"lint": "oxlint --type-aware",
|
|
53
55
|
"lint:fix": "oxlint --fix --type-aware",
|
|
54
|
-
"format": "
|
|
55
|
-
"format:check": "
|
|
56
|
+
"format": "prettier --write .",
|
|
57
|
+
"format:check": "prettier --check .",
|
|
56
58
|
"release": "pnpm lint && pnpm test && pnpm prepack && changelogen --release && pnpm publish && git push --follow-tags",
|
|
57
59
|
"test": "vitest run",
|
|
58
60
|
"test:watch": "vitest watch",
|