0
# Forms
1
2
Form components and validation utilities for user input collection and data entry.
3
4
## Capabilities
5
6
### VForm
7
8
Form wrapper component with validation, submission handling, and state management.
9
10
```typescript { .api }
11
/**
12
* Form wrapper with validation and submission handling
13
*/
14
const VForm: Component;
15
16
interface FormProps {
17
/** Form model value for validation state */
18
modelValue?: boolean;
19
/** Fast fail validation mode */
20
fastFail?: boolean;
21
/** Read-only form state */
22
readonly?: boolean;
23
/** Disabled form state */
24
disabled?: boolean;
25
/** Validate on blur */
26
validateOn?: 'blur' | 'input' | 'submit' | 'blur lazy' | 'input lazy' | 'submit lazy';
27
}
28
29
interface FormExposed {
30
/** Validate all form fields */
31
validate(): Promise<{ valid: boolean; errors: ValidationError[] }>;
32
/** Reset all form fields */
33
reset(): void;
34
/** Reset validation state */
35
resetValidation(): void;
36
/** Check if form is valid */
37
isValid: Ref<boolean>;
38
/** Form validation errors */
39
errors: Ref<ValidationError[]>;
40
}
41
42
// Events
43
interface FormEvents {
44
'update:modelValue': (valid: boolean) => void;
45
'submit': (event: SubmitEventPromise) => void;
46
}
47
48
interface SubmitEventPromise extends Event {
49
/** Promise that resolves when validation completes */
50
readonly valid: Promise<{ valid: boolean; errors: ValidationError[] }>;
51
}
52
53
interface ValidationError {
54
/** Field identifier */
55
id: string | number;
56
/** Error message */
57
errorMessages: string[];
58
}
59
```
60
61
**Usage Examples:**
62
63
```vue
64
<template>
65
<v-form
66
ref="form"
67
v-model="valid"
68
@submit.prevent="handleSubmit"
69
>
70
<v-text-field
71
v-model="name"
72
:rules="nameRules"
73
label="Name"
74
required
75
/>
76
77
<v-text-field
78
v-model="email"
79
:rules="emailRules"
80
label="Email"
81
type="email"
82
required
83
/>
84
85
<v-btn
86
type="submit"
87
:disabled="!valid"
88
color="primary"
89
>
90
Submit
91
</v-btn>
92
</v-form>
93
</template>
94
95
<script setup>
96
const form = ref();
97
const valid = ref(false);
98
const name = ref('');
99
const email = ref('');
100
101
const nameRules = [
102
v => !!v || 'Name is required',
103
v => v.length >= 2 || 'Name must be at least 2 characters',
104
];
105
106
const emailRules = [
107
v => !!v || 'Email is required',
108
v => /.+@.+\..+/.test(v) || 'Email must be valid',
109
];
110
111
const handleSubmit = async () => {
112
const { valid } = await form.value.validate();
113
if (valid) {
114
// Submit form data
115
console.log('Form is valid, submitting...');
116
}
117
};
118
</script>
119
```
120
121
### VTextField
122
123
Single-line text input field with validation and formatting capabilities.
124
125
```typescript { .api }
126
/**
127
* Single-line text input component
128
*/
129
const VTextField: Component;
130
131
interface TextFieldProps {
132
/** Input value */
133
modelValue?: string | number;
134
/** Input type */
135
type?: 'text' | 'password' | 'email' | 'url' | 'tel' | 'number';
136
/** Field label */
137
label?: string;
138
/** Placeholder text */
139
placeholder?: string;
140
/** Hint text */
141
hint?: string;
142
/** Persistent hint */
143
persistentHint?: boolean;
144
/** Validation rules */
145
rules?: ValidationRule[];
146
/** Error messages */
147
errorMessages?: string | string[];
148
/** Error state */
149
error?: boolean;
150
/** Success state */
151
success?: boolean;
152
/** Disabled state */
153
disabled?: boolean;
154
/** Readonly state */
155
readonly?: boolean;
156
/** Required field indicator */
157
required?: boolean;
158
/** Field density */
159
density?: 'default' | 'comfortable' | 'compact';
160
/** Field variant */
161
variant?: 'filled' | 'outlined' | 'underlined' | 'plain' | 'solo' | 'solo-inverted' | 'solo-filled';
162
/** Hide details */
163
hideDetails?: boolean | 'auto';
164
/** Prepend icon */
165
prependIcon?: string;
166
/** Append icon */
167
appendIcon?: string;
168
/** Prepend inner icon */
169
prependInnerIcon?: string;
170
/** Append inner icon */
171
appendInnerIcon?: string;
172
/** Clear icon */
173
clearIcon?: string;
174
/** Clearable input */
175
clearable?: boolean;
176
/** Counter for character count */
177
counter?: boolean | number | string;
178
/** Maximum length */
179
maxlength?: number | string;
180
/** Prefix text */
181
prefix?: string;
182
/** Suffix text */
183
suffix?: string;
184
/** Loading state */
185
loading?: boolean;
186
/** Autofocus */
187
autofocus?: boolean;
188
}
189
190
// Events
191
interface TextFieldEvents {
192
'update:modelValue': (value: string | number) => void;
193
'click:prepend': (event: MouseEvent) => void;
194
'click:append': (event: MouseEvent) => void;
195
'click:prependInner': (event: MouseEvent) => void;
196
'click:appendInner': (event: MouseEvent) => void;
197
'click:clear': (event: MouseEvent) => void;
198
'focus': (event: FocusEvent) => void;
199
'blur': (event: FocusEvent) => void;
200
'keydown': (event: KeyboardEvent) => void;
201
}
202
```
203
204
**Usage Examples:**
205
206
```vue
207
<template>
208
<!-- Basic text field -->
209
<v-text-field
210
v-model="username"
211
label="Username"
212
prepend-inner-icon="mdi-account"
213
/>
214
215
<!-- Password field -->
216
<v-text-field
217
v-model="password"
218
:type="showPassword ? 'text' : 'password'"
219
label="Password"
220
:append-inner-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
221
@click:append-inner="showPassword = !showPassword"
222
/>
223
224
<!-- Validated field -->
225
<v-text-field
226
v-model="email"
227
:rules="emailRules"
228
label="Email"
229
type="email"
230
hint="Enter a valid email address"
231
persistent-hint
232
/>
233
234
<!-- With counter -->
235
<v-text-field
236
v-model="description"
237
label="Description"
238
counter="200"
239
maxlength="200"
240
/>
241
</template>
242
```
243
244
### VTextarea
245
246
Multi-line text input area for longer text content.
247
248
```typescript { .api }
249
/**
250
* Multi-line text input component
251
*/
252
const VTextarea: Component;
253
254
interface TextareaProps extends Omit<TextFieldProps, 'type' | 'prependInnerIcon' | 'appendInnerIcon'> {
255
/** Number of rows */
256
rows?: number | string;
257
/** Maximum number of rows */
258
maxRows?: number | string;
259
/** Auto-grow height */
260
autoGrow?: boolean;
261
/** No resize handle */
262
noResize?: boolean;
263
}
264
```
265
266
**Usage Examples:**
267
268
```vue
269
<template>
270
<!-- Basic textarea -->
271
<v-textarea
272
v-model="message"
273
label="Message"
274
rows="3"
275
/>
276
277
<!-- Auto-growing textarea -->
278
<v-textarea
279
v-model="content"
280
label="Content"
281
auto-grow
282
max-rows="10"
283
/>
284
285
<!-- With validation -->
286
<v-textarea
287
v-model="feedback"
288
:rules="[v => v.length >= 10 || 'Minimum 10 characters required']"
289
label="Feedback"
290
counter="500"
291
maxlength="500"
292
/>
293
</template>
294
```
295
296
### VSelect
297
298
Dropdown selection component with single or multiple selection modes.
299
300
```typescript { .api }
301
/**
302
* Dropdown selection component
303
*/
304
const VSelect: Component;
305
306
interface SelectProps {
307
/** Selected value(s) */
308
modelValue?: any;
309
/** Selection items */
310
items?: any[];
311
/** Item title key */
312
itemTitle?: string | ((item: any) => string);
313
/** Item value key */
314
itemValue?: string | ((item: any) => any);
315
/** Item props key */
316
itemProps?: string | ((item: any) => Record<string, any>);
317
/** Return object instead of value */
318
returnObject?: boolean;
319
/** Multiple selection */
320
multiple?: boolean;
321
/** Chips display for multiple */
322
chips?: boolean;
323
/** Closable chips */
324
closableChips?: boolean;
325
/** Field label */
326
label?: string;
327
/** Placeholder text */
328
placeholder?: string;
329
/** Validation rules */
330
rules?: ValidationRule[];
331
/** Menu props */
332
menuProps?: Record<string, any>;
333
/** Clearable selection */
334
clearable?: boolean;
335
/** Loading state */
336
loading?: boolean;
337
/** Hide selected items from list */
338
hideSelected?: boolean;
339
/** Menu open state */
340
menu?: boolean;
341
}
342
343
// Events
344
interface SelectEvents {
345
'update:modelValue': (value: any) => void;
346
'update:menu': (open: boolean) => void;
347
}
348
```
349
350
**Usage Examples:**
351
352
```vue
353
<template>
354
<!-- Basic select -->
355
<v-select
356
v-model="selectedItem"
357
:items="items"
358
label="Choose an option"
359
item-title="text"
360
item-value="value"
361
/>
362
363
<!-- Multiple select with chips -->
364
<v-select
365
v-model="selectedItems"
366
:items="items"
367
label="Multiple selection"
368
multiple
369
chips
370
closable-chips
371
item-title="text"
372
item-value="value"
373
/>
374
375
<!-- Object return format -->
376
<v-select
377
v-model="selectedObject"
378
:items="complexItems"
379
label="Select user"
380
item-title="name"
381
item-value="id"
382
return-object
383
/>
384
</template>
385
386
<script setup>
387
const items = [
388
{ text: 'Option 1', value: 1 },
389
{ text: 'Option 2', value: 2 },
390
{ text: 'Option 3', value: 3 },
391
];
392
393
const complexItems = [
394
{ id: 1, name: 'John Doe', email: 'john@example.com' },
395
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' },
396
];
397
</script>
398
```
399
400
### VCombobox
401
402
Combobox component allowing both selection from list and free text input.
403
404
```typescript { .api }
405
/**
406
* Combobox with selection and text input capabilities
407
*/
408
const VCombobox: Component;
409
410
interface ComboboxProps extends SelectProps {
411
/** Allow custom values */
412
customValue?: boolean;
413
/** Delimiter for multiple values */
414
delimiters?: string[];
415
/** Filter function */
416
customFilter?: FilterFunction;
417
}
418
```
419
420
**Usage Examples:**
421
422
```vue
423
<template>
424
<!-- Basic combobox -->
425
<v-combobox
426
v-model="selectedTags"
427
:items="availableTags"
428
label="Tags"
429
multiple
430
chips
431
delimiters=" ,"
432
/>
433
434
<!-- Custom value combobox -->
435
<v-combobox
436
v-model="customSelection"
437
:items="predefinedOptions"
438
label="Select or enter custom"
439
custom-value
440
/>
441
</template>
442
```
443
444
### VAutocomplete
445
446
Autocomplete component with filtering and async data loading capabilities.
447
448
```typescript { .api }
449
/**
450
* Autocomplete input with filtering
451
*/
452
const VAutocomplete: Component;
453
454
interface AutocompleteProps extends SelectProps {
455
/** Search input value */
456
search?: string;
457
/** Custom filter function */
458
customFilter?: FilterFunction;
459
/** Filter function keys */
460
customKeyFilter?: Record<string, FilterFunction>;
461
/** No filter mode for server-side filtering */
462
noFilter?: boolean;
463
/** Auto-select first item */
464
autoSelectFirst?: boolean;
465
}
466
467
// Events
468
interface AutocompleteEvents extends SelectEvents {
469
'update:search': (search: string) => void;
470
}
471
```
472
473
**Usage Examples:**
474
475
```vue
476
<template>
477
<!-- Basic autocomplete -->
478
<v-autocomplete
479
v-model="selectedUser"
480
:items="users"
481
label="Search users"
482
item-title="name"
483
item-value="id"
484
/>
485
486
<!-- Server-side filtering -->
487
<v-autocomplete
488
v-model="selectedItem"
489
v-model:search="searchQuery"
490
:items="searchResults"
491
:loading="searching"
492
label="Search items"
493
no-filter
494
@update:search="performSearch"
495
/>
496
</template>
497
498
<script setup>
499
const searchQuery = ref('');
500
const searchResults = ref([]);
501
const searching = ref(false);
502
503
const performSearch = async (query) => {
504
if (!query) {
505
searchResults.value = [];
506
return;
507
}
508
509
searching.value = true;
510
try {
511
const results = await api.search(query);
512
searchResults.value = results;
513
} finally {
514
searching.value = false;
515
}
516
};
517
</script>
518
```
519
520
### VCheckbox
521
522
Checkbox input component for boolean selections.
523
524
```typescript { .api }
525
/**
526
* Checkbox input component
527
*/
528
const VCheckbox: Component;
529
530
interface CheckboxProps {
531
/** Checkbox value */
532
modelValue?: any;
533
/** True value when checked */
534
trueValue?: any;
535
/** False value when unchecked */
536
falseValue?: any;
537
/** Indeterminate state */
538
indeterminate?: boolean;
539
/** Checkbox label */
540
label?: string;
541
/** Validation rules */
542
rules?: ValidationRule[];
543
/** Disabled state */
544
disabled?: boolean;
545
/** Readonly state */
546
readonly?: boolean;
547
/** Error state */
548
error?: boolean;
549
/** Checkbox color */
550
color?: string;
551
/** Hide details */
552
hideDetails?: boolean | 'auto';
553
/** Field density */
554
density?: 'default' | 'comfortable' | 'compact';
555
}
556
557
// Events
558
interface CheckboxEvents {
559
'update:modelValue': (value: any) => void;
560
'update:indeterminate': (indeterminate: boolean) => void;
561
}
562
```
563
564
**Usage Examples:**
565
566
```vue
567
<template>
568
<!-- Basic checkbox -->
569
<v-checkbox
570
v-model="agreed"
571
label="I agree to the terms"
572
/>
573
574
<!-- Custom values -->
575
<v-checkbox
576
v-model="status"
577
true-value="active"
578
false-value="inactive"
579
label="Active status"
580
/>
581
582
<!-- Indeterminate checkbox -->
583
<v-checkbox
584
v-model="selectAll"
585
:indeterminate="someSelected"
586
@click="toggleAll"
587
label="Select all"
588
/>
589
</template>
590
```
591
592
### VRadio & VRadioGroup
593
594
Radio button components for single selection from multiple options.
595
596
```typescript { .api }
597
/**
598
* Radio button component
599
*/
600
const VRadio: Component;
601
602
interface RadioProps {
603
/** Radio value */
604
value?: any;
605
/** Radio label */
606
label?: string;
607
/** Disabled state */
608
disabled?: boolean;
609
/** Readonly state */
610
readonly?: boolean;
611
/** Radio color */
612
color?: string;
613
/** Field density */
614
density?: 'default' | 'comfortable' | 'compact';
615
}
616
617
/**
618
* Radio group container
619
*/
620
const VRadioGroup: Component;
621
622
interface RadioGroupProps {
623
/** Selected value */
624
modelValue?: any;
625
/** Group label */
626
label?: string;
627
/** Validation rules */
628
rules?: ValidationRule[];
629
/** Error state */
630
error?: boolean;
631
/** Error messages */
632
errorMessages?: string | string[];
633
/** Disabled state */
634
disabled?: boolean;
635
/** Readonly state */
636
readonly?: boolean;
637
/** Inline layout */
638
inline?: boolean;
639
/** Hide details */
640
hideDetails?: boolean | 'auto';
641
/** Field density */
642
density?: 'default' | 'comfortable' | 'compact';
643
}
644
645
// Events
646
interface RadioGroupEvents {
647
'update:modelValue': (value: any) => void;
648
}
649
```
650
651
**Usage Examples:**
652
653
```vue
654
<template>
655
<v-radio-group v-model="selectedOption" label="Choose an option">
656
<v-radio
657
v-for="option in options"
658
:key="option.value"
659
:value="option.value"
660
:label="option.text"
661
/>
662
</v-radio-group>
663
664
<!-- Inline radio group -->
665
<v-radio-group
666
v-model="size"
667
label="Size"
668
inline
669
>
670
<v-radio value="small" label="Small" />
671
<v-radio value="medium" label="Medium" />
672
<v-radio value="large" label="Large" />
673
</v-radio-group>
674
</template>
675
```
676
677
### VSwitch
678
679
Toggle switch component for boolean state control.
680
681
```typescript { .api }
682
/**
683
* Toggle switch component
684
*/
685
const VSwitch: Component;
686
687
interface SwitchProps {
688
/** Switch value */
689
modelValue?: any;
690
/** True value when on */
691
trueValue?: any;
692
/** False value when off */
693
falseValue?: any;
694
/** Switch label */
695
label?: string;
696
/** Validation rules */
697
rules?: ValidationRule[];
698
/** Disabled state */
699
disabled?: boolean;
700
/** Readonly state */
701
readonly?: boolean;
702
/** Loading state */
703
loading?: boolean;
704
/** Error state */
705
error?: boolean;
706
/** Switch color */
707
color?: string;
708
/** Inset style */
709
inset?: boolean;
710
/** Flat style (no elevation) */
711
flat?: boolean;
712
/** Hide details */
713
hideDetails?: boolean | 'auto';
714
/** Field density */
715
density?: 'default' | 'comfortable' | 'compact';
716
}
717
718
// Events
719
interface SwitchEvents {
720
'update:modelValue': (value: any) => void;
721
}
722
```
723
724
**Usage Examples:**
725
726
```vue
727
<template>
728
<!-- Basic switch -->
729
<v-switch
730
v-model="enabled"
731
label="Enable notifications"
732
/>
733
734
<!-- Custom values -->
735
<v-switch
736
v-model="mode"
737
true-value="dark"
738
false-value="light"
739
label="Dark mode"
740
/>
741
742
<!-- Loading switch -->
743
<v-switch
744
v-model="autoSave"
745
:loading="saving"
746
label="Auto-save"
747
/>
748
</template>
749
```
750
751
### VSlider & VRangeSlider
752
753
Slider components for numeric value selection.
754
755
```typescript { .api }
756
/**
757
* Single value slider component
758
*/
759
const VSlider: Component;
760
761
interface SliderProps {
762
/** Slider value */
763
modelValue?: number | string;
764
/** Minimum value */
765
min?: number | string;
766
/** Maximum value */
767
max?: number | string;
768
/** Step increment */
769
step?: number | string;
770
/** Slider label */
771
label?: string;
772
/** Validation rules */
773
rules?: ValidationRule[];
774
/** Disabled state */
775
disabled?: boolean;
776
/** Readonly state */
777
readonly?: boolean;
778
/** Show thumb label */
779
thumbLabel?: boolean | 'always';
780
/** Thumb size */
781
thumbSize?: number | string;
782
/** Show ticks */
783
showTicks?: boolean | 'always';
784
/** Tick labels */
785
tickLabels?: string[];
786
/** Tick size */
787
tickSize?: number | string;
788
/** Vertical orientation */
789
vertical?: boolean;
790
/** Slider color */
791
color?: string;
792
/** Track color */
793
trackColor?: string;
794
/** Track fill color */
795
trackFillColor?: string;
796
/** Track size */
797
trackSize?: number | string;
798
/** Thumb color */
799
thumbColor?: string;
800
/** Hide details */
801
hideDetails?: boolean | 'auto';
802
/** Field density */
803
density?: 'default' | 'comfortable' | 'compact';
804
}
805
806
/**
807
* Range slider with dual handles
808
*/
809
const VRangeSlider: Component;
810
811
interface RangeSliderProps extends Omit<SliderProps, 'modelValue'> {
812
/** Range values [min, max] */
813
modelValue?: number[];
814
}
815
816
// Events
817
interface SliderEvents {
818
'update:modelValue': (value: number | number[]) => void;
819
'start': (value: number | number[]) => void;
820
'end': (value: number | number[]) => void;
821
}
822
```
823
824
**Usage Examples:**
825
826
```vue
827
<template>
828
<!-- Basic slider -->
829
<v-slider
830
v-model="volume"
831
:min="0"
832
:max="100"
833
label="Volume"
834
thumb-label
835
/>
836
837
<!-- Range slider -->
838
<v-range-slider
839
v-model="priceRange"
840
:min="0"
841
:max="1000"
842
:step="10"
843
label="Price Range"
844
thumb-label="always"
845
/>
846
847
<!-- Slider with ticks -->
848
<v-slider
849
v-model="rating"
850
:min="1"
851
:max="5"
852
:step="1"
853
label="Rating"
854
show-ticks="always"
855
:tick-labels="['Poor', 'Fair', 'Good', 'Very Good', 'Excellent']"
856
/>
857
</template>
858
```
859
860
### VFileInput
861
862
File upload input component with drag-and-drop support.
863
864
```typescript { .api }
865
/**
866
* File input component
867
*/
868
const VFileInput: Component;
869
870
interface FileInputProps {
871
/** Selected files */
872
modelValue?: File | File[];
873
/** Accept file types */
874
accept?: string;
875
/** Multiple file selection */
876
multiple?: boolean;
877
/** Field label */
878
label?: string;
879
/** Placeholder text */
880
placeholder?: string;
881
/** Validation rules */
882
rules?: ValidationRule[];
883
/** Disabled state */
884
disabled?: boolean;
885
/** Readonly state */
886
readonly?: boolean;
887
/** Show file size */
888
showSize?: boolean | ((file: File) => string);
889
/** Clearable selection */
890
clearable?: boolean;
891
/** Chips display for multiple files */
892
chips?: boolean;
893
/** Counter for file count */
894
counter?: boolean;
895
/** Prepend icon */
896
prependIcon?: string;
897
/** Append icon */
898
appendIcon?: string;
899
/** Hide details */
900
hideDetails?: boolean | 'auto';
901
}
902
903
// Events
904
interface FileInputEvents {
905
'update:modelValue': (files: File | File[]) => void;
906
'click:prepend': (event: MouseEvent) => void;
907
'click:append': (event: MouseEvent) => void;
908
'click:clear': (event: MouseEvent) => void;
909
}
910
```
911
912
**Usage Examples:**
913
914
```vue
915
<template>
916
<!-- Basic file input -->
917
<v-file-input
918
v-model="selectedFile"
919
label="Choose file"
920
accept="image/*"
921
/>
922
923
<!-- Multiple files with chips -->
924
<v-file-input
925
v-model="selectedFiles"
926
label="Choose files"
927
multiple
928
chips
929
show-size
930
counter
931
/>
932
933
<!-- With validation -->
934
<v-file-input
935
v-model="document"
936
:rules="fileRules"
937
label="Upload document"
938
accept=".pdf,.doc,.docx"
939
/>
940
</template>
941
942
<script setup>
943
const fileRules = [
944
v => !!v || 'File is required',
945
v => !v || v.size <= 5 * 1024 * 1024 || 'File must be less than 5MB',
946
];
947
</script>
948
```
949
950
### VNumberInput
951
952
Numeric input component with increment/decrement controls.
953
954
```typescript { .api }
955
/**
956
* Number input with controls
957
*/
958
const VNumberInput: Component;
959
960
interface NumberInputProps {
961
/** Number value */
962
modelValue?: number;
963
/** Minimum value */
964
min?: number;
965
/** Maximum value */
966
max?: number;
967
/** Step increment */
968
step?: number;
969
/** Field label */
970
label?: string;
971
/** Validation rules */
972
rules?: ValidationRule[];
973
/** Disabled state */
974
disabled?: boolean;
975
/** Readonly state */
976
readonly?: boolean;
977
/** Hide control buttons */
978
hideControls?: boolean;
979
/** Control variant */
980
controlVariant?: 'default' | 'stacked' | 'split';
981
/** Reverse controls */
982
reverse?: boolean;
983
/** Hide details */
984
hideDetails?: boolean | 'auto';
985
}
986
987
// Events
988
interface NumberInputEvents {
989
'update:modelValue': (value: number) => void;
990
}
991
```
992
993
**Usage Examples:**
994
995
```vue
996
<template>
997
<!-- Basic number input -->
998
<v-number-input
999
v-model="quantity"
1000
:min="1"
1001
:max="100"
1002
label="Quantity"
1003
/>
1004
1005
<!-- Stacked controls -->
1006
<v-number-input
1007
v-model="price"
1008
:step="0.01"
1009
:min="0"
1010
label="Price"
1011
control-variant="stacked"
1012
/>
1013
</template>
1014
```
1015
1016
### VOtpInput
1017
1018
One-time password (OTP) input component for verification codes.
1019
1020
```typescript { .api }
1021
/**
1022
* OTP/PIN input component
1023
*/
1024
const VOtpInput: Component;
1025
1026
interface OtpInputProps {
1027
/** OTP value */
1028
modelValue?: string;
1029
/** Number of input fields */
1030
length?: number;
1031
/** Input type */
1032
type?: 'text' | 'number' | 'password';
1033
/** Field variant */
1034
variant?: 'filled' | 'outlined' | 'underlined' | 'plain';
1035
/** Validation rules */
1036
rules?: ValidationRule[];
1037
/** Disabled state */
1038
disabled?: boolean;
1039
/** Readonly state */
1040
readonly?: boolean;
1041
/** Field density */
1042
density?: 'default' | 'comfortable' | 'compact';
1043
/** Hide details */
1044
hideDetails?: boolean | 'auto';
1045
/** Placeholder character */
1046
placeholder?: string;
1047
/** Autofocus */
1048
autofocus?: boolean;
1049
}
1050
1051
// Events
1052
interface OtpInputEvents {
1053
'update:modelValue': (value: string) => void;
1054
'finish': (value: string) => void;
1055
}
1056
```
1057
1058
**Usage Examples:**
1059
1060
```vue
1061
<template>
1062
<!-- Basic OTP input -->
1063
<v-otp-input
1064
v-model="otpCode"
1065
:length="6"
1066
type="number"
1067
@finish="handleOtpComplete"
1068
/>
1069
1070
<!-- Password OTP -->
1071
<v-otp-input
1072
v-model="pinCode"
1073
:length="4"
1074
type="password"
1075
variant="outlined"
1076
/>
1077
</template>
1078
```
1079
1080
## Types
1081
1082
```typescript { .api }
1083
// Validation types
1084
type ValidationRule<T = any> =
1085
| true
1086
| string
1087
| ((value: T) => true | string);
1088
1089
// Form submission event
1090
interface SubmitEventPromise extends Event {
1091
readonly valid: Promise<{ valid: boolean; errors: ValidationError[] }>;
1092
}
1093
1094
// Validation error structure
1095
interface ValidationError {
1096
id: string | number;
1097
errorMessages: string[];
1098
}
1099
1100
// Field variants
1101
type FieldVariant = 'filled' | 'outlined' | 'underlined' | 'plain' | 'solo' | 'solo-inverted' | 'solo-filled';
1102
1103
// Input types
1104
type InputType = 'text' | 'password' | 'email' | 'url' | 'tel' | 'number';
1105
1106
// Density options
1107
type Density = 'default' | 'comfortable' | 'compact';
1108
1109
// Filter function for autocomplete/combobox
1110
type FilterFunction = (item: any, queryText: string, itemText: string) => boolean;
1111
```