@overgaming/valiform 0.2.0 → 0.2.2

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.
Files changed (2) hide show
  1. package/README.md +268 -0
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -0,0 +1,268 @@
1
+ # Valiform
2
+
3
+ Lightweight, headless form validation library for Vue 3. Framework-agnostic validation rules, composable field state, and full localization support — with zero UI assumptions.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @overgaming/valiform
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ ### Vue
14
+
15
+ ```ts
16
+ import { createApp } from 'vue';
17
+ import { FormsPlugin } from '@overgaming/valiform';
18
+ import { es } from '@overgaming/valiform/locales';
19
+
20
+ const app = createApp(App);
21
+
22
+ app.use(FormsPlugin, {
23
+ locale: 'es',
24
+ locales: { es }
25
+ });
26
+ ```
27
+
28
+ ### Nuxt
29
+
30
+ ```ts
31
+ // nuxt.config.ts
32
+ export default defineNuxtConfig({
33
+ modules: ['@overgaming/valiform/nuxt'],
34
+ valiform: {
35
+ locale: 'es',
36
+ locales: { es }
37
+ }
38
+ });
39
+ ```
40
+
41
+ The Nuxt module auto-imports `<Form>`, `<Field>`, `useLocale`, `useFormContext` and `useFieldContext`.
42
+
43
+ ---
44
+
45
+ ## Usage
46
+
47
+ ### With custom components (recommended)
48
+
49
+ Build a custom input component using `useFieldContext` and `defineModel`:
50
+
51
+ ```vue
52
+ <!-- MyInput.vue -->
53
+ <template>
54
+ <input
55
+ class="my-input"
56
+ :class="{ 'my-input--error': error }"
57
+ v-model.trim="inputValue"
58
+ v-bind="inputProps"
59
+ :type
60
+ />
61
+ </template>
62
+
63
+ <script setup lang="ts">
64
+ import { useFieldContext } from '@overgaming/valiform';
65
+
66
+ defineProps({
67
+ type: { type: String, default: 'text' }
68
+ });
69
+
70
+ const model = defineModel({ type: String, default: '' });
71
+ const { inputValue, inputProps, error } = useFieldContext({ inputValue: model });
72
+ </script>
73
+ ```
74
+
75
+ Then use it inside a `<Field>`:
76
+
77
+ ```vue
78
+ <template>
79
+ <Form v-model="formData" @submit="handleSubmit" v-slot="{ isValid }">
80
+ <Field
81
+ name="name"
82
+ validation="required|min:3"
83
+ v-slot="{ labelProps, errorProps, error, isTouched }"
84
+ >
85
+ <label v-bind="labelProps">Name</label>
86
+ <MyInput />
87
+ <span v-if="error && isTouched" v-bind="errorProps">{{ error }}</span>
88
+ </Field>
89
+
90
+ <button type="submit" :disabled="!isValid">Submit</button>
91
+ </Form>
92
+ </template>
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Components
98
+
99
+ ### `<Form>`
100
+
101
+ Wraps your form and manages the global form state.
102
+
103
+ | Prop | Type | Description |
104
+ | ------------ | ------------------------- | -------------------------------- |
105
+ | `modelValue` | `Record<string, unknown>` | Form values (use with `v-model`) |
106
+
107
+ | Event | Payload | Description |
108
+ | -------- | -------------------------------- | ---------------------------- |
109
+ | `submit` | `(values, { setErrors, reset })` | Emitted on valid form submit |
110
+
111
+ | Slot prop | Type | Description |
112
+ | ---------- | ------------ | ----------------------------------- |
113
+ | `isValid` | `boolean` | Whether all fields are valid |
114
+ | `errors` | `string[]` | Array of all form-level errors |
115
+ | `reset` | `() => void` | Resets all fields to initial values |
116
+ | `validate` | `() => void` | Triggers validation on all fields |
117
+
118
+ ### `<Field>`
119
+
120
+ Manages a single field's state and validation.
121
+
122
+ | Prop | Type | Description |
123
+ | -------------------- | ------------------------- | --------------------------------------- |
124
+ | `name` | `string` | Field name (used as key in form values) |
125
+ | `modelValue` | `unknown` | Field value when used outside `<Form>` |
126
+ | `validation` | `string \| Function` | Validation rules |
127
+ | `validationMessages` | `Record<string, unknown>` | Custom error messages for this field |
128
+ | `error` | `string \| string[]` | External error (e.g. from API) |
129
+ | `id` | `string` | Override the auto-generated input id |
130
+
131
+ | Slot prop | Type | Description |
132
+ | ------------ | ------------------------- | --------------------------------------------------------------------------------------------------------- |
133
+ | `inputProps` | `object` | Props for custom Vue components (`modelValue`, `onUpdate:modelValue`, `onBlur`, `id`, `name`, aria attrs) |
134
+ | `inputValue` | `unknown` | Current field value (writable) |
135
+ | `labelProps` | `{ for: string }` | Props for `<label>` |
136
+ | `errorProps` | `{ id, role, aria-live }` | Props for the error element |
137
+ | `helpProps` | `{ id: string }` | Props for a help text element |
138
+ | `error` | `string \| null` | First error message |
139
+ | `errors` | `string[]` | All error messages |
140
+ | `isValid` | `boolean` | Whether the field is valid |
141
+ | `isTouched` | `boolean` | Whether the field has been blurred |
142
+ | `isDirty` | `boolean` | Whether the value has changed |
143
+ | `validate` | `() => void` | Triggers validation manually |
144
+ | `reset` | `() => void` | Resets to initial value |
145
+
146
+ ---
147
+
148
+ ## Validation rules
149
+
150
+ Rules are specified as a pipe-separated string: `"required|min:3|max:100"`.
151
+
152
+ | Rule | Arguments | Description |
153
+ | ------------------- | -------------------- | ------------------------------------------ |
154
+ | `required` | — | Value must not be empty |
155
+ | `min` | `min` | Minimum string length |
156
+ | `max` | `max` | Maximum string length |
157
+ | `email` | — | Valid email address |
158
+ | `url` | — | Valid URL |
159
+ | `number` | — | Must be a number |
160
+ | `alpha` | — | Letters only |
161
+ | `alphanumeric` | — | Letters and numbers only |
162
+ | `alphaSpaces` | — | Letters and spaces only |
163
+ | `lowercase` | — | Lowercase only |
164
+ | `uppercase` | — | Uppercase only |
165
+ | `between` | `min,max` | Number between two values |
166
+ | `length` | `exact` or `min,max` | String length |
167
+ | `matches` | `value1,value2,...` | Must match one of the values |
168
+ | `is` | `value` | Strict equality |
169
+ | `not` | `value` | Must not equal value |
170
+ | `accepted` | — | Must be truthy (checkboxes) |
171
+ | `confirm` | `fieldName` | Must match another field's value |
172
+ | `startsWith` | `prefix` | Must start with prefix |
173
+ | `endsWith` | `suffix` | Must end with suffix |
174
+ | `containsAlpha` | — | Must contain at least one letter |
175
+ | `containsNumeric` | — | Must contain at least one number |
176
+ | `containsUppercase` | — | Must contain at least one uppercase letter |
177
+ | `containsLowercase` | — | Must contain at least one lowercase letter |
178
+ | `containsSymbol` | — | Must contain at least one symbol |
179
+ | `dateFormat` | `format` | Valid date format |
180
+ | `dateAfter` | `date` | Date must be after |
181
+ | `dateBefore` | `date` | Date must be before |
182
+ | `dateBetween` | `start,end` | Date between two dates |
183
+
184
+ ### Custom rules
185
+
186
+ ```ts
187
+ app.use(FormsPlugin, {
188
+ rules: {
189
+ myRule: (value, { args, messages }) => {
190
+ if (value !== args[0]) return messages.myRule ?? 'Invalid value';
191
+ return true;
192
+ }
193
+ }
194
+ });
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Localization
200
+
201
+ Built-in locales: `en` (default), `es`.
202
+
203
+ ```ts
204
+ import { en, es } from '@overgaming/valiform';
205
+
206
+ app.use(FormsPlugin, {
207
+ locale: 'es',
208
+ locales: { en, es }
209
+ });
210
+ ```
211
+
212
+ ### Switch locale at runtime
213
+
214
+ ```vue
215
+ <script setup>
216
+ import { useLocale } from '@overgaming/valiform';
217
+
218
+ const { locale, setLocale } = useLocale();
219
+ </script>
220
+ ```
221
+
222
+ ### Custom locale
223
+
224
+ ```ts
225
+ app.use(FormsPlugin, {
226
+ locales: {
227
+ en: {
228
+ required: 'This field is required',
229
+ email: 'Enter a valid email',
230
+ min: ({ args }) => `Minimum ${args[0]} characters`
231
+ }
232
+ }
233
+ });
234
+ ```
235
+
236
+ ---
237
+
238
+ ## Composables
239
+
240
+ ### `useFormContext()`
241
+
242
+ Access the parent `<Form>` state from any descendant component.
243
+
244
+ ```ts
245
+ const { values, isValid, errors, reset, validate, setErrors } = useFormContext();
246
+ ```
247
+
248
+ ### `useFieldContext(options?)`
249
+
250
+ Access the parent `<Field>` state from any descendant component. Optionally pass `{ inputValue }` to sync a local ref (e.g. from `defineModel`) bidirectionally with the field value.
251
+
252
+ ```ts
253
+ // Basic usage
254
+ const { inputValue, inputProps, error, isValid, isTouched, isDirty } = useFieldContext();
255
+
256
+ // With defineModel sync
257
+ const model = defineModel({ type: String, default: '' });
258
+ const { inputValue, inputProps, error } = useFieldContext({ inputValue: model });
259
+ ```
260
+
261
+ ### `useLocale()`
262
+
263
+ Access and change the active locale.
264
+
265
+ ```ts
266
+ const { locale, setLocale } = useLocale();
267
+ setLocale('es');
268
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overgaming/valiform",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Vue 3 form validation library",
5
5
  "keywords": [
6
6
  "form",