or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

components.mdcomposables.mddata-display.mddirectives.mdfeedback.mdforms.mdframework-core.mdicons.mdindex.mdinternationalization.mdlab-components.mdnavigation.mdtheming.mdtransitions.mdutilities.md

forms.mddocs/

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

```