nuxt-ui-formwerk 0.1.3 → 0.1.5

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
@@ -5,6 +5,13 @@
5
5
  [![License][license-src]][license-href]
6
6
  [![Nuxt][nuxt-src]][nuxt-href]
7
7
 
8
+ > [!WARNING]
9
+ > **⚠️ Experimental Module**
10
+ >
11
+ > This module is currently in an experimental phase. APIs may change, and some features may not be fully stable. Use with caution in production environments and please report any issues you encounter.
12
+ >
13
+ > **Technical Note:** This module works by tapping into Nuxt UI's form component injection mechanism and intercepting bus events to coordinate between Nuxt UI's native form system and formwerk's validation engine. Changes to Nuxt UI's internal form architecture may require updates to this module.
14
+
8
15
  Enhanced form components for Nuxt UI with [@formwerk/core](https://formwerk.dev/) integration. This module bridges the gap between Formwerk's powerful form validation and state management with Nuxt UI's beautiful form components.
9
16
 
10
17
  - [✨  Release Notes](/CHANGELOG.md)
@@ -31,8 +38,8 @@ Add the module to your `nuxt.config.ts`:
31
38
 
32
39
  ```ts
33
40
  export default defineNuxtConfig({
34
- modules: ['@nuxt/ui', 'nuxt-ui-formwerk']
35
- })
41
+ modules: ["@nuxt/ui", "nuxt-ui-formwerk"],
42
+ });
36
43
  ```
37
44
 
38
45
  That's it! You can now use enhanced form components in your Nuxt app ✨
@@ -47,21 +54,26 @@ The root form component that provides validation context and tracks form state.
47
54
 
48
55
  ```vue
49
56
  <script setup lang="ts">
50
- import { z } from 'zod'
57
+ import { z } from "zod";
51
58
 
52
59
  const schema = z.object({
53
60
  email: z.string().email(),
54
- password: z.string().min(8)
55
- })
61
+ password: z.string().min(8),
62
+ });
56
63
 
57
64
  const state = reactive({
58
- email: '',
59
- password: ''
60
- })
65
+ email: "",
66
+ password: "",
67
+ });
61
68
  </script>
62
69
 
63
70
  <template>
64
- <FormwerkForm :schema="schema" :state="state" validate-on="blur" #="{ blurredFields, touchedFields, dirtyFields }">
71
+ <FormwerkForm
72
+ :schema="schema"
73
+ :state="state"
74
+ validate-on="blur"
75
+ #="{ blurredFields, touchedFields, dirtyFields }"
76
+ >
65
77
  <!-- Form content here -->
66
78
  <p>Blurred fields: {{ blurredFields.size }}</p>
67
79
  </FormwerkForm>
@@ -70,10 +82,10 @@ const state = reactive({
70
82
 
71
83
  #### Props
72
84
 
73
- | Prop | Type | Default | Description |
74
- | ------------ | ------------------------------ | -------- | ----------------------------------------------- |
75
- | `validateOn` | `'touched' \| 'blur' \| 'dirty'` | `'blur'` | When to trigger validation |
76
- | `disabled` | `boolean` | `false` | Disable all form fields |
85
+ | Prop | Type | Default | Description |
86
+ | ------------ | -------------------------------- | -------- | -------------------------- |
87
+ | `validateOn` | `'touched' \| 'blur' \| 'dirty'` | `'blur'` | When to trigger validation |
88
+ | `disabled` | `boolean` | `false` | Disable all form fields |
77
89
 
78
90
  #### Slot Props
79
91
 
@@ -137,43 +149,64 @@ Groups related form fields together for nested validation.
137
149
 
138
150
  ```vue
139
151
  <script setup lang="ts">
140
- import { z } from 'zod'
152
+ import { z } from "zod";
141
153
 
142
154
  const schema = z.object({
143
- name: z.string().min(2, 'Name must be at least 2 characters'),
144
- email: z.string().email('Invalid email address'),
145
- password: z.string().min(8, 'Password must be at least 8 characters')
146
- })
155
+ name: z.string().min(2, "Name must be at least 2 characters"),
156
+ email: z.string().email("Invalid email address"),
157
+ password: z.string().min(8, "Password must be at least 8 characters"),
158
+ });
147
159
 
148
160
  const state = reactive({
149
- name: '',
150
- email: '',
151
- password: ''
152
- })
161
+ name: "",
162
+ email: "",
163
+ password: "",
164
+ });
153
165
 
154
166
  const onSubmit = () => {
155
- console.log('Form submitted:', state)
156
- }
167
+ console.log("Form submitted:", state);
168
+ };
157
169
  </script>
158
170
 
159
171
  <template>
160
- <FormwerkForm :schema="schema" :state="state" validate-on="blur" #="{ blurredFields }">
172
+ <FormwerkForm
173
+ :schema="schema"
174
+ :state="state"
175
+ validate-on="blur"
176
+ #="{ blurredFields }"
177
+ >
161
178
  <div class="space-y-4">
162
179
  <FormwerkField name="name" label="Name" required #="{ setValue, value }">
163
180
  <UInput :model-value="value" @update:model-value="setValue" />
164
181
  </FormwerkField>
165
182
 
166
- <FormwerkField name="email" label="Email" required #="{ setValue, value }">
167
- <UInput :model-value="value" @update:model-value="setValue" type="email" />
183
+ <FormwerkField
184
+ name="email"
185
+ label="Email"
186
+ required
187
+ #="{ setValue, value }"
188
+ >
189
+ <UInput
190
+ :model-value="value"
191
+ @update:model-value="setValue"
192
+ type="email"
193
+ />
168
194
  </FormwerkField>
169
195
 
170
- <FormwerkField name="password" label="Password" required #="{ setValue, value }">
171
- <UInput :model-value="value" @update:model-value="setValue" type="password" />
196
+ <FormwerkField
197
+ name="password"
198
+ label="Password"
199
+ required
200
+ #="{ setValue, value }"
201
+ >
202
+ <UInput
203
+ :model-value="value"
204
+ @update:model-value="setValue"
205
+ type="password"
206
+ />
172
207
  </FormwerkField>
173
208
 
174
- <UButton type="submit" @click="onSubmit">
175
- Submit
176
- </UButton>
209
+ <UButton type="submit" @click="onSubmit"> Submit </UButton>
177
210
 
178
211
  <p class="text-sm text-gray-500">
179
212
  Fields blurred: {{ blurredFields.size }}
@@ -207,38 +240,38 @@ The integration allows you to use Nuxt UI's beautiful form components while leve
207
240
  <details>
208
241
  <summary>Local development</summary>
209
242
 
210
- ```bash
211
- # Install dependencies
212
- pnpm install
243
+ ```bash
244
+ # Install dependencies
245
+ pnpm install
213
246
 
214
- # Generate type stubs and prepare playground
215
- pnpm dev:prepare
247
+ # Generate type stubs and prepare playground
248
+ pnpm dev:prepare
216
249
 
217
- # Develop with the playground
218
- pnpm dev
250
+ # Develop with the playground
251
+ pnpm dev
219
252
 
220
- # Build the playground
221
- pnpm dev:build
253
+ # Build the playground
254
+ pnpm dev:build
222
255
 
223
- # Run linter (oxlint)
224
- pnpm lint
256
+ # Run linter (oxlint)
257
+ pnpm lint
225
258
 
226
- # Fix linting issues
227
- pnpm lint:fix
259
+ # Fix linting issues
260
+ pnpm lint:fix
228
261
 
229
- # Format code (oxfmt)
230
- pnpm format
262
+ # Format code (oxfmt)
263
+ pnpm format
231
264
 
232
- # Run tests
233
- pnpm test
234
- pnpm test:watch
265
+ # Run tests
266
+ pnpm test
267
+ pnpm test:watch
235
268
 
236
- # Type check
237
- pnpm test:types
269
+ # Type check
270
+ pnpm test:types
238
271
 
239
- # Release new version
240
- pnpm release
241
- ```
272
+ # Release new version
273
+ pnpm release
274
+ ```
242
275
 
243
276
  </details>
244
277
 
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-ui-formwerk",
3
3
  "configKey": "uiElements",
4
- "version": "0.1.3",
4
+ "version": "0.1.5",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -6,6 +6,9 @@ const module$1 = defineNuxtModule({
6
6
  configKey: "uiElements"
7
7
  },
8
8
  defaults: {},
9
+ moduleDependencies: {
10
+ "@nuxt/ui": {}
11
+ },
9
12
  setup(_options, _nuxt) {
10
13
  const resolver = createResolver(import.meta.url);
11
14
  const logger = useLogger("nuxt-ui-formwerk");
@@ -1,4 +1,4 @@
1
- import type { FormFieldProps } from "@nuxt/ui";
1
+ import { type FormFieldProps } from "@nuxt/ui";
2
2
  type __VLS_Props = Omit<FormFieldProps, "validateOnInputDelay" | "errorPattern" | "eagerValidation" | "error">;
3
3
  declare var __VLS_8: {
4
4
  setValue: (value: any) => void;
@@ -1,6 +1,12 @@
1
1
  <script setup>
2
+ import {} from "@nuxt/ui";
2
3
  import { useCustomControl } from "@formwerk/core";
3
- import { formwerkOptionsInjectionKey, formwerkBusInjectionKey } from "./Form.vue";
4
+ import { formBusInjectionKey } from "#imports";
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: { errorMessage, fieldValue, setValue, setBlurred, setTouched, isTouched, isBlurred, isDirty }
21
- } = useCustomControl({ name: props.name, required: props.required, disabled: formwerkOptions?.value?.disabled });
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) return errorMessage.value ? errorMessage.value : void 0;
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,4 @@
1
- import type { FormFieldProps } from "@nuxt/ui";
1
+ import { type FormFieldProps } from "@nuxt/ui";
2
2
  type __VLS_Props = Omit<FormFieldProps, "validateOnInputDelay" | "errorPattern" | "eagerValidation" | "error">;
3
3
  declare var __VLS_8: {
4
4
  setValue: (value: any) => void;
@@ -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(`formwerk-form-${context.id}`);
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 :blurred-fields="blurredFields" :touched-fields="touchedFields" :dirty-fields="dirtyFields" />
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",
3
+ "version": "0.1.5",
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
- "@nuxt/ui": "^4.0.0",
46
- "@formwerk/core": "^0.14.4"
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": "oxfmt --write",
55
- "format:check": "oxfmt --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",