[
  {
    "path": ".changeset/README.md",
    "content": "# Changesets\n\nHello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works\nwith multi-package repos, or single-package repos to help you version and publish your code. You can\nfind the full documentation for it [in our repository](https://github.com/changesets/changesets)\n\nWe have a quick list of common questions to get you started engaging with this project in\n[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)\n"
  },
  {
    "path": ".changeset/config.json",
    "content": "{\n  \"$schema\": \"https://unpkg.com/@changesets/config@2.3.0/schema.json\",\n  \"changelog\": \"@changesets/cli/changelog\",\n  \"commit\": false,\n  \"fixed\": [[\"vee-validate\", \"@vee-validate/i18n\", \"@vee-validate/rules\", \"@vee-validate/nuxt\"]],\n  \"linked\": [],\n  \"access\": \"public\",\n  \"baseBranch\": \"main\",\n  \"updateInternalDependencies\": \"patch\",\n  \"ignore\": []\n}\n"
  },
  {
    "path": ".changeset/evil-loops-shine.md",
    "content": "---\n'vee-validate': minor\n---\n\nfeat: remove deprecated useField props\n"
  },
  {
    "path": ".changeset/gentle-geckos-share.md",
    "content": "---\n'vee-validate': patch\n---\n\nfix(devtools): prevent SSR memory leak in DevTools integration\n"
  },
  {
    "path": ".changeset/happy-wasps-rush.md",
    "content": "---\n'vee-validate': patch\n---\n\nfeat: expose `getConfig` as a public API\n"
  },
  {
    "path": ".changeset/pre.json",
    "content": "{\n  \"mode\": \"pre\",\n  \"tag\": \"beta\",\n  \"initialVersions\": {\n    \"vee-validate-docs\": null,\n    \"@vee-validate/i18n\": \"4.15.1\",\n    \"@vee-validate/nuxt\": \"4.15.1\",\n    \"@vee-validate/rules\": \"4.15.1\",\n    \"vee-validate\": \"4.15.1\"\n  },\n  \"changesets\": [\n    \"evil-loops-shine\",\n    \"gentle-geckos-share\",\n    \"happy-wasps-rush\",\n    \"pretty-onions-add\",\n    \"revert-number-to-string\",\n    \"six-parrots-flash\",\n    \"smart-needles-own\",\n    \"stupid-friends-relate\"\n  ]\n}\n"
  },
  {
    "path": ".changeset/pretty-onions-add.md",
    "content": "---\n'vee-validate': patch\n---\n\nFix dev tools not showing all field states\n"
  },
  {
    "path": ".changeset/revert-number-to-string.md",
    "content": "---\n'vee-validate': patch\n---\n\nfix: revert number input type back to string from number, closes #4699 and #4482"
  },
  {
    "path": ".changeset/six-parrots-flash.md",
    "content": "---\n'vee-validate': minor\n---\n\nfeat: remove deprecated useForm define methods\n"
  },
  {
    "path": ".changeset/smart-needles-own.md",
    "content": "---\n'vee-validate': major\n'@vee-validate/rules': major\n'@vee-validate/nuxt': major\n'@vee-validate/i18n': major\n---\n\nfeat: implement standard schema\n"
  },
  {
    "path": ".changeset/stupid-friends-relate.md",
    "content": "---\n'vee-validate': patch\n---\n\nFix dev tools do not display nested fields with name 'id'\n"
  },
  {
    "path": ".circleci/config.yml",
    "content": "# Use the latest 2.1 version of CircleCI pipeline process engine.\n# See: https://circleci.com/docs/2.0/configuration-reference\nversion: 2.1\n\njobs:\n  # Below is the definition of your job to build and test your app, you can rename and customize it as you want.\n  test:\n    docker:\n      - image: cimg/node:22.11\n    steps:\n      # Checkout the code as the first step.\n      - checkout\n      - restore_cache:\n          name: Restore pnpm Package Cache\n          keys:\n            - pnpm-packages-{{ checksum \"pnpm-lock.yaml\" }}\n      - run:\n          name: Use latest Corepack\n          command: |\n            echo \"Before: corepack version => $(corepack --version || echo 'not installed')\"\n            sudo npm install -g corepack@latest\n            echo \"After : corepack version => $(corepack --version)\"\n      - run:\n          name: Install pnpm package manager\n          command: |\n            corepack enable --install-directory ~/bin\n            corepack prepare pnpm@latest-9 --activate\n            pnpm --version\n            pnpm config set store-dir .pnpm-store\n      - run:\n          name: Install dependencies\n          command: pnpm install\n      - save_cache:\n          name: Save pnpm Package Cache\n          key: pnpm-packages-{{ checksum \"pnpm-lock.yaml\" }}\n          paths:\n            - .pnpm-store\n      - run:\n          name: Build\n          command: pnpm build\n      - run:\n          name: Type check\n          command: pnpm typecheck\n      - run:\n          name: Generate Coverage\n          command: pnpm cover\n      - run:\n          name: Upload Coverage\n          command: bash <(curl -s https://codecov.io/bash)\n\nworkflows:\n  ci:\n    jobs:\n      - test\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: logaretm\n# patreon: logaretm\n# open_collective: vee-validate\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: # 'https://www.buymeacoffee.com/logaretm'\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Feature_request.md",
    "content": "---\r\nname: 🚀 Feature request\r\nabout: Suggest an idea for this project.\r\n---\r\n\r\n**Is your feature request related to a problem? Please describe.**\r\n\r\n<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->\r\n\r\n**Describe the solution you'd like**\r\n\r\n<!-- A clear and concise description of what you want to happen. -->\r\n\r\n**Describe alternatives you've considered**\r\n\r\n<!-- A clear and concise description of any alternative solutions or features you've considered. -->\r\n\r\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yaml",
    "content": "name: Bug Report\r\ndescription: File a bug report\r\ntitle: '<title>'\r\nbody:\r\n  - type: markdown\r\n    attributes:\r\n      value: |\r\n        Thanks for taking the time to fill out this bug report!\r\n  - type: textarea\r\n    id: what-happened\r\n    attributes:\r\n      label: What happened?\r\n      description: Describe the bug\r\n      placeholder: Tell us what you see!\r\n    validations:\r\n      required: true\r\n  - type: textarea\r\n    id: repro\r\n    attributes:\r\n      label: Reproduction steps\r\n      description: 'How do you trigger this bug? Please walk us through it step by step.'\r\n      value: |\r\n        1.\r\n        2.\r\n        3.\r\n        ...\r\n  - type: dropdown\r\n    id: version\r\n    attributes:\r\n      label: Version\r\n      description: What version of Vue.js and vee-validate are you running?\r\n      options:\r\n        - Vue.js 3.x and vee-validate 5.x\r\n        - Vue.js 3.x and vee-validate 4.x\r\n        - Vue.js 2.x and vee-validate 3.x\r\n        - Vue.js 2.x and vee-validate 2.x\r\n    validations:\r\n      required: true\r\n  - type: checkboxes\r\n    id: browsers\r\n    attributes:\r\n      label: What browsers are you seeing the problem on?\r\n      options:\r\n        - label: Firefox\r\n        - label: Chrome\r\n        - label: Safari\r\n        - label: Microsoft Edge\r\n  - type: textarea\r\n    id: logs\r\n    attributes:\r\n      label: Relevant log output\r\n      description: If you have an error log or stacktrace, copy it and paste it here\r\n      render: shell\r\n  - type: input\r\n    id: demo\r\n    attributes:\r\n      label: Demo link\r\n      description: If you can reproduce this issue on codesandbox/codepen, please paste the link here\r\n    validations:\r\n      required: true\r\n  - type: checkboxes\r\n    attributes:\r\n      label: Code of Conduct\r\n      description: The Code of Conduct helps create a friendly environment\r\n      options:\r\n        - label: I agree to follow this project's [Code of Conduct](CONDUCT.md)\r\n          required: true\r\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "🔎 __Overview__\n\n<!-- Explain the why behind adding this PR, here is a couple of examples -->\n<!--\n  This PR {adds/fixes/improves} the {feature/bug/something}.\n  This PR changes the {locale} messages style because {reason}\n-->\n\n🤓 __Code snippets/examples (if applicable)__\n\n```js\n// some code\n```\n\n✔ __Issues affected__\n\n<!-- list of issues formatted like this\ncloses #{issue id}\n -->\n \n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non: [push, workflow_call]\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v2\n      - run: corepack enable\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: 'pnpm'\n      - name: Install dependencies\n        run: pnpm install\n      - name: Build\n        run: pnpm build\n      - name: Lint\n        run: pnpm lint\n\n  typecheck:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v2\n      - run: corepack enable\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: 'pnpm'\n      - name: Install dependencies\n        run: pnpm install\n      - name: Build\n        run: pnpm build\n      - name: Type Check\n        run: pnpm typecheck\n\n  tests:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v2\n      - run: corepack enable\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 22\n          cache: 'pnpm'\n      - name: Install dependencies\n        run: pnpm install\n      - name: Build\n        run: pnpm build\n      - name: Test\n        run: pnpm test\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non: workflow_dispatch\n\npermissions:\n  id-token: write\n  contents: write\n\njobs:\n  checks:\n    uses: ./.github/workflows/ci.yml\n\n  release:\n    needs: checks\n    runs-on: ubuntu-latest\n    permissions:\n      id-token: write\n      contents: write\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n      - run: corepack enable\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 24\n          cache: 'pnpm'\n          registry-url: 'https://registry.npmjs.org'\n      - name: Install dependencies\n        run: pnpm install\n      - name: Tag and Release\n        run: |\n          git config --global user.email \"github-action@users.noreply.github.com\"\n          git config --global user.name \"GitHub Action\"\n          pnpm ci:version\n          git add .\n          git commit -m \"chore(release): publish\"\n          pnpm ci:tag\n          pnpm ci:publish\n          git push && git push --tags\n        env:\n          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}\n          NPM_CONFIG_PROVENANCE: true\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n.nyc_output\nnpm-debug.log\ncoverage\n.idea\n.vscode\n.vs\nyarn-error.log\ndist\n.rpt2_cache\n./types\n\n.DS_STORE\n\nlerna-debug.log\npackages/*/src/playground.ts\n"
  },
  {
    "path": ".husky/.gitignore",
    "content": "_\n"
  },
  {
    "path": ".husky/commit-msg",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\npnpm commitlint --edit $1\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\npnpm lint-staged\n"
  },
  {
    "path": ".prettierrc",
    "content": " {\n  \"printWidth\": 120,\n  \"tabWidth\": 2,\n  \"semi\": true,\n  \"singleQuote\": true,\n  \"bracketSpacing\": true,\n  \"arrowParens\": \"avoid\",\n  \"endOfLine\": \"lf\",\n  \"plugins\": [\"prettier-plugin-astro\"],\n  \"overrides\": [\n    {\n      \"files\": \"*.astro\",\n      \"options\": {\n        \"parser\": \"astro\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\n## 5.0.0-beta.1\n\n### Minor Changes\n\n- f629397: feat: remove deprecated useField props\n- fb5e04e: feat: remove deprecated useForm define methods\n\n### Patch Changes\n\n- f2807b8: fix(devtools): prevent SSR memory leak in DevTools integration\n- e6db423: feat: expose `getConfig` as a public API\n- 49fcf4c: Fix dev tools not showing all field states\n- 1ce0731: fix: revert number input type back to string from number, closes #4699 and #4482\n- 095df65: Fix dev tools do not display nested fields with name 'id'\n\n## 5.0.0-beta.0\n\n### Major Changes\n\n- 04ff47c: feat: implement standard schema\n\n## 4.15.1\n\n### Patch Changes\n\n- 721e980: Align FormErrors type with its actual structure at runtime.\n- 546d82e: fix: normalize objects before equality checks closes #5006\n\n## 4.15.0\n\n### Patch Changes\n\n- 30281f5: fix: lazy load the devtools dep to force it out of production bundle\n- ec121b1: fix: skip loading devtools if in SSR\n\n## 4.14.7\n\n### Patch Changes\n\n- be994b4: fix: show uncontrolled field info in devtools closes #4914\n\n## 4.14.6\n\n## 4.14.5\n\n### Patch Changes\n\n- e9f8c88: fix: force loading the mjs module when using nuxt\n\n## 4.14.4\n\n### Patch Changes\n\n- f33974c: fix(types): expose field and form slot prop types closes #4900\n- 0991c01: fix: devtools crashing when a field name is defined as getter\n- ecb540a: fix: handle getter field names properly closes #4877\n- 4f88d85: fix: specify module type on package.json\n\n## 4.14.3\n\n### Patch Changes\n\n- 07c27d5: fix: remove rogue console.log\n\n## 4.14.2\n\n### Patch Changes\n\n- f0d4e24: fix: upgrade vue devtools dependency version closes #4863\n\n## 4.14.1\n\n## 4.14.0\n\n### Minor Changes\n\n- 404cf57: chore: bump release\n\n### Patch Changes\n\n- f7a4929: feat: expose useFormContext closes #4490\n- 97cebd8: chore: add 'exports' field in package.json for all packages\n- 421ae69: \"fix(types): export component internal types\"\n\n## 4.13.2\n\n### Patch Changes\n\n- afbd0e5: feat: support valibot 0.33.0\n\n## 4.13.1\n\n## 4.13.0\n\n### Minor Changes\n\n- 454bc45: fix: force resetForm should not merge values closes #4680 closes #4729\n- 27fe5c8: feat: provide form values as context for yup closes #4753\n\n### Patch Changes\n\n- ae3772a: feat: expose setValue on Field instance and slot props closes #4755\n- fd008c1: feat: added ResetFormOpts arg to useResetForm closes #4707\n\n## 4.12.8\n\n### Patch Changes\n\n- f8bab9c: \"fix: field-level validation not working with typed scheams closes #4744\"\n\n## 4.12.7\n\n### Patch Changes\n\n- 1376794: fix: handle meta.required for single field schemas closes #4738\n- 1376794: fix: add try-catch for schema description logic across all major schema providers\n- c4415f8: fix: ensure meta.required is reactive whenever the schema changes closes #4738\n\n## 4.12.6\n\n### Patch Changes\n\n- 07d01fd: fix: re-apply errors to avoid race conditions\n\n## 4.12.5\n\n### Patch Changes\n\n- d779980: fix: make sure removePathState removes the correct path state\n- 9eda544: \"fix: remove event arg from define field handlers for component compat closes #4637\"\n\n## 4.12.4\n\n### Patch Changes\n\n- 2a09a58: \"fix: check if both source and target objects are POJOs\"\n\n## 4.12.3\n\n### Patch Changes\n\n- 72e4379: fix: remove deep data mutation warning closes #4597\n- a18c19f: feat: allow path meta querying for nested fields closes #4575\n- e2171f8: feat: expose some state on form instance\n\n## 4.12.2\n\n### Patch Changes\n\n- b2203c8e: fix: apply schema casts when submitting closes #4565\n- ec8a4d7e: fix: defineField should respect global validateOnModelUpdate closes #4567\n\n## 4.12.1\n\n### Patch Changes\n\n- 36f6b9e6: fix: reset form and field behaviors for unspecified values closes #4564\n- c1c6f399: fix: unref initial values when initializing the form closes #4563\n\n## 4.12.0\n\n### Minor Changes\n\n- bbecc973: feat: deprecate reactive initial values closes #4402\n\n### Patch Changes\n\n- f9a95843: feat: add label support to defineField closes #4530\n- f688896f: fix: avoid overriding paths and destroy path on remove closes #4476 closes #4557\n- 2abb8966: fix: clone values before reset closes #4536\n- e370413b: fix: handle hoisted paths overriding one another\n- 95b701f7: feat: allow getters for field arrays\n\n## 4.11.8\n\n### Patch Changes\n\n- d1b5b855: fix: avoid triggering extra model value events closes #4461\n- 78c4668e: feat: allow null as a valid Form prop type closes #4483\n\n## 4.11.7\n\n### Patch Changes\n\n- a1414f6a: fix: export ModelessBinds type closes #4478\n\n## 4.11.6\n\n### Patch Changes\n\n- f683e909: fix(types): infer the model value prop name correctly\n\n## 4.11.5\n\n### Patch Changes\n\n- 27c9ef24: feat(types): stronger define component bind types closes #4421\n- 804ec6fa: fix: use flags to avoid validating during reset #4404 #4467\n\n## 4.11.4\n\n### Patch Changes\n\n- 4d8ed7eb: feat: added reset opts to force values closes #4440\n- b53400e2: fix: silent validation should not mark a field as validated\n- 8f680bf1: fix: clone the schema object before validating closes #4459\n- 5231f439: fix: respect validate on model update configuration closes #4451, closes #4467\n\n## 4.11.3\n\n## 4.11.2\n\n### Patch Changes\n\n- 2ff045c1: fix: do not warn if a form or a field was resolved closes #4399\n- 73219b40: feat: expose all internal types\n- 4947e88f: feat: expose BaseInputBinds and BaseComponentBinds interfaces #4409\n- ecbb690d: feat: query fields meta state\n\n## 4.11.1\n\n### Patch Changes\n\n- 5e23dcb9: fix: add support for parsing range inputs\n\n## 4.11.0\n\n### Minor Changes\n\n- 2d8143f9: feat: added composition setter functions\n\n## 4.10.9\n\n### Patch Changes\n\n- c02337f3: fix: correct the setErrors type to allow for string[]\n\n## 4.10.8\n\n### Patch Changes\n\n- a9a473b4: feat(perf): improve performance setFieldError and setFieldValue closes #4382\n\n## 4.10.7\n\n### Patch Changes\n\n- 9290f5a9: fix: clone values inserted into field arrays closes #4372\n- 93f8001a: fix: do not warn if the validation is for removed paths closes #4368\n\n## 4.10.6\n\n### Patch Changes\n\n- 40ce7a91: feat: expose normalizeRules closes #4348\n- e9b215a7: fix: resetForm should cast typed schema values closes #4347\n- 4e11ff95: fix: validate form values on setValues by default closes #4359\n- e354a13a: fix: Normalize error paths to use brackets for indices closes #4211\n- 68080d28: feat: use silent validation when field is initialized closes #4312\n\n## 4.10.5\n\n### Patch Changes\n\n- 6a1dc9bd: fix: component blur event and respect model update config closes #4346\n\n## 4.10.4\n\n### Patch Changes\n\n- 2f9ca91c: fix(types): remove deep readonly type for now\n\n## 4.10.3\n\n### Patch Changes\n\n- 32537e14: fix: less strict object checks for undefined and missing keys closes #4341\n- c3698f07: fix: respect model modifiers when emitting the value closes #4333\n\n## 4.10.2\n\n### Patch Changes\n\n- 1660048e: fix: define binds not respecting config events\n\n## 4.10.1\n\n### Patch Changes\n\n- fc416918: fix: handle NaN when parsing number inputs closes #4328\n- 435e7857: fix: reset present values after all path mutation\n- 273cca74: fix: reset field should not validate closes #4323\n\n## 4.10.0\n\n### Minor Changes\n\n- 7a548f42: chore: require vue 3.3 and refactor types\n- 7ce9d671: feat(breaking): disable v-model support by default closes #4283\n- bfd6b00a: \"feat: allow custom models for defineComponentBinds\"\n- d4fafc95: \"feat: allow handleBlur to run validations\"\n- 05d957ec: feat: mark form values as readonly closes #4282\n\n### Patch Changes\n\n- 77345c42: fix: reset form should merge values closes #4320\n- f1dc1359: fix: use event value if no checked value for checkbox/radio closes #4308\n- 3e4a7c13: feat(dx): make `syncVModel` accept the model propName\n- 2cf0eec9: feat: allow multiple messages in a validator fn closes #4322 #4318\n- ed208918: fix: trigger validation with setFieldValue by default closes #4314\n- 6a3f9f15: fix: parse native number fields closes #4313\n\n## 4.9.6\n\n### Patch Changes\n\n- b138282a: fix(types): export SetFieldValueOptions interface closes #4290\n- 6e074f77: fix: handleBlur should respect blur validate config closes #4285\n\n## 4.9.5\n\n### Patch Changes\n\n- 7356c102: fix: setFieldError should set meta.valid closes #4274\n\n## 4.9.4\n\n### Patch Changes\n\n- f4ea2c05: fix: exclude undefined and null from initial values closes #4139\n\n## 4.9.3\n\n### Patch Changes\n\n- 09d5596b: fix: run validation on value change closes #4251\n- 9bfbfaaf: feat: added isValidating to useForm\n- 48b45d91: fix: hoist nested errors path to the deepest direct parent closes #4063\n\n## 4.9.2\n\n### Patch Changes\n\n- 31090e0d: avoid double unset path with field array remove\n- 9046308b: fixed validations running for unmounted fields\n- fe322a07: batch unsets and sort paths unset order for safer unsets closes #4115\n\n## 4.9.1\n\n### Patch Changes\n\n- 681bbab4: Added type-fest to core package dependencies\n\n## 4.9.0\n\n### Minor Changes\n\n- 41b5d39b: Implemented path types into various form API functions\n- 95409080: Added component and input binds helpers\n\n### Patch Changes\n\n- 7554d4a6: fix field array triggering validation when an item is removed\n- 298577b7: setValues does not delete unspecified fields values\n\n## 4.8.6\n\n### Patch Changes\n\n- 6e0b0557: Introduced official nuxt module package\n\n## 4.8.5\n\n### Patch Changes\n\n- 9048a238: fixed zod union issues not showing up as errors closes #4204\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n## [4.8.4](https://github.com/logaretm/vee-validate/compare/v4.8.3...v4.8.4) (2023-03-24)\n\n### Bug Fixes\n\n- make initial values partial closes [#4195](https://github.com/logaretm/vee-validate/issues/4195) ([eeccd0c](https://github.com/logaretm/vee-validate/commit/eeccd0c55814408670eced3717d0347590da3488))\n- properly unref the schema before checking for default values closes [#4196](https://github.com/logaretm/vee-validate/issues/4196) ([8e3663d](https://github.com/logaretm/vee-validate/commit/8e3663d18357574ea4d394197f2c66889eeef6fa))\n\n### Features\n\n- allow name ref to be a lazy function ([8fb543a](https://github.com/logaretm/vee-validate/commit/8fb543a6e91c17d8541389e29c7014dc1f804c91))\n\n## [4.8.3](https://github.com/logaretm/vee-validate/compare/v4.8.2...v4.8.3) (2023-03-15)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.8.2](https://github.com/logaretm/vee-validate/compare/v4.8.1...v4.8.2) (2023-03-14)\n\n### Bug Fixes\n\n- do not use name as a default label for useField closes [#4164](https://github.com/logaretm/vee-validate/issues/4164) ([d5acff7](https://github.com/logaretm/vee-validate/commit/d5acff719797c77ba4ff3be5f78c4a45374f9809))\n\n## [4.8.1](https://github.com/logaretm/vee-validate/compare/v4.8.0...v4.8.1) (2023-03-12)\n\n### Bug Fixes\n\n- make sure to have a fallback for undefined casts closes [#4186](https://github.com/logaretm/vee-validate/issues/4186) ([9f1c63b](https://github.com/logaretm/vee-validate/commit/9f1c63b4dbc59f30c17bfe427020586db36cbdec))\n\n### Features\n\n- expose errorBag to <Form /> slot props ([371744e](https://github.com/logaretm/vee-validate/commit/371744eea3d3cb0a244dcd9788f4f3f2a7714132))\n\n# [4.8.0](https://github.com/logaretm/vee-validate/compare/v4.7.4...v4.8.0) (2023-03-12)\n\n### Bug Fixes\n\n- finally handicap yup schema resolution ([303b1fb](https://github.com/logaretm/vee-validate/commit/303b1fb771ee78816ef0916e4f0e26318ad641b0))\n- initial sync with v-model if enabled closes [#4163](https://github.com/logaretm/vee-validate/issues/4163) ([1040643](https://github.com/logaretm/vee-validate/commit/1040643f40ba622010ab935095dffb8d926cd76d))\n- properly aggregrate nested errors for yup ([7f90bbc](https://github.com/logaretm/vee-validate/commit/7f90bbceeaeb7806a9626adb72981933a69db96f))\n- remove console.log from devtools integration ([3c2d51c](https://github.com/logaretm/vee-validate/commit/3c2d51c56f80918ef6644b034594df1a3e81eb03))\n- remove yup schema type and rely on assertions ([5cbb913](https://github.com/logaretm/vee-validate/commit/5cbb913071e315264d62fda7d1219bdc28d3faf0))\n- render zod multiple errors in nested objects closes [#4078](https://github.com/logaretm/vee-validate/issues/4078) ([f74fb69](https://github.com/logaretm/vee-validate/commit/f74fb69977d17ef8fab4c22734ffd76ca1c02a48))\n- run silent validation after array mutations closes [#4096](https://github.com/logaretm/vee-validate/issues/4096) ([044b4b4](https://github.com/logaretm/vee-validate/commit/044b4b44601908330c65541ce2bee6a110b1604f))\n- type inference fix ([ac0383f](https://github.com/logaretm/vee-validate/commit/ac0383f1fb335bf92c9249f65bf319ca182545b7))\n- watch and re-init array fields if form data changed closes [#4153](https://github.com/logaretm/vee-validate/issues/4153) ([6e784cc](https://github.com/logaretm/vee-validate/commit/6e784ccacbe89b5cd9daa9e3827808f7056aac04))\n\n### Features\n\n- Better Yup and Zod typing with output types and input inference ([#4064](https://github.com/logaretm/vee-validate/issues/4064)) ([3820a5b](https://github.com/logaretm/vee-validate/commit/3820a5b8eb3f8c6cd9239057746ccfb4b2e57e76))\n- export type `FieldState` ([#4159](https://github.com/logaretm/vee-validate/issues/4159)) ([69c0d12](https://github.com/logaretm/vee-validate/commit/69c0d12434d50b52f4691c2f95d739049a3d1fcb))\n\n## [4.7.4](https://github.com/logaretm/vee-validate/compare/v4.7.3...v4.7.4) (2023-02-07)\n\n### Bug Fixes\n\n- pass the field label as a seperate value closes [#4097](https://github.com/logaretm/vee-validate/issues/4097) ([89f8689](https://github.com/logaretm/vee-validate/commit/89f8689b673be27f0fc221d6c096efa11dacd3e6))\n\n### Features\n\n- **#4117:** add resetField on Form/useForm ([#4120](https://github.com/logaretm/vee-validate/issues/4120)) ([87c4278](https://github.com/logaretm/vee-validate/commit/87c42787c0b4de5a09abe0d29deb92b28b59023e)), closes [#4117](https://github.com/logaretm/vee-validate/issues/4117)\n- expose state getters on the form instance via template refs ([#4121](https://github.com/logaretm/vee-validate/issues/4121)) ([7f1c39c](https://github.com/logaretm/vee-validate/commit/7f1c39c0d9a0d1f7b7768b68c6705b5bfda91599))\n\n## [4.7.3](https://github.com/logaretm/vee-validate/compare/v4.7.2...v4.7.3) (2022-11-13)\n\n### Bug Fixes\n\n- use cloned value when setting field value closes [#3991](https://github.com/logaretm/vee-validate/issues/3991) ([90b61fc](https://github.com/logaretm/vee-validate/commit/90b61fc8810a1fdc677507251735b4210f175f4b))\n\n## [4.7.2](https://github.com/logaretm/vee-validate/compare/v4.7.1...v4.7.2) (2022-11-02)\n\n### Bug Fixes\n\n- don't mutate validated meta when silent validation closes [#3981](https://github.com/logaretm/vee-validate/issues/3981) closes [#3982](https://github.com/logaretm/vee-validate/issues/3982) ([6652a22](https://github.com/logaretm/vee-validate/commit/6652a22f99cde5b018c633365025d74e15dde835))\n\n## [4.7.1](https://github.com/logaretm/vee-validate/compare/v4.7.0...v4.7.1) (2022-10-23)\n\n### Bug Fixes\n\n- clean up single group value after unmount closes [#3963](https://github.com/logaretm/vee-validate/issues/3963) ([#3972](https://github.com/logaretm/vee-validate/issues/3972)) ([8ccfd2b](https://github.com/logaretm/vee-validate/commit/8ccfd2b2b542963d3d35cfe5f82490c94ec1635f))\n- correctly mutate deep field array item and trigger validation ([#3974](https://github.com/logaretm/vee-validate/issues/3974)) ([267736f](https://github.com/logaretm/vee-validate/commit/267736f43ca207a8fe35af30020fc61fdc009265))\n- mark slot prop field value as any closes [#3969](https://github.com/logaretm/vee-validate/issues/3969) ([#3973](https://github.com/logaretm/vee-validate/issues/3973)) ([70ddc5b](https://github.com/logaretm/vee-validate/commit/70ddc5b60232f0dc761b7803a3220010d2f8ba69))\n\n# [4.7.0](https://github.com/logaretm/vee-validate/compare/v4.6.10...v4.7.0) (2022-10-09)\n\n### Features\n\n- allow passing form control to useField closes [#3204](https://github.com/logaretm/vee-validate/issues/3204) ([#3923](https://github.com/logaretm/vee-validate/issues/3923)) ([4c59d63](https://github.com/logaretm/vee-validate/commit/4c59d634f25d7fff024b50f3ffd667f7fdf0076c))\n- expose controlled values on useForm ([#3924](https://github.com/logaretm/vee-validate/issues/3924)) ([2517319](https://github.com/logaretm/vee-validate/commit/25173196f3b689d919015cf8e7df8254b9e3090e))\n\n## [4.6.10](https://github.com/logaretm/vee-validate/compare/v4.6.9...v4.6.10) (2022-09-30)\n\n### Bug Fixes\n\n- use ssr safe file check ([56663aa](https://github.com/logaretm/vee-validate/commit/56663aa2e50d7aa285ca1cb22887c8e8b3f7fd3c))\n\n## [4.6.9](https://github.com/logaretm/vee-validate/compare/v4.6.8...v4.6.9) (2022-09-19)\n\n### Bug Fixes\n\n- perform field reset before all values reset closes [#3934](https://github.com/logaretm/vee-validate/issues/3934) ([1c016d9](https://github.com/logaretm/vee-validate/commit/1c016d93b367229644dca643931ef63bc6e433dc))\n\n## [4.6.8](https://github.com/logaretm/vee-validate/compare/v4.6.7...v4.6.8) (2022-09-19)\n\n### Bug Fixes\n\n- ensure validation if we skip checkbox value setting [#3927](https://github.com/logaretm/vee-validate/issues/3927) ([#3930](https://github.com/logaretm/vee-validate/issues/3930)) ([82d05db](https://github.com/logaretm/vee-validate/commit/82d05dbd2a5c7d5ea2fe7b73222dd339e92ee373))\n- extend is equal with file comparison logic [#3911](https://github.com/logaretm/vee-validate/issues/3911) ([#3932](https://github.com/logaretm/vee-validate/issues/3932)) ([c7c806c](https://github.com/logaretm/vee-validate/commit/c7c806c0c5393f3188c16384f5fc1b46ebc78cbd))\n- handle nested value change validation [#3926](https://github.com/logaretm/vee-validate/issues/3926) ([#3929](https://github.com/logaretm/vee-validate/issues/3929)) ([771e7f2](https://github.com/logaretm/vee-validate/commit/771e7f21cf332052b74c5506a8c2f38f666cae55))\n\n### Features\n\n- expose RuleExpression type closes [#3913](https://github.com/logaretm/vee-validate/issues/3913) ([cdaf22d](https://github.com/logaretm/vee-validate/commit/cdaf22df04b42a68f55133ad3854aae9a7ad6953))\n\n## [4.6.7](https://github.com/logaretm/vee-validate/compare/v4.6.6...v4.6.7) (2022-08-27)\n\n### Bug Fixes\n\n- allow generics for generic function type ([91e97aa](https://github.com/logaretm/vee-validate/commit/91e97aa41bca278970780973fcbf90e17fb29920))\n- handle validation races for async validations ([#3908](https://github.com/logaretm/vee-validate/issues/3908)) ([8c82079](https://github.com/logaretm/vee-validate/commit/8c82079dac8535678e45428ad8e5afe7dcd3da63))\n\n## [4.6.6](https://github.com/logaretm/vee-validate/compare/v4.6.5...v4.6.6) (2022-08-16)\n\n### Bug Fixes\n\n- return value if no model modifiers are defined closes [#3895](https://github.com/logaretm/vee-validate/issues/3895) ([#3896](https://github.com/logaretm/vee-validate/issues/3896)) ([6ab40df](https://github.com/logaretm/vee-validate/commit/6ab40df4452c5bee8a487a37164e2273c2aaf0ba))\n\n## [4.6.5](https://github.com/logaretm/vee-validate/compare/v4.6.4...v4.6.5) (2022-08-11)\n\n### Bug Fixes\n\n- reset the original value when resetField is called [#3891](https://github.com/logaretm/vee-validate/issues/3891) ([#3892](https://github.com/logaretm/vee-validate/issues/3892)) ([7113dcc](https://github.com/logaretm/vee-validate/commit/7113dccdeb962d8efa064ff0ebd171b2aa2f4c4d))\n\n## [4.6.4](https://github.com/logaretm/vee-validate/compare/v4.6.3...v4.6.4) (2022-08-07)\n\n### Bug Fixes\n\n- make sure to deep watch created models by useFieldModel ([fbe273c](https://github.com/logaretm/vee-validate/commit/fbe273c6f2c5d30a1996777561eda2268d8a02e0))\n\n## [4.6.3](https://github.com/logaretm/vee-validate/compare/v4.6.2...v4.6.3) (2022-08-07)\n\n### Features\n\n- Expose InvalidSubmissionHandler and GenericValidateFunction types ([#3853](https://github.com/logaretm/vee-validate/issues/3853)) ([3ccf27d](https://github.com/logaretm/vee-validate/commit/3ccf27d5b9c1fe9cf655b89533eb1802cb5717d4))\n\n## [4.6.2](https://github.com/logaretm/vee-validate/compare/v4.6.1...v4.6.2) (2022-07-17)\n\n### Bug Fixes\n\n- avoid toggling field array checkboxes values closes [#3844](https://github.com/logaretm/vee-validate/issues/3844) ([fffad4b](https://github.com/logaretm/vee-validate/commit/fffad4bea68cc949d0bce440b5daf43901aaca7f))\n\n### Features\n\n- expose field and form options closes [#3843](https://github.com/logaretm/vee-validate/issues/3843) ([7437612](https://github.com/logaretm/vee-validate/commit/7437612ab554f8f65b445f7b065725b570a9a14a))\n\n## [4.6.1](https://github.com/logaretm/vee-validate/compare/v4.6.0...v4.6.1) (2022-07-12)\n\n### Bug Fixes\n\n- pass onInvalidSubmit prop to submitForm closes [#3841](https://github.com/logaretm/vee-validate/issues/3841) ([b6cf543](https://github.com/logaretm/vee-validate/commit/b6cf543b600246942fc7f6802a0cc6ea1038603a))\n\n# [4.6.0](https://github.com/logaretm/vee-validate/compare/v4.5.11...v4.6.0) (2022-07-11)\n\n### Bug Fixes\n\n- added existing undefined path fallback closes [#3801](https://github.com/logaretm/vee-validate/issues/3801) ([fd0500c](https://github.com/logaretm/vee-validate/commit/fd0500c9cb4448b232eddb4cd5d8d081e5d48d08))\n- avoid inserting value binding for file type inputs closes [#3760](https://github.com/logaretm/vee-validate/issues/3760) ([3c76bb2](https://github.com/logaretm/vee-validate/commit/3c76bb2ebcbafaf46047b8e41bcc053e41cf27bf))\n- avoid validating when field instance exists ([3759df2](https://github.com/logaretm/vee-validate/commit/3759df20f5ba48a43d5dea4bb6d94e875f15c331))\n- compare form meta.dirty based on original values than staged initials closes [#3782](https://github.com/logaretm/vee-validate/issues/3782) ([f3ffd3c](https://github.com/logaretm/vee-validate/commit/f3ffd3c00ac1f2b73b6a3039cb997d08cf8e452b))\n- expose ValidationOptions type closes [#3825](https://github.com/logaretm/vee-validate/issues/3825) ([9854865](https://github.com/logaretm/vee-validate/commit/9854865ae60431256e6fb9c921d1eabc9093b5e4))\n- exposed component APIs to their TS defs with refs closes [#3292](https://github.com/logaretm/vee-validate/issues/3292) ([ae59d0f](https://github.com/logaretm/vee-validate/commit/ae59d0f6f3728a2a95732517d11fdf970127fe9c))\n- fast equal before deciding value was changed closes [#3808](https://github.com/logaretm/vee-validate/issues/3808) ([3d582ec](https://github.com/logaretm/vee-validate/commit/3d582ec6c884467199cc7fb86ffe0e571d85c4fb))\n- use multiple batch queues for both validation modes closes [#3783](https://github.com/logaretm/vee-validate/issues/3783) ([6156603](https://github.com/logaretm/vee-validate/commit/6156603f537fb46030017fb3a4d003b6bec0d4e8))\n\n### Features\n\n- **4.6:** Allow mutating field array iterable's value property ([#3618](https://github.com/logaretm/vee-validate/issues/3618)) ([#3759](https://github.com/logaretm/vee-validate/issues/3759)) ([c3c40e5](https://github.com/logaretm/vee-validate/commit/c3c40e50b68cbf8aee3356416561fdf5d23ac6d2))\n- add move to FieldArray ([a52f133](https://github.com/logaretm/vee-validate/commit/a52f13356c44616d699e02f9a243dd08c7bcc38e))\n- added unsetValueOnUnmount config ([#3815](https://github.com/logaretm/vee-validate/issues/3815)) ([e6e1c1d](https://github.com/logaretm/vee-validate/commit/e6e1c1d66bfd4c453ac21c00b3faa2d6470040a8))\n- added useFieldModel to useForm API ([26c828e](https://github.com/logaretm/vee-validate/commit/26c828e21495c485d489ea1319575d9b5c271801))\n- allow keep values config to be reactive ([5009bd8](https://github.com/logaretm/vee-validate/commit/5009bd88c09f7a8c753fc52dd5bf8d4d5234567b))\n- better normalization for native input file events ([2751552](https://github.com/logaretm/vee-validate/commit/2751552a42b4eaa57d22ea24c38cd31cfd5b9955))\n- Remove yup type dependency ([#3704](https://github.com/logaretm/vee-validate/issues/3704)) ([e772f9a](https://github.com/logaretm/vee-validate/commit/e772f9a7b9f0e45680a65dfae249ee2092ca850e))\n- Sync useField with component v-model ([#3806](https://github.com/logaretm/vee-validate/issues/3806)) ([0ef7582](https://github.com/logaretm/vee-validate/commit/0ef75823d1b90e1213f8a31014c2cf347d386ec1))\n\n## [4.5.11](https://github.com/logaretm/vee-validate/compare/v4.5.10...v4.5.11) (2022-04-10)\n\n### Bug Fixes\n\n- ignore validation of removed array elements closes [#3748](https://github.com/logaretm/vee-validate/issues/3748) ([3d49faa](https://github.com/logaretm/vee-validate/commit/3d49faa4101902c2e77aee0a2d43cd29b69f7b4e))\n\n### Features\n\n- chain of GenericValidateFunction in useField ([#3725](https://github.com/logaretm/vee-validate/issues/3725)) ([#3726](https://github.com/logaretm/vee-validate/issues/3726)) ([8db4077](https://github.com/logaretm/vee-validate/commit/8db407785c5611c10c221eabd747c3f31770145b))\n\n## [4.5.10](https://github.com/logaretm/vee-validate/compare/v4.5.9...v4.5.10) (2022-03-08)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.5.9](https://github.com/logaretm/vee-validate/compare/v4.5.8...v4.5.9) (2022-02-22)\n\n### Bug Fixes\n\n- mark fields validated via form validate as validated ([ad9fa9d](https://github.com/logaretm/vee-validate/commit/ad9fa9d853a8cabb26cdde04c20c07d4f2673aa4))\n\n## [4.5.8](https://github.com/logaretm/vee-validate/compare/v4.5.7...v4.5.8) (2022-01-23)\n\n### Bug Fixes\n\n- clear old error path error when changing field name closes [#3664](https://github.com/logaretm/vee-validate/issues/3664) ([f736e62](https://github.com/logaretm/vee-validate/commit/f736e62b1bb82f940d14d74a6d505c913c1c3dde))\n- field array swap not working when falsy values are present at paths ([40afbd9](https://github.com/logaretm/vee-validate/commit/40afbd9cc3fb3de71de3f6ebb0a1b2774d9018ff))\n\n## [4.5.7](https://github.com/logaretm/vee-validate/compare/v4.5.6...v4.5.7) (2021-12-07)\n\n### Bug Fixes\n\n- always attach model update event closes [#3583](https://github.com/logaretm/vee-validate/issues/3583) ([6a53e80](https://github.com/logaretm/vee-validate/commit/6a53e80525a9c38ce8851407b832bc8409c3f334))\n\n## [4.5.6](https://github.com/logaretm/vee-validate/compare/v4.5.5...v4.5.6) (2021-11-17)\n\n### Bug Fixes\n\n- corrected the typing for the resetField function closes [#3568](https://github.com/logaretm/vee-validate/issues/3568) ([4e9460e](https://github.com/logaretm/vee-validate/commit/4e9460e3a4f51f4a78ddcdf17f7c3073f899404f))\n- new devtools typings ([f288ca5](https://github.com/logaretm/vee-validate/commit/f288ca5a59d36f23ba7f6bdd210493588f744940))\n- use watchEffect to compute form meta closes [#3580](https://github.com/logaretm/vee-validate/issues/3580) ([e8729dc](https://github.com/logaretm/vee-validate/commit/e8729dc72d2a027a666515360c9537a62a8d46ad))\n\n## [4.5.5](https://github.com/logaretm/vee-validate/compare/v4.5.4...v4.5.5) (2021-11-01)\n\n### Bug Fixes\n\n- prevent toggle checkboxes when form resets closes [#3551](https://github.com/logaretm/vee-validate/issues/3551) ([cad12ba](https://github.com/logaretm/vee-validate/commit/cad12ba7502af7268029930a9176d8e160efeef6))\n\n## [4.5.4](https://github.com/logaretm/vee-validate/compare/v4.5.3...v4.5.4) (2021-10-20)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.5.3](https://github.com/logaretm/vee-validate/compare/v4.5.2...v4.5.3) (2021-10-17)\n\n### Features\n\n- added slot typings for components closes [#3534](https://github.com/logaretm/vee-validate/issues/3534) ([#3537](https://github.com/logaretm/vee-validate/issues/3537)) ([52a2a38](https://github.com/logaretm/vee-validate/commit/52a2a385ec6e65c7eaaed0a67615c45aba07de64))\n\n## [4.5.2](https://github.com/logaretm/vee-validate/compare/v4.5.1...v4.5.2) (2021-09-30)\n\n### Bug Fixes\n\n- use klona/full mode to handle luxon values closes [#3508](https://github.com/logaretm/vee-validate/issues/3508) ([048c9c0](https://github.com/logaretm/vee-validate/commit/048c9c03d38ffd871ee4b3504daf1c83d42e9516))\n\n## [4.5.1](https://github.com/logaretm/vee-validate/compare/v4.5.0...v4.5.1) (2021-09-29)\n\n**Note:** Version bump only for package vee-validate\n\n# [4.5.0](https://github.com/logaretm/vee-validate/compare/v4.4.11...v4.5.0) (2021-09-26)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.4.11](https://github.com/logaretm/vee-validate/compare/v4.4.10...v4.4.11) (2021-09-11)\n\n### Bug Fixes\n\n- dynamic rule forcing validation closes [#3485](https://github.com/logaretm/vee-validate/issues/3485) ([d3f0fc0](https://github.com/logaretm/vee-validate/commit/d3f0fc094c89375bd67bdd3f533e5ab545a83611))\n\n## [4.4.10](https://github.com/logaretm/vee-validate/compare/v4.4.9...v4.4.10) (2021-08-31)\n\n### Bug Fixes\n\n- added silent validation run after reset closes [#3463](https://github.com/logaretm/vee-validate/issues/3463) ([a61f7ab](https://github.com/logaretm/vee-validate/commit/a61f7ab532d6d2fd9f237145f91bbcc9043431f6))\n- handle absent model value closes [#3468](https://github.com/logaretm/vee-validate/issues/3468) ([2c4a7ff](https://github.com/logaretm/vee-validate/commit/2c4a7ffb84811ae86a1698e6e15f41dc32f8fb8d))\n- **types:** remove arguments of PrivateFieldContext.handleReset ([2e45d1f](https://github.com/logaretm/vee-validate/commit/2e45d1f8a8444c0aabfd307364cadfab74802d02))\n- ensure option bound value type is preserved closes [#3440](https://github.com/logaretm/vee-validate/issues/3440) ([b144615](https://github.com/logaretm/vee-validate/commit/b1446152d6f6cd4843ab206d667a7d744c2a14fc))\n\n## [4.4.9](https://github.com/logaretm/vee-validate/compare/v4.4.8...v4.4.9) (2021-08-05)\n\n### Bug Fixes\n\n- ensure to clone user passed values in setters closes [#3428](https://github.com/logaretm/vee-validate/issues/3428) ([a720c24](https://github.com/logaretm/vee-validate/commit/a720c2444b64d28743ba0500aa970419029352cb))\n- prioritize the current value if another field of same name is mounted closes [#3429](https://github.com/logaretm/vee-validate/issues/3429) ([cf036ec](https://github.com/logaretm/vee-validate/commit/cf036ecf9a5dad401c752c132ef5333d0f442441))\n\n## [4.4.8](https://github.com/logaretm/vee-validate/compare/v4.4.7...v4.4.8) (2021-07-31)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.4.7](https://github.com/logaretm/vee-validate/compare/v4.4.6...v4.4.7) (2021-07-20)\n\n### Bug Fixes\n\n- avoid watching values at the end of reset calls closes [#3407](https://github.com/logaretm/vee-validate/issues/3407) ([86f594f](https://github.com/logaretm/vee-validate/commit/86f594f4a7cee5ed5f581419bdbd985fc53f8358))\n\n### Features\n\n- add standalone prop for fields ([#3379](https://github.com/logaretm/vee-validate/issues/3379)) ([3689437](https://github.com/logaretm/vee-validate/commit/36894378aa3636eeb4fb54aa747319e21c6eb5cd))\n- expose FieldContext type closes [#3398](https://github.com/logaretm/vee-validate/issues/3398) ([a6e4c0a](https://github.com/logaretm/vee-validate/commit/a6e4c0ac580d4145c72118ac535bfa082c771068))\n- expose form and field injection keys ([6034e66](https://github.com/logaretm/vee-validate/commit/6034e66836e0566e17f36744da19088aca33fbad))\n\n## [4.4.6](https://github.com/logaretm/vee-validate/compare/v4.4.5...v4.4.6) (2021-07-08)\n\n### Bug Fixes\n\n- clean error message for singular fields after unmount ([#3385](https://github.com/logaretm/vee-validate/issues/3385)) ([4e81cce](https://github.com/logaretm/vee-validate/commit/4e81cce292380974728b952a2fa1724c1ea4f086))\n- quit unsetting path if its already unset ([cfe45ba](https://github.com/logaretm/vee-validate/commit/cfe45ba38690ec27b5ee4e48a80336834a932a78))\n- expose setters in composition API ([d79747d](https://github.com/logaretm/vee-validate/commit/d79747de4a25d1ced151d9bd5b767e815d7e32bf))\n\n## [4.4.5](https://github.com/logaretm/vee-validate/compare/v4.4.4...v4.4.5) (2021-06-13)\n\n## [4.4.4](https://github.com/logaretm/vee-validate/compare/v4.4.3...v4.4.4) (2021-06-05)\n\n### Bug Fixes\n\n- field with pre-register schema errors should be validated on register closes [#3342](https://github.com/logaretm/vee-validate/issues/3342) ([61c7359](https://github.com/logaretm/vee-validate/commit/61c73597b2e69c094e75c02476d825c5236710b5))\n- make sure to create the container path if it exists while null or undefined ([79d3779](https://github.com/logaretm/vee-validate/commit/79d37798ccf2fef56714bdad4db553086df0ad48))\n- make sure to create the container path if it exists while null or undefined ([79d3779](https://github.com/logaretm/vee-validate/commit/79d37798ccf2fef56714bdad4db553086df0ad48))\n\n### Features\n\n- expose setters in composition API ([61f942f](https://github.com/logaretm/vee-validate/commit/61f942f511e6fcceb10a74272ac845017ce88997))\n\n## [4.4.3](https://github.com/logaretm/vee-validate/compare/v4.4.2...v4.4.3) (2021-06-02)\n\n### Bug Fixes\n\n- respect the Field bails option closes [#3332](https://github.com/logaretm/vee-validate/issues/3332) ([6679387](https://github.com/logaretm/vee-validate/commit/66793878e317f32f4759b3d01e27e3b9072eff67))\n\n## [4.4.2](https://github.com/logaretm/vee-validate/compare/v4.4.1...v4.4.2) (2021-05-28)\n\n### Bug Fixes\n\n- clean up the old values path when fields exchange names fixes [#3325](https://github.com/logaretm/vee-validate/issues/3325) ([fe51c12](https://github.com/logaretm/vee-validate/commit/fe51c126ae6258ac0888ee47d9d01a27b889a5c1))\n\n## [4.4.1](https://github.com/logaretm/vee-validate/compare/v4.4.0...v4.4.1) (2021-05-24)\n\n### Bug Fixes\n\n- forgot adding errors in useValidationForm ([d032d3b](https://github.com/logaretm/vee-validate/commit/d032d3b55438169fa87c18d89e073fffe3988d56))\n- re-introduce the errors prop back on the form validation result closes [#3317](https://github.com/logaretm/vee-validate/issues/3317) ([b439a73](https://github.com/logaretm/vee-validate/commit/b439a73bf3c37298c251b74223984d54b8949a95))\n\n# [4.4.0](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.2...v4.4.0) (2021-05-23)\n\n### Bug Fixes\n\n- seperate model detection from event emitting closes [#3312](https://github.com/logaretm/vee-validate/issues/3312) ([5e72852](https://github.com/logaretm/vee-validate/commit/5e72852e80b971121d10422cf84085b07bb2d8fb))\n\n# [4.4.0-alpha.2](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.1...v4.4.0-alpha.2) (2021-05-14)\n\n### Bug Fixes\n\n- avoid clearing all errors before validating schema ([51c2e78](https://github.com/logaretm/vee-validate/commit/51c2e7890b87d971850dfc609c09d19b79a96fb6))\n\n# [4.4.0-alpha.1](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.0...v4.4.0-alpha.1) (2021-05-14)\n\n### Bug Fixes\n\n- minifier issue when handling await ([f206cac](https://github.com/logaretm/vee-validate/commit/f206cacd7e0d03a36fce5b236c23906997e0287b))\n\n# [4.4.0-alpha.0](https://github.com/logaretm/vee-validate/compare/v4.3.6...v4.4.0-alpha.0) (2021-05-14)\n\n### Bug Fixes\n\n- deprecate handleInput and use handleChange for both events ([#3303](https://github.com/logaretm/vee-validate/issues/3303)) ([4cb10de](https://github.com/logaretm/vee-validate/commit/4cb10de0a5f589f72c82cdd4a8859b7f044ae84c))\n\n### Features\n\n- custom values and errors ([#3305](https://github.com/logaretm/vee-validate/issues/3305)) ([427802b](https://github.com/logaretm/vee-validate/commit/427802b94ea309d12df26ba51ac1b3a24e4e8d46))\n\n## [4.3.6](https://github.com/logaretm/vee-validate/compare/v4.3.5...v4.3.6) (2021-05-08)\n\n### Bug Fixes\n\n- added a symbol to detect non passed props with Vue 3.1.x ([#3295](https://github.com/logaretm/vee-validate/issues/3295)) ([0663539](https://github.com/logaretm/vee-validate/commit/06635397424526c3a3c4a53f63322bbfd55000ee))\n\n## [4.3.5](https://github.com/logaretm/vee-validate/compare/v4.3.4...v4.3.5) (2021-05-01)\n\n### Bug Fixes\n\n- priotrize self injections over parent injections closes [#3270](https://github.com/logaretm/vee-validate/issues/3270) ([07c1234](https://github.com/logaretm/vee-validate/commit/07c12341d7f2e25e41a56ea0d5e38e9a374ae84b))\n\n## [4.3.4](https://github.com/logaretm/vee-validate/compare/v4.3.3...v4.3.4) (2021-04-27)\n\n### Bug Fixes\n\n- update the valid flag regardless of mode closes [#3284](https://github.com/logaretm/vee-validate/issues/3284) ([6594ad1](https://github.com/logaretm/vee-validate/commit/6594ad15e4423c6a7861da188560b06f98365d9d))\n\n## [4.3.3](https://github.com/logaretm/vee-validate/compare/v4.3.2...v4.3.3) (2021-04-22)\n\n### Features\n\n- touch all fields on submit ([#3278](https://github.com/logaretm/vee-validate/issues/3278)) ([fc4e400](https://github.com/logaretm/vee-validate/commit/fc4e400f7d9349c1e82bba8412d13e0cf69be0e1))\n\n## [4.3.2](https://github.com/logaretm/vee-validate/compare/v4.3.1...v4.3.2) (2021-04-21)\n\n### Bug Fixes\n\n- unwrap initial value with useField.resetField fixes [#3272](https://github.com/logaretm/vee-validate/issues/3272) ([#3274](https://github.com/logaretm/vee-validate/issues/3274)) ([f6e9574](https://github.com/logaretm/vee-validate/commit/f6e95741f31fc085f718e07d3b1f1adfe0229df6))\n\n## [4.3.1](https://github.com/logaretm/vee-validate/compare/v4.3.0...v4.3.1) (2021-04-18)\n\n### Bug Fixes\n\n- give error message component a name ([b7dcebf](https://github.com/logaretm/vee-validate/commit/b7dcebfcd202538cf082314817f97c3b8e07fefb))\n- minor perf enhancement by lazy evaulation of slot props ([a306b1b](https://github.com/logaretm/vee-validate/commit/a306b1b0047ec82eaf727a6e380856de077c4fbe))\n\n# [4.3.0](https://github.com/logaretm/vee-validate/compare/v4.2.4...v4.3.0) (2021-04-07)\n\n### Features\n\n- added support for reactive schemas ([#3238](https://github.com/logaretm/vee-validate/issues/3238)) ([295d656](https://github.com/logaretm/vee-validate/commit/295d6567035bc3c452ad0f13fce13ff362b08005))\n- added support for setting multiple field errors closes [#3117](https://github.com/logaretm/vee-validate/issues/3117) ([db0a6a0](https://github.com/logaretm/vee-validate/commit/db0a6a02cdc0fdab02a18e4756005c46dc06b1f8))\n- support v-model.number ([#3252](https://github.com/logaretm/vee-validate/issues/3252)) ([8f491da](https://github.com/logaretm/vee-validate/commit/8f491da0b0998d0f7383a6a444d6aa498e3d96f4))\n\n## [4.2.4](https://github.com/logaretm/vee-validate/compare/v4.2.3...v4.2.4) (2021-03-26)\n\n### Bug Fixes\n\n- validation triggered on value change ([10549b7](https://github.com/logaretm/vee-validate/commit/10549b77dc350cee4f198cb14e3fd12f61e12b80))\n\n## [4.2.3](https://github.com/logaretm/vee-validate/compare/v4.2.2...v4.2.3) (2021-03-22)\n\n### Bug Fixes\n\n- prevent yup schema from setting non-interacted fields errors closes [#3228](https://github.com/logaretm/vee-validate/issues/3228) ([534f8b2](https://github.com/logaretm/vee-validate/commit/534f8b28850c9f28245a748f956d1358bb7cb2e1))\n\n## [4.2.2](https://github.com/logaretm/vee-validate/compare/v4.2.1...v4.2.2) (2021-03-03)\n\n### Bug Fixes\n\n- ensure having a truthy fallback for fields missing in schema ([7cd6941](https://github.com/logaretm/vee-validate/commit/7cd694114403f7c252b6ba6b83c159110cdc58cf))\n- handle pending validation runs during field unmounting ([ef5a7cc](https://github.com/logaretm/vee-validate/commit/ef5a7ccb269db8bbdee446e76dd60ebe8704b57e))\n\n## [4.2.1](https://github.com/logaretm/vee-validate/compare/v4.2.0...v4.2.1) (2021-02-26)\n\n### Bug Fixes\n\n- added initial check against the field errors ([4288fb6](https://github.com/logaretm/vee-validate/commit/4288fb6291a3ed17d46569fd2b0baa690beb9cb1))\n\n# [4.2.0](https://github.com/logaretm/vee-validate/compare/v4.1.20...v4.2.0) (2021-02-24)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.1.20](https://github.com/logaretm/vee-validate/compare/v4.1.19...v4.1.20) (2021-02-24)\n\n### Bug Fixes\n\n- avoid setting checkbox values before registeration closes [#3183](https://github.com/logaretm/vee-validate/issues/3183) ([ab5f821](https://github.com/logaretm/vee-validate/commit/ab5f82103f8cfe5f5934a51057ce989ad30d0d44))\n- change errors source to form closes [#3177](https://github.com/logaretm/vee-validate/issues/3177) ([7c13c92](https://github.com/logaretm/vee-validate/commit/7c13c92f477bc3d63067509fd9fec72964263f5d))\n- use the issues array for zod error aggregation closes [#3184](https://github.com/logaretm/vee-validate/issues/3184) ([01b89e4](https://github.com/logaretm/vee-validate/commit/01b89e4940e997ef65dc950be3a13e0ffc18e881))\n\n## [4.1.19](https://github.com/logaretm/vee-validate/compare/v4.1.18...v4.1.19) (2021-02-16)\n\n### Bug Fixes\n\n- use relative imports for shared type ([6790545](https://github.com/logaretm/vee-validate/commit/6790545dc9c35550d231fb14a310f3655dbc7256))\n\n### Features\n\n- improve typing for field yup schema ([c59f1f0](https://github.com/logaretm/vee-validate/commit/c59f1f01526b160a1081f276d732523ad9ab5ba2))\n\n## [4.1.18](https://github.com/logaretm/vee-validate/compare/v4.1.17...v4.1.18) (2021-02-10)\n\n### Bug Fixes\n\n- avoid unsetting field value if switched with another closes [#3166](https://github.com/logaretm/vee-validate/issues/3166) ([f5a79fe](https://github.com/logaretm/vee-validate/commit/f5a79fe3b15f7437acf183c162e69178fd4fa7ec))\n\n## [4.1.17](https://github.com/logaretm/vee-validate/compare/v3.2.0...v4.1.17) (2021-02-08)\n\n### Bug Fixes\n\n- add a handler for regex object params closes [#3073](https://github.com/logaretm/vee-validate/issues/3073) ([7a5e2eb](https://github.com/logaretm/vee-validate/commit/7a5e2ebf8303395372ae08ebcca55427a58faecb))\n- added emits and onSubmit custom prop ([#3115](https://github.com/logaretm/vee-validate/issues/3115)) ([8f2c110](https://github.com/logaretm/vee-validate/commit/8f2c110f14add0fbd82a28a91601e89938144624))\n- array radio fields not switching value correctly closes [#3141](https://github.com/logaretm/vee-validate/issues/3141) ([3d4efef](https://github.com/logaretm/vee-validate/commit/3d4efef68c63a3b57e2bf14fed913dbf841a7f5e))\n- avoid returning undefined for form errors when form does not exist ([8cce17a](https://github.com/logaretm/vee-validate/commit/8cce17ae2846be912d51926c79e557ed8bb39582))\n- avoid validating dependencies via watcheffect closes [#3156](https://github.com/logaretm/vee-validate/issues/3156) ([a7b91f6](https://github.com/logaretm/vee-validate/commit/a7b91f6e6c38f0b5262e2d4c1814154efa3b78c8))\n- cast radio buttons value correctly closes [#3064](https://github.com/logaretm/vee-validate/issues/3064) ([3e0f9a4](https://github.com/logaretm/vee-validate/commit/3e0f9a47369edac32d0c8a068f8b61d8f761458f))\n- clear out initial values for unregistered fields closes [#3060](https://github.com/logaretm/vee-validate/issues/3060) ([56206de](https://github.com/logaretm/vee-validate/commit/56206de995fe8f2eaca3e303ab6980784a3c95b1))\n- correctly set the initial value from the v-model closes [#3107](https://github.com/logaretm/vee-validate/issues/3107) ([4bed9a8](https://github.com/logaretm/vee-validate/commit/4bed9a806323139d2f274e51b6bfe3de2190e54d))\n- export submission types [#3112](https://github.com/logaretm/vee-validate/issues/3112) ([3f35167](https://github.com/logaretm/vee-validate/commit/3f351670da02364b0fb8e61198145dfa02dc59b9))\n- fill the target rule params for message generators closes [#3077](https://github.com/logaretm/vee-validate/issues/3077) ([f5e1bd3](https://github.com/logaretm/vee-validate/commit/f5e1bd3cbc278a8588fa0c96af66823d82eefb8c))\n- handle formless checkboxes value toggling closes [#3105](https://github.com/logaretm/vee-validate/issues/3105) ([504f30b](https://github.com/logaretm/vee-validate/commit/504f30bfcbcb1db710397ef05545b5008b0103fb))\n- handle reactive field names and value swaps ([cf8051d](https://github.com/logaretm/vee-validate/commit/cf8051d3b92eb43103f4e7c682e615343239d717))\n- missing export for useErrors helpers ([28537cc](https://github.com/logaretm/vee-validate/commit/28537cc547cf945b10adc485620ad226f71d60fc))\n- pass down listeners to the input node closes [#3048](https://github.com/logaretm/vee-validate/issues/3048) ([2526a63](https://github.com/logaretm/vee-validate/commit/2526a63c2361e412b528cf370c03b39cb84b606d))\n- prevent default reset behavior with handleReset ([a66df13](https://github.com/logaretm/vee-validate/commit/a66df13c3f39d84984581dc3c0ce368b052b6e8e))\n- prevent resetForm from toggling checkbox value [#3084](https://github.com/logaretm/vee-validate/issues/3084) ([38778f9](https://github.com/logaretm/vee-validate/commit/38778f96471b6aa16fb020cfb1bde56b77a19cfb))\n- react to validation events changes ([078e61b](https://github.com/logaretm/vee-validate/commit/078e61b17bd299a28752b733b494a0ddb368a812))\n- reset meta correctly with resetField ([012658c](https://github.com/logaretm/vee-validate/commit/012658c082a00b1beeb53ce8cf3fcd91bc5b21ec))\n- resolve component before rendering closes [#3014](https://github.com/logaretm/vee-validate/issues/3014) ([f8f481d](https://github.com/logaretm/vee-validate/commit/f8f481daad754a4b18a91e2b07b9549433d023f9))\n- resolve path values with global rules closes [#3157](https://github.com/logaretm/vee-validate/issues/3157) ([beaf316](https://github.com/logaretm/vee-validate/commit/beaf3168490aee585542a19c9a910d9493e78208))\n- set field initial value on the fid lookup closes [#3128](https://github.com/logaretm/vee-validate/issues/3128) ([650d5cf](https://github.com/logaretm/vee-validate/commit/650d5cf9f75f9b9247fc813acf2aff4089f05415))\n- support dynamic labels closes [#3053](https://github.com/logaretm/vee-validate/issues/3053) ([31b2238](https://github.com/logaretm/vee-validate/commit/31b223878bda75c3150217ea80bb878d8dc1e320))\n- typing issue from [#3134](https://github.com/logaretm/vee-validate/issues/3134) ([29e5cff](https://github.com/logaretm/vee-validate/commit/29e5cffc654a2502f29fe616eda088de958e02d3))\n- use the custom injection fn for initial field values ([38cd32b](https://github.com/logaretm/vee-validate/commit/38cd32bd3ae9f263510d0ab4a1713c6a9a2011af))\n\n### Features\n\n- add submit count state ([#3070](https://github.com/logaretm/vee-validate/issues/3070)) ([a7fe71e](https://github.com/logaretm/vee-validate/commit/a7fe71e01072dacfeb7baa80eebf0b8d7d9d3ffd))\n- added context awareness to composition helpers for fields ([b59fe88](https://github.com/logaretm/vee-validate/commit/b59fe88197ce3cd587edfc33666bcb676030fa61))\n- added context information to validation functions ([7e6675d](https://github.com/logaretm/vee-validate/commit/7e6675db6a103eae33cbb6d959621b4549af66b2))\n- added test cases and fallbacks for unresolved cases ([71bda03](https://github.com/logaretm/vee-validate/commit/71bda03a72a9e8f27bc0b7620ce78ba48a194309))\n- added the useResetForm helper ([4c57715](https://github.com/logaretm/vee-validate/commit/4c57715ab621526a5c987cff9a53cb5b7af2155a))\n- added unchecked-value prop to the field component ([af910c3](https://github.com/logaretm/vee-validate/commit/af910c3f3c6343538658ab90f356dd8957bb6a1a))\n- added useErrors and useField error helpers ([4cda2fe](https://github.com/logaretm/vee-validate/commit/4cda2fea6428a7f10b53b633daa46252bf779289))\n- added useIsDirty helpers ([6b7e4ab](https://github.com/logaretm/vee-validate/commit/6b7e4abfcdb2f0eebe0dd8c62785178fbee8d25f))\n- added useIsSubmitting helper ([7a58fd8](https://github.com/logaretm/vee-validate/commit/7a58fd840425a5e09f625054389aebbb096c2e1a))\n- added useIsTouched helpers ([fdb2d5a](https://github.com/logaretm/vee-validate/commit/fdb2d5a3c7c82d55aefef2deb95823e1ba6ba93d))\n- added useIsValid helpers ([26fbb29](https://github.com/logaretm/vee-validate/commit/26fbb29467bab66c159e98793e4269768845b938))\n- added useSubmitCount helper ([c4a6dea](https://github.com/logaretm/vee-validate/commit/c4a6deae68b588494ff0e2477d7ec2b9302c6f09))\n- added useSubmitForm hook ([#3101](https://github.com/logaretm/vee-validate/issues/3101)) ([d042882](https://github.com/logaretm/vee-validate/commit/d04288295a090328f7022641799dbaee1c404b91))\n- added useValidateField and useValidateForm helpers ([62355a8](https://github.com/logaretm/vee-validate/commit/62355a8db6477562f0689208669d0a1be63de03c))\n- added validate field function to form and useForm ([#3133](https://github.com/logaretm/vee-validate/issues/3133)) ([926bed1](https://github.com/logaretm/vee-validate/commit/926bed1bded6990f17a51ca68e9aa47c339a80f2))\n- added validate method on the form ref instance closes [#3030](https://github.com/logaretm/vee-validate/issues/3030) ([ed0faff](https://github.com/logaretm/vee-validate/commit/ed0faffd79615830a9f7c247abf1eae2254ee3f9))\n- added validation trigger config per component closes [#3066](https://github.com/logaretm/vee-validate/issues/3066) ([f0e30a2](https://github.com/logaretm/vee-validate/commit/f0e30a2cc79843040028b7070bc88846f2447c85))\n- added value change support for native multi select ([#3146](https://github.com/logaretm/vee-validate/issues/3146)) ([0601586](https://github.com/logaretm/vee-validate/commit/0601586eabbf76fac9d4fa79e6ae1d86fd3a0e37))\n- added values helpers ([e0f16d6](https://github.com/logaretm/vee-validate/commit/e0f16d6f5c01c7b1e4e8832b3490b8cc7e7b8aa7))\n- added warnings for non existent fields and allow reactive paths ([4182d2f](https://github.com/logaretm/vee-validate/commit/4182d2f1716d712962dff3b6be27916e311e5870))\n- avoid watching rules when passed as functions ([539f753](https://github.com/logaretm/vee-validate/commit/539f7535bf935e62030b83f8c7b19e95256bcc52))\n- dont render any tags when no message exists closes [#3118](https://github.com/logaretm/vee-validate/issues/3118) ([92eba41](https://github.com/logaretm/vee-validate/commit/92eba41a2cdef643bc2af4c2a0366382cdffc625))\n- enhance ts typing for form functions ([8f7d8e8](https://github.com/logaretm/vee-validate/commit/8f7d8e89864b5df5255cbe5e88713022537ec236))\n- enhance useField types ([dcb8049](https://github.com/logaretm/vee-validate/commit/dcb80495ffdefb2e789887e1d40b2c4a57ade257))\n- enrich form validation results ([0c84c80](https://github.com/logaretm/vee-validate/commit/0c84c809fa729cd2b8620329305b4da0a45e9eaf))\n- export some internal types closes [#3065](https://github.com/logaretm/vee-validate/issues/3065) ([b88dffd](https://github.com/logaretm/vee-validate/commit/b88dffdb4c638bd439d093f653bfa1915f4ad9be))\n- field.reset() should reset the field to its initial value ([a11f1b7](https://github.com/logaretm/vee-validate/commit/a11f1b7dda3deafe683e13a00b28a7fab09b82cb))\n- implement similar reset API for fields ([38c3923](https://github.com/logaretm/vee-validate/commit/38c392320b4154061ccc5d70dde11517357467e8))\n- new reset API ([6983738](https://github.com/logaretm/vee-validate/commit/69837383e42636c24d6ee7d15cb5fe8e98f2ac55))\n- rename reset methods to be more consistent ([3a0dc4d](https://github.com/logaretm/vee-validate/commit/3a0dc4db2f1a00a8a4f3940ddd452d9b1369cace))\n- update docs ([0f5ac98](https://github.com/logaretm/vee-validate/commit/0f5ac98153f74bdbbd1d9f5090e4dc4b438c998f))\n- use internal yup types ([#3123](https://github.com/logaretm/vee-validate/issues/3123)) ([7554bfc](https://github.com/logaretm/vee-validate/commit/7554bfc49b0103f218f901148bc06e6a455f09b0))\n- use resolveDynamicComponent instead ([f1b5f89](https://github.com/logaretm/vee-validate/commit/f1b5f896840ed159df06cf59badd83282496b777))\n\n### Performance Improvements\n\n- cache field props in a computed property ([d266878](https://github.com/logaretm/vee-validate/commit/d2668787d0ffcab5ba2e8be048ee7334d2b0f9e7))\n- cache form slot props in a computed property ([49fa2c1](https://github.com/logaretm/vee-validate/commit/49fa2c1b4a337149c533c13725d2e71bb2664706))\n\n## [4.1.16](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.15...vee-validate@4.1.16) (2021-02-07)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.1.15](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.14...vee-validate@4.1.15) (2021-02-07)\n\n### Bug Fixes\n\n- resolve path values with global rules closes [#3157](https://github.com/logaretm/vee-validate/issues/3157) ([beaf316](https://github.com/logaretm/vee-validate/commit/beaf3168490aee585542a19c9a910d9493e78208))\n\n## [4.1.14](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.13...vee-validate@4.1.14) (2021-02-06)\n\n### Bug Fixes\n\n- avoid validating dependencies via watcheffect closes [#3156](https://github.com/logaretm/vee-validate/issues/3156) ([a7b91f6](https://github.com/logaretm/vee-validate/commit/a7b91f6e6c38f0b5262e2d4c1814154efa3b78c8))\n\n## [4.1.13](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.12...vee-validate@4.1.13) (2021-02-01)\n\n### Features\n\n- added value change support for native multi select ([#3146](https://github.com/logaretm/vee-validate/issues/3146)) ([0601586](https://github.com/logaretm/vee-validate/commit/0601586eabbf76fac9d4fa79e6ae1d86fd3a0e37))\n\n## [4.1.12](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.11...vee-validate@4.1.12) (2021-01-26)\n\n### Bug Fixes\n\n- array radio fields not switching value correctly closes [#3141](https://github.com/logaretm/vee-validate/issues/3141) ([3d4efef](https://github.com/logaretm/vee-validate/commit/3d4efef68c63a3b57e2bf14fed913dbf841a7f5e))\n- clear out initial values for unregistered fields closes [#3060](https://github.com/logaretm/vee-validate/issues/3060) ([56206de](https://github.com/logaretm/vee-validate/commit/56206de995fe8f2eaca3e303ab6980784a3c95b1))\n- typing issue from [#3134](https://github.com/logaretm/vee-validate/issues/3134) ([29e5cff](https://github.com/logaretm/vee-validate/commit/29e5cffc654a2502f29fe616eda088de958e02d3))\n\n## [4.1.11](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.10...vee-validate@4.1.11) (2021-01-19)\n\n### Features\n\n- added validate field function to form and useForm ([#3133](https://github.com/logaretm/vee-validate/issues/3133)) ([926bed1](https://github.com/logaretm/vee-validate/commit/926bed1bded6990f17a51ca68e9aa47c339a80f2))\n\n## [4.1.10](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.9...vee-validate@4.1.10) (2021-01-17)\n\n### Bug Fixes\n\n- set field initial value on the fid lookup closes [#3128](https://github.com/logaretm/vee-validate/issues/3128) ([650d5cf](https://github.com/logaretm/vee-validate/commit/650d5cf9f75f9b9247fc813acf2aff4089f05415))\n\n## [4.1.9](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.8...vee-validate@4.1.9) (2021-01-13)\n\n### Features\n\n- use internal yup types ([#3123](https://github.com/logaretm/vee-validate/issues/3123)) ([7554bfc](https://github.com/logaretm/vee-validate/commit/7554bfc49b0103f218f901148bc06e6a455f09b0))\n\n## [4.1.8](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.7...vee-validate@4.1.8) (2021-01-12)\n\n### Features\n\n- dont render any tags when no message exists closes [#3118](https://github.com/logaretm/vee-validate/issues/3118) ([92eba41](https://github.com/logaretm/vee-validate/commit/92eba41a2cdef643bc2af4c2a0366382cdffc625))\n\n## [4.1.7](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.6...vee-validate@4.1.7) (2021-01-12)\n\n### Bug Fixes\n\n- export submission types [#3112](https://github.com/logaretm/vee-validate/issues/3112) ([3f35167](https://github.com/logaretm/vee-validate/commit/3f351670da02364b0fb8e61198145dfa02dc59b9))\n\n## [4.1.6](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.5...vee-validate@4.1.6) (2021-01-11)\n\n### Bug Fixes\n\n- added emits and onSubmit custom prop ([#3115](https://github.com/logaretm/vee-validate/issues/3115)) ([8f2c110](https://github.com/logaretm/vee-validate/commit/8f2c110f14add0fbd82a28a91601e89938144624))\n\n## [4.1.5](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.4...vee-validate@4.1.5) (2021-01-05)\n\n### Bug Fixes\n\n- correctly set the initial value from the v-model closes [#3107](https://github.com/logaretm/vee-validate/issues/3107) ([4bed9a8](https://github.com/logaretm/vee-validate/commit/4bed9a806323139d2f274e51b6bfe3de2190e54d))\n\n## [4.1.4](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.3...vee-validate@4.1.4) (2021-01-04)\n\n### Bug Fixes\n\n- handle formless checkboxes value toggling closes [#3105](https://github.com/logaretm/vee-validate/issues/3105) ([504f30b](https://github.com/logaretm/vee-validate/commit/504f30bfcbcb1db710397ef05545b5008b0103fb))\n\n## [4.1.3](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.2...vee-validate@4.1.3) (2021-01-02)\n\n### Features\n\n- enhance useField types ([dcb8049](https://github.com/logaretm/vee-validate/commit/dcb80495ffdefb2e789887e1d40b2c4a57ade257))\n\n## [4.1.2](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.1...vee-validate@4.1.2) (2020-12-26)\n\n### Features\n\n- added useSubmitForm hook ([#3101](https://github.com/logaretm/vee-validate/issues/3101)) ([d042882](https://github.com/logaretm/vee-validate/commit/d04288295a090328f7022641799dbaee1c404b91))\n\n## [4.1.1](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.0...vee-validate@4.1.1) (2020-12-18)\n\n### Bug Fixes\n\n- missing export for useErrors helpers ([28537cc](https://github.com/logaretm/vee-validate/commit/28537cc547cf945b10adc485620ad226f71d60fc))\n\n# [4.1.0](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.7...vee-validate@4.1.0) (2020-12-18)\n\n### Bug Fixes\n\n- avoid returning undefined for form errors when form does not exist ([8cce17a](https://github.com/logaretm/vee-validate/commit/8cce17ae2846be912d51926c79e557ed8bb39582))\n\n### Features\n\n- added context awareness to composition helpers for fields ([b59fe88](https://github.com/logaretm/vee-validate/commit/b59fe88197ce3cd587edfc33666bcb676030fa61))\n- added test cases and fallbacks for unresolved cases ([71bda03](https://github.com/logaretm/vee-validate/commit/71bda03a72a9e8f27bc0b7620ce78ba48a194309))\n- added the useResetForm helper ([4c57715](https://github.com/logaretm/vee-validate/commit/4c57715ab621526a5c987cff9a53cb5b7af2155a))\n- added useErrors and useField error helpers ([4cda2fe](https://github.com/logaretm/vee-validate/commit/4cda2fea6428a7f10b53b633daa46252bf779289))\n- added useIsDirty helpers ([6b7e4ab](https://github.com/logaretm/vee-validate/commit/6b7e4abfcdb2f0eebe0dd8c62785178fbee8d25f))\n- added useIsSubmitting helper ([7a58fd8](https://github.com/logaretm/vee-validate/commit/7a58fd840425a5e09f625054389aebbb096c2e1a))\n- added useIsTouched helpers ([fdb2d5a](https://github.com/logaretm/vee-validate/commit/fdb2d5a3c7c82d55aefef2deb95823e1ba6ba93d))\n- added useIsValid helpers ([26fbb29](https://github.com/logaretm/vee-validate/commit/26fbb29467bab66c159e98793e4269768845b938))\n- added useSubmitCount helper ([c4a6dea](https://github.com/logaretm/vee-validate/commit/c4a6deae68b588494ff0e2477d7ec2b9302c6f09))\n- added useValidateField and useValidateForm helpers ([62355a8](https://github.com/logaretm/vee-validate/commit/62355a8db6477562f0689208669d0a1be63de03c))\n- added values helpers ([e0f16d6](https://github.com/logaretm/vee-validate/commit/e0f16d6f5c01c7b1e4e8832b3490b8cc7e7b8aa7))\n- added warnings for non existent fields and allow reactive paths ([4182d2f](https://github.com/logaretm/vee-validate/commit/4182d2f1716d712962dff3b6be27916e311e5870))\n- enhance ts typing for form functions ([8f7d8e8](https://github.com/logaretm/vee-validate/commit/8f7d8e89864b5df5255cbe5e88713022537ec236))\n- enrich form validation results ([0c84c80](https://github.com/logaretm/vee-validate/commit/0c84c809fa729cd2b8620329305b4da0a45e9eaf))\n- export some internal types closes [#3065](https://github.com/logaretm/vee-validate/issues/3065) ([b88dffd](https://github.com/logaretm/vee-validate/commit/b88dffdb4c638bd439d093f653bfa1915f4ad9be))\n\n## [4.0.7](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.6...vee-validate@4.0.7) (2020-12-18)\n\n### Bug Fixes\n\n- react to validation events changes ([078e61b](https://github.com/logaretm/vee-validate/commit/078e61b17bd299a28752b733b494a0ddb368a812))\n\n## [4.0.6](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.5...vee-validate@4.0.6) (2020-12-15)\n\n### Bug Fixes\n\n- prevent default reset behavior with handleReset ([a66df13](https://github.com/logaretm/vee-validate/commit/a66df13c3f39d84984581dc3c0ce368b052b6e8e))\n- prevent resetForm from toggling checkbox value [#3084](https://github.com/logaretm/vee-validate/issues/3084) ([38778f9](https://github.com/logaretm/vee-validate/commit/38778f96471b6aa16fb020cfb1bde56b77a19cfb))\n\n### Features\n\n- added unchecked-value prop to the field component ([af910c3](https://github.com/logaretm/vee-validate/commit/af910c3f3c6343538658ab90f356dd8957bb6a1a))\n\n### Performance Improvements\n\n- cache field props in a computed property ([d266878](https://github.com/logaretm/vee-validate/commit/d2668787d0ffcab5ba2e8be048ee7334d2b0f9e7))\n- cache form slot props in a computed property ([49fa2c1](https://github.com/logaretm/vee-validate/commit/49fa2c1b4a337149c533c13725d2e71bb2664706))\n\n## [4.0.5](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.4...vee-validate@4.0.5) (2020-12-12)\n\n### Features\n\n- added validation trigger config per component closes [#3066](https://github.com/logaretm/vee-validate/issues/3066) ([f0e30a2](https://github.com/logaretm/vee-validate/commit/f0e30a2cc79843040028b7070bc88846f2447c85))\n\n## [4.0.4](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.3...vee-validate@4.0.4) (2020-12-09)\n\n### Bug Fixes\n\n- add a handler for regex object params closes [#3073](https://github.com/logaretm/vee-validate/issues/3073) ([7a5e2eb](https://github.com/logaretm/vee-validate/commit/7a5e2ebf8303395372ae08ebcca55427a58faecb))\n- fill the target rule params for message generators closes [#3077](https://github.com/logaretm/vee-validate/issues/3077) ([f5e1bd3](https://github.com/logaretm/vee-validate/commit/f5e1bd3cbc278a8588fa0c96af66823d82eefb8c))\n\n### Features\n\n- add submit count state ([#3070](https://github.com/logaretm/vee-validate/issues/3070)) ([a7fe71e](https://github.com/logaretm/vee-validate/commit/a7fe71e01072dacfeb7baa80eebf0b8d7d9d3ffd))\n\n## [4.0.3](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.2...vee-validate@4.0.3) (2020-12-05)\n\n### Bug Fixes\n\n- cast radio buttons value correctly closes [#3064](https://github.com/logaretm/vee-validate/issues/3064) ([3e0f9a4](https://github.com/logaretm/vee-validate/commit/3e0f9a47369edac32d0c8a068f8b61d8f761458f))\n- reset meta correctly with resetField ([012658c](https://github.com/logaretm/vee-validate/commit/012658c082a00b1beeb53ce8cf3fcd91bc5b21ec))\n- use the custom injection fn for initial field values ([38cd32b](https://github.com/logaretm/vee-validate/commit/38cd32bd3ae9f263510d0ab4a1713c6a9a2011af))\n\n## [4.0.2](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.1...vee-validate@4.0.2) (2020-11-27)\n\n### Bug Fixes\n\n- support dynamic labels closes [#3053](https://github.com/logaretm/vee-validate/issues/3053) ([31b2238](https://github.com/logaretm/vee-validate/commit/31b223878bda75c3150217ea80bb878d8dc1e320))\n\n## [4.0.1](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0...vee-validate@4.0.1) (2020-11-25)\n\n### Bug Fixes\n\n- pass down listeners to the input node closes [#3048](https://github.com/logaretm/vee-validate/issues/3048) ([2526a63](https://github.com/logaretm/vee-validate/commit/2526a63c2361e412b528cf370c03b39cb84b606d))\n\n# [4.0.0](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.19...vee-validate@4.0.0) (2020-11-16)\n\n### Features\n\n- added validate method on the form ref instance closes [#3030](https://github.com/logaretm/vee-validate/issues/3030) ([ed0faff](https://github.com/logaretm/vee-validate/commit/ed0faffd79615830a9f7c247abf1eae2254ee3f9))\n- update docs ([0f5ac98](https://github.com/logaretm/vee-validate/commit/0f5ac98153f74bdbbd1d9f5090e4dc4b438c998f))\n\n# [4.0.0-beta.19](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.18...vee-validate@4.0.0-beta.19) (2020-11-07)\n\n### Bug Fixes\n\n- resolve component before rendering closes [#3014](https://github.com/logaretm/vee-validate/issues/3014) ([f8f481d](https://github.com/logaretm/vee-validate/commit/f8f481daad754a4b18a91e2b07b9549433d023f9))\n\n### Features\n\n- field.reset() should reset the field to its initial value ([a11f1b7](https://github.com/logaretm/vee-validate/commit/a11f1b7dda3deafe683e13a00b28a7fab09b82cb))\n- implement similar reset API for fields ([38c3923](https://github.com/logaretm/vee-validate/commit/38c392320b4154061ccc5d70dde11517357467e8))\n- new reset API ([6983738](https://github.com/logaretm/vee-validate/commit/69837383e42636c24d6ee7d15cb5fe8e98f2ac55))\n- rename reset methods to be more consistent ([3a0dc4d](https://github.com/logaretm/vee-validate/commit/3a0dc4db2f1a00a8a4f3940ddd452d9b1369cace))\n- use resolveDynamicComponent instead ([f1b5f89](https://github.com/logaretm/vee-validate/commit/f1b5f896840ed159df06cf59badd83282496b777))\n\n# [4.0.0-beta.18](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.17...vee-validate@4.0.0-beta.18) (2020-11-05)\n\n### Bug Fixes\n\n- handle reactive field names and value swaps ([cf8051d](https://github.com/logaretm/vee-validate/commit/cf8051d3b92eb43103f4e7c682e615343239d717))\n\n### Features\n\n- avoid watching rules when passed as functions ([539f753](https://github.com/logaretm/vee-validate/commit/539f7535bf935e62030b83f8c7b19e95256bcc52))\n\n# [4.0.0-beta.17](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.16...vee-validate@4.0.0-beta.17) (2020-11-04)\n\n### Features\n\n- added context information to validation functions ([7e6675d](https://github.com/logaretm/vee-validate/commit/7e6675db6a103eae33cbb6d959621b4549af66b2))\n\n# [4.0.0-beta.16](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.15...vee-validate@4.0.0-beta.16) (2020-10-29)\n\n### Features\n\n- initial form meta ([#3003](https://github.com/logaretm/vee-validate/issues/3003)) ([f7fd407](https://github.com/logaretm/vee-validate/commit/f7fd407cf0e6dad9c92585a4a82594af962de8f4))\n\n# [4.0.0-beta.15](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.14...vee-validate@4.0.0-beta.15) (2020-10-28)\n\n### Features\n\n- add `initialErrors` prop ([#3002](https://github.com/logaretm/vee-validate/issues/3002)) ([9850b3f](https://github.com/logaretm/vee-validate/commit/9850b3f2f1c1739f31ff05f32890196097ef426e))\n\n# [4.0.0-beta.14](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.13...vee-validate@4.0.0-beta.14) (2020-10-26)\n\n### Features\n\n- deprecate the disabled prop ([29f4dca](https://github.com/logaretm/vee-validate/commit/29f4dca6bd4d02281bf71f8ed4c836f30e0e46d0))\n- use injection keys to type inject API ([79207b2](https://github.com/logaretm/vee-validate/commit/79207b25a23782acc527394af23703b138c881db))\n\n# [4.0.0-beta.13](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.12...vee-validate@4.0.0-beta.13) (2020-10-23)\n\n### Features\n\n- `useForm` Field types ([#2996](https://github.com/logaretm/vee-validate/issues/2996)) ([727f229](https://github.com/logaretm/vee-validate/commit/727f2295d421ef92620995a356bcaee53770299b))\n\n# [4.0.0-beta.12](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.11...vee-validate@4.0.0-beta.12) (2020-10-21)\n\n### Bug Fixes\n\n- upgrade to Vue 3.0.2 and fix broken cases ([ede7214](https://github.com/logaretm/vee-validate/commit/ede72147bd998b888825457541ff964df5e7a2fd))\n\n# [4.0.0-beta.11](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.10...vee-validate@4.0.0-beta.11) (2020-10-18)\n\n### Bug Fixes\n\n- provide yup object schema type to the useForm closes [#2988](https://github.com/logaretm/vee-validate/issues/2988) ([29157f7](https://github.com/logaretm/vee-validate/commit/29157f7a36dd14dc9a6c411ffddbbeb9d3749f6e))\n\n# [4.0.0-beta.10](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.9...vee-validate@4.0.0-beta.10) (2020-10-15)\n\n### Bug Fixes\n\n- properly initialize initial values closes [#2978](https://github.com/logaretm/vee-validate/issues/2978) ([c0ba699](https://github.com/logaretm/vee-validate/commit/c0ba699757cbd2c3ab409d5ee8d2fa3a205907d8))\n- typos in test descriptions ([#2970](https://github.com/logaretm/vee-validate/issues/2970)) ([a0132df](https://github.com/logaretm/vee-validate/commit/a0132dfcc2aab4ba48f175b846228544c80fe4a8))\n\n# [4.0.0-beta.9](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.8...vee-validate@4.0.0-beta.9) (2020-10-14)\n\n### Bug Fixes\n\n- improve useForm meta types ([#2963](https://github.com/logaretm/vee-validate/issues/2963)) ([6b46047](https://github.com/logaretm/vee-validate/commit/6b46047278633a095243fcce4ba94ddd94e08c11))\n\n### Features\n\n- meta setters ([#2967](https://github.com/logaretm/vee-validate/issues/2967)) ([5036e13](https://github.com/logaretm/vee-validate/commit/5036e13e0f5974589387746398446fa5f318dc0d))\n\n# [4.0.0-beta.8](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.7...vee-validate@4.0.0-beta.8) (2020-10-12)\n\n### Features\n\n- added handleInput and handleBlur to field scoped slot props ([69d5833](https://github.com/logaretm/vee-validate/commit/69d5833e85d1f455fa43de83251c634b8efa89fa))\n- expose reset() on the form controller object ([3229ee7](https://github.com/logaretm/vee-validate/commit/3229ee722e8df5f2e79155e1a4e5ec4729dff726))\n- new meta tags API ([#2958](https://github.com/logaretm/vee-validate/issues/2958)) ([7494bfc](https://github.com/logaretm/vee-validate/commit/7494bfc6533fa29bd0668294d694aca96721d52d))\n- remove aria attributes and leave it to userland ([365d825](https://github.com/logaretm/vee-validate/commit/365d825b9bc3e2955b31b941f12d5856c9be8bfe))\n- remove valid fields from errors mapping ([1eee524](https://github.com/logaretm/vee-validate/commit/1eee52407f4d7156a541811053b529f7540c931c))\n\n# [4.0.0-beta.7](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.6...vee-validate@4.0.0-beta.7) (2020-10-10)\n\n### Bug Fixes\n\n- avoid accessing properties in form directly to avoid warninings ([c5627af](https://github.com/logaretm/vee-validate/commit/c5627af64b252c8f7ec18e7f0a4296f315c7bf99))\n- update the handleSubmit signature ([#2954](https://github.com/logaretm/vee-validate/issues/2954)) ([d17517d](https://github.com/logaretm/vee-validate/commit/d17517daf692c48ac4fa1cfce5ac0bb051e73d2e))\n\n# [4.0.0-beta.6](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.5...vee-validate@4.0.0-beta.6) (2020-10-10)\n\n### Features\n\n- form and fields values setters ([#2949](https://github.com/logaretm/vee-validate/issues/2949)) ([cc2cb41](https://github.com/logaretm/vee-validate/commit/cc2cb413dfa23aefeb8be6e4bf7fa17927e0e1ce))\n- reactive initial form values ([#2946](https://github.com/logaretm/vee-validate/issues/2946)) ([ac2c68f](https://github.com/logaretm/vee-validate/commit/ac2c68fdbfb7062674f8294a1f0f6d33fc8792b3))\n\n# [4.0.0-beta.5](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.4...vee-validate@4.0.0-beta.5) (2020-10-08)\n\n### Bug Fixes\n\n- sync model value on input closes [#2944](https://github.com/logaretm/vee-validate/issues/2944) ([5f77fa9](https://github.com/logaretm/vee-validate/commit/5f77fa931bdb01cc6415c4edd1dcaa7eb7e1a0d2))\n\n# [4.0.0-beta.4](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.3...vee-validate@4.0.0-beta.4) (2020-10-08)\n\n### Bug Fixes\n\n- prevent recursive re-render model update ([#2943](https://github.com/logaretm/vee-validate/issues/2943)) ([9fa319f](https://github.com/logaretm/vee-validate/commit/9fa319f0e42f8225565e2f54d1bebd07898574a4))\n- set falsy initial values ([4b29e72](https://github.com/logaretm/vee-validate/commit/4b29e721f06fe30a5f7207935ae3d6291ea464fe))\n- use validateField instead of onChange handler for blur events ([636077a](https://github.com/logaretm/vee-validate/commit/636077a35183b33372825cd4075a143383ed0c68))\n\n# [4.0.0-beta.3](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.2...vee-validate@4.0.0-beta.3) (2020-10-06)\n\n### Bug Fixes\n\n- avoid toggling checkbox `checked` attr in `handleChange` ([#2937](https://github.com/logaretm/vee-validate/issues/2937)) ([b8dafbd](https://github.com/logaretm/vee-validate/commit/b8dafbdb75e305f00c6effc21391f364db9236d0))\n\n### Features\n\n- added `validateOnMount` prop to `Field` and `Form` components ([#2938](https://github.com/logaretm/vee-validate/issues/2938)) ([3a0d878](https://github.com/logaretm/vee-validate/commit/3a0d878e453163f305acc87c5d4c93812f77f340))\n\n# [4.0.0-beta.2](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.1...vee-validate@4.0.0-beta.2) (2020-10-05)\n\n### Features\n\n- field labels ([#2933](https://github.com/logaretm/vee-validate/issues/2933)) ([513137f](https://github.com/logaretm/vee-validate/commit/513137f28c6266d3e752448b00eb1c3d410ae474))\n\n# [4.0.0-beta.1](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.0...vee-validate@4.0.0-beta.1) (2020-10-02)\n\n### Bug Fixes\n\n- avoid binding the value to file inputs ([02a2745](https://github.com/logaretm/vee-validate/commit/02a27456ba961540a882ec4f94a24a271b0ea3a3))\n\n# [4.0.0-beta.0](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.14...vee-validate@4.0.0-beta.0) (2020-10-01)\n\n### Bug Fixes\n\n- make sure to unwrap initial value ([0298a92](https://github.com/logaretm/vee-validate/commit/0298a926de5536154a69088b55cb688133638a39))\n\n### Features\n\n- validation triggers ([#2927](https://github.com/logaretm/vee-validate/issues/2927)) ([e725f43](https://github.com/logaretm/vee-validate/commit/e725f43a47dd1993699c0450fd8777aa921c7a49))\n\n# [4.0.0-alpha.14](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.13...vee-validate@4.0.0-alpha.14) (2020-09-20)\n\n### Bug Fixes\n\n- **core:** in case of radio or checkbox explicitly set initialValue ([#2907](https://github.com/logaretm/vee-validate/issues/2907)) ([e45ec82](https://github.com/logaretm/vee-validate/commit/e45ec82ee8fa6fabd4d3012a03ba8f9b72854631))\n\n### Features\n\n- use symbols to avoid provide/inject conflicts ([cc80032](https://github.com/logaretm/vee-validate/commit/cc8003213c34a8a33d84802f2c93598e1ac3c6f0))\n- workspaces ([#2904](https://github.com/logaretm/vee-validate/issues/2904)) ([0c05f94](https://github.com/logaretm/vee-validate/commit/0c05f9486a73744273de6816f00f689916aba91c))\n\n# [4.0.0-alpha.13](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.12...vee-validate@4.0.0-alpha.13) (2020-09-16)\n\n### Features\n\n- nested objects/arrays ([#2897](https://github.com/logaretm/vee-validate/issues/2897)) ([8d161a1](https://github.com/logaretm/vee-validate/commit/8d161a137a65c90ec8f7189743be24802231cf29))\n\n# [4.0.0-alpha.12](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.11...vee-validate@4.0.0-alpha.12) (2020-09-15)\n\n### Features\n\n- cast single checkboxes values to booleans closes [#2889](https://github.com/logaretm/vee-validate/issues/2889) ([7a08184](https://github.com/logaretm/vee-validate/commit/7a081845ac6a4bc09c51e52c5996b65814a48baf))\n- invoke generateMessage handler for local functions closes [#2893](https://github.com/logaretm/vee-validate/issues/2893) ([e9fe773](https://github.com/logaretm/vee-validate/commit/e9fe77365877edda51548c9539ec085fff91586b))\n\n# [4.0.0-alpha.11](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.10...vee-validate@4.0.0-alpha.11) (2020-09-02)\n\n**Note:** Version bump only for package vee-validate\n\n# [4.0.0-alpha.10](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.9...vee-validate@4.0.0-alpha.10) (2020-08-29)\n\n### Bug Fixes\n\n- added temporary fix for [#2873](https://github.com/logaretm/vee-validate/issues/2873) with form meta ([6e1bf17](https://github.com/logaretm/vee-validate/commit/6e1bf176e7ba5c890afab6c11731dac54924d39b))\n\n# [4.0.0-alpha.9](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.8...vee-validate@4.0.0-alpha.9) (2020-08-28)\n\n### Bug Fixes\n\n- adapt to the breaking changes in #vue-1682 closes [#2873](https://github.com/logaretm/vee-validate/issues/2873) ([05f7df3](https://github.com/logaretm/vee-validate/commit/05f7df313f9f47ca79bdf99be35cb2ccfea0c346))\n\n# [4.0.0-alpha.8](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.7...vee-validate@4.0.0-alpha.8) (2020-08-13)\n\n### Bug Fixes\n\n- detect initial values from v-model ([e566302](https://github.com/logaretm/vee-validate/commit/e566302bb485353f03baccdf98f35a255605e15d))\n- handle unmount issue when removed value is falsy for checkboxes ([b6393f4](https://github.com/logaretm/vee-validate/commit/b6393f4adce9346cadaf1f423dca29645bf3c2f1))\n- initial array values for checkboxes not populated correctly in form ([fb99edc](https://github.com/logaretm/vee-validate/commit/fb99edc309c26f9be2baa71f90ec1ac59ddcdc9d))\n- umounting group of checkbox issues ([8c77af5](https://github.com/logaretm/vee-validate/commit/8c77af52955b235a6bd2357a35036097e109e37f))\n\n### Features\n\n- added basic v-model support ([c93d125](https://github.com/logaretm/vee-validate/commit/c93d125b4d6c0af8365920ee577c883493e60648))\n- merge ctx.attrs to any rendered root node ([5c9979c](https://github.com/logaretm/vee-validate/commit/5c9979ce45d4ab10cd019ad0c25159e013198301))\n- sync the model value with inner value ([57d7923](https://github.com/logaretm/vee-validate/commit/57d79232f490be3525c2576ef83376a2f5643386))\n\n# [4.0.0-alpha.7](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.6...vee-validate@4.0.0-alpha.7) (2020-08-04)\n\n### Bug Fixes\n\n- avoid removing array value for a non-group field closes [#2847](https://github.com/logaretm/vee-validate/issues/2847) ([69f2092](https://github.com/logaretm/vee-validate/commit/69f2092db7d53665986dd384cae561d1b13bd8f5))\n- bails affects yup non-object validators ([a50645b](https://github.com/logaretm/vee-validate/commit/a50645b1c0206d0e7d85ec6681ff6dc224536fa2))\n- initial values on HTML inputs ([c4f4eb9](https://github.com/logaretm/vee-validate/commit/c4f4eb9fe97b13fedb93ac760614eb53c177ffb3))\n\n### Features\n\n- deprecate the skipOptional config ([e62f5ea](https://github.com/logaretm/vee-validate/commit/e62f5ea6d31e82ac9f257627e8544431b933c4f9))\n\n# [4.0.0-alpha.6](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.5...vee-validate@4.0.0-alpha.6) (2020-07-27)\n\n### Bug Fixes\n\n- render input tags by default for the field component ([858c47b](https://github.com/logaretm/vee-validate/commit/858c47b4a7fa740611abaf026e6e5db6cdb41050))\n\n# [4.0.0-alpha.5](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.4...vee-validate@4.0.0-alpha.5) (2020-07-24)\n\n### Bug Fixes\n\n- unregister fields once they are unmounted ([0d601cb](https://github.com/logaretm/vee-validate/commit/0d601cb60b3ba907e6c0d73dd129c0c7b086316e))\n\n### Features\n\n- **v4:** add checkbox and radio HTML input support ([#2835](https://github.com/logaretm/vee-validate/issues/2835)) ([ab3d499](https://github.com/logaretm/vee-validate/commit/ab3d4998caf5950656dc0476f13215d598b28832))\n- render input by default for the field component ([81d055d](https://github.com/logaretm/vee-validate/commit/81d055d704deaa12b392fd9197218733b3a0bb8d))\n\n# [4.0.0-alpha.4](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.3...vee-validate@4.0.0-alpha.4) (2020-07-23)\n\n**Note:** Version bump only for package vee-validate\n\n# [4.0.0-alpha.3](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.2...vee-validate@4.0.0-alpha.3) (2020-07-21)\n\n### Features\n\n- automatic injection of the form controller ([c039831](https://github.com/logaretm/vee-validate/commit/c0398318ec70c925b6bcb2afa859ec89488e1f78))\n- remove debounce feature and make it userland ([b7263ce](https://github.com/logaretm/vee-validate/commit/b7263ce0f887388709846975b59965e440636089))\n\n# [4.0.0-alpha.2](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.1...vee-validate@4.0.0-alpha.2) (2020-07-19)\n\n### Features\n\n- always render a from by default ([402603a](https://github.com/logaretm/vee-validate/commit/402603a8f755a377a056debf24815611a01c3037))\n\n# 4.0.0-alpha.1 (2020-07-18)\n\n### Bug Fixes\n\n- added check for cross-fields extraction on unsupported schema ([0ff1bad](https://github.com/logaretm/vee-validate/commit/0ff1bad84a90189f11897cada01fd091e5593bb7))\n- added errorMessage prop to the field type ([f1553d0](https://github.com/logaretm/vee-validate/commit/f1553d01b94a74580700fd8712b67688f9c89c15))\n- added single error message prop to the provider slot props ([bc97d0c](https://github.com/logaretm/vee-validate/commit/bc97d0c6463cd7e466bb7b3555671e7891d4c60b))\n- added unwrap util function ([121bffc](https://github.com/logaretm/vee-validate/commit/121bffc05a9c6e2e204b843d5eb8d7678e5d0fff))\n- adjust the useField options to be less strict ([7ea8263](https://github.com/logaretm/vee-validate/commit/7ea826373a78b4fa6343f1da9db0e43879fa0e4e))\n- check if a form is present before accessing its schema ([3656181](https://github.com/logaretm/vee-validate/commit/3656181b17a6e44c8f470570ee5126cf2a83ae41))\n- debouncing not working correctly and move it to hoc only ([86280a1](https://github.com/logaretm/vee-validate/commit/86280a15e9fb1f94ef8c042a9d04d437f38936b0))\n- ensure we unwrap the field id if it was reactive ([7f91e93](https://github.com/logaretm/vee-validate/commit/7f91e930ec8cce4f2e17b49ee9d642d7e9343d6f))\n- initial validation not respecting the config opts ([2443d44](https://github.com/logaretm/vee-validate/commit/2443d44b1b00eda39ff884f33f85414aa2b1d34e))\n- localization default fallback not being interpolated correctly ([165e89c](https://github.com/logaretm/vee-validate/commit/165e89c6136126d6b946640623261f32b299a2a3))\n- no clue why this isn't building ([0d3e7fd](https://github.com/logaretm/vee-validate/commit/0d3e7fdea6f28e29d25f488cae527e925608da7e))\n- only add novalidate attr if the rendered element is form ([3638cea](https://github.com/logaretm/vee-validate/commit/3638cead19c9501783e23b43248ce49d7bdf51d7))\n- param mapping causing target names to resolve incorrectly ([fb77dc6](https://github.com/logaretm/vee-validate/commit/fb77dc673cb1eff72a1508cff7b4aaed60d8450e))\n- set pending back to false earlier in the cycle ([a4237a2](https://github.com/logaretm/vee-validate/commit/a4237a2f8dfde5efcc1d39b5a400e988b8740df9))\n- temporary fix for the unamed import issue with vue-beta 4 ([62d27e9](https://github.com/logaretm/vee-validate/commit/62d27e9c9293026d26d62709c2e691d3eb15753e))\n- unwrap flags before sending them to the observer slot ([19f7886](https://github.com/logaretm/vee-validate/commit/19f7886adae59b4442139f6e1a3f3905ab54f86a))\n- use the proper model event name ([5704db8](https://github.com/logaretm/vee-validate/commit/5704db879019b89b001f496f5f113df24ad09bc6))\n- watch target fields once they change ([a4184b0](https://github.com/logaretm/vee-validate/commit/a4184b0065c26df77b680cfbda7450a81b6764ef))\n\n### Features\n\n- adapt the changes from the v3 master branch ([2301c5a](https://github.com/logaretm/vee-validate/commit/2301c5ae75eb8590cb2cc919215ffe4ae934b885))\n- add name resolution from v3 ([ba77fdd](https://github.com/logaretm/vee-validate/commit/ba77fdde4f7e5400c6755331af4705715ecc885b))\n- add native submit alternative to handleSubmit ([bc00888](https://github.com/logaretm/vee-validate/commit/bc008880607f0393c4e6bd9eb2d44ebb40aa3604))\n- added 'as' prop to the validation provider ([5c8ae9c](https://github.com/logaretm/vee-validate/commit/5c8ae9cac2dd418c5bf78b8a0c68e7d256dc96ce))\n- added alert role to the error message ([714abfe](https://github.com/logaretm/vee-validate/commit/714abfede6cb2cd2ab1dd72319d27630af6fe9b6))\n- added aria and a11y improvements ([ca74f16](https://github.com/logaretm/vee-validate/commit/ca74f165988be3c0c5a6f828508b6aed3fd6e3a0))\n- added built-in support for yup validation schema ([e436b75](https://github.com/logaretm/vee-validate/commit/e436b75c4b8b7a085adf701d07b54b798da9a774))\n- added ErrorMessage component ([9570412](https://github.com/logaretm/vee-validate/commit/957041270b947e1b70301c3935b6d1ac0bb05a5d))\n- added support for custom components ([c661c7e](https://github.com/logaretm/vee-validate/commit/c661c7e1f352e2806c2e2da7bc2c860cfa62f3ff))\n- added useField and useForm hooks ([c1e9007](https://github.com/logaretm/vee-validate/commit/c1e900736ed9585d8997d2080f001aad28060281))\n- allow the as prop to be a component definition ([29790d4](https://github.com/logaretm/vee-validate/commit/29790d47f17fe49c897bf5b2fda0508f57990479))\n- allow the observer to render forms and handle submit events ([9e0d59b](https://github.com/logaretm/vee-validate/commit/9e0d59b11d239c7f1e6d4bc287d9e49aa0376f0d))\n- allow validation schema to accept other expressions ([ddeeaea](https://github.com/logaretm/vee-validate/commit/ddeeaea8041c3fad894aff0c827dd9f71b65224d))\n- change default field value to undefiend ([00c8754](https://github.com/logaretm/vee-validate/commit/00c87549244447423e0833f8294c5c607bdcf105))\n- deprecate names option on validate API ([fe90820](https://github.com/logaretm/vee-validate/commit/fe90820b4b0d4d10df81c2bbd019c3b63d371edf))\n- deprecate the 'required' flag ([283caa0](https://github.com/logaretm/vee-validate/commit/283caa0fdd353d990680d42e64be8d8362b6aad5))\n- enable interaction modes and localization APIs ([8486aaf](https://github.com/logaretm/vee-validate/commit/8486aaf0fadba03f38b5dd8a5ab857c10e7aa49c))\n- expose errorMessage prop on useField and Provider ([04eecaa](https://github.com/logaretm/vee-validate/commit/04eecaa13cc8ab0cc18336021bb912f924e37968))\n- expose the form values and pass them to the handleSubmit ([de51155](https://github.com/logaretm/vee-validate/commit/de511555c371bef73037d514e19d44eb4d292eae))\n- hook up the provider with new observer implementation ([4d18a65](https://github.com/logaretm/vee-validate/commit/4d18a6572af6af4630bdc2508e027e67d3c0d579))\n- implement bails for useField and ValidationProvider ([486babd](https://github.com/logaretm/vee-validate/commit/486babd031efd5a71a819ff535a0e0c661bc45fe))\n- implement initial values ([8239130](https://github.com/logaretm/vee-validate/commit/82391301152751eb03097dad4521dc1c275c47e7))\n- implement validation debounce ([e294409](https://github.com/logaretm/vee-validate/commit/e2944099ef2074d59f908f7949df3a1059ab3b4e))\n- implemented disabled prop ([88bf28e](https://github.com/logaretm/vee-validate/commit/88bf28e89d9e635ebbc79e593a326d4dd2025cdb))\n- make rules watchable ([90530cd](https://github.com/logaretm/vee-validate/commit/90530cdebede5bf33a62221371380ad8554326ba))\n- make the as prop take priority to determine what to render ([d5a033f](https://github.com/logaretm/vee-validate/commit/d5a033fc57b7ddea8aff4a0f4fe802d7c2489a9c))\n- new field binding object ([a58a84b](https://github.com/logaretm/vee-validate/commit/a58a84b009fef5dbfffa2a93a54643b3830cb4bc))\n- new handleSubmit signature ([63cbeaf](https://github.com/logaretm/vee-validate/commit/63cbeafd1cfb5e1e14ec42e34c0691a26b258897))\n- only export the provider for now ([0bf3efe](https://github.com/logaretm/vee-validate/commit/0bf3efe230be2d80b9e4693779e095c04997a52b))\n- remove vid from fields ([1b9bded](https://github.com/logaretm/vee-validate/commit/1b9bdedeb68006535c7087aef267906e2f7bed1d))\n- support immediate validation ([42cd6ed](https://github.com/logaretm/vee-validate/commit/42cd6edcfc0c11ea05106e66486ed4772c749548))\n- support inline rules as functions ([3c74681](https://github.com/logaretm/vee-validate/commit/3c7468186ac5a6e7fa6bb44b30de4102ef5c31cd))\n- support yup validation schemas on field-level ([0802512](https://github.com/logaretm/vee-validate/commit/0802512e181a8a33feaa227770f9e203fcf0cea5))\n- updated vnode utils to handle Vue 3 VNode API ([29a4fe8](https://github.com/logaretm/vee-validate/commit/29a4fe859823d5a74814c2dabb3b664185e56366))\n- use defineComponent to type Provider and Observer definitions ([80980cf](https://github.com/logaretm/vee-validate/commit/80980cfec81447638aa82b42c208f9ec6f9826f8))\n- validate yup form schemas using object validation ([bf216dd](https://github.com/logaretm/vee-validate/commit/bf216dde30a6d90c976bac844129ccbd08a00392))\n- validation schema support ([523824a](https://github.com/logaretm/vee-validate/commit/523824a0977d599f6ff2a271ee2edebd5aef36ef))\n- working draft for the vprovider with composition api ([b830054](https://github.com/logaretm/vee-validate/commit/b8300547cbafa9904f2b769b8309925ad6da180f))\n"
  },
  {
    "path": "CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at logaretm1@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Vee-Validate\n\nFirst of all, thanks for taking interest into contributing to this repository, below is what you need to know about the project.\n\n## Getting Started\n\nFork the repository, or clone it:\n\n```sh\ngit clone https://github.com/logaretm/vee-validate.git\n```\n\nInstall dependencies using [pnpm](https://pnpm.io/)\n\n```sh\npnpm i\n```\n\n## Issues\n\nWhen creating issues, please provide as much details as possible. A clear explanation on the issue and a reliable production example can help us greatly in improving this project. Your issue may get closed if it cannot be easily reproduced so please provide a working example using either [Codesandbox](https://codesandbox.io/) or [StackBlitz](https://stackblitz.com/). Your example should only focus on the issue, minimal and clearly produces the issue.\n\nYou can fork this [StackBlitz template](https://stackblitz.com/edit/vee-validate-issue-template?file=src%App.vue) to get a starting working environment ready for your demo with all vee-validate packages pre-installed and using the latest release.\n\nIf your issue gets closed for not providing enough info or not responding to the maintainers' comments, do not consider it a hostile action. There are probably other issues that the maintainers are working on and must give priority to issues that are well investigated, you can always revisit the issue and address the reasons that it was closed and we will be happy to re-open it and address it properly. Sometimes a commit will close your issue without a response from the maintainers so make sure you read the issue timeline to prevent any misunderstandings.\n\n## Code Style\n\nThe code style is enforced with `eslint` and `prettier` and is checked automatically whenever you commit. Any violation of the code style may prevent merging your contribution so make sure you follow it. And yes we love our semi-colons.\n\n## Commit Style\n\nCommit messages are enforced with `commitlint` which is configured to help you write a suitable commit message, the checks are run automatically when you commit.\n\n## Contributing To The Docs\n\nIf you want to contribute to the docs you can find it in the `docs` folder.\n\nThe docs are using [astro](https://astro.build/) and the [MDX plugin](https://docs.astro.build/en/guides/integrations-guide/mdx/) to write the doc pages.\n\nTo run the documentation locally:\n\n```sh\npnpm docs:dev\n```\n\n## Pull Requests\n\n**Before you open a PR, make sure to communicate via issues about your intent to avoid PRing something you think is an issue when it might be a design choice**. This is a checklist of the stuff you need to be aware of:\n\n- Make sure you fill the PR template provided\n- PRs should have titles that are clear as possible\n- Make sure that your PR is up to date with the branch you are targeting, use `git rebase` for this\n- Unfinished/In-Progress PRs should be marked as a `draft`\n- Make sure to mention which issues are being fixed by the PR so they can be closed properly\n- Make sure to preview all pending PRs to make sure your work won't conflict with other ongoing pull-request\n- Coordinate with ongoing conflicting PRs' authors to make it easier to merge both your PRs\n- Make sure to generate a changeset on the PR branch before merging it, this will help us generate a changelog for the next release\n\n## Source Code\n\nCurrently we are using TypeScript for the codebase, feel free to use any of it's features with a minor exception to:\n\n- `Enums` as we prefer to use string literals instead.\n- `namespace` not needed in our codebase\n\n## Testing\n\nEach test file represents a unit test to the corresponding file in the src folder.\n\nYou need to build the files before you run the tests:\n\n```sh\npnpm build\n```\n\nThen to run the tests:\n\n```sh\npnpm test\n```\n\nTo check the tests coverage:\n\n```sh\npnpm cover\n```\n\n## Mono repo\n\nthis project uses mono-repo style using pnpm workspaces and [changesets](https://github.com/changesets/changesets).\n\n## Building\n\nUse this command to build all project bundles\n\n```sh\npnpm build\n```\n\nIf you are working on a specific package within the vee-validate mono repo and only want to build that, then use the following command to build specific packages, the package id is the folder name in the `packages` folder.\n\n```sh\npnpm build vee-validate\npnpm build rules\npnpm build zod\n# etc...\n```\n\n## Tips for Testing your changes\n\nIf you need to try out your changes, here is a few tips\n\n- Build vee-validate dist files once you are done with your changes\n- To use the built files you can either use `pnpm link {PKG_NAME}` and link the package dist files to your project, or use [yalc](https://github.com/whitecolor/yalc).\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) Abdelrahman Awad <logaretm1@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\r\n  <a href=\"https://vee-validate.logaretm.com\" target=\"_blank\">\r\n    <img src=\"https://raw.githubusercontent.com/logaretm/vee-validate/main/logo.png\" width=\"200\" title=\"Go to website\">\r\n  </a>\r\n</p>\r\n\r\n<p align=\"center\">\r\nPainless Vue forms\r\n</p>\r\n\r\n<p align=\"center\">\r\n\r\n<a target=\"_blank\" href=\"https://www.npmjs.com/package/vee-validate\">\r\n  <img src=\"https://img.shields.io/npm/v/vee-validate.svg?label=&color=05bda8\">\r\n</a>\r\n\r\n<a target=\"_blank\" href=\"https://npm-stat.com/charts.html?package=vee-validate\">\r\n  <img src=\"https://img.shields.io/npm/dm/vee-validate.svg?color=05bd6d&label=\">\r\n</a>\r\n\r\n<a href=\"https://vee-validate.logaretm.com/v5/\" target=\"_blank\">\r\n  <img src=\"https://img.shields.io/badge/-docs%20and%20demos-009f53\">\r\n</a>\r\n\r\n<a href=\"https://github.com/sponsors/logaretm\">\r\n  <img src=\"https://img.shields.io/badge/-%E2%99%A5%20Sponsors-ec5cc6\">\r\n\r\n</a>\r\n\r\n</p>\r\n\r\n<br>\r\n\r\n<p align=\"center\">\r\n  <a href=\"https://github.com/sponsors/logaretm\">\r\n    <img src='https://sponsors.logaretm.com/sponsors.svg'>\r\n  </a>\r\n</p>\r\n\r\n<br>\r\n\r\n## Features\r\n\r\n- **🍞 Easy:** Declarative validation that is familiar and easy to setup\r\n- **🧘‍♀️ Flexible:** Synchronous, Asynchronous, field-level or form-level validation\r\n- **⚡️ Fast:** Build faster forms faster with intuitive API and small footprint\r\n- **🏏 Minimal:** Only handles the complicated form concerns, gives you full control over everything else\r\n- **😎 UI Agnostic:** Works with native HTML elements or your favorite UI library components\r\n- **🦾 Progressive:** Works whether you use Vue.js as a progressive enhancement or in a complex setup\r\n- **✅ Built-in Rules:** Companion lib with 25+ Rules that covers most needs in most web applications\r\n- **🌐 i18n:** 45+ locales for built-in rules contributed by developers from all over the world\r\n\r\n## Getting Started\r\n\r\n### Installation\r\n\r\n```sh\r\n# Install with yarn\r\nyarn add vee-validate\r\n\r\n# Install with npm\r\nnpm install vee-validate --save\r\n```\r\n\r\n### Vue version support\r\n\r\nThe main v4 version supports Vue 3.x only, for previous versions of Vue, check the following the table\r\n\r\n| vue Version | vee-validate version | Documentation Link                                                                       |\r\n| ----------- | -------------------- | ---------------------------------------------------------------------------------------- |\r\n| `2.x`       | `2.x` or `3.x`       | [v2](https://vee-validate.logaretm.com/v2) or [v3](https://vee-validate.logaretm.com/v3) |\r\n| `3.x`       | `4.x` or `5.x`       | [v4](https://vee-validate.logaretm.com/v4) or [v5](https://vee-validate.logaretm.com/v5) |\r\n\r\n### Usage\r\n\r\nvee-validate offers two styles to integrate form validation into your Vue.js apps.\r\n\r\n#### Composition API\r\n\r\nThe fastest way to create a form and manage its validation, behavior, and values is with the composition API.\r\n\r\nCreate your form with `useForm` and then use `defineField` to create your field model and props/attributes and `handleSubmit` to use the values and send them to an API.\r\n\r\n```vue\r\n<script setup>\r\nimport { useForm } from 'vee-validate';\r\n\r\n// Validation, or use `yup` or `zod`\r\nfunction required(value) {\r\n  return value ? true : 'This field is required';\r\n}\r\n\r\n// Create the form\r\nconst { defineField, handleSubmit, errors } = useForm({\r\n  validationSchema: {\r\n    field: required,\r\n  },\r\n});\r\n\r\n// Define fields\r\nconst [field, fieldProps] = defineField('field');\r\n\r\n// Submit handler\r\nconst onSubmit = handleSubmit(values => {\r\n  // Submit to API\r\n  console.log(values);\r\n});\r\n</script>\r\n\r\n<template>\r\n  <form @submit=\"onSubmit\">\r\n    <input v-model=\"field\" v-bind=\"fieldProps\" />\r\n    <span>{{ errors.field }}</span>\r\n\r\n    <button>Submit</button>\r\n  </form>\r\n</template>\r\n```\r\n\r\nYou can do so much more than this, for more info [check the composition API documentation](https://vee-validate.logaretm.com/v5/guide/composition-api/getting-started/).\r\n\r\n#### Declarative Components\r\n\r\nHigher-order components can also be used to build forms. Register the `Field` and `Form` components and create a simple `required` validator:\r\n\r\n```vue\r\n<script setup>\r\nimport { Field, Form } from 'vee-validate';\r\n\r\n// Validation, or use `yup` or `zod`\r\nfunction required(value) {\r\n  return value ? true : 'This field is required';\r\n}\r\n\r\n// Submit handler\r\nfunction onSubmit(values) {\r\n  // Submit to API\r\n  console.log(values);\r\n}\r\n</script>\r\n\r\n<template>\r\n  <Form v-slot=\"{ errors }\" @submit=\"onSubmit\">\r\n    <Field name=\"field\" :rules=\"required\" />\r\n\r\n    <span>{{ errors.field }}</span>\r\n\r\n    <button>Submit</button>\r\n  </Form>\r\n</template>\r\n```\r\n\r\nThe `Field` component renders an `input` of type `text` by default but you can [control that](https://vee-validate.logaretm.com/v5/api/field#rendering-fields)\r\n\r\n## 📚 Documentation\r\n\r\nRead the [documentation and demos](https://vee-validate.logaretm.com/v4).\r\n\r\n## Contributing\r\n\r\nYou are welcome to contribute to this project, but before you do, please make sure you read the [contribution guide](/CONTRIBUTING.md).\r\n\r\n## Credits\r\n\r\n- Inspired by Laravel's [validation syntax](https://laravel.com/docs/5.4/validation)\r\n- v4 API Inspired by [Formik's](https://github.com/formium/formik)\r\n- Nested path types by [react-hook-form](https://github.com/react-hook-form/react-hook-form)\r\n- Logo by [Baianat](https://github.com/baianat)\r\n\r\n## Emeriti\r\n\r\nHere we honor past contributors and sponsors who have been a major part on this project.\r\n\r\n- [Baianat](https://github.com/baianat).\r\n\r\n## ⚖️ License\r\n\r\nReleased under [MIT](/LICENSE) by [@logaretm](https://github.com/logaretm).\r\n"
  },
  {
    "path": "commitlint.config.mjs",
    "content": "export default {\n  extends: ['@commitlint/config-conventional'],\n  rules: {\n    'body-leading-blank': [1, 'always'],\n    'footer-leading-blank': [1, 'always'],\n    'header-max-length': [2, 'always', 72],\n    'scope-case': [2, 'always', 'lower-case'],\n    'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']],\n    'subject-empty': [2, 'never'],\n    'subject-full-stop': [2, 'never', '.'],\n    'type-case': [2, 'always', 'lower-case'],\n    'type-empty': [2, 'never'],\n    'type-enum': [\n      2,\n      'always',\n      ['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test'],\n    ],\n  },\n};\n"
  },
  {
    "path": "docs/.gitignore",
    "content": ".nuxt\ndist\nnode_modules\n\nsw.*"
  },
  {
    "path": "docs/CHANGELOG.md",
    "content": "# vee-validate-docs\n\n## null\n\n### Patch Changes\n\n- Updated dependencies [9867e59]\n- Updated dependencies [721e980]\n- Updated dependencies [9803aa2]\n- Updated dependencies [546d82e]\n  - @vee-validate/valibot@4.15.1\n  - vee-validate@4.15.1\n  - @vee-validate/yup@4.15.1\n  - @vee-validate/zod@4.15.1\n\n## null\n\n### Patch Changes\n\n- Updated dependencies [5cba0aa]\n- Updated dependencies [30281f5]\n- Updated dependencies [ec121b1]\n- Updated dependencies [db26a74]\n- Updated dependencies [f92455a]\n  - @vee-validate/yup@4.15.0\n  - vee-validate@4.15.0\n  - @vee-validate/valibot@4.15.0\n  - @vee-validate/zod@4.15.0\n\n## null\n\n### Patch Changes\n\n- Updated dependencies [be994b4]\n  - vee-validate@4.14.7\n  - @vee-validate/valibot@4.14.7\n  - @vee-validate/yup@4.14.7\n  - @vee-validate/zod@4.14.7\n\n## null\n\n### Patch Changes\n\n- vee-validate@4.14.6\n- @vee-validate/zod@4.14.6\n- @vee-validate/yup@4.14.6\n- @vee-validate/valibot@4.14.6\n\n## null\n\n### Patch Changes\n\n- Updated dependencies [e9f8c88]\n  - vee-validate@4.14.5\n  - @vee-validate/valibot@4.14.5\n  - @vee-validate/yup@4.14.5\n  - @vee-validate/zod@4.14.5\n\n## null\n\n### Patch Changes\n\n- Updated dependencies [f33974c]\n- Updated dependencies [0991c01]\n- Updated dependencies [ecb540a]\n- Updated dependencies [4f88d85]\n  - vee-validate@4.14.4\n  - @vee-validate/valibot@4.14.4\n  - @vee-validate/yup@4.14.4\n  - @vee-validate/zod@4.14.4\n\n## null\n\n### Patch Changes\n\n- Updated dependencies [07c27d5]\n  - vee-validate@4.14.3\n  - @vee-validate/valibot@4.14.3\n  - @vee-validate/yup@4.14.3\n  - @vee-validate/zod@4.14.3\n\n## null\n\n### Patch Changes\n\n- Updated dependencies [f0d4e24]\n  - vee-validate@4.14.2\n  - @vee-validate/valibot@4.14.2\n  - @vee-validate/yup@4.14.2\n  - @vee-validate/zod@4.14.2\n\n## null\n\n### Patch Changes\n\n- vee-validate@4.14.1\n- @vee-validate/zod@4.14.1\n- @vee-validate/yup@4.14.1\n- @vee-validate/valibot@4.14.1\n\n## null\n\n### Patch Changes\n\n- Updated dependencies [f7a4929]\n- Updated dependencies [97cebd8]\n- Updated dependencies [404cf57]\n- Updated dependencies [421ae69]\n  - vee-validate@4.14.0\n  - @vee-validate/valibot@4.14.0\n  - @vee-validate/yup@4.14.0\n  - @vee-validate/zod@4.14.0\n\n## null\n\n### Patch Changes\n\n- Updated dependencies [afbd0e5]\n  - vee-validate@4.13.2\n  - @vee-validate/valibot@4.13.2\n  - @vee-validate/yup@4.13.2\n  - @vee-validate/zod@4.13.2\n"
  },
  {
    "path": "docs/_redirects",
    "content": "# redirects old component api paths to new one\n/guide/validation                     /v5/guide/components/validation\n/guide/handling-forms                 /v5/guide/components/handling-forms\n/guide/nested-objects-and-arrays      /v5/guide/components/nested-objects-and-arrays\n\n/v5/guide/composition/validation     /v5/guide/composition/getting-started\n"
  },
  {
    "path": "docs/astro.config.ts",
    "content": "import { defineConfig } from 'astro/config';\nimport vue from '@astrojs/vue';\nimport remarkGfm from 'remark-gfm';\nimport sitemap from '@astrojs/sitemap';\nimport mdx from '@astrojs/mdx';\nimport highlight from './highlight';\nimport baseLink from './baseLink';\nimport { svgSprite } from './src/integrations/svgSprite';\n\nimport partytown from '@astrojs/partytown';\n\n// https://astro.build/config\nexport default defineConfig({\n  site: process.env.NODE_ENV === 'production' ? 'https://vee-validate.logaretm.com/' : 'http://localhost:4321/',\n  trailingSlash: 'always',\n  base: '/v5',\n  vite: {\n    ssr: {\n      noExternal: ['@vue/repl'],\n    },\n  },\n  integrations: [\n    vue(),\n    sitemap(),\n    mdx({\n      remarkPlugins: [baseLink('/v5'), highlight, remarkGfm],\n    }),\n    svgSprite,\n    partytown({\n      config: {\n        forward: ['dataLayer.push'],\n      },\n    }),\n  ],\n});\n"
  },
  {
    "path": "docs/baseLink.ts",
    "content": "import { visit } from 'unist-util-visit';\n\nexport default function addBasePath(basePath: string) {\n  return function () {\n    return function (ast) {\n      visit(ast, 'link', node => {\n        if (node.url.startsWith('/') && !node.url.startsWith(`${basePath}/`)) {\n          node.url = `${basePath}${node.url}`;\n        }\n\n        if (node.url.startsWith('http')) {\n          addProperties(node, {\n            rel: 'noopener',\n            target: '_blank',\n          });\n        }\n      });\n\n      return ast;\n    };\n  };\n}\n\nfunction addProperties(node: any, props: Record<string, string>) {\n  if (!node.data) {\n    node.data = {};\n  }\n\n  if (!node.data.hProperties) {\n    node.data.hProperties = {};\n  }\n\n  node.data.hProperties = {\n    ...node.data.hProperties,\n    ...props,\n  };\n}\n"
  },
  {
    "path": "docs/highlight.ts",
    "content": "import * as shiki from 'shiki';\nimport { JSDOM } from 'jsdom';\nimport { visit } from 'unist-util-visit';\nimport theme from './theme.json';\n\nconst dom = new JSDOM();\nconst document = dom.window.document;\n\n/**\n * Some langs are highlighted with different grammar rules but need to be displayed\n */\nconst LANG_REPLACEMENTS = {\n  'vue-html': 'vue',\n};\n\nconst highlighterPromise = shiki.getHighlighter({\n  // Complete themes: https://github.com/shikijs/shiki/tree/master/packages/themes\n  theme: theme as any,\n  langs: ['js', 'ts', 'vue', 'graphql', 'jsx', 'css', 'sh', 'yaml', 'json', 'vue-html', 'html'],\n});\n\nexport default function highlight() {\n  return async function (tree) {\n    const highlighter = await highlighterPromise;\n    visit(tree, 'code', visitor);\n\n    function visitor(node) {\n      const { lang, lines, fileName } = parseParts(node.lang || 'sh');\n      try {\n        const html = replaceColorsWithVariables(highlighter.codeToHtml(node.value, { lang: lang || 'sh' }));\n        const fragment = document.createDocumentFragment();\n        const wrapper = document.createElement('div');\n        wrapper.classList.add('shiki-snippet');\n        wrapper.innerHTML = html;\n        fragment.appendChild(wrapper);\n\n        const langSpan = createSpan(LANG_REPLACEMENTS[lang] || lang, 'shiki-language', {\n          'data-language': lang,\n        });\n        const shikiEl = fragment.querySelector('.shiki') as HTMLElement | null;\n        shikiEl?.prepend(langSpan);\n\n        if (lines.length) {\n          lines.forEach(line => {\n            const lineEl = fragment.querySelector(`.line:nth-child(${line})`) as HTMLElement | null;\n            lineEl?.classList.add('is-highlighted');\n          });\n          shikiEl?.classList.add('with-line-highlights');\n        }\n        fragment.querySelector('.line:last-child:empty')?.remove();\n        if ([...fragment.querySelectorAll('.line')].length === 1) {\n          shikiEl?.classList.add('single-line');\n        }\n\n        if (fileName) {\n          wrapper.prepend(createSpan(fileName, 'filename'));\n          shikiEl?.classList.add('with-filename');\n        }\n        node.value = fragment.querySelector('.shiki-snippet')?.outerHTML;\n        node.type = 'html';\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error(err);\n        // eslint-disable-next-line no-console\n        console.log(node.lang);\n      }\n    }\n  };\n}\n\nfunction createSpan(text: string, className: string, attrs?: Record<string, string>) {\n  const document = dom.window.document;\n\n  const span = document.createElement('span');\n  span.textContent = text;\n  span.classList.add(className);\n  if (attrs) {\n    Object.keys(attrs).forEach(attr => {\n      span.setAttribute(attr, attrs[attr]);\n    });\n  }\n\n  return span;\n}\n\nfunction replaceColorsWithVariables(html) {\n  const colors = [\n    { variable: '--code-foreground', value: '#f8f8f2' },\n    { variable: '--code-background', value: '#22212c' },\n    { variable: '--code-token-constant', value: '#9580ff' },\n    { variable: '--code-token-operator', value: '#ff80bf' },\n    { variable: '--code-token-type', value: '#80ffea' },\n    { variable: '--code-token-parameter', value: '#ffca80' },\n    { variable: '--code-token-attribute', value: '#8aff80' },\n    { variable: '--code-token-regex', value: '#ff9580' },\n    { variable: '--code-token-string', value: '#ffff80' },\n    { variable: '--code-token-comment', value: '#7970a9' },\n  ];\n\n  let str = html;\n  colors.forEach(color => {\n    str = str.replace(new RegExp(`color:\\\\s*${color.value}`, 'ig'), `color: var(${color.variable})`);\n  });\n\n  return str;\n}\n\nfunction parseLines(lines) {\n  return lines.split(',').reduce((acc, line) => {\n    if (/-/.test(line)) {\n      const [start, end] = line.split('-').map(ln => Number(ln));\n      let current = start;\n      while (current <= end) {\n        acc.push(current);\n        current++;\n      }\n\n      return acc;\n    }\n\n    acc.push(Number(line));\n\n    return acc;\n  }, []);\n}\n\nconst fileNameRE = /\\[(.+)\\]/;\nconst linesRE = /\\{(.+)\\}/;\n\nfunction parseParts(lang) {\n  lang = lang.trim();\n  const [, fileName] = lang.match(fileNameRE) || [];\n  const [, lines] = lang.match(linesRE) || [];\n  const rawLang = lang.replace(fileNameRE, '').replace(linesRE, '');\n\n  return {\n    lang: rawLang,\n    lines: lines ? parseLines(lines.replace()) : [],\n    fileName,\n  };\n}\n"
  },
  {
    "path": "docs/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"vee-validate-docs\",\n  \"scripts\": {\n    \"dev\": \"astro dev\",\n    \"start\": \"astro dev\",\n    \"build\": \"astro build && node scripts/afterBuild.js\"\n  },\n  \"dependencies\": {\n    \"@astrojs/mdx\": \"^1.1.5\",\n    \"@astrojs/partytown\": \"^2.0.2\",\n    \"@astrojs/sitemap\": \"^3.0.3\",\n    \"@astrojs/vue\": \"^3.0.4\",\n    \"@docsearch/css\": \"^3.5.2\",\n    \"@docsearch/js\": \"^3.5.2\",\n    \"@floating-ui/dom\": \"^1.5.3\",\n    \"@stackblitz/sdk\": \"^1.9.0\",\n    \"@types/fs-extra\": \"^11.0.4\",\n    \"@types/lodash-es\": \"^4.17.12\",\n    \"@vue/repl\": \"^3.0.0\",\n    \"@vueuse/core\": \"^10.7.0\",\n    \"astro\": \"^3.6.4\",\n    \"autoprefixer\": \"^10.4.16\",\n    \"fs-extra\": \"^11.2.0\",\n    \"jsdom\": \"^23.0.1\",\n    \"lodash-es\": \"^4.17.21\",\n    \"remark-gfm\": \"^3.0.1\",\n    \"shiki\": \"^0.14.6\",\n    \"tailwindcss\": \"^3.4.15\",\n    \"unist-util-visit\": \"^5.0.0\",\n    \"valibot\": \"^1.0.0-beta.7\",\n    \"vee-validate\": \"workspace:*\",\n    \"vue\": \"^3.4.26\",\n    \"yup\": \"^1.3.2\",\n    \"zod\": \"^3.22.4\"\n  },\n  \"version\": null\n}\n"
  },
  {
    "path": "docs/postcss.config.js",
    "content": "module.exports = {\n  plugins: {\n    'tailwindcss/nesting': {},\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n"
  },
  {
    "path": "docs/public/img/browserconfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig><msapplication><tile><square70x70logo src=\"/ms-icon-70x70.png\"/><square150x150logo src=\"/ms-icon-150x150.png\"/><square310x310logo src=\"/ms-icon-310x310.png\"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>"
  },
  {
    "path": "docs/public/img/manifest.json",
    "content": "{\n \"name\": \"App\",\n \"icons\": [\n  {\n   \"src\": \"\\/android-icon-36x36.png\",\n   \"sizes\": \"36x36\",\n   \"type\": \"image\\/png\",\n   \"density\": \"0.75\"\n  },\n  {\n   \"src\": \"\\/android-icon-48x48.png\",\n   \"sizes\": \"48x48\",\n   \"type\": \"image\\/png\",\n   \"density\": \"1.0\"\n  },\n  {\n   \"src\": \"\\/android-icon-72x72.png\",\n   \"sizes\": \"72x72\",\n   \"type\": \"image\\/png\",\n   \"density\": \"1.5\"\n  },\n  {\n   \"src\": \"\\/android-icon-96x96.png\",\n   \"sizes\": \"96x96\",\n   \"type\": \"image\\/png\",\n   \"density\": \"2.0\"\n  },\n  {\n   \"src\": \"\\/android-icon-144x144.png\",\n   \"sizes\": \"144x144\",\n   \"type\": \"image\\/png\",\n   \"density\": \"3.0\"\n  },\n  {\n   \"src\": \"\\/android-icon-192x192.png\",\n   \"sizes\": \"192x192\",\n   \"type\": \"image\\/png\",\n   \"density\": \"4.0\"\n  }\n ]\n}"
  },
  {
    "path": "docs/public/loadTheme.js",
    "content": "(function setUserPreferredTheme() {\n  const themeSetting = localStorage.getItem('theme');\n  // no dark setting, get it from browser\n  const theme = themeSetting || 'dark';\n\n  document.documentElement.classList.toggle('dark', theme === 'dark');\n  localStorage.setItem('theme', theme);\n})();\n"
  },
  {
    "path": "docs/scripts/afterBuild.js",
    "content": "/* eslint-disable @typescript-eslint/no-var-requires */\n\nconst path = require('path');\nconst fs = require('fs');\n\nfs.copyFileSync(path.join(__dirname, '../_redirects'), path.join(__dirname, '../dist/_redirects'));\n"
  },
  {
    "path": "docs/src/components/Ad.vue",
    "content": "<template>\n  <div v-if=\"!hasError\" id=\"ad\" :class=\"{ 'placement-home': placement === 'home-page' }\">\n    <!-- Show an image ad -->\n    <div data-ea-publisher=\"vee-validatelogaretmcom\" data-ea-type=\"image\"></div>\n  </div>\n\n  <div v-else id=\"ad\" class=\"error\">\n    <div class=\"p-4 flex flex-col\">\n      <span class=\"font-bold font-display\">🙏 Enable Ads</span>\n      <span class=\"mt-2\"> Please enable ads on your browser for this website. </span>\n      <span class=\"mt-1\"> Ads are a funding source to this project. </span>\n\n      <div class=\"mt-2 or-fund-it\">\n        <span class=\"mx-1 whitespace-nowrap\">or consider</span>\n      </div>\n\n      <a\n        target=\"_blank\"\n        rel=\"noopener\"\n        href=\"https://github.com/sponsors/logaretm\"\n        class=\"mt-2 bg-pink-600 py-1 px-2 text-white font-medium flex items-center justify-center font-display rounded group hover:bg-pink-700\"\n      >\n        <svg\n          class=\"stroke-current transform transition duration-200 group-hover:scale-110 w-5 h-5 mr-1\"\n          fill=\"none\"\n          viewBox=\"0 0 24 24\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n        >\n          <path\n            stroke-linecap=\"round\"\n            stroke-linejoin=\"round\"\n            stroke-width=\"2\"\n            d=\"M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z\"\n          ></path>\n        </svg>\n\n        Sponsor\n      </a>\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, ref } from 'vue';\n\ndefineProps<{\n  placement?: 'content' | 'home-page';\n}>();\n\nconst hasError = ref(false);\n\nfunction loadScript() {\n  const script = document.createElement('script');\n  script.src = 'https://media.ethicalads.io/media/client/ethicalads.min.js';\n\n  const el = document.querySelector('#ad');\n  el?.appendChild(script);\n  script.onerror = error => {\n    if (navigator.onLine) {\n      hasError.value = true;\n    }\n  };\n}\n\nonMounted(loadScript);\n</script>\n\n<style lang=\"postcss\">\n#ad {\n  @apply static text-gray-400 mt-4 hidden md:block;\n  z-index: 1;\n\n  .ea-placement {\n    @apply rounded-md overflow-hidden bg-zinc-200;\n\n    .ea-content {\n      @apply m-0 rounded-none;\n\n      a {\n        @apply text-zinc-500;\n      }\n\n      strong {\n        @apply text-accent-900;\n      }\n    }\n\n    .ea-callout {\n      @apply m-0 py-2 px-4 text-center bg-zinc-300 rounded-none;\n    }\n  }\n\n  &.error {\n    width: 180px;\n  }\n}\n\n.dark {\n  #ad {\n    .ea-placement {\n      @apply bg-zinc-800;\n    }\n\n    .ea-callout {\n      @apply bg-zinc-950;\n\n      a {\n        @apply text-zinc-600;\n      }\n    }\n\n    &.error {\n      @apply bg-zinc-800;\n    }\n  }\n}\n\n.or-fund-it {\n  @apply text-zinc-500 flex items-center space-x-2;\n\n  &::before,\n  &::after {\n    height: 1px;\n    width: 100%;\n    content: '';\n    @apply flex-shrink bg-zinc-500;\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/CodeTitle.vue",
    "content": "<template>\n  <component :is=\"tag\">\n    <slot />\n  </component>\n</template>\n\n<script>\nexport default {\n  props: {\n    level: [Number, String],\n  },\n  computed: {\n    tag() {\n      return `h${this.level}`;\n    },\n  },\n};\n</script>\n\n<style lang=\"postcss\" scoped>\nh4:deep(code:not([class])) {\n  @apply text-lg;\n}\n\nh5:deep(code:not([class])) {\n  @apply text-base;\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/ContentWrapper.vue",
    "content": "<template>\n  <div class=\"rendered-content\">\n    <slot />\n  </div>\n</template>\n\n<style lang=\"postcss\">\n.rendered-content {\n  hr {\n    @apply mt-10 mb-8 border  border-gray-300;\n  }\n\n  h1 {\n    @apply text-5xl mb-8 font-bold;\n  }\n\n  h2 {\n    @apply text-2xl lg:text-3xl;\n  }\n\n  h3 {\n    @apply text-lg lg:text-xl;\n  }\n\n  h4,\n  h5 {\n    @apply text-lg;\n  }\n\n  h1,\n  h2,\n  h3 {\n    @apply font-display;\n  }\n\n  h2,\n  h3,\n  h4,\n  h5 {\n    @apply font-semibold my-8 relative w-max max-w-full break-normal;\n    transform: translateX(2ch);\n    &::before {\n      @apply absolute text-accent-800;\n      margin-left: -2ch;\n      content: '#';\n    }\n\n    @screen lg {\n      transform: none;\n    }\n\n    &::after {\n      content: '';\n      display: block;\n    }\n  }\n\n  p + p {\n    @apply mt-4;\n  }\n\n  ul {\n    @apply px-8 my-4 list-disc;\n\n    li + li {\n      @apply mt-2;\n    }\n  }\n\n  ul {\n    li {\n      @apply relative antialiased list-none;\n      &:before {\n        @apply w-6 h-6 text-lg absolute rounded-full flex items-center justify-center flex-shrink-0;\n        content: '';\n        background-image: url(\"data:image/svg+xml,%3Csvg fill='none' stroke='%2309a884' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z'%3E%3C/path%3E%3C/svg%3E\");\n        left: -2rem;\n      }\n    }\n  }\n\n  .shiki-snippet {\n    @apply my-5 rounded-md text-sm shadow;\n\n    .filename {\n      @apply inline-block py-2 px-8 bottom-full  rounded-t-md font-extrabold text-sm select-none tracking-wide border border-b-0 border-emerald-500 border-opacity-30 bg-gray-200;\n      font-family: 'Courier New', monospace;\n    }\n\n    .shiki-language {\n      @apply absolute right-2 top-2 text-xs;\n      color: var(--code-lang-label);\n    }\n  }\n\n  .shiki {\n    @apply font-mono pb-4 pt-6 text-sm border border-emerald-500 border-opacity-30 relative rounded-md;\n    counter-reset: step;\n    counter-increment: step 0;\n    line-height: 1.4;\n    overflow: auto;\n    overflow: overlay;\n\n    &.with-filename {\n      @apply rounded-tl-none rounded-tr-md;\n    }\n\n    code {\n      @apply flex flex-col w-full;\n    }\n\n    &.with-line-highlights {\n      .line {\n        @apply transition-all duration-300;\n      }\n\n      .line:not(.is-highlighted) {\n        @apply filter grayscale opacity-40 brightness-100;\n      }\n\n      &:hover {\n        .line:not(.is-highlighted) {\n          @apply filter-none opacity-100;\n        }\n\n        .line.is-highlighted {\n          background-color: var(--code-line-highlight);\n        }\n      }\n    }\n\n    &:not(.single-line) {\n      .line {\n        @apply block pr-2;\n        padding-left: 1.4rem;\n        line-height: 1.6;\n\n        &::before {\n          @apply select-none;\n          content: counter(step);\n          counter-increment: step;\n          width: 1rem;\n          border-left: 0.2rem transparent solid;\n          margin-right: 1.3rem;\n          display: inline-block;\n          text-align: right;\n          color: var(--code-line-numbers);\n        }\n\n        &.is-highlighted {\n          padding-left: 0;\n\n          &::before {\n            padding-left: 1.4rem;\n            margin-right: 2rem;\n            border-color: var(--code-line-highlight-border);\n          }\n        }\n      }\n    }\n\n    &.single-line {\n      @apply px-6;\n    }\n  }\n\n  blockquote {\n    @apply py-4 rounded-r-lg pl-4 bg-black border-l-4 border-accent-800 italic my-8 text-lg;\n  }\n\n  pre[class*='language-'] {\n    @apply rounded-lg my-4 block border border-gray-100;\n  }\n\n  *:not(pre) > code:not([class]) {\n    @apply text-sm px-1 rounded bg-gray-100 border border-gray-200 text-gray-900;\n  }\n\n  iframe {\n    @apply my-8;\n  }\n\n  details {\n    @apply my-10 px-3;\n\n    summary {\n      @apply outline-none mb-8;\n    }\n  }\n\n  ol {\n    @apply list-decimal px-8;\n  }\n\n  p,\n  li,\n  td {\n    a[href] {\n      @apply text-accent-800;\n\n      &:hover {\n        @apply underline;\n      }\n    }\n  }\n\n  table {\n    @apply w-full my-4 overflow-hidden;\n  }\n\n  th,\n  td {\n    @apply border border-gray-100;\n  }\n\n  th {\n    @apply text-sm font-medium;\n  }\n\n  th,\n  td {\n    @apply p-3;\n  }\n}\n\n.dark {\n  *:not(pre) > code:not([class]) {\n    @apply px-1 bg-black border border-gray-500 text-gray-200;\n  }\n\n  pre code,\n  pre[class*='language-'] code {\n    color: #f8f8f2;\n  }\n\n  *[class*='language-']::before {\n    color: #7970a9;\n  }\n\n  pre[class*='language-'] {\n    @apply border-carbon;\n  }\n\n  th,\n  td {\n    @apply border-gray-500;\n  }\n\n  .shiki-snippet {\n    .filename {\n      @apply bg-gray-700;\n    }\n  }\n\n  hr {\n    @apply border border-carbon;\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/DocBadge.vue",
    "content": "<template>\n  <span class=\"px-2 py-1 bg-accent-800 text-white text-sm rounded-lg\">{{ title }}</span>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps<{\n  title: string;\n}>();\n</script>\n"
  },
  {
    "path": "docs/src/components/DocFlavor.vue",
    "content": "<template>\n  <div class=\"mt-8\">\n    <h2 class=\"text-2xl font-display inline-block\">Choose a flavor</h2>\n    <p class=\"mt-4\">Before you go on, you should choose which flavor of vee-validate you want to use.</p>\n\n    <div class=\"mt-8 grid grid-cols-1 lg:grid-cols-2 gap-x-8 gap-y-8 text-white\">\n      <a :href=\"`/v5/guide/components/${next}/`\" class=\"bg-gray-600 hover:bg-accent-900 p-6 rounded-lg relative\">\n        <p class=\"text-xl font-semibold font-display\">Components</p>\n        <p class=\"mt-8\">Simple, high-level, dynamic template-based higher-order components.</p>\n        <p class=\"mt-4\">Great for simple UI components and native HTML elements with custom styling.</p>\n\n        <svg\n          class=\"w-20 h-20 absolute top-0 right-0 mt-4 mr-4 text-gray-900 opacity-10\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          viewBox=\"0 0 24 24\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n        >\n          <path\n            stroke-linecap=\"round\"\n            stroke-linejoin=\"round\"\n            stroke-width=\"2\"\n            d=\"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4\"\n          ></path>\n        </svg>\n      </a>\n\n      <a :href=\"`/v5/guide/composition-api/${next}/`\" class=\"bg-gray-600 hover:bg-accent-900 p-6 rounded-lg relative\">\n        <p class=\"text-xl font-semibold font-display\">Composition API</p>\n        <p class=\"mt-8\">Low level, intuitive composition API functions.</p>\n        <p class=\"mt-4\">Great for building complex UI form components and general purpose data validation.</p>\n        <svg\n          class=\"w-20 h-20 absolute top-0 right-0 mt-4 mr-4 text-gray-900 opacity-10\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          viewBox=\"0 0 24 24\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n        >\n          <path\n            stroke-linecap=\"round\"\n            stroke-linejoin=\"round\"\n            stroke-width=\"2\"\n            d=\"M17 14v6m-3-3h6M6 10h2a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v2a2 2 0 002 2zm10 0h2a2 2 0 002-2V6a2 2 0 00-2-2h-2a2 2 0 00-2 2v2a2 2 0 002 2zM6 20h2a2 2 0 002-2v-2a2 2 0 00-2-2H6a2 2 0 00-2 2v2a2 2 0 002 2z\"\n          ></path>\n        </svg>\n      </a>\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps({\n  next: String,\n});\n</script>\n\n<style lang=\"postcss\" scoped>\np {\n  @apply text-lg lg:text-base;\n}\n\nh2 {\n  @apply font-semibold relative text-3xl lg:text-xl;\n\n  transform: translateX(2ch);\n  &::before {\n    @apply absolute text-accent-800;\n    margin-left: -2ch;\n    content: '#';\n  }\n\n  @screen lg {\n    transform: none;\n  }\n}\n\na {\n  transition: background-color 0.4s ease-in-out;\n\n  svg {\n    transition: transform 0.5s ease-in-out;\n  }\n\n  &:hover {\n    svg {\n      transform: scale(1.1) translate3d(-2px, 2px, 0);\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/DocMenu.vue",
    "content": "<template>\n  <div class=\"relative mt-20 lg:mt-4 font-ui\">\n    <div\n      class=\"bg-gradient-to-b from-white dark:from-dark to-transparent h-4 absolute -top-px lg:top-0 inset-x-0\"\n    ></div>\n    <nav class=\"space-y-8 md:text-sm overflow-y-auto overscroll-y-contain px-8 lg:px-2 py-4\">\n      <div v-for=\"category in menu\" :key=\"category.title\">\n        <p v-if=\"category.pages.length > 1\" class=\"md:text-xs font-bold text-gray-400 uppercase\">\n          {{ category.title }}\n        </p>\n        <div class=\"mt-3 space-y-2 w-full\">\n          <a\n            v-if=\"category.pages.length === 1\"\n            :href=\"category.pages[0].path\"\n            :aria-current=\"currentUrl === category.pages[0].path ? 'page' : undefined\"\n            class=\"flex items-center\"\n          >\n            <span v-if=\"category.pages[0].icon\" class=\"mr-2 bg-gray-200 dark:bg-gray-500 rounded p-1\">\n              <Icon :name=\"category.pages[0].icon\" class=\"w-5 h-5 fill-current\" />\n            </span>\n            {{ category.pages[0].menuTitle || category.pages[0].title }}\n          </a>\n\n          <template v-else>\n            <div v-for=\"page in category.pages\" :key=\"page.title\" class=\"group\">\n              <a\n                v-if=\"!page.children\"\n                :href=\"page.path\"\n                :aria-current=\"currentUrl === page.path ? 'page' : undefined\"\n                class=\"flex items-center ml-2\"\n              >\n                {{ page.menuTitle || page.title }}\n\n                <span v-if=\"page.new\" class=\"ml-2 w-2 h-2 rounded-full flex-shrink-0 bg-blue-600\"></span>\n              </a>\n\n              <div v-else class=\"flex flex-col bg-gray-200 dark:bg-gray-600 w-full rounded-lg py-3 px-2\">\n                <button\n                  type=\"button\"\n                  class=\"w-full flex items-center focus:outline-none transition-colors duration-300\"\n                  @click=\"expanded[page.title] = !expanded[page.title]\"\n                >\n                  <Icon :name=\"page.icon\" class=\"w-5 h-5 fill-current\" />\n                  <span class=\"ml-2 group-hover:text-accent-800\">{{ page.menuTitle || page.title }}</span>\n\n                  <svg\n                    class=\"ml-auto w-5 h-5\"\n                    fill=\"none\"\n                    stroke=\"currentColor\"\n                    viewBox=\"0 0 24 24\"\n                    xmlns=\"http://www.w3.org/2000/svg\"\n                  >\n                    <path\n                      v-if=\"!expanded[page.title]\"\n                      stroke-linecap=\"round\"\n                      stroke-linejoin=\"round\"\n                      stroke-width=\"2\"\n                      d=\"M12 6v6m0 0v6m0-6h6m-6 0H6\"\n                    ></path>\n\n                    <path v-else stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 12H4\"></path>\n                  </svg>\n                </button>\n\n                <ExpandTransition>\n                  <ul v-show=\"expanded[page.title]\" class=\"mt-3 space-y-2\">\n                    <li v-for=\"childPage in page.children\" :key=\"childPage.title\" class=\"pl-7 flex items-center\">\n                      <a :href=\"childPage.path\" :aria-current=\"currentUrl === childPage.path ? 'page' : undefined\">\n                        {{ childPage.menuTitle || childPage.title }}\n                      </a>\n\n                      <span v-if=\"childPage.new\" class=\"ml-2 w-2 h-2 rounded-full flex-shrink-0 bg-blue-600\"></span>\n                    </li>\n                  </ul>\n                </ExpandTransition>\n              </div>\n            </div>\n          </template>\n        </div>\n      </div>\n    </nav>\n    <div\n      class=\"bg-gradient-to-b from-transparent to-white dark:to-dark h-4 absolute -bottom-px lg:bottom-0 inset-x-0\"\n    ></div>\n  </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { reactive } from 'vue';\nimport ExpandTransition from '@/components/ExpandTransition.vue';\nimport Icon from '@/components/Icon.vue';\n\nexport interface CategoryMenuItem {\n  title: string;\n  pages: {\n    title: string;\n    menuTitle?: string;\n    path: string;\n    new?: boolean;\n    icon?: string;\n    children?: {\n      title: string;\n      new?: boolean;\n      menuTitle?: string;\n      path: string;\n    }[];\n  }[];\n}\n\nconst props = defineProps<{\n  menu: CategoryMenuItem[];\n  currentUrl: string;\n}>();\n\nconst expanded = reactive<Record<string, boolean>>({});\nif (props.currentUrl) {\n  if (props.currentUrl.includes('/composition-api')) {\n    expanded['Composition API'] = true;\n  }\n\n  if (props.currentUrl.includes('/components')) {\n    expanded['Components'] = true;\n  }\n}\n</script>\n\n<style lang=\"postcss\" scoped>\nnav {\n  max-height: calc(80vh - 96px);\n  a {\n    @screen motion {\n      transition: color 0.2s ease-in-out;\n    }\n\n    &:hover {\n      @apply text-accent-800;\n    }\n\n    &[aria-current='page'] {\n      @apply text-accent-800;\n    }\n  }\n\n  /* Global Scrollbar styling */\n  &::-webkit-scrollbar {\n    width: 7px;\n    cursor: pointer;\n    /*background-color: rgba(229, 231, 235, var(--bg-opacity));*/\n  }\n  &::-webkit-scrollbar-track {\n    background-color: none;\n    cursor: pointer;\n    /*background: red;*/\n  }\n  &::-webkit-scrollbar-thumb {\n    cursor: pointer;\n    background-color: #e8e8e8; /* #E7E5E4; */\n    border-radius: 50px;\n    /*outline: 1px solid grey;*/\n  }\n}\n\n.dark {\n  nav {\n    /* Global Scrollbar styling */\n    &::-webkit-scrollbar {\n      width: 7px;\n      cursor: pointer;\n      /*background-color: rgba(229, 231, 235, var(--bg-opacity));*/\n    }\n    &::-webkit-scrollbar-track {\n      background-color: none;\n      cursor: pointer;\n      /*background: red;*/\n    }\n    &::-webkit-scrollbar-thumb {\n      cursor: pointer;\n      background-color: #333; /* #E7E5E4; */\n      border-radius: 50px;\n      /*outline: 1px solid grey;*/\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/DocNextStep.vue",
    "content": "<template>\n  <div class=\"pt-4\">\n    <h2 class=\"text-xl\">Next Step</h2>\n\n    <p v-if=\"intro\">{{ intro }}</p>\n\n    <a :href=\"href\" class=\"mt-8 bg-accent-800 w-full flex items-start p-4 rounded text-white\">\n      <svg\n        class=\"w-5 h-5 mr-2 mt-1 flex-shrink-0\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        viewBox=\"0 0 24 24\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n      >\n        <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M14 5l7 7m0 0l-7 7m7-7H3\"></path>\n      </svg>\n      <div class=\"NextTitle flex flex-col\">\n        <span class=\"text-lg font-semibold flex\">{{ title }}</span>\n        <span class=\"mt-2 text-sm\">{{ description }}</span>\n      </div>\n    </a>\n  </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed } from 'vue';\nimport { trim, trimEnd } from 'lodash-es';\n\nconst props = defineProps<{\n  title: string;\n  description: string;\n  path: string;\n  intro: string;\n}>();\n\nconst href = computed(() => {\n  return `${trimEnd(import.meta.env.BASE_URL, '/')}/${trim(props.path, '/')}/`;\n});\n</script>\n\n<style lang=\"postcss\" scoped>\nh2 {\n  @apply font-semibold mb-8 relative;\n  transform: translateX(2ch);\n  &::before {\n    @apply absolute text-accent-800;\n    margin-left: -2ch;\n    content: '#';\n  }\n\n  @screen lg {\n    transform: none;\n  }\n}\n\na {\n  .NextTitle {\n    transition: transform 0.3s ease-in-out;\n  }\n\n  &:hover {\n    .NextTitle {\n      transform: translate3d(10px, 0, 0);\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/DocSearch.vue",
    "content": "<template>\n  <div>\n    <button\n      type=\"button\"\n      class=\"border border-gray-200 hover:border-gray-300 dark:border-carbon dark:bg-gray-600 dark:hover:border-accent-800 dark:hover:border-opacity-50 flex items-center px-4 py-2 rounded-md w-full\"\n      @click=\"onClick\"\n    >\n      <svg\n        width=\"24\"\n        height=\"24\"\n        fill=\"none\"\n        aria-hidden=\"true\"\n        class=\"mr-3 flex-none text-gray-300 dark:text-gray-400\"\n      >\n        <path\n          d=\"m19 19-3.5-3.5\"\n          stroke=\"currentColor\"\n          stroke-width=\"2\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        ></path>\n        <circle\n          cx=\"11\"\n          cy=\"11\"\n          r=\"6\"\n          stroke=\"currentColor\"\n          stroke-width=\"2\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        ></circle>\n      </svg>\n\n      <span class=\"text-sm text-gray-400 dark:text-gray-300\"> Search Docs...</span>\n\n      <span class=\"ml-auto flex items-center text-xs text-gray-500 dark:text-gray-300 space-x-1\">\n        <kbd class=\"bg-gray-200 dark:bg-gray-500 p-1 shadow flex-shrink-0 w-4 h-4 flex items-center justify-center\"\n          >⌘</kbd\n        >\n        <kbd class=\"bg-gray-200 dark:bg-gray-500 p-1 shadow flex-shrink-0 w-4 h-4 flex items-center justify-center\"\n          >K</kbd\n        >\n      </span>\n    </button>\n\n    <div id=\"docsearch\" class=\"hidden\"></div>\n  </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { onMounted } from 'vue';\nimport config from '@/config';\nimport docsearch from '@docsearch/js';\n\nfunction stripTrailingSlash(url: string) {\n  return url.replace(/\\/$|\\/(?=\\?)|\\/(?=#)/g, '');\n}\n\nfunction getRelativePath(absoluteUrl: string) {\n  const { pathname, hash } = new URL(absoluteUrl);\n  const url = pathname + hash;\n\n  return stripTrailingSlash(url);\n}\n\nfunction initialize(userOptions) {\n  docsearch({\n    ...userOptions,\n    container: '#docsearch',\n    debug: process.env.NODE_ENV !== 'production',\n    transformItems: items => {\n      return items.map(item => {\n        return {\n          ...item,\n          url: getRelativePath(item.url),\n        };\n      });\n    },\n  });\n}\n\nonMounted(() => {\n  initialize(config.algolia);\n});\n\nfunction onClick() {\n  (document.querySelector('#docsearch button') as HTMLElement)?.click();\n}\n</script>\n\n<style lang=\"postcss\">\n@import '@docsearch/css';\n\n.DocSearch {\n  font-family: Arial, Helvetica, sans-serif;\n  --docsearch-primary-color: var(--accent);\n  --docsearch-highlight-color: var(--docsearch-primary-color);\n  --docsearch-text-color: var(--color-gray-200);\n  --docsearch-modal-background: #f6f6f6;\n  --docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);\n  --docsearch-searchbox-background: #e8e8e8;\n  --docsearch-searchbox-focus-background: #e8e8e8;\n  --docsearch-hit-color: var(--color-gray-200);\n  --docsearch-muted-color: var(--color-gray-500);\n  --docsearch-logo-color: var(--accent);\n}\n\n.DocSearch-Button {\n  @apply w-full ml-0 rounded-md px-3 !important;\n}\n\n.DocSearch-Button-Placeholder {\n  @apply px-3 !important;\n}\n\n.DocSearch-Screen-Icon > svg {\n  display: inline !important;\n}\n\n.dark {\n  .DocSearch {\n    --docsearch-text-color: #fff;\n    --docsearch-container-background: rgba(9, 10, 17, 0.8);\n    --docsearch-modal-background: hsl(240 6% 9%);\n    --docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;\n    --docsearch-searchbox-background: hsl(0 0% 29%);\n    --docsearch-searchbox-focus-background: hsl(0 0% 29%);\n    --docsearch-hit-color: #fff;\n    --docsearch-hit-shadow: none;\n    --docsearch-hit-background: #333;\n    --docsearch-key-gradient: linear-gradient(-26.5deg, #161618, #4a4a4a);\n    --docsearch-key-shadow: inset 0 -2px 0 0 #5a6069, inset 0 0 1px 1px #959595, 0 2px 2px 0 rgba(3, 4, 9, 0.3);\n    --docsearch-footer-background: hsl(240 6% 9%);\n    --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5), 0 -4px 8px 0 rgba(0, 0, 0, 0.2);\n    --docsearch-logo-color: var(--accent);\n    --docsearch-muted-color: var(--color-gray-500);\n  }\n\n  .DocSearch-NoResults,\n  .DocSearch-Footer,\n  .DocSearch-Help,\n  .DocSearch-Reset {\n    color: #e8e8e8;\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/DocTip.vue",
    "content": "<template>\n  <div\n    class=\"p-6 rounded my-8 border-l-4 bg-gray-100 dark:bg-zinc-800\"\n    :class=\"{\n      'border-accent-800 text-accent-800': !type || type === 'tip',\n      'border-warning text-warning': type === 'warn',\n      'border-error text-error': type === 'danger',\n    }\"\n  >\n    <div class=\"flex flex-row items-center\">\n      <svg v-if=\"['danger', 'warn'].includes(type)\" fill=\"currentColor\" class=\"h-6 w-6 mr-2\" viewBox=\"0 0 20 20\">\n        <path\n          fill-rule=\"evenodd\"\n          d=\"M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z\"\n          clip-rule=\"evenodd\"\n        ></path>\n      </svg>\n\n      <svg v-if=\"type === 'tip' || !type\" class=\"h-6 w-6 mr-2\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n        <path\n          d=\"M11 3a1 1 0 10-2 0v1a1 1 0 102 0V3zM15.657 5.757a1 1 0 00-1.414-1.414l-.707.707a1 1 0 001.414 1.414l.707-.707zM18 10a1 1 0 01-1 1h-1a1 1 0 110-2h1a1 1 0 011 1zM5.05 6.464A1 1 0 106.464 5.05l-.707-.707a1 1 0 00-1.414 1.414l.707.707zM5 10a1 1 0 01-1 1H3a1 1 0 110-2h1a1 1 0 011 1zM8 16v-1h4v1a2 2 0 11-4 0zM12 14c.015-.34.208-.646.477-.859a4 4 0 10-4.954 0c.27.213.462.519.476.859h4.002z\"\n        ></path>\n      </svg>\n\n      <p v-if=\"title\" class=\"font-bold text-base\">{{ title }}</p>\n      <p v-else class=\"font-bold text-base uppercase\">{{ type || 'tip' }}</p>\n    </div>\n\n    <div class=\"mt-4 text-black dark:text-white\">\n      <slot />\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps<{\n  title?: string;\n  type?: 'tip' | 'warn' | 'danger';\n}>();\n</script>\n"
  },
  {
    "path": "docs/src/components/DocToc.vue",
    "content": "<template>\n  <nav class=\"py-4 overflow-y-auto overscroll-y-contain\" v-show=\"headings.length\">\n    <p class=\"font-bold text-xs uppercase text-gray-400\">On this page</p>\n    <ul class=\"mt-4 space-y-1 text-sm\">\n      <li v-for=\"heading in headings\" :key=\"heading.slug\" :class=\"{ 'ml-4': heading.depth === 3 }\">\n        <a class=\"inline-block py-1\" :href=\"`#${heading.slug}`\">{{ heading.text }}</a>\n      </li>\n    </ul>\n  </nav>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst props = defineProps<{\n  headings: { depth: number; slug: string; text: string }[];\n}>();\n\nconst headings = computed(() => {\n  return props.headings.filter(h => h.depth <= 3 && h.depth !== 1);\n});\n</script>\n\n<style lang=\"postcss\" scoped>\nnav {\n  a {\n    @screen motion {\n      transition: transform 0.3s ease-in-out, color 0.2s ease-in-out;\n    }\n\n    &:hover {\n      @apply text-accent-800;\n      @screen motion {\n        transform: translate3d(10px, 0, 0);\n      }\n    }\n  }\n}\n\nnav {\n  max-height: calc(80vh - 225px);\n  a {\n    @screen motion {\n      transition: color 0.2s ease-in-out;\n    }\n\n    &:hover {\n      @apply text-accent-800;\n    }\n\n    &[aria-current='page'] {\n      @apply text-accent-800;\n    }\n  }\n\n  /* Global Scrollbar styling */\n  &::-webkit-scrollbar {\n    width: 7px;\n    cursor: pointer;\n    /*background-color: rgba(229, 231, 235, var(--bg-opacity));*/\n  }\n  &::-webkit-scrollbar-track {\n    background-color: none;\n    cursor: pointer;\n    /*background: red;*/\n  }\n  &::-webkit-scrollbar-thumb {\n    cursor: pointer;\n    background-color: #e8e8e8; /* #E7E5E4; */\n    border-radius: 50px;\n    /*outline: 1px solid grey;*/\n  }\n}\n\n.dark {\n  nav {\n    /* Global Scrollbar styling */\n    &::-webkit-scrollbar {\n      width: 7px;\n      cursor: pointer;\n      /*background-color: rgba(229, 231, 235, var(--bg-opacity));*/\n    }\n    &::-webkit-scrollbar-track {\n      background-color: none;\n      cursor: pointer;\n      /*background: red;*/\n    }\n    &::-webkit-scrollbar-thumb {\n      cursor: pointer;\n      background-color: #333; /* #E7E5E4; */\n      border-radius: 50px;\n      /*outline: 1px solid grey;*/\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/EditPage.vue",
    "content": "<template>\n  <div class=\"flex items-center\">\n    <a\n      :href=\"pageLink\"\n      target=\"_blank\"\n      rel=\"noopener\"\n      class=\"flex items-center text-sm font-bold text-carbon dark:text-gray-400\"\n    >\n      <svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n        <path\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n          stroke-width=\"2\"\n          d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n        ></path>\n      </svg>\n      <span class=\"ml-2\">Edit This Page on GitHub</span>\n    </a>\n  </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed } from 'vue';\n\nconst props = defineProps<{\n  path: string;\n}>();\n\nconst pageLink = computed(() => {\n  const path = props.path.replace(/\\/$/g, '');\n\n  return `https://github.com/logaretm/vee-validate/edit/main/${path}`;\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/ExpandTransition.vue",
    "content": "<template>\n  <transition name=\"expand\" :appear=\"appear\" @enter=\"enter\" @after-enter=\"afterEnter\" @leave=\"leave\">\n    <slot />\n  </transition>\n</template>\n\n<script>\nexport default {\n  name: 'TransitionExpand',\n  props: {\n    appear: {\n      type: Boolean,\n      default: false,\n    },\n  },\n  methods: {\n    enter(element) {\n      const width = getComputedStyle(element).width;\n\n      element.style.width = width;\n      element.style.position = 'absolute';\n      element.style.visibility = 'hidden';\n      element.style.height = 'auto';\n\n      requestAnimationFrame(() => {\n        const height = getComputedStyle(element).height;\n\n        element.style.width = null;\n        element.style.position = null;\n        element.style.visibility = null;\n        element.style.height = 0;\n\n        requestAnimationFrame(() => {\n          element.style.height = height;\n        });\n      });\n    },\n    afterEnter(element) {\n      element.style.height = 'auto';\n    },\n    leave(element) {\n      const height = getComputedStyle(element).height;\n\n      element.style.height = height;\n\n      // Force repaint to make sure the\n      // animation is triggered correctly.\n      // eslint-disable-next-line no-unused-expressions\n      getComputedStyle(element).height;\n\n      setTimeout(() => {\n        element.style.height = 0;\n      });\n    },\n  },\n};\n</script>\n\n<style lang=\"postcss\" scoped>\n.expand-enter-active,\n.expand-leave-active {\n  transition-property: opacity, height;\n  transition-duration: 0.3s;\n  transition-timing-function: ease-in-out;\n  overflow: hidden;\n}\n\n.expand-enter,\n.expand-leave-to {\n  height: 0;\n}\n\n* {\n  will-change: height;\n  transform: translateZ(0);\n  backface-visibility: hidden;\n  perspective: 1000px;\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/FeatureCard.vue",
    "content": "<template>\n  <div\n    ref=\"elementRef\"\n    class=\"FeatureCard bg-gradient-to-br from-gray-200 to-gray-100 dark:from-zinc-800 dark:to-zinc-900 p-6 rounded-3xl font-display shadow-sm\"\n  >\n    <h3 class=\"text-xl font-bold z-10\">{{ feature.title }}</h3>\n    <p class=\"z-10 mt-4 font-display font-medium text-gray-600 dark:text-gray-300\" v-html=\"feature.details\" />\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { shallowRef } from 'vue';\nimport { useEventListener } from '@vueuse/core';\n\nconst props = defineProps<{\n  feature: {\n    title: string;\n    details: string;\n  };\n}>();\n\nconst elementRef = shallowRef<HTMLElement>();\n\nuseEventListener(\n  elementRef,\n  'mousemove',\n  evt => {\n    if (!elementRef.value) {\n      return;\n    }\n\n    const { x, y } = elementRef.value.getBoundingClientRect();\n\n    elementRef.value.style.setProperty('--x', `${evt.clientX - x}px`);\n    elementRef.value.style.setProperty('--y', `${evt.clientY - y}px`);\n  },\n  { passive: true },\n);\n</script>\n\n<style lang=\"postcss\" scoped>\n.FeatureCard {\n  @apply relative;\n\n  &:before {\n    @apply pointer-events-none absolute select-none rounded-3xl opacity-0;\n    z-index: -1;\n    content: '';\n    inset: -1px;\n    transition-property: opacity;\n    transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n    transition-duration: 0.3s;\n    animation-duration: 0.3s;\n    background: radial-gradient(200px circle at var(--x) var(--y), #009f53 0, #06d77b 0, #009f53 25%, transparent 80%);\n  }\n\n  &:hover:before {\n    @apply opacity-100;\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/FloatingMenu.vue",
    "content": "<template>\n  <slot name=\"trigger\" :toggle=\"onMenuToggle\" :isOpen=\"isOpen\" />\n\n  <div ref=\"menuRef\" class=\"fixed z-40 max-w-xs top-0 left-0\">\n    <transition name=\"menu\">\n      <div\n        v-if=\"isOpen\"\n        class=\"bg-white shadow border border-gray-200 dark:bg-zinc-800 dark:border-zinc-700 p-3 rounded-md\"\n      >\n        <slot name=\"menu\" />\n      </div>\n    </transition>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { onClickOutside } from '@vueuse/core';\nimport { computePosition, Placement, offset } from '@floating-ui/dom';\n\nconst props = defineProps<{\n  placement?: Placement;\n}>();\n\nconst menuRef = ref<HTMLElement>();\nconst isOpen = ref(false);\n\nasync function updateStyle(reference: HTMLElement) {\n  if (!menuRef.value) {\n    return;\n  }\n\n  const { x, y } = await computePosition(reference, menuRef.value, {\n    strategy: 'fixed',\n    placement: props.placement || 'bottom',\n    middleware: [offset({ mainAxis: 10 })],\n  });\n\n  menuRef.value.style.transform = `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`;\n}\n\nfunction onMenuToggle(e: Event) {\n  isOpen.value = !isOpen.value;\n  if (isOpen.value) {\n    updateStyle(e.target as HTMLElement);\n  }\n}\n\nonClickOutside(menuRef, () => {\n  isOpen.value = false;\n});\n</script>\n\n<style scoped lang=\"postcss\">\n.menu-enter-active,\n.menu-leave-active {\n  transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out;\n}\n\n.menu-enter-from,\n.menu-leave-to {\n  opacity: 0;\n  transform: scale(0.8);\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/Icon.vue",
    "content": "<template>\n  <svg class=\"icon flex-shrink-0\">\n    <use :xlink:href=\"`${basePath}#icon-${name}`\"></use>\n  </svg>\n</template>\n\n<script setup lang=\"ts\">\nconst props = defineProps<{\n  name: string;\n}>();\n\nconst basePath = import.meta.env.DEV ? '' : '/v5/sprite.svg';\n</script>\n"
  },
  {
    "path": "docs/src/components/LiveExample.vue",
    "content": "<template>\n  <div ref=\"elRef\"></div>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, ref } from 'vue';\nimport sdk from '@stackblitz/sdk';\n\nconst props = defineProps<{\n  id: string;\n  previewOnly?: boolean;\n  clickToLoad?: boolean;\n}>();\n\nconst elRef = ref<HTMLElement>();\n\nonMounted(() => {\n  if (!elRef.value) {\n    return;\n  }\n\n  sdk.embedProjectId(elRef.value, props.id, {\n    forceEmbedLayout: true,\n    openFile: 'src/App.vue',\n    hideNavigation: true,\n    height: 500,\n    view: props.previewOnly ? 'preview' : undefined,\n    clickToLoad: props.clickToLoad,\n  });\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/LogQueryStr.vue",
    "content": "<template>\n  <div>\n    Submitted data:\n\n    <pre>{{ queryObj }}</pre>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, ref } from 'vue';\n\nconst queryObj = ref();\n\nonMounted(() => {\n  try {\n    const query = new URLSearchParams(window.location.search);\n\n    queryObj.value = Object.fromEntries(query.entries());\n  } catch {\n    queryObj.value = { Error: 'Invalid query string in URL' };\n  }\n});\n</script>\n\n<style scoped></style>\n"
  },
  {
    "path": "docs/src/components/MainPageExample.vue",
    "content": "<template>\n  <div class=\"mt-14 flex flex-col items-center\">\n    <div\n      class=\"bg-gray-200 dark:bg-black max-w-xs p-1 rounded-md flex items-center gap-2 font-display font-semibold text-sm mb-8\"\n    >\n      <button\n        type=\"button\"\n        class=\"flavor-btn\"\n        :aria-pressed=\"currentFlavor === 'components'\"\n        @click=\"setFlavor('components')\"\n      >\n        Components\n      </button>\n      <button\n        type=\"button\"\n        class=\"flavor-btn\"\n        :aria-pressed=\"currentFlavor === 'composition'\"\n        @click=\"setFlavor('composition')\"\n      >\n        Composition API\n      </button>\n    </div>\n\n    <div v-if=\"currentFlavor === 'components'\" class=\"w-full\">\n      <MdxRepl :files=\"{ 'App.vue': 'ComponentsBasic' }\" />\n    </div>\n\n    <div v-else class=\"w-full\">\n      <MdxRepl :files=\"{ 'App.vue': 'CompositionBasic' }\" />\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport MdxRepl from './MdxRepl.vue';\n\nconst currentFlavor = ref<'components' | 'composition'>('components');\n\nfunction setFlavor(flavor: (typeof currentFlavor)['value']) {\n  currentFlavor.value = flavor;\n}\n</script>\n\n<style lang=\"postcss\" scoped>\n.flavor-btn {\n  @apply px-3 py-1.5 rounded-md hover:text-emerald-500 select-none;\n\n  &[aria-pressed='true'] {\n    @apply bg-emerald-500 dark:bg-emerald-600 text-white hover:text-white;\n  }\n}\n\niframe {\n  @apply w-full min-h-[800px] rounded-md border-4 border-emerald-500 border-opacity-60;\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/MdxRepl.vue",
    "content": "<template>\n  <div class=\"my-8 relative\">\n    <Suspense v-if=\"editor\">\n      <Repl :editor=\"editor\" :files=\"files\" />\n\n      <template #fallback>\n        <div class=\"bg-gray-200 dark:bg-zinc-950 w-full h-full rounded-md absolute inset-0\"></div>\n      </template>\n    </Suspense>\n\n    <div v-else class=\"bg-gray-200 dark:bg-zinc-950 w-full h-full rounded-md absolute inset-0\"></div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { defineAsyncComponent, onMounted, shallowRef } from 'vue';\n\nconst Repl = defineAsyncComponent(() => import('./Repl.vue'));\n\nconst props = defineProps<{\n  files: Record<string, string>;\n}>();\n\nlet editor = shallowRef();\nonMounted(async () => {\n  editor.value = (await import('@vue/repl/codemirror-editor')).default;\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/Repl.vue",
    "content": "<script setup lang=\"ts\" async>\nimport { ref, version } from 'vue';\nimport { useFullscreen } from '@vueuse/core';\nimport { Repl, ReplStore } from '@vue/repl';\nimport { getViteProjectConfig } from '@/utils/examples';\nimport StackBlitzSdk from '@stackblitz/sdk';\n\nconst props = defineProps<{\n  files: Record<string, string>;\n  editor: any;\n}>();\n\nconst containerRef = ref<HTMLElement>();\nconst { isFullscreen, toggle: toggleFullscreen } = useFullscreen(containerRef);\n\nconst files = await Promise.all(\n  Object.entries(props.files).map(async ([filename, componentName]) => {\n    const code = await import(`./examples/${componentName}.vue?raw`);\n\n    return [filename, code.default];\n  }),\n);\n\nconst store = new ReplStore({\n  serializedState: btoa(JSON.stringify(Object.fromEntries(files))),\n});\n\n// pre-set import map\nstore.setImportMap({\n  imports: {\n    'vee-validate': 'https://unpkg.com/vee-validate@latest/dist/vee-validate.mjs',\n    '@vee-validate/i18n': 'https://unpkg.com/@vee-validate/i18n@latest/dist/vee-validate-i18n.esm.js',\n    '@vee-validate/rules': 'https://unpkg.com/@vee-validate/rules@latest/dist/vee-validate-rules.esm.js',\n    'property-expr': 'https://esm-repo.netlify.app/property-expr.esm.js',\n    'tiny-case': 'https://esm-repo.netlify.app/tiny-case.esm.js',\n    toposort: 'https://esm-repo.netlify.app/topsort.esm.js',\n    yup: 'https://unpkg.com/yup@1.2.0/index.esm.js',\n    zod: 'https://unpkg.com/zod@3.21.4/lib/index.mjs',\n    valibot: 'https://unpkg.com/valibot@1.0.0-beta.7/dist/index.js',\n    '@vue/devtools-api': 'https://unpkg.com/@vue/devtools-api@6.5.0/lib/esm/index.js',\n    vue: `https://unpkg.com/vue@${version}/dist/vue.esm-browser.prod.js`,\n  },\n});\n\n// use a specific version of Vue\nstore.setVueVersion(version);\n\nfunction onForkClick() {\n  const exampleFiles = files.reduce(\n    (acc, file) => {\n      acc[file[0]] = file[1];\n\n      return acc;\n    },\n    {} as Record<string, string>,\n  );\n\n  StackBlitzSdk.openProject(getViteProjectConfig(exampleFiles), {\n    newWindow: true,\n    startScript: 'dev',\n    openFile: 'src/App.vue',\n  });\n}\n</script>\n\n<template>\n  <div\n    class=\"flex flex-col border border-gray-300 dark:border-emerald-500 border-opacity-80 rounded-md shadow-sm overflow-hidden relative\"\n    ref=\"containerRef\"\n  >\n    <div class=\"flex items-center justify-end py-1.5 px-2 absolute z-10 right-0 h-[var(--header-height)]\">\n      <button\n        type=\"button\"\n        class=\"ml-1 p-1 hover:bg-white hover:bg-opacity-10 rounded\"\n        title=\"Go full screen\"\n        @click=\"toggleFullscreen\"\n      >\n        <svg\n          class=\"w-4 h-4 text-white\"\n          fill=\"currentColor\"\n          viewBox=\"0 0 20 20\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          aria-hidden=\"true\"\n        >\n          <path\n            v-if=\"!isFullscreen\"\n            d=\"M13.28 7.78l3.22-3.22v2.69a.75.75 0 001.5 0v-4.5a.75.75 0 00-.75-.75h-4.5a.75.75 0 000 1.5h2.69l-3.22 3.22a.75.75 0 001.06 1.06zM2 17.25v-4.5a.75.75 0 011.5 0v2.69l3.22-3.22a.75.75 0 011.06 1.06L4.56 16.5h2.69a.75.75 0 010 1.5h-4.5a.747.747 0 01-.75-.75zM12.22 13.28l3.22 3.22h-2.69a.75.75 0 000 1.5h4.5a.747.747 0 00.75-.75v-4.5a.75.75 0 00-1.5 0v2.69l-3.22-3.22a.75.75 0 10-1.06 1.06zM3.5 4.56l3.22 3.22a.75.75 0 001.06-1.06L4.56 3.5h2.69a.75.75 0 000-1.5h-4.5a.75.75 0 00-.75.75v4.5a.75.75 0 001.5 0V4.56z\"\n          ></path>\n          <path\n            v-else\n            d=\"M3.28 2.22a.75.75 0 00-1.06 1.06L5.44 6.5H2.75a.75.75 0 000 1.5h4.5A.75.75 0 008 7.25v-4.5a.75.75 0 00-1.5 0v2.69L3.28 2.22zM13.5 2.75a.75.75 0 00-1.5 0v4.5c0 .414.336.75.75.75h4.5a.75.75 0 000-1.5h-2.69l3.22-3.22a.75.75 0 00-1.06-1.06L13.5 5.44V2.75zM3.28 17.78l3.22-3.22v2.69a.75.75 0 001.5 0v-4.5a.75.75 0 00-.75-.75h-4.5a.75.75 0 000 1.5h2.69l-3.22 3.22a.75.75 0 101.06 1.06zM13.5 14.56l3.22 3.22a.75.75 0 101.06-1.06l-3.22-3.22h2.69a.75.75 0 000-1.5h-4.5a.75.75 0 00-.75.75v4.5a.75.75 0 001.5 0v-2.69z\"\n          ></path>\n        </svg>\n      </button>\n\n      <button\n        type=\"button\"\n        class=\"ml-1 p-1 hover:bg-white hover:bg-opacity-10 rounded\"\n        title=\"Fork in StackBlitz\"\n        @click=\"onForkClick\"\n      >\n        <svg\n          class=\"w-4 h-4 text-white\"\n          fill=\"currentColor\"\n          viewBox=\"0 0 20 20\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          aria-hidden=\"true\"\n        >\n          <path\n            d=\"M11.983 1.907a.75.75 0 00-1.292-.657l-8.5 9.5A.75.75 0 002.75 12h6.572l-1.305 6.093a.75.75 0 001.292.657l8.5-9.5A.75.75 0 0017.25 8h-6.572l1.305-6.093z\"\n          ></path>\n        </svg>\n      </button>\n    </div>\n    <Repl\n      :store=\"store\"\n      :editor=\"editor\"\n      :show-ts-config=\"false\"\n      :showCompileOutput=\"false\"\n      :ssr=\"false\"\n      :showImportMap=\"false\"\n      :class=\"{ 'no-files': files.length <= 1, 'is-fullscreen': isFullscreen }\"\n    />\n  </div>\n</template>\n\n<style lang=\"postcss\" scoped>\n.vue-repl {\n  @apply flex-grow;\n  --bg: #e8e8e8 !important;\n  --bg-soft: #e8e8e8 !important;\n  --border: hsl(0 0% 74%) !important;\n  --text-light: #000 !important;\n  --color-branding: #009f53 !important;\n  --color-branding-dark: #009f53 !important;\n\n  &:deep(iframe) {\n    margin: 0;\n  }\n\n  &:deep(.wrapper) {\n    &:has(.toggle) {\n      @apply hidden;\n    }\n  }\n\n  &:deep(.stretch) {\n    @apply items-stretch;\n  }\n\n  &:deep(.right) {\n    height: unset;\n\n    .active {\n      @apply border-none;\n    }\n  }\n\n  &:deep(.add) {\n    @apply hidden;\n  }\n\n  &:deep(.right .tab-buttons) {\n    @apply invisible;\n  }\n\n  &:deep(.output-container) {\n    @apply h-full;\n  }\n\n  &:deep(.editor-container) {\n    @apply h-full;\n  }\n\n  &.no-files {\n    &:deep(.file-selector) {\n      @apply hidden;\n    }\n  }\n\n  &:deep(.file .remove) {\n    @apply hidden;\n  }\n\n  &:deep(.CodeMirror) {\n    background-color: #f6f6f6;\n    color: var(--symbols);\n    --symbols: #2c3e50;\n    --base: #2c3e50;\n    --comment: #848486;\n    --keyword: #b2085f;\n    --string: #0a7a34;\n    --variable: #c25205;\n    --number: #9580ff;\n    --tags: #b2085f;\n    --brackets: var(--symbols);\n    --property: var(--symbols);\n    --attribute: #c25205;\n    --cursor: #fff;\n    --selected-bg: #454158;\n    --selected-bg-non-focus: rgba(255, 255, 255, 0.15);\n  }\n\n  &:deep(.CodeMirror-scroll) {\n    max-height: 500px;\n  }\n\n  &.is-fullscreen {\n    &:deep(.CodeMirror-scroll) {\n      max-height: unset;\n    }\n  }\n}\n\n.dark {\n  .vue-repl {\n    --bg: #1c1c21 !important;\n    --bg-soft: hsl(240 6% 9%) !important;\n    --border: #333 !important;\n    --text-light: #aaa !important;\n    --color-branding: #06d77b !important;\n    --color-branding-dark: #06d77b !important;\n\n    &:deep(.CodeMirror) {\n      color: var(--symbols);\n      background-color: #1c1c21;\n      --symbols: #f8f8f2;\n      --base: #f8f8f2;\n      --comment: #7970a9;\n      --keyword: #ff80bf;\n      --string: #ffff80;\n      --variable: #8aff80;\n      --number: #9580ff;\n      --tags: #ff80bf;\n      --brackets: var(--symbols);\n      --property: var(--symbols);\n      --attribute: #8aff80;\n      --cursor: #fff;\n      --selected-bg: #454158;\n      --selected-bg-non-focus: rgba(255, 255, 255, 0.15);\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/SideMenu.vue",
    "content": "<template>\n  <transition name=\"slide\">\n    <div v-if=\"modelValue\" class=\"SideMenu lg:hidden\">\n      <DocMenu :menu=\"menu\" :current-url=\"currentUrl\" />\n    </div>\n  </transition>\n</template>\n\n<script setup lang=\"ts\">\nimport { watch } from 'vue';\nimport DocMenu from '@/components/DocMenu.vue';\n\nconst props = defineProps<{\n  modelValue: boolean;\n  menu: { title: string; pages: any[] }[];\n  currentUrl: string;\n}>();\n\nwatch(\n  () => props.modelValue,\n  val => {\n    document.body.classList.toggle('overflow-hidden', val);\n  }\n);\n</script>\n\n<style lang=\"postcss\" scoped>\n.SideMenu {\n  @apply fixed h-screen w-screen inset-0 z-20 overflow-y-auto bg-white dark:bg-dark dark:text-white text-dark flex flex-col overflow-hidden;\n}\n\n@screen motion {\n  .slide-enter-active,\n  .slide-leave-active {\n    transition: transform 0.25s ease-in-out, opacity 0.25s ease-in-out;\n  }\n  .slide-enter,\n  .slide-leave-to {\n    opacity: 0;\n    transform: translate3d(100%, 0, 0);\n  }\n}\n\nnav {\n  a {\n    transition: color 0.3s ease-in-out;\n\n    &::-moz-focus-inner {\n      border: 0;\n    }\n\n    &:hover {\n      @apply text-accent-800;\n    }\n\n    &:focus {\n      @apply text-accent-800;\n      outline: 2px dotted currentColor;\n      outline-offset: 2px;\n    }\n\n    &::after {\n      @apply absolute inset-0 w-full h-full;\n      border: 6px solid transparent;\n      transition: border-color 0.3s ease-in-out;\n      content: '';\n    }\n\n    &.active {\n      &::after {\n        transition: border-color 0.3s ease-in-out;\n\n        @apply border-accent-800;\n      }\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/SideMenuButton.vue",
    "content": "<template>\n  <button\n    @click=\"$emit('update:modelValue', !modelValue)\"\n    class=\"burger burger-squeeze\"\n    aria-label=\"Menu\"\n    :class=\"{ open: modelValue }\"\n  >\n    <div class=\"burger-lines\"></div>\n  </button>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps({\n  modelValue: {\n    type: Boolean,\n    required: true,\n  },\n});\n</script>\n\n<style lang=\"postcss\" scoped>\n.burger {\n  height: 3em;\n  width: 3em;\n  font-size: 12px;\n  cursor: pointer;\n  -webkit-transition: 0.2s all;\n  -o-transition: 0.2s all;\n  transition: 0.2s all;\n  -webkit-tap-highlight-color: transparent;\n  &:focus {\n    outline: none;\n  }\n}\n.burger .burger-lines:after {\n  left: 0;\n  top: -1em;\n}\n.burger .burger-lines:before {\n  left: 1em;\n  top: 1em;\n}\n.burger:after {\n  content: '';\n  display: block;\n  position: absolute;\n  height: 150%;\n  width: 150%;\n  top: -25%;\n  left: -25%;\n}\n.burger .burger-lines {\n  top: 50%;\n  margin-top: -0.125em;\n}\n.burger .burger-lines,\n.burger .burger-lines:after,\n.burger .burger-lines:before {\n  pointer-events: none;\n  display: block;\n  content: '';\n  width: 100%;\n  border-radius: 0.25em;\n  background-color: #000;\n  height: 0.25em;\n  position: absolute;\n  -webkit-transform: rotate(0);\n  -ms-transform: rotate(0);\n  transform: rotate(0);\n}\n\n.dark {\n  .burger .burger-lines,\n  .burger .burger-lines:after,\n  .burger .burger-lines:before {\n    background-color: #fff;\n  }\n}\n\n.burger .burger-lines:after {\n  left: 0;\n  top: -1em;\n}\n.burger .burger-lines:before {\n  left: 1em;\n  top: 1em;\n}\n\n.burger.burger-squeeze .burger-lines:after,\n.burger.burger-squeeze .burger-lines:before {\n  width: 2em;\n}\n\n@screen motion {\n  .burger.burger-squeeze .burger-lines,\n  .burger.burger-squeeze .burger-lines:after,\n  .burger.burger-squeeze .burger-lines:before {\n    -webkit-transition:\n      0.2s top 0.2s,\n      0.1s left,\n      0.2s transform,\n      0.4s background-color 0.2s;\n    -o-transition:\n      0.2s top 0.2s,\n      0.1s left,\n      0.2s transform,\n      0.4s background-color 0.2s;\n    transition:\n      0.2s top 0.2s,\n      0.1s left,\n      0.2s transform,\n      0.4s background-color 0.2s;\n  }\n\n  .burger.burger-squeeze.open .burger-lines,\n  .burger.burger-squeeze.open .burger-lines:after,\n  .burger.burger-squeeze.open .burger-lines:before {\n    -webkit-transition:\n      0.2s background-color,\n      0.2s top,\n      0.2s left,\n      0.2s transform 0.15s;\n    -o-transition:\n      0.2s background-color,\n      0.2s top,\n      0.2s left,\n      0.2s transform 0.15s;\n    transition:\n      0.2s background-color,\n      0.2s top,\n      0.2s left,\n      0.2s transform 0.15s;\n  }\n}\n.burger.burger-squeeze.open .burger-lines {\n  background-color: transparent;\n}\n\n.burger.burger-squeeze.open .burger-lines:before,\n.burger.burger-squeeze.open .burger-lines:after {\n  left: 0.5em;\n  top: 0px;\n}\n\n.burger.burger-squeeze.open .burger-lines:before {\n  -webkit-transform: rotate(-45deg);\n  -ms-transform: rotate(-45deg);\n  transform: rotate(-45deg);\n}\n\n.burger.burger-squeeze.open .burger-lines:after {\n  -webkit-transform: rotate(45deg);\n  -ms-transform: rotate(45deg);\n  transform: rotate(45deg);\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/SiteHead.astro",
    "content": "---\nimport { generateLinks, generateMetaTags, generateSocialImage } from '@/utils/seo';\nimport config from '@/config';\n\nconst { frontmatter } = Astro.props;\n\nconst title = frontmatter?.title || 'VeeValidate: Painless Vue.js forms';\nconst description = frontmatter?.description || 'Painless Vue.js forms';\nconst path = frontmatter?.url || '/v5/';\nconst image = generateSocialImage({\n  title: title,\n  tagline: description,\n  imagePublicID: 'open-source/vee-validate-share.png',\n});\n\nconst metaTags = generateMetaTags({\n  title,\n  description,\n  url: `${config.appURL}${path}`,\n  image,\n});\n\nconst links = generateLinks({\n  url: `${config.appURL}${path}`,\n});\n---\n\n<head>\n  <title>{title}</title>\n  <meta charset=\"utf-8\" />\n  <link rel=\"icon\" type=\"image/x-icon\" href=\"/v5/img/favicon.ico\" />\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, viewport-fit=cover\" />\n  {metaTags.map(t => <meta content={t.content} name={t.name} property={t.property} />)}\n  {links.map(t => <link href={t.href} rel={t.rel} />)}\n  <script is:inline src=\"/v5/loadTheme.js\"></script>\n  <script type=\"text/partytown\" src=\"https://www.googletagmanager.com/gtag/js?id=G-T7VXTJ0MFH\"></script>\n  <script type=\"text/partytown\">\n    window.dataLayer = window.dataLayer || [];\n    function gtag() {\n      dataLayer.push(arguments);\n    }\n    gtag('js', new Date());\n\n    gtag('config', 'G-T7VXTJ0MFH');\n  </script>\n  <script async src=\"https://media.bitterbrains.com/main.js?from=AWADDEV&type=top\"></script>\n</head>\n"
  },
  {
    "path": "docs/src/components/SponsorButton.vue",
    "content": "<template>\n  <a\n    target=\"_blank\"\n    rel=\"noopener\"\n    href=\"https://github.com/sponsors/logaretm\"\n    class=\"flex items-center group text-white bg-pink-600 rounded-md shadow hover:bg-pink-700 focus:ring focus:ring-pink-500 focus:outline-none\"\n    :class=\"{ 'px-3.5 py-1': !size || size === 'sm', 'px-5 py-2.5': size === 'lg' }\"\n  >\n    <svg\n      class=\"stroke-current transform transition duration-200 group-hover:scale-110\"\n      :class=\"{ 'w-5 h-5': !size || size === 'sm', 'w-6 h-6': size === 'lg' }\"\n      fill=\"none\"\n      viewBox=\"0 0 24 24\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        stroke-linecap=\"round\"\n        stroke-linejoin=\"round\"\n        stroke-width=\"2\"\n        d=\"M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z\"\n      ></path>\n    </svg>\n\n    <span class=\"ml-1 font-display\" :class=\"{ 'text-sm': !size || size === 'sm', 'font-medium': size === 'lg' }\"\n      >Sponsor</span\n    >\n  </a>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps<{\n  size?: 'sm' | 'lg';\n}>();\n</script>\n"
  },
  {
    "path": "docs/src/components/SpriteSheet.astro",
    "content": "---\nconst iconModules = import.meta.env.DEV ? await import.meta.glob('../icons/*.svg', { as: 'raw' }) : {};\n\nconst icons = import.meta.env.DEV\n  ? await Promise.all(\n      Object.keys(iconModules).map(k => {\n        return iconModules[k]().then(content => {\n          const id = k.split('/').pop().split('.').shift();\n\n          return content.replace('<svg', `<symbol id=\"icon-${id}\"`).replace('</svg>', '</symbol>');\n        });\n      })\n    )\n  : [];\n---\n\n{\n  import.meta.env.DEV && (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" class=\"hidden\">\n      {icons.map(icon => {\n        return <Fragment set:html={icon} />;\n      })}\n    </svg>\n  )\n}\n"
  },
  {
    "path": "docs/src/components/StarCount.vue",
    "content": "<template>\n  <a\n    href=\"https://github.com/logaretm/vee-validate/stargazers\"\n    target=\"_blank\"\n    rel=\"noopener\"\n    class=\"flex items-center text-xs font-bold font-body border-2 text-zinc-400 border-zinc-400 rounded-full px-3 py-1.5 hover:border-emerald-500 hover:text-emerald-500 select-none transition-colors duration-300\"\n  >\n    <Icon name=\"star\" class=\"w-4 h-4 mr-1\" />\n    {{ format(count) }}\n  </a>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, ref } from 'vue';\nimport Icon from '@/components/Icon.vue';\nimport { fetchStarCount } from '@/utils/github';\n\nconst props = defineProps<{\n  initialCount?: number;\n}>();\n\nfunction format(number: number) {\n  return number.toLocaleString();\n}\n\nconst count = ref(props.initialCount || 10000);\n\nonMounted(async () => {\n  count.value = (await fetchStarCount()) || count.value;\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/TheHeader.vue",
    "content": "<template>\n  <header class=\"pt-3 pb-3 sticky top-0 dark:bg-gray-700 bg-white z-20 border-b dark:border-gray-600 border-gray-200\">\n    <div\n      class=\"px-4 lg:px-8 py-2 lg:py-0 text-sm lg:text-base w-full text-black bg-warning fixed font-bold bottom-0 lg:top-0 lg:h-10 flex items-center\"\n      v-if=\"displayWarning\"\n    >\n      <p class=\"ml-auto\">\n        ⛔️ HEADS UP: You are viewing the documentation for v4.x (Vue 3.0) For Vue 2.x head over to\n        <a href=\"https://vee-validate.logaretm.com/v3/\" class=\"underline\"> v3.x documentation</a>\n      </p>\n      <button class=\"ml-auto\" title=\"close warning\" @click=\"hideWarning\">\n        <svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n          <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"></path>\n        </svg>\n      </button>\n    </div>\n\n    <svg style=\"width: 0; height: 0; position: absolute\" aria-hidden=\"true\" focusable=\"false\">\n      <linearGradient id=\"logo-fill\" x2=\"1\" y2=\"1\">\n        <stop offset=\"0\" stop-color=\"#06d77b\"></stop>\n        <stop offset=\"1\" stop-color=\"#009f53\"></stop>\n      </linearGradient>\n    </svg>\n\n    <div class=\"flex items-center header__content px-6 lg:px-10\" :class=\"{ 'lg:mt-8': displayWarning }\">\n      <a class=\"mr-auto flex items-center\" href=\"/v5/\">\n        <Icon name=\"logo\" class=\"h-8 w-8 lg:w-10 lg:h-10 logo\" />\n\n        <span\n          class=\"ml-2 font-display text-xl bg-clip-text bg-gradient-to-r from-emerald-400 to-emerald-500 text-transparent font-semibold\"\n          >VeeValidate</span\n        >\n      </a>\n\n      <SideMenuButton class=\"ml-auto block lg:hidden relative z-30\" v-model=\"isMenuOpen\" />\n      <SideMenu v-model=\"isMenuOpen\" :menu=\"menu\" :current-url=\"currentUrl\" />\n\n      <VersionSwitcher />\n\n      <a\n        href=\"https://github.com/logaretm/vee-validate/\"\n        target=\"_blank\"\n        rel=\"noopener\"\n        class=\"ml-4 transition-opacity opacity-50 dark:text-white hover:opacity-100 text-gray-700 duration-200 hidden lg:block\"\n      >\n        <Icon name=\"github\" class=\"fill-current w-5 h-5\" />\n      </a>\n\n      <ThemeSwitcher class=\"ml-4 hidden lg:flex\" />\n    </div>\n  </header>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, ref } from 'vue';\nimport SideMenuButton from '@/components/SideMenuButton.vue';\nimport Icon from '@/components/Icon.vue';\nimport ThemeSwitcher from '@/components/ThemeSwitcher.vue';\nimport SideMenu from '@/components/SideMenu.vue';\nimport VersionSwitcher from '@/components/VersionSwitcher.vue';\n\nconst props = defineProps<{\n  menu: { title: string; pages: any[] }[];\n  currentUrl: string;\n}>();\n\nconst isMenuOpen = ref(false);\nconst displayWarning = ref(false);\n\nonMounted(() => {\n  displayWarning.value = !localStorage.getItem('hide_version_warning');\n});\n\nfunction hideWarning() {\n  displayWarning.value = false;\n  localStorage.setItem('hide_version_warning', '1');\n}\n</script>\n\n<style lang=\"postcss\" scoped>\n.header__content {\n  max-width: 1300px;\n  @apply mx-auto;\n}\n\n.logo {\n  fill: url(#logo-fill) #06d77b;\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/ThemeSwitcher.vue",
    "content": "<template>\n  <button class=\"opacity-50 transition-opacity duration-200 hover:opacity-100\" @click=\"isDark = !isDark\">\n    <transition name=\"popup\" mode=\"out-in\">\n      <Icon v-if=\"isDark\" name=\"dark\" class=\"w-6 h-6 fill-current text-white\" />\n      <Icon v-else name=\"light\" class=\"w-6 h-6 fill-current text-dark\" />\n    </transition>\n  </button>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, ref, watch } from 'vue';\nimport Icon from '@/components/Icon.vue';\n\nconst isDark = ref(false);\nwatch(isDark, val => {\n  document.documentElement.classList.toggle('dark', val);\n  localStorage.setItem('theme', val ? 'dark' : 'light');\n});\n\nonMounted(() => {\n  const themeSetting = localStorage.getItem('theme');\n  isDark.value = themeSetting === 'dark';\n});\n</script>\n\n<style lang=\"postcss\" scoped>\nbutton {\n  @apply outline-none items-center justify-center relative;\n  min-width: 24px;\n  min-height: 24px;\n}\n\nsvg {\n  @apply absolute;\n}\n\n@screen motion {\n  .popup-enter-active,\n  .popup-leave-active {\n    transition: transform 0.5s ease-in-out, opacity 0.3s ease-in-out;\n  }\n\n  .popup-enter,\n  .popup-leave-to {\n    transform: translate3d(0, -50px, 0);\n    opacity: 0;\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/UiLibraries.vue",
    "content": "<template>\n  <div class=\"grid grid-flow-col justify-center content-center py-8 gap-10\">\n    <div v-for=\"lib in libraries\" :key=\"lib.name\">\n      <a :href=\"lib.link\" :title=\"lib.name\" target=\"_blank\" rel=\"noopener\">\n        <img :src=\"lib.logoLight\" loading=\"lazy\" class=\"dark:hidden w-24 h-24\" :alt=\"lib.name\" />\n        <img :src=\"lib.logoDark\" loading=\"lazy\" class=\"hidden dark:block w-24 h-24\" :alt=\"lib.name\" />\n      </a>\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nconst libraries = [\n  {\n    name: 'Shadcn Vue',\n    link: 'https://www.shadcn-vue.com/docs/components/form',\n    logoLight: '/v5/img/shadcn.svg',\n    logoDark: '/v5/img/shadcn.svg',\n  },\n  {\n    name: 'Vuetify',\n    link: 'https://vuetifyjs.com/en/components/forms/#vee-validate',\n    logoLight: 'https://cdn.vuetifyjs.com/docs/images/logos/vuetify-logo-v3-light.svg',\n    logoDark: 'https://cdn.vuetifyjs.com/docs/images/logos/vuetify-logo-v3-light.svg',\n  },\n];\n</script>\n"
  },
  {
    "path": "docs/src/components/VersionSwitcher.vue",
    "content": "<template>\n  <FloatingMenu>\n    <template #trigger=\"{ toggle, isOpen }\">\n      <button\n        type=\"button\"\n        @click=\"toggle\"\n        class=\"group hidden lg:flex items-center text-sm font-semibold text-gray-400 hover:text-gray-500 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 px-2 py-1 rounded-md font-display\"\n        :class=\"{ 'bg-gray-200 text-gray-500 dark:bg-gray-600 dark:text-gray-400': isOpen }\"\n      >\n        {{ versions[0].text }}\n        <svg class=\"ml-2 fill-current h-4 w-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\">\n          <path d=\"M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z\"></path>\n        </svg>\n      </button>\n    </template>\n\n    <template #menu>\n      <ul class=\"text-sm space-y-1\">\n        <li\n          v-for=\"(version, idx) in versions\"\n          :key=\"idx\"\n          @click=\"onChange(version)\"\n          class=\"hover:bg-gray-200 hover:dark:bg-gray-500 hover:dark:text-white cursor-pointer select-none px-2 py-1 rounded-md text-gray-600 dark:text-gray-200 font-semibold font-display\"\n        >\n          <div class=\"flex items-center\">\n            <span class=\"text-sm\"> {{ version.text }}</span>\n            <span class=\"ml-3 text-xs text-gray-400\">Vue {{ version.vueVersion }}</span>\n          </div>\n        </li>\n      </ul>\n    </template>\n  </FloatingMenu>\n</template>\n\n<script setup lang=\"ts\">\nimport FloatingMenu from '@/components/FloatingMenu.vue';\n\nconst versions = [\n  {\n    text: 'v5.x',\n    vueVersion: '3.x',\n    link: 'https://vee-validate.logaretm.com/v5/',\n  },\n  {\n    text: 'v4.x',\n    vueVersion: '3.x',\n    link: 'https://vee-validate.logaretm.com/v4/',\n  },\n  {\n    text: 'v3.x',\n    vueVersion: '2.x',\n    link: 'https://vee-validate.logaretm.com/v3/',\n  },\n  {\n    text: 'v2.x',\n    vueVersion: '2.x',\n    link: 'https://vee-validate.logaretm.com/v2/',\n  },\n];\n\nfunction onChange(version: (typeof versions)[0]) {\n  window.location.href = version.link;\n}\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/ComponentsBasic.vue",
    "content": "<script setup>\nimport { Field, Form, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().email().required(),\n  password: yup.string().min(6).required(),\n});\n\nfunction onSubmit(values) {\n  alert(JSON.stringify(values, null, 2));\n}\n</script>\n\n<template>\n  <Form :validation-schema=\"schema\" @submit=\"onSubmit\">\n    <Field name=\"email\" type=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" type=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionBasic.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().email().required(),\n  password: yup.string().min(6).required(),\n});\n\nconst { defineField, errors, handleSubmit } = useForm({\n  validationSchema: schema,\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n</script>\n\n<template>\n  <form @submit=\"onSubmit\">\n    <input v-model=\"email\" v-bind=\"emailAttrs\" name=\"email\" type=\"email\" />\n    <span>{{ errors.email }}</span>\n\n    <input v-model=\"password\" v-bind=\"passwordAttrs\" name=\"password\" type=\"password\" />\n    <span>{{ errors.password }}</span>\n\n    <button>Submit</button>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionComponentBindsBasic01.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport CustomInput from './CustomInput.vue';\n\nconst { values, defineField } = useForm();\n\nconst [email, emailProps] = defineField('email');\n</script>\n\n<template>\n  <CustomInput v-model=\"email\" v-bind=\"emailProps\" />\n\n  <pre>values: {{ values }}</pre>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionComponentBindsBasic02.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\nimport CustomInput from './CustomInput.vue';\n\nconst { values, errors, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n  }),\n});\n\nconst [email, emailProps] = defineField('email');\n</script>\n\n<template>\n  <CustomInput v-model=\"email\" v-bind=\"emailProps\" />\n\n  <pre>errors: {{ errors }}</pre>\n  <pre>values: {{ values }}</pre>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionComponentBindsBasic03.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\nimport CustomInput from './CustomInput.vue';\n\nconst { values, errors, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n  }),\n});\n\nconst [email, emailProps] = defineField('email', {\n  validateOnModelUpdate: false,\n});\n</script>\n\n<template>\n  <CustomInput v-model=\"email\" v-bind=\"emailProps\" />\n  <div>{{ errors.email }}</div>\n\n  <pre>values: {{ values }}</pre>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionComponentBindsBasic04.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\nimport CustomInput from './CustomInput.vue';\n\nconst { values, errors, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n  }),\n});\n\nconst [email, emailProps] = defineField('email', {\n  props: state => ({\n    error: state.errors[0],\n  }),\n});\n</script>\n\n<template>\n  <CustomInput v-model=\"email\" v-bind=\"emailProps\" />\n\n  <pre>values: {{ values }}</pre>\n  <pre>errors: {{ errors }}</pre>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionComponentBindsBasic05.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { values, errors, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email', state => {\n  return {\n    // validate aggressively as long as there are errors on the input\n    validateOnModelUpdate: state.errors.length > 0,\n  };\n});\n</script>\n\n<template>\n  <input v-model=\"email\" v-bind=\"emailAttrs\" />\n  <div>{{ errors.email }}</div>\n\n  <pre>values: {{ values }}</pre>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionCustomField01.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\">\n    <InputText name=\"firstName\" />\n    <InputText name=\"lastName\" />\n    <InputText name=\"email\" type=\"email\" />\n    <InputText name=\"password\" type=\"password\" />\n    <InputText name=\"passwordConfirm\" type=\"password\" />\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\nimport InputText from './InputText.vue';\n\nconst { handleSubmit } = useForm({\n  validationSchema: yup.object({\n    firstName: yup.string().required(),\n    lastName: yup.string().required(),\n    email: yup.string().required().email(),\n    password: yup.string().required().min(6),\n    passwordConfirm: yup\n      .string()\n      .required()\n      .min(6)\n      .oneOf([yup.ref('password')]),\n  }),\n});\n\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionCustomField02.vue",
    "content": "<template>\n  <InputText name=\"email\" type=\"email\" v-model=\"email\" />\n\n  <pre>Model: {{ email }}</pre>\n</template>\n\n<script setup>\nimport { ref } from 'vue';\nimport InputText from './InputText.vue';\n\nconst email = ref('');\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionCustomField03.vue",
    "content": "<template>\n  <InputText name=\"email\" type=\"email\" />\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\nimport InputText from './InputText.vue';\n\nuseForm({\n  validationSchema: yup.object({\n    email: yup.string().required().email(),\n  }),\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionCustomField04.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\">\n    <InputText name=\"firstName\" />\n    <InputText name=\"lastName\" />\n    <InputText name=\"email\" type=\"email\" />\n    <InputText name=\"password\" type=\"password\" />\n    <InputText name=\"passwordConfirm\" type=\"password\" />\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\nimport InputText from './InputText.vue';\n\nconst { handleSubmit } = useForm({\n  validationSchema: yup.object({\n    firstName: yup.string().required().min(1),\n    lastName: yup.string().required().min(2),\n    email: yup.string().required().email(),\n    password: yup.string().required().min(6),\n    passwordConfirm: yup\n      .string()\n      .required()\n      .min(6)\n      .oneOf([yup.ref('password')]),\n  }),\n});\n\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionCustomField05.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\">\n    <InputText name=\"firstName\" />\n    <InputText name=\"lastName\" />\n    <InputText name=\"email\" type=\"email\" />\n    <InputText name=\"password\" type=\"password\" />\n    <InputText name=\"passwordConfirm\" type=\"password\" />\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\nimport InputText from './InputText.vue';\n\nconst { handleSubmit } = useForm({\n  validationSchema: yup.object({\n    firstName: yup.string().required().min(1),\n    lastName: yup.string().required().min(2),\n    email: yup.string().required().email(),\n    password: yup.string().required().min(6),\n    passwordConfirm: yup\n      .string()\n      .required()\n      .min(6)\n      .oneOf([yup.ref('password')]),\n  }),\n});\n\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionCustomFieldCheckbox.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\nimport CustomCheckbox from './CustomCheckbox.vue';\n\nconst { values, errors } = useForm({\n  validationSchema: yup.object({\n    drinks: yup.array().of(yup.string()).min(1, 'Please select at least 1 drink').required(),\n  }),\n});\n</script>\n\n<template>\n  <CustomCheckbox name=\"drinks\" checked-value=\"coffee\" /> Coffee\n\n  <CustomCheckbox name=\"drinks\" checked-value=\"tea\" /> Tea\n\n  <CustomCheckbox name=\"drinks\" checked-value=\"coke\" /> Coke\n\n  <pre>values: {{ values }}</pre>\n  <pre>errors: {{ errors }}</pre>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionDynamicSchemaComputed.vue",
    "content": "<script setup>\nimport { ref, computed } from 'vue';\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst limit = ref(5);\n\nconst { errors, defineField } = useForm({\n  validationSchema: computed(() =>\n    yup.object({\n      content: yup.string().max(limit.value),\n    }),\n  ),\n});\n\nconst [content, contentAttrs] = defineField('content');\n</script>\n\n<template>\n  <input v-model.number=\"limit\" />\n\n  <input v-model=\"content\" v-bind=\"contentAttrs\" />\n  <div>{{ errors.content }}</div>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionDynamicSchemaYupLazy.vue",
    "content": "<script setup>\nimport { ref } from 'vue';\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst limit = ref(5);\n\nconst { errors, defineField } = useForm({\n  validationSchema: yup.lazy(() =>\n    yup.object({\n      content: yup.string().max(limit.value),\n    }),\n  ),\n});\n\nconst [content, contentAttrs] = defineField('content');\n</script>\n\n<template>\n  <input v-model.number=\"limit\" />\n\n  <input v-model=\"content\" v-bind=\"contentAttrs\" />\n  <div>{{ errors.content }}</div>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms01.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { meta, defineField } = useForm();\n\nconst [name, nameAttrs] = defineField('name');\n</script>\n\n<template>\n  <input v-model=\"name\" v-bind=\"nameAttrs\" />\n\n  <button :disabled=\"!meta.touched\">Submit</button>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms02.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { errors, handleSubmit, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n    password: yup.string().min(6).required(),\n  }),\n});\n\n// Creates a submission handler\n// It validate all fields and doesn't call your function unless all fields are valid\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n\n<template>\n  <form @submit=\"onSubmit\">\n    <input type=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n    <div>{{ errors.email }}</div>\n\n    <input type=\"password\" v-model=\"password\" v-bind=\"passwordAttrs\" />\n    <div>{{ errors.password }}</div>\n\n    <button>Submit</button>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms03.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { errors, handleSubmit, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n    password: yup.string().min(6).required(),\n  }),\n});\n\nconst onSubmit = handleSubmit(\n  values => {\n    alert(JSON.stringify(values, null, 2));\n  },\n  ({ errors }) => {\n    const firstError = Object.keys(errors)[0];\n    const el = document.querySelector(`[name=\"${firstError}\"]`);\n    el?.scrollIntoView({\n      behavior: 'smooth',\n    });\n    el.focus();\n  },\n);\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n\n<template>\n  <form @submit=\"onSubmit\">\n    <input v-model=\"email\" v-bind=\"emailAttrs\" name=\"email\" type=\"email\" />\n    <span>{{ errors.email }}</span>\n\n    <input v-model=\"password\" v-bind=\"passwordAttrs\" name=\"password\" type=\"password\" />\n    <span>{{ errors.password }}</span>\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<style>\ninput,\nbutton {\n  margin-top: 300px;\n  display: block;\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms04.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { handleSubmit, defineField, isSubmitting, errors } = useForm();\n\nconst onSubmit = handleSubmit(values => {\n  // Simulates a 2 second delay\n  return new Promise(resolve => {\n    setTimeout(() => {\n      console.log('Submitted', JSON.stringify(values, null, 2));\n      resolve();\n    }, 2000);\n  });\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n\n<template>\n  <form @submit=\"onSubmit\">\n    <input type=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n    <span>{{ errors.email }}</span>\n\n    <input type=\"password\" v-model=\"password\" v-bind=\"passwordAttrs\" />\n    <span>{{ errors.password }}</span>\n\n    <button :disabled=\"isSubmitting\">\n      {{ isSubmitting ? 'Submitting...' : 'Submit' }}\n    </button>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms05.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { handleSubmit, defineField, submitCount, errors } = useForm();\n\nconst onSubmit = handleSubmit(values => {\n  console.log('Submitted', JSON.stringify(values, null, 2));\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n\n<template>\n  <form @submit=\"onSubmit\">\n    <pre>Submit count: {{ submitCount }}</pre>\n\n    <input type=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n    <span>{{ errors.email }}</span>\n\n    <input type=\"password\" v-model=\"password\" v-bind=\"passwordAttrs\" />\n    <span>{{ errors.password }}</span>\n\n    <button :disabled=\"submitCount > 5\">\n      {{ submitCount > 5 ? 'You submitted too many times' : 'Submit' }}\n    </button>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms06.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\">\n    <input type=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n\n    <input type=\"password\" v-model=\"password\" v-bind=\"passwordAttrs\" />\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { handleSubmit, defineField } = useForm({\n  initialValues: {\n    email: 'test@example.com',\n    password: 'p@$$w0rd',\n  },\n});\n\nconst onSubmit = handleSubmit(values => {\n  console.log(JSON.stringify(values, null, 2));\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms07.vue",
    "content": "<template>\n  <input type=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n\n  <input type=\"password\" v-model=\"password\" v-bind=\"passwordAttrs\" />\n\n  <button @click=\"updateValues\">Update values</button>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { defineField, setFieldValue, setValues } = useForm();\n\nfunction updateValues() {\n  // set a single field value\n  // setFieldValue('email', 'test@example.com');\n\n  // set multiple fields values\n  setValues({\n    email: 'test@example.com',\n    password: 'p@$$w0rd',\n  });\n}\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms08.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { resetForm, defineField, meta, errors } = useForm({\n  validationSchema: yup.object({\n    name: yup.string().required(),\n    email: yup.string().email().required(),\n    password: yup.string().min(6).required(),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [name, nameAttrs] = defineField('name');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n\n<template>\n  <form>\n    <input v-model=\"name\" v-bind=\"nameAttrs\" />\n    {{ errors.name }}\n\n    <input type=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n    {{ errors.email }}\n\n    <input type=\"password\" v-model=\"password\" v-bind=\"passwordAttrs\" />\n    {{ errors.password }}\n\n    <div>\n      <button type=\"button\" @click=\"resetForm()\">Reset</button>\n      <button\n        type=\"button\"\n        @click=\"resetForm({ values: { email: 'test@email.com' }, errors: { password: 'Password taken :-)' } })\"\n      >\n        Reset to specific state\n      </button>\n    </div>\n\n    <pre>{{ meta }}</pre>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms09.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { defineField, errors, handleSubmit } = useForm({\n  validationSchema: yup.object({\n    name: yup.string().required(),\n    email: yup.string().email().required(),\n    password: yup.string().min(6).required(),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [name, nameAttrs] = defineField('name');\nconst [password, passwordAttrs] = defineField('password');\n\nconst onSubmit = handleSubmit((values, { resetForm }) => {\n  console.log(values); // send data to API\n  // reset the form and the field values to their initial values\n  resetForm();\n});\n</script>\n\n<template>\n  <form @submit=\"onSubmit\">\n    <input v-model=\"name\" v-bind=\"nameAttrs\" />\n    {{ errors.name }}\n\n    <input type=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n    {{ errors.email }}\n\n    <input type=\"password\" v-model=\"password\" v-bind=\"passwordAttrs\" />\n    {{ errors.password }}\n\n    <button>Submit</button>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms10.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { defineField, errorBag } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required().min(6),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\n</script>\n\n<template>\n  <form @submit=\"onSubmit\">\n    <input v-model=\"email\" v-bind=\"emailAttrs\" />\n    {{ errorBag.email }}\n\n    <button>Submit</button>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms11.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\">\n    <input type=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n    {{ errors.email }}\n\n    <input type=\"password\" v-model=\"password\" v-bind=\"passwordAttrs\" />\n    {{ errors.password }}\n\n    <button>Login</button>\n  </form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { defineField, handleSubmit, errors, setFieldError } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n    password: yup.string().min(6).required(),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n\nconst onSubmit = handleSubmit((values, { setFieldError }) => {\n  console.log(values); // send data to API\n\n  // Set errors on Fields\n  setFieldError('email', 'Incorrect credentials');\n  setFieldError('password', 'Incorrect credentials');\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms12.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst initialUserData = {\n  id: 1,\n  name: '',\n  address: '',\n  createdAt: Date.now(),\n};\n\nconst { defineField, handleSubmit } = useForm({\n  initialValues: initialUserData,\n});\n\nconst [name, nameAttrs] = defineField('name');\nconst [address, addressAttrs] = defineField('address');\n\nconst onSubmit = handleSubmit.withControlled(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n</script>\n\n<template>\n  <form @submit=\"onSubmit\">\n    <input name=\"name\" v-model=\"name\" v-bind=\"nameAttrs\" />\n\n    <textarea name=\"address\" v-model=\"address\" v-bind=\"addressAttrs\"></textarea>\n\n    <button>Submit</button>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms13.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { errors, submitForm, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n    password: yup.string().min(6).required(),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n\n<template>\n  <form action=\"/v5/submit-target/\" method=\"get\" target=\"_blank\" @submit=\"submitForm\">\n    <input name=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n    <span>{{ errors.email }}</span>\n\n    <input name=\"password\" v-model=\"password\" v-bind=\"passwordAttrs\" />\n    <span>{{ errors.password }}</span>\n\n    <button>Submit</button>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionHandlingForms14.vue",
    "content": "<script setup>\nimport { onMounted } from 'vue';\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\n/**\n * Simulate fetching data from an API\n */\nasync function fetchData() {\n  return new Promise(resolve => {\n    setTimeout(() => {\n      resolve({\n        name: 'John Doe',\n        email: 'test@email.com',\n      });\n    }, 1500);\n  });\n}\n\nconst { errors, resetForm, handleSubmit, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n    name: yup.string().required(),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [name, nameAttrs] = defineField('name');\n\n// Fetch data on mounted\nonMounted(async () => {\n  const data = await fetchData();\n\n  resetForm({ values: data });\n});\n\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n</script>\n\n<template>\n  <form @submit=\"onSubmit\">\n    <input name=\"email\" v-model=\"email\" v-bind=\"emailAttrs\" />\n    <span>{{ errors.email }}</span>\n\n    <input name=\"name\" v-model=\"name\" v-bind=\"nameAttrs\" />\n    <span>{{ errors.name }}</span>\n\n    <button>Submit</button>\n  </form>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionInputBindsBasic01.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { values, defineField } = useForm();\n\nconst [email, emailAttrs] = defineField('email');\n</script>\n\n<template>\n  <input v-model=\"email\" v-bind=\"emailAttrs\" type=\"text\" />\n\n  <pre>values: {{ values }}</pre>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionInputBindsBasic02.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { values, errors, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\n</script>\n\n<template>\n  <input v-model=\"email\" v-bind=\"emailAttrs\" />\n\n  <pre>values: {{ values }}</pre>\n  <pre>errors: {{ errors }}</pre>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionInputBindsBasic03.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { values, errors, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email', {\n  validateOnModelUpdate: false,\n});\n</script>\n\n<template>\n  <input v-model=\"email\" v-bind=\"emailAttrs\" />\n\n  <pre>values: {{ values }}</pre>\n  <pre>errors: {{ errors }}</pre>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionInputFieldFn.vue",
    "content": "<template>\n  <input type=\"text\" v-model=\"value\" />\n  {{ errorMessage }}\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\nimport * as yup from 'yup';\n\nfunction isEmail(value) {\n  return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value) ? true : 'Must be a valid email';\n}\n\nconst { value, errorMessage } = useField('email', isEmail);\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionInputFieldValibot.vue",
    "content": "<template>\n  <input type=\"text\" v-model=\"value\" />\n  {{ errorMessage }}\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\nimport * as v from 'valibot';\n\nconst { value, errorMessage } = useField('email', v.pipe(v.string(), v.email('Invalid email'), v.nonEmpty('Required')));\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionInputFieldYup.vue",
    "content": "<template>\n  <input type=\"text\" v-model=\"value\" />\n  {{ errorMessage }}\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { value, errorMessage } = useField('email', yup.string().email().required());\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionInputFieldZod.vue",
    "content": "<template>\n  <input type=\"text\" v-model=\"value\" />\n  {{ errorMessage }}\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\nimport { z } from 'zod';\n\nconst { value, errorMessage } = useField('email', z.string().email().min(1, 'Required'));\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionNested01.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\">\n    <input v-model=\"twitter\" type=\"url\" placeholder=\"twitter\" />\n    <input v-model=\"github\" type=\"url\" placeholder=\"github\" />\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { handleSubmit, defineField } = useForm();\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n\nconst [twitter] = defineField('links.twitter');\nconst [github] = defineField('links.github');\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionNested02.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\">\n    <input v-model=\"twitter\" type=\"url\" placeholder=\"twitter\" />\n    <input v-model=\"github\" type=\"url\" placeholder=\"github\" />\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { handleSubmit, defineField } = useForm();\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n\nconst [twitter] = defineField('links[0]');\nconst [github] = defineField('links[1]');\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionNested03.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\">\n    <input v-model=\"twitter\" type=\"url\" placeholder=\"twitter\" />\n    <input v-model=\"github\" type=\"url\" placeholder=\"github\" />\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { useField, useForm } from 'vee-validate';\n\nconst { handleSubmit, defineField } = useForm();\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n\nconst [twitter] = defineField('[links.twitter]');\nconst [github] = defineField('[links.github]');\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionNested04.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\" novalidate>\n    <div v-for=\"(field, idx) in fields\" :key=\"field.key\">\n      <input v-model=\"field.value\" type=\"url\" />\n\n      <button type=\"button\" @click=\"remove(idx)\">Remove</button>\n    </div>\n\n    <button type=\"button\" @click=\"push('')\">Add</button>\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { useForm, useFieldArray } from 'vee-validate';\n\nconst { handleSubmit } = useForm({\n  initialValues: {\n    links: ['https://github.com/logaretm'],\n  },\n});\n\nconst { remove, push, fields } = useFieldArray('links');\n\nconst onSubmit = handleSubmit(values => {\n  console.log(JSON.stringify(values, null, 2));\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionNested05.vue",
    "content": "<template>\n  <form @submit=\"onSubmit\">\n    <input v-model=\"name\" v-bind=\"nameAttrs\" />\n    <span>{{ errors['user.name'] }}</span>\n    <input v-model=\"address\" v-bind=\"addressAttrs\" />\n    <span>{{ errors['user.addresses[0]'] }}</span>\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { useField, useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { handleSubmit, errors, defineField } = useForm({\n  validationSchema: yup.object({\n    user: yup.object({\n      name: yup.string().required(),\n      addresses: yup.array().of(yup.string().required()),\n    }),\n  }),\n});\n\nconst [name, nameAttrs] = defineField('user.name');\nconst [address, addressAttrs] = defineField('user.addresses[0]');\n\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionValibotBasic.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as v from 'valibot';\n\nconst { errors, defineField } = useForm({\n  validationSchema: v.object({\n    email: v.pipe(v.string(), v.email('Invalid Email'), v.nonEmpty('Email is required')),\n    password: v.pipe(v.string(), v.minLength(6, 'password too short')),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n\n<template>\n  <input v-model=\"email\" v-bind=\"emailAttrs\" />\n  <div>{{ errors.email }}</div>\n\n  <input v-model=\"password\" v-bind=\"passwordAttrs\" />\n  <div>{{ errors.password }}</div>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionValidateFnBasic.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\n\nfunction isEmail(value) {\n  return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\n}\n\nconst { errors, defineField } = useForm({\n  validationSchema: {\n    email: val => (isEmail(val) ? true : 'Invalid email'),\n  },\n});\n\nconst [email, emailProps] = defineField('email');\n</script>\n\n<template>\n  <input v-model=\"email\" v-bind=\"emailProps\" />\n  <span>{{ errors.email }}</span>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionYupBasic.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { errors, defineField } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n    password: yup.string().min(6).required(),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n\n<template>\n  <input v-model=\"email\" v-bind=\"emailAttrs\" />\n  <div>{{ errors.email }}</div>\n\n  <input v-model=\"password\" v-bind=\"passwordAttrs\" />\n  <div>{{ errors.password }}</div>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CompositionZodBasic.vue",
    "content": "<script setup>\nimport { useForm } from 'vee-validate';\nimport { z } from 'zod';\n\nconst { errors, defineField } = useForm({\n  validationSchema: z.object({\n    email: z.string().min(1).email(),\n    password: z.string().min(6),\n  }),\n});\n\nconst [email, emailAttrs] = defineField('email');\nconst [password, passwordAttrs] = defineField('password');\n</script>\n\n<template>\n  <input v-model=\"email\" v-bind=\"emailAttrs\" />\n  <div>{{ errors.email }}</div>\n\n  <input v-model=\"password\" v-bind=\"passwordAttrs\" />\n  <div>{{ errors.password }}</div>\n</template>\n"
  },
  {
    "path": "docs/src/components/examples/CustomCheckboxInputBasic.vue",
    "content": "<template>\n  <input :value=\"checkedValue\" :checked=\"checked\" @change=\"handleChange\" type=\"checkbox\" />\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\nconst props = defineProps({\n  name: String,\n  checkedValue: String,\n});\n\n// The `name` is returned in a function because we want to make sure it stays reactive\n// If the name changes you want `useField` to be able to pick it up\nconst { handleChange, checked } = useField(() => props.name, undefined, {\n  type: 'checkbox',\n  checkedValue: props.checkedValue,\n});\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CustomInputBasic.vue",
    "content": "<template>\n  <input :value=\"modelValue\" @input=\"$emit('update:modelValue', $event.target.value)\" @blur=\"$emit('blur')\" />\n</template>\n\n<script setup>\nconst props = defineProps({\n  modelValue: String,\n});\n\nconst emit = defineEmits(['update:modelValue', 'blur']);\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CustomInputBasicError.vue",
    "content": "<template>\n  <div>\n    <input :value=\"modelValue\" @input=\"$emit('update:modelValue', $event.target.value)\" @blur=\"$emit('blur')\" />\n    <span>{{ error }}</span>\n  </div>\n</template>\n\n<script setup>\nconst props = defineProps({\n  error: String,\n  modelValue: String,\n});\n\nconst emit = defineEmits(['update:modelValue', 'blur']);\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CustomInputBasicValueEvent.vue",
    "content": "<template>\n  <input :value=\"value\" @input=\"$emit('update:value', $event.target.value)\" @blur=\"$emit('blur')\" />\n</template>\n\n<script setup>\nconst props = defineProps({\n  value: String,\n});\n\nconst emit = defineEmits(['update:value', 'blur']);\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CustomInputFieldAggressive.vue",
    "content": "<template>\n  <input @input=\"handleChange\" :value=\"value\" type=\"text\" />\n  <span>{{ errorMessage }}</span>\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\nconst props = defineProps({\n  name: String,\n  type: String,\n});\n\nconst { errorMessage, value, handleChange } = useField(() => props.name);\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CustomInputFieldBasic.vue",
    "content": "<template>\n  <input v-model=\"value\" :type=\"type || 'text'\" />\n  {{ errorMessage }}\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\nconst props = defineProps({\n  name: String,\n  type: String,\n});\n\n// The `name` is returned in a function because we want to make sure it stays reactive\n// If the name changes you want `useField` to be able to pick it up\nconst { value, errorMessage } = useField(() => props.name);\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CustomInputFieldEager.vue",
    "content": "<template>\n  <input :value=\"value\" v-on=\"validationListeners\" type=\"text\" />\n  <span>{{ errorMessage }}</span>\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\nconst props = defineProps({\n  name: String,\n  type: String,\n});\n\nconst { errorMessage, value, handleChange, handleBlur } = useField(() => props.name, undefined, {\n  validateOnValueUpdate: false,\n});\n\nconst validationListeners = {\n  blur: evt => handleBlur(evt, true),\n  change: handleChange,\n  input: evt => handleChange(evt, !!errorMessage.value),\n};\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CustomInputFieldMeta.vue",
    "content": "<template>\n  <div class=\"input-field\">\n    <input\n      :value=\"value\"\n      :type=\"type || 'text'\"\n      :class=\"{ dirty: meta.dirty, valid: meta.touched && meta.valid, invalid: meta.touched && !meta.valid }\"\n      @change=\"handleChange\"\n      @blur=\"handleBlur\"\n    />\n    <span>{{ errorMessage }}</span>\n  </div>\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\nconst props = defineProps({\n  name: String,\n  type: String,\n});\n\n// The `name` is returned in a function because we want to make sure it stays reactive\n// If the name changes you want `useField` to be able to pick it up\nconst { handleChange, value, handleBlur, errorMessage, meta } = useField(() => props.name, undefined);\n</script>\n\n<style scoped>\n.input-field {\n  font-size: 14px;\n}\n\ninput {\n  display: block;\n}\n\ninput.valid {\n  border-color: #41b883;\n}\n\ninput.invalid {\n  border-color: #e74c3c;\n}\n\ninput.dirty::after {\n  content: '*';\n  color: cadetblue;\n}\n\n.error {\n  color: red;\n  display: block;\n}\n</style>\n"
  },
  {
    "path": "docs/src/components/examples/CustomInputFieldMultiErrors.vue",
    "content": "<template>\n  <input v-model=\"value\" :type=\"type || 'text'\" />\n  <ul v-if=\"errors.length\">\n    <li v-for=\"error in errors\">{{ error }}</li>\n  </ul>\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\nconst props = defineProps({\n  name: String,\n  type: String,\n});\n\n// The `name` is returned in a function because we want to make sure it stays reactive\n// If the name changes you want `useField` to be able to pick it up\nconst { value, errors } = useField(() => props.name, undefined);\n</script>\n"
  },
  {
    "path": "docs/src/components/examples/CustomInputFieldVModel.vue",
    "content": "<template>\n  <input v-model=\"value\" :type=\"type || 'text'\" />\n  {{ errorMessage }}\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\nconst props = defineProps({\n  name: String,\n  type: String,\n  modelValue: String,\n});\n\n// The `name` is returned in a function because we want to make sure it stays reactive\n// If the name changes you want `useField` to be able to pick it up\nconst { value, errorMessage } = useField(() => props.name, undefined, {\n  syncVModel: true,\n});\n</script>\n"
  },
  {
    "path": "docs/src/config.ts",
    "content": "export default {\n  algolia: {\n    apiKey: '63f5a0934f840b36e5d33af009ddff15',\n    appId: 'F6BYW6NAIH',\n    indexName: 'vee-validate-v4',\n  },\n  appURL: process.env.NODE_ENV === 'production' ? 'https://vee-validate.logaretm.com' : 'http://localhost:3000',\n  gaId: 'UA-100131478-1',\n} as const;\n"
  },
  {
    "path": "docs/src/constants.ts",
    "content": "export const features = [\n  { title: 'Form-level validation', description: '' },\n  { title: 'Field-level validation', description: '' },\n  { title: 'Array fields', description: '' },\n  {\n    title: 'UI Agnostic',\n    description: 'Use any HTML markup, or use any 3rd party components, or bring or build your very own.',\n  },\n  { title: 'Higher-order Components', description: '' },\n  { title: 'Composition API', description: '' },\n  { title: 'Async validators', description: 'Use sync or async validators or a mix of both.' },\n  {\n    title: 'Backend API errors',\n    description: 'The form actions API allow you to easily set form errors from your Backend API, or at any time.',\n  },\n  {\n    title: 'Form Submissions',\n    description: 'Gives you access to both valid and invalid submissions so you can build amazing UX.',\n  },\n  {\n    title: 'Flexible validator API',\n    description:\n      'Use plain JS functions, or Yup or Zod schemas, or use the included validators. The validator API is very flexible and you can integrate any 3rd party validator.',\n  },\n  {\n    title: 'State-store friendly',\n    description: 'Straightforward API that you can use with Pinia or any composition-capable state store.',\n  },\n  {\n    title: 'Vue Devtools integration',\n    description: 'A custom inspector is provided so you can easily debug your from state and submissions.',\n  },\n];\n"
  },
  {
    "path": "docs/src/env.d.ts",
    "content": "/// <reference types=\"astro/client\" />\n"
  },
  {
    "path": "docs/src/integrations/svgSprite.ts",
    "content": "import path from 'path';\nimport { AstroIntegration } from 'astro';\nimport { writeFile } from 'fs-extra';\n\nconst integration: AstroIntegration = {\n  name: 'svgSprite',\n  hooks: {\n    async 'astro:build:done'() {\n      const iconModules = await import.meta.glob('../icons/*.svg', { as: 'raw' });\n\n      const icons = await Promise.all(\n        Object.keys(iconModules).map(k => {\n          return iconModules[k]().then(content => {\n            const id = k.split('/').pop().split('.').shift();\n\n            return content.replace('<svg', `<symbol id=\"icon-${id}\"`).replace('</svg>', '</symbol>');\n          });\n        }),\n      );\n\n      const sprite = `<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" class=\"hidden\">${icons.join(\n        '\\n',\n      )}</svg>`;\n\n      await writeFile(path.join(path.resolve(), '../docs/dist/sprite.svg'), sprite, { encoding: 'utf-8' });\n    },\n  },\n};\n\nexport { integration as svgSprite };\n"
  },
  {
    "path": "docs/src/layouts/HomeLayout.astro",
    "content": "---\nimport TheHeader from '@/components/TheHeader.vue';\nimport SiteHead from '@/components/SiteHead.astro';\nimport Ad from '@/components/Ad.vue';\nimport SpriteSheet from '@/components/SpriteSheet.astro';\nimport '@/styles/tailwind.css';\nimport '@/styles/home.css';\nimport { buildMenu, Frontmatter } from '@/utils/seo';\n\nconst menu = [\n  {\n    title: 'tutorials',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/tutorials/*.mdx')),\n  },\n  {\n    title: 'guide',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/guide/*.mdx')),\n  },\n  {\n    title: 'examples',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/examples/*.mdx')),\n  },\n  {\n    title: 'resources',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/resources.mdx')),\n  },\n  {\n    title: 'integrations',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/integrations/*.mdx')),\n  },\n  {\n    title: 'api reference',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/api/*.mdx')),\n  },\n];\n---\n\n<html lang=\"en\">\n  <SiteHead {...Astro.props} />\n  <body>\n    <SpriteSheet />\n    <TheHeader client:load menu={menu} currentUrl=\"\" />\n    <div class=\"App\">\n      <main class=\"main\">\n        <slot />\n      </main>\n      <Ad client:idle placement=\"home-page\" />\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/src/layouts/PageLayout.astro",
    "content": "---\nimport path from 'path';\nimport SiteHead from '@/components/SiteHead.astro';\nimport Ad from '@/components/Ad.vue';\nimport SpriteSheet from '@/components/SpriteSheet.astro';\nimport TheHeader from '@/components/TheHeader.vue';\nimport EditPage from '@/components/EditPage.vue';\nimport SponsorButton from '@/components/SponsorButton.vue';\nimport DocMenu from '@/components/DocMenu.vue';\nimport DocToc from '@/components/DocToc.vue';\nimport DocNextStep from '@/components/DocNextStep.vue';\nimport DocSearch from '@/components/DocSearch.vue';\nimport ContentWrapper from '@/components/ContentWrapper.vue';\nimport { buildMenu, Frontmatter } from '@/utils/seo';\nimport '@/styles/tailwind.css';\nimport '@/styles/page.css';\n\nconst { headings, frontmatter } = Astro.props;\nconst filePath = path.relative(path.resolve('../'), frontmatter.file);\n\nconst page = frontmatter as Frontmatter;\n\nconst menu = [\n  {\n    title: 'resources',\n    pages: buildMenu([\n      {\n        ...(await Astro.glob<Frontmatter>('../pages/resources.mdx'))[0],\n        icon: 'grid',\n      },\n    ]),\n  },\n  {\n    title: 'tutorials',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/tutorials/*.mdx')),\n  },\n  {\n    title: 'guide',\n    pages: buildMenu([\n      ...(await Astro.glob<Frontmatter>('../pages/guide/*.mdx')),\n      {\n        frontmatter: {\n          order: 2,\n          title: 'Components',\n        },\n        children: await Astro.glob<Frontmatter>('../pages/guide/components/*.mdx'),\n        icon: 'code',\n      },\n      {\n        frontmatter: {\n          order: 3,\n          title: 'Composition API',\n        },\n        children: await Astro.glob<Frontmatter>('../pages/guide/composition-api/*.mdx'),\n        icon: 'grid-add',\n      },\n    ]),\n  },\n  {\n    title: 'examples',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/examples/*.mdx')),\n  },\n  {\n    title: 'integrations',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/integrations/*.mdx')),\n  },\n  {\n    title: 'api reference',\n    pages: buildMenu(await Astro.glob<Frontmatter>('../pages/api/*.mdx')),\n  },\n];\n---\n\n<html lang=\"en\">\n  <SiteHead {...Astro.props} />\n  <body>\n    <SpriteSheet />\n    <TheHeader client:load currentUrl={frontmatter.url} menu={menu} />\n    <div class=\"PageApp\">\n      <main class=\"main\">\n        <ContentWrapper>\n          <slot />\n        </ContentWrapper>\n\n        {page.next && <DocNextStep {...page.next} />}\n\n        <div class=\"mt-20 pt-2 border-t dark:border-gray-600 border-gray-200 flex items-center\">\n          <EditPage path={filePath} />\n\n          <SponsorButton class=\"ml-auto\" />\n        </div>\n      </main>\n\n      <aside class=\"lside hidden lg:block px-5\">\n        <div class=\"sticky top-24\">\n          <DocSearch client:idle />\n          <DocMenu currentUrl={frontmatter.url} menu={menu} client:idle />\n        </div>\n      </aside>\n\n      <aside class=\"rside hidden xl:block\">\n        <div class=\"sticky top-24 flex flex-col\">\n          <div class=\"relative flex-auto\">\n            <div\n              class=\"bg-gradient-to-b from-white dark:from-dark to-transparent h-4 absolute -top-px lg:top-0 inset-x-0\"\n            >\n            </div>\n\n            <DocToc headings={headings} />\n\n            <div\n              class=\"bg-gradient-to-b from-transparent to-white dark:to-dark h-4 absolute -bottom-px lg:bottom-0 inset-x-0\"\n            >\n            </div>\n          </div>\n\n          <Ad client:idle />\n        </div>\n      </aside>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "docs/src/pages/api/composition-helpers.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Composition Helpers\ndescription: Various composable functions to compose validation logic into your components\norder: 9\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport CodeTitle from '@/components/CodeTitle.vue';\n\n# Composition Helpers\n\nThe composition helpers are various functions that you can use to craft specialized form components, like a submission indicator component or a custom error messages component.\n\nThese functions expose validation state to child components, most of these functions expose 2 variants of each state. On a form level and a field level.\n\n## API Reference\n\n<DocTip>\n\nAll of the following code snippets assume you are using them inside a `setup` function.\n\n</DocTip>\n\n<CodeTitle level=\"4\">\n\n`useFieldError(field?: string): ComputedRef<string | undefined>`\n\n</CodeTitle>\n\nReturns a computed ref to a single field's error message, returns `undefined` if no errors were found for that field or if the field does not exist.\n\n```js\nimport { useFieldError } from 'vee-validate';\n\nconst message = useFieldError('fieldName');\n\nmessage.value; // string or `undefined`\n```\n\nYou can also use it in a child component that has a parent that used `useField`, The `useFieldError` will automatically pick up the field and produce its error messages.\n\n```js\nimport { useFieldError } from 'vee-validate';\n\n// Will look for the first parent that used `useField`\nconst message = useFieldError();\nmessage.value;\n```\n\n<CodeTitle level=\"4\">\n\n`useFormErrors(): ComputedRef<Record<string, string | undefined>>`\n\n</CodeTitle>\n\nReturns a computed ref to the error bag of the entire form, fields with no errors will not be included in the error bag object.\n\n```js\nimport { useFormErrors } from 'vee-validate';\n\nconst errors = useFormErrors();\n\nmessage.value; // {}\n```\n\n<CodeTitle level=\"4\">\n\n`useIsFieldDirty(field?: string): ComputedRef<boolean>`\n\n</CodeTitle>\n\nReturns a computed ref to the specified field's `dirty` meta state.\n\n```js\nimport { useIsFieldDirty } from 'vee-validate';\n\nconst isDirty = useIsFieldDirty();\n\nisDirty.value; // true or false\n```\n\nYou can also use it in a child component that has a parent that used `useField`, The `useIsFieldDirty` will automatically pick up the field and produce its meta `dirty` value\n\n```js\nimport { useIsFieldDirty } from 'vee-validate';\n\n// Will look for the first parent that used `useField`\nconst isDirty = useIsFieldDirty();\n```\n\n<CodeTitle level=\"4\">\n\n`useIsFormDirty(): ComputedRef<boolean>`\n\n</CodeTitle>\n\nReturns a computed ref to the context form `dirty` meta state.\n\n```js\nimport { useIsFormDirty } from 'vee-validate';\n\nconst isDirty = useIsFormDirty();\n\nisDirty.value; // true or false\n```\n\n<CodeTitle level=\"4\">\n\n`useIsFieldTouched(field?: string): ComputedRef<boolean>`\n\n</CodeTitle>\n\nReturns a computed ref to the specified field's `touched` meta state.\n\n```js\nimport { useIsFieldTouched } from 'vee-validate';\n\nconst isTouched = useIsFieldTouched('fieldName');\n\nisTouched.value; // true or false\n```\n\nYou can also use it in a child component that has a parent that used `useField`, The `useIsFieldTouched` will automatically pick up the field and produce its meta `touched` value\n\n```js\nimport { useIsFieldTouched } from 'vee-validate';\n\n// Will look for the first parent that used `useField`\nconst isTouched = useIsFieldTouched();\n```\n\n<CodeTitle level=\"4\">\n\n`useIsFormTouched(): ComputedRef<boolean>`\n\n</CodeTitle>\n\nReturns a computed ref to the context form `touched` meta state.\n\n```js\nimport { useIsFormTouched } from 'vee-validate';\n\nconst isTouched = useIsFormTouched();\n\nisTouched.value; // true or false\n```\n\n<CodeTitle level=\"4\">\n\n`useIsFieldValid(field?: string): ComputedRef<boolean>`\n\n</CodeTitle>\n\nReturns a computed ref to the specified field's `valid` meta state, inner `value` will be `true` if the field has no errors, and `false` if it has any error message.\n\n```js\nimport { useIsFieldValid } from 'vee-validate';\n\nconst isValid = useIsFieldValid('fieldName');\n\nisValid.value; // true or false\n```\n\nYou can also use it in a child component that has a parent that used `useField`, The `useIsFieldValid` will automatically pick up the field and produce its meta `valid` value\n\n```js\nimport { useIsFieldValid } from 'vee-validate';\n\n// Will look for the first parent that used `useField`\nconst isValid = useIsFieldValid();\n```\n\n<DocTip type=\"warn\">\n\nCreating disabled buttons based on the `valid` attribute isn't accurate, because if the field hasn't been validated yet it, the `valid` property will be `true` which isn't accurate. You should combine `valid` checks with `dirty` state to get the most accuracy.\n\n</DocTip>\n\n<CodeTitle level=\"4\">\n\n`useIsFormValid(): ComputedRef<boolean>`\n\n</CodeTitle>\n\nReturns a computed ref to the context form `valid` meta state.\n\n```js\nimport { useIsFormValid } from 'vee-validate';\n\nconst isValid = useIsFormValid();\n\nisValid.value; // true or false\n```\n\n<DocTip type=\"warn\">\n\nCreating disabled buttons based on the `valid` attribute isn't accurate, because if the form hasn't been validated yet it, the `valid` property will be `true` which isn't accurate. You should combine `valid` checks with `dirty` state to get the most accuracy.\n\n</DocTip>\n\n<CodeTitle level=\"4\">\n\n`useValidateField(field?: string): () => Promise<ValidationResult>`\n\n</CodeTitle>\n\nReturns a function that validates the field and returns a validation result object containing any errors, if the `errors` field is empty then it means the field is valid. If a field doesn't not exist it will return an empty `errors` field with a warning.\n\n```js\nimport { useValidateField } from 'vee-validate';\n\nconst validate = useValidateField('fieldName');\n\nawait validate();\n```\n\nYou can also use it in a child component that has a parent that used `useField`, The `useValidateField` will automatically pick up the field and will return the function that validates it.\n\n```js\nimport { useValidateField } from 'vee-validate';\n\n// Will look for the first parent that used `useField`\nconst validate = useValidateField();\n```\n\n<CodeTitle level=\"4\">\n\n`useValidateForm(): () => Promise<FormValidationResult>`\n\n</CodeTitle>\n\nReturns a function that validates the form and returns a `Form`.\n\n```js\nimport { useValidateForm } from 'vee-validate';\n\nconst validate = useValidateForm();\n\nawait validate();\n```\n\n<CodeTitle level=\"4\">\n\n`useIsSubmitting(): ComputedRef<boolean>`\n\n</CodeTitle>\n\nReturns a computed ref to the form's `isSubmitting` state.\n\n```js\nimport { useIsSubmitting } from 'vee-validate';\n\nconst isSubmitting = useIsSubmitting();\n\nisSubmitting.value; // true or false\n```\n\n<CodeTitle level=\"4\">\n\n`useIsValidating(): ComputedRef<boolean>`\n\n</CodeTitle>\n\nReturns a computed ref to the form's `isValidating` state.\n\n```js\nimport { useIsValidating } from 'vee-validate';\n\nconst isValidating = useIsValidating();\n\nisValidating.value; // true or false\n```\n\n<CodeTitle level=\"4\">\n\n`useSubmitCount(): ComputedRef<number>`\n\n</CodeTitle>\n\nReturns a computed ref to the form's `submitCount` state.\n\n```js\nimport { useSubmitCount } from 'vee-validate';\n\nconst count = useSubmitCount();\n\ncount.value;\n```\n\n<CodeTitle level=\"4\">\n\n`useResetForm(): () => void`\n\n</CodeTitle>\n\nReturns a function that you can use to reset the form\n\n```js\nimport { useResetForm } from 'vee-validate';\n\nconst resetForm = useResetForm();\n\nresetForm(); // resets the form\n```\n\n<CodeTitle level=\"4\">\n\n`useSubmitForm(cb: SubmissionHandler): () => void`\n\n</CodeTitle>\n\nReturns a function that you can use to validate the form and submit if it turns out valid. It does this by accepting a function that should handle the submission logic like sending data to your API. That function will not run unless the form is valid and it receives all the fields current values packed in an object.\n\n```js\nimport { useSubmitForm } from 'vee-validate';\n\nconst submitForm = useSubmitForm((values, actions) => {\n  // Send data to your api ...\n  alert(JSON.stringify(values, null, 2));\n\n  // You can perform any of the form actions using the actions object\n  // set a single field value\n  actions.setFieldValue('field', 'hello');\n  // set multiple fields values\n  actions.setValues({ email: 'value', password: 'hi' });\n  // set a single field error\n  actions.setFieldError('field', 'this field is bad');\n  // set multiple fields errors\n  actions.setErrors({ email: 'bad email', password: 'bad password' });\n  // reset the form\n  actions.resetForm();\n});\n```\n\n<DocTip title=\"Virtual Forms\">\n\nWhile it is recommended to use actual `form` elements for accessibility, you could still use `useSubmitForm` to submit any group of data which may or may not be involved with a `form` element.\n\n</DocTip>\n\n<CodeTitle level=\"4\">\n\n`useFieldValue(field?: string): ComputedRef<any>`\n\n</CodeTitle>\n\nReturns a computed ref to the specified field's current value.\n\n```js\nimport { useFieldValue } from 'vee-validate';\n\nconst currentValue = useFieldValue('fieldName');\n\ncurrentValue.value;\n```\n\nYou can also use it in a child component that has a parent that used `useField`, The `useFieldValue` will automatically pick up the field and produce its current value.\n\n```js\nimport { useFieldValue } from 'vee-validate';\n\n// Will look for the first parent that used `useField`\nconst currentValue = useFieldValue();\n```\n\n<CodeTitle level=\"4\">\n\n`useFormValues(): ComputedRef<Record<string, any>>`\n\n</CodeTitle>\n\nReturns a computed ref to the context form current values.\n\n```js\nimport { useFormValues } from 'vee-validate';\n\nconst values = useFormValues();\n\nvalues.value;\n```\n"
  },
  {
    "path": "docs/src/pages/api/configuration.mdx",
    "content": "---\r\nlayout: ../../layouts/PageLayout.astro\r\ntitle: Configuration\r\ndescription: VeeValidate Global Config Reference\r\norder: 8\r\n---\r\n\r\nimport DocTip from '@/components/DocTip.vue';\r\n\r\n# Configuration\r\n\r\nvee-validate exposes global configs to help with a few repeated or certain behaviors that needs to be set app-wide.\r\n\r\n## Config Options\r\n\r\n| Option                | Type                                       | Description                                                                                                                                                                                                                                                                                                                                           |\r\n| --------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\r\n| bails                 | `boolean`                                  | Whether to run validations to completion or quit on the first, default is `true`. Doesn't affect `yup` schemas                                                                                                                                                                                                                                        |\r\n| generateMessage       | `(ctx: FieldValidationMetaInfo) => string` | A message generator function for i18n libraries and a fallback for rules with no messages. For more information about the [`FieldValidationMetaInfo`](https://github.com/logaretm/vee-validate/blob/main/packages/shared/types.ts#L1-L9) type and the purpose of this, see the [Global Message Generator Guide](/guide/i18n#global-message-generator) |\r\n| validateOnBlur        | `boolean`                                  | If validation should be triggered on `blur` event, default is `true`                                                                                                                                                                                                                                                                                  |\r\n| validateOnChange      | `boolean`                                  | If validation should be triggered on `change` event, default is `true`                                                                                                                                                                                                                                                                                |\r\n| validateOnInput       | `boolean`                                  | If validation should be triggered on `input` event, default is `false`                                                                                                                                                                                                                                                                                |\r\n| validateOnModelUpdate | `boolean`                                  | If validation should be triggered on `update:modelValue` (v-model) event, default is `true`                                                                                                                                                                                                                                                           |\r\n\r\nThis is slightly verbose, but this gives you exact control on which events triggers validation.\r\n\r\n## Updating The Config\r\n\r\nYou can change the global config using the `configure` function exposed by vee-validate passing any options that you need to change. You can call that function at any time during runtime but the changes will take effect for new `Field` and `useField` afterwards.\r\n\r\nHere is an example:\r\n\r\n```js\r\nimport { configure } from 'vee-validate';\r\n\r\nconfigure({\r\n  bails: false,\r\n});\r\n```\r\n\r\n<DocTip>\r\n\r\nNote that the following config do not affect `useField`, they only apply to the `<Field />` component:\r\n\r\n- `validateOnBlur`\r\n- `validateOnChange`\r\n- `validateOnInput`\r\n- `validateOnModelUpdate`\r\n\r\n</DocTip>\r\n"
  },
  {
    "path": "docs/src/pages/api/error-message.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: ErrorMessage\ndescription: API reference for the ErrorMessage component\nmenuTitle: '<ErrorMessage />'\norder: 3\n---\n\nimport DocTip from '@/components/DocTip.vue';\n\n# ErrorMessage\n\nThe `ErrorMessage` component is used to conveniently display error messages without resorting to scoped slots on either the `Form` and `Field` components. It also renders nothing if there are no messages for the associated field.\n\nThe basic usage looks like this:\n\n```vue\n<template>\n  <Form>\n    <Field name=\"email\" type=\"email\" :rules=\"validateEmail\" />\n    <ErrorMessage name=\"email\" />\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst validateEmail = yup.string().required().email();\n</script>\n```\n\n## Rendering Messages\n\nThe `ErrorMessage` component accepts an `as` prop that allows to control the root node to render for your error messages, by default it will render a `span` if none provided if there is an error message for the field.\n\n```vue-html\n<ErrorMessage name=\"email\" as=\"p\" />\n```\n\nFor more flexible markup and the ability to render multiple root nodes, you can use the `ErrorMessage` component's default scoped slot\n\n```vue-html\n<ErrorMessage name=\"email\" v-slot=\"{ message }\">\n  <p>Error:</p>\n  <p>{{ message }}</p>\n</ErrorMessage>\n```\n\nIf an `as` prop is not provided while having a slot, it will render the slot contents only. _Effectively becoming a renderless-component._\n\nYou can use a combination of both to render a root node with children:\n\n```vue-html\n<ErrorMessage as=\"div\" name=\"email\" v-slot=\"{ message }\">\n  <p>Error:</p>\n  <p>{{ message }}</p>\n</ErrorMessage>\n```\n\n<DocTip title=\"No Errors Rendering\" type=\"danger\">\n\nWhen there are not any error messages for the field the `<ErrorMessage />` component will render nothing, even if you used the slot or `as` prop.\n\n</DocTip>\n\n## API\n\n### Props\n\n| Prop | Type     | Required/Default | Description                              |\n| :--- | :------- | :--------------- | :--------------------------------------- |\n| as   | `string` | `\"span\"`         | The element to render as a root node     |\n| name | `string` | Required         | The field's name to display messages for |\n\n### Slots\n\n#### default\n\nThe default slot gives you access to the following props:\n\n| Scoped Prop | Type     | Description                 |\n| :---------- | :------- | :-------------------------- |\n| message     | `string` | The element's error message |\n\nCheck the sample above for rendering with scoped slots\n\n## Caveats\n\n- The ErrorMessage component must be used inside a `Form` component otherwise it won't be able to find the errors.\n- ErrorMessage component can only display errors for a field that exists within the same form, it cannot reference fields outside its own form.\n"
  },
  {
    "path": "docs/src/pages/api/field-array.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: FieldArray\ndescription: API reference for the Field Array component\nmenuTitle: '<FieldArray />'\norder: 4\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport DocBadge from '@/components/DocBadge.vue';\nimport CodeTitle from '@/components/CodeTitle.vue';\n\n# FieldArray <DocBadge title=\"v4.5\" />\n\n<DocTip title=\"Form Context\" type=\"warn\">\n\nThe `<FieldArray />` component requires being used inside a `Form` component or a `useForm` to be called at its parent tree.\n\n</DocTip>\n\nThe `<FieldArray />` component is used to manage repeatable array fields. It is a renderless component, meaning it doesn't render anything of its own.\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\" :initial-values=\"initialValues\">\n    <FieldArray name=\"links\" v-slot=\"{ fields, push, remove }\">\n      <div v-for=\"(field, idx) in fields\" :key=\"field.key\">\n        <Field :name=\"`links[${idx}].url`\" type=\"url\" />\n\n        <button type=\"button\" @click=\"remove(idx)\">Remove</button>\n      </div>\n\n      <button type=\"button\" @click=\"push({ id: Date.now(), name: '', url: '' })\">Add</button>\n    </FieldArray>\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\n// you can set initial values for those array fields\nconst initialValues = {\n  links: [{ id: 1, url: 'https://github.com/logaretm' }],\n};\n\nfunction onSubmit(values) {\n  alert(JSON.stringify(values, null, 2));\n}\n</script>\n```\n\n## API Reference\n\n### Props\n\n| Prop        | Type     | Required/Default | Description                            |\n| :---------- | :------- | :--------------- | :------------------------------------- |\n| `arrayPath` | `string` | Yes              | The form array path you wish to manage |\n\n### Slots\n\n#### default\n\nThe default slot gives you access to the following props:\n\n<CodeTitle level=\"4\">\n\n`fields: FieldArrayEntry<TValue>`\n\n</CodeTitle>\n\nThis is a **read-only** version of your array items, wrapped inside a `FieldArrayEntry` object which has the following interface:\n\n```ts\ninterface FieldEntry<TValue = unknown> {\n  // The actual value of the item, this is what exists in the form values\n  value: TValue;\n  // a value you can use as a key for iteration, automatically generated.\n  key: string | number;\n  // true if this is the first array item\n  isFirst: boolean;\n  // true if this is the last array item\n  isLast: boolean;\n}\n```\n\n<CodeTitle level=\"4\">\n\n`push(item: any)`\n\n</CodeTitle>\n\nAdds an item to the end of the array.\n\n<CodeTitle level=\"4\">\n\n`prepend(item: any)`\n\n</CodeTitle>\n\nAdds an item to the start of the array.\n\n<CodeTitle level=\"4\">\n\n`remove(idx: number)`\n\n</CodeTitle>\n\nRemoves the item at the specified index from the array if it exists.\n\n<CodeTitle level=\"4\">\n\n`swap(idxA: number, idxB: number)`\n\n</CodeTitle>\n\nSwaps the items at the given indexes with each other. Both indexes must exist in the array or it won't have an effect.\n\n<CodeTitle level=\"4\">\n\n`insert(idx: number, item: any)`\n\n</CodeTitle>\n\nAdds an item at the specified index. If the specified index will place the item out of bounds (i.e: larger than length) the operation will be ignored, you still can add items as the last item of the array.\n\n<CodeTitle level=\"4\">\n\n`update(idx: number, value: any)`\n\n</CodeTitle>\n\nUpdates the value at the specified index, note that it doesn't merge the values if they are objects. If the specified index is outside the array boundary the operation will be ignored.\n\n<CodeTitle level=\"4\">\n\n`replace(items: any[])`\n\n</CodeTitle>\n\nReplaces the entire array of fields.\n\n<CodeTitle level=\"4\">\n\n`move(oldIdx: number, newIdx: number)`\n\n</CodeTitle>\n\nMoves an array item to a different position within the array. If one of the indices is outside of the array boundaries the operation will be ignored.\n"
  },
  {
    "path": "docs/src/pages/api/field.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Field\ndescription: API reference for the Field component\nmenuTitle: '<Field />'\norder: 1\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport CodeTitle from '@/components/CodeTitle.vue';\n\n# Field\n\nThe `<Field />` component is an extremely flexible component that makes rendering input fields easy and intuitive, By default it renders an HTML `input` tag. So a simple text input can be rendered like this:\n\n```vue\n<template>\n  <Field name=\"field\" type=\"text\" />\n</template>\n\n<script setup>\nimport { Field } from 'vee-validate';\n</script>\n```\n\n## Rendering Fields\n\nThe `Field` component allows you to render practically anything and gives you complete flexibility and control over how your fields are rendered. The `Field` component renders an HTML `input` tag if not specified otherwise. Which can be done in two ways.\n\n### Rendering simple fields with 'as' prop\n\nThe `as` prop tells the Field component which tag to render in its place, you can pass any additional attributes like `type=\"text\"` and it will be passed to the rendered `input` tag as well as any listeners and slots.\n\nFor example you could render a `select` input like this:\n\n```vue-html\n<Field name=\"field\" as=\"select\">\n  <option>Coffee</option>\n  <option>Tea</option>\n  <option>Coke</option>\n</Field>\n```\n\n<DocTip>\n\nThe `Field` component has partial support for native `select[multiple]` element, while it picks up the multiple values correctly, it doesn't set the initial values UI state on the element itself. You may use `v-model` here or bind the `selected` attributes on the options which is straightforward with the `value` prop exposed on the slot props.\n\n```vue-html\n<Field v-slot=\"{ value }\" name=\"drink\" as=\"select\" multiple>\n  <option value=\"\" disabled>Select a drink</option>\n  <option v-for=\"drink in drinks\" :key=\"drink\" :value=\"drink\" :selected=\"value && value.includes(drink)\">{{ drink }}</option>\n</Field>\n```\n\n</DocTip>\n\nYou can also render any globally defined components:\n\n```vue-html\n<Field name=\"field\" as=\"my-text-field\" />\n```\n\n<DocTip>\n\nFor validation to work, the rendered tag with `as` prop must conform to the events that the `Field` component listens for, you can view a list of these in the [Validation Behavior](/guide/components/validation#validation-behavior)\n\n</DocTip>\n\n### Rendering Complex Fields with Scoped Slots\n\nThe `as` prop is very easy to use but also limited as you cannot render a group of markup. Fortunately the `Field` component makes use of the scoped-slots (v-slot) feature to allow you to render complex markup:\n\n```vue-html\n<Field name=\"password\" v-slot=\"{ field }\">\n  <input v-bind=\"field\" type=\"password\">\n  <p>Hint: Enter a secure password you can remember</p>\n</Field>\n```\n\nThe most crucial part of rendering fields with `v-slot` is that you **bind the `field` object to your input element/input**, the `field` object contains all the common attributes and listeners required for the field to be validated, this is done automatically if you are using the `as` prop.\n\n<DocTip title=\"File Inputs and Custom Components\" type=\"warn\">\n\nWhen rendering File inputs and custom components, binding the `field` object may not be a good idea in these cases as generally you need to pick the suitable attributes that you should bind. In the case of `input[type=\"file\"]` you could do something like this:\n\n```vue-html\n<Field name=\"file\" v-slot=\"{ handleChange, handleBlur }\">\n  <input type=\"file\" @change=\"handleChange\" @blur=\"handleBlur\" />\n</Field>\n```\n\nThis is because the file input doesn't work with two-way binding since you cannot really force pick a file from a user's device. Custom components may emit different events and may have additional requirements for two-way binding to work. You can check the [UI Libraries](/examples/ui-libraries) section for a few examples on how to do that.\n\n</DocTip>\n\nWhen using `v-slot` on the `Field` component you no longer have to provide an `as` prop and then it will become a renderless component.\n\n<DocTip title=\"Passing Props and Attrs\">\n\nWhichever element/component you chose to render with `<Field />` you can pass also any props or attributes the element/component would normally receive for example if you render `input` elements you can pass any of it's attributes like `type` or `disabled` to just name a few.\n\n</DocTip>\n\n### Using v-model\n\nThe `<Field />` component uses a different way to apply input values to your rendered inputs using the `v-bind=\"field\"` syntax which adds various listeners and attributes to your rendered inputs.\n\nBecause of this, using `v-model` will conflict with `v-bind=\"field\"` because both will attempt to update the input value.\n\nFor simple inputs this is not an issue:\n\n```vue-html\n<!-- ✅  Simple Field -->\n<Field type=\"text\" name=\"name\" v-model=\"name\" />\n```\n\nBut for complex inputs rendered with scoped slots (v-slot), you need to place it on the `Field` component tag itself, not the rendered input.\n\n```vue-html\n<!-- DONT: ⛔️  v-model on input tag -->\n<Field type=\"text\" name=\"name\" v-slot=\"{ field }\">\n  <!-- Conflict between v-model and `v-bind=field` -->\n  <input v-bind=\"field\" v-model=\"name\">\n</Field>\n\n<!-- DO: ✅  v-model on field tag -->\n<Field v-model=\"name\" type=\"text\" name=\"name\" v-slot=\"{ field }\">\n  <input v-bind=\"field\">\n</Field>\n```\n\nNote that you no longer should use `v-model` on your input as `v-bind=\"field\"` will take care of the rest.\n\n## API Reference\n\n### Props\n\n| Prop                  | Type                           | Required/Default | Description                                                                                                                                                                                                                     |\n| :-------------------- | :----------------------------- | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| as                    | `string`                       | `\"span\"`         | The element to render as a root node, defaults to `input`                                                                                                                                                                       |\n| name                  | `string`                       | Required         | The field's name, must be inside `<Form />`                                                                                                                                                                                     |\n| rules                 | `object \\| string \\| Function` | `null`           | The field's validation rules                                                                                                                                                                                                    |\n| validateOnMount       | `boolean`                      | `false`          | If true, field will be validated when the component is mounted                                                                                                                                                                  |\n| validateOnInput       | `boolean`                      | `false`          | If true, field will be validated when `input` event is dispatched/emitted                                                                                                                                                       |\n| validateOnChange      | `boolean`                      | `true`           | If true, field will be validated when `change` event is dispatched/emitted                                                                                                                                                      |\n| validateOnBlur        | `boolean`                      | `true`           | If true, field will be validated when `blur` event is dispatched/emitted                                                                                                                                                        |\n| validateOnModelUpdate | `boolean`                      | `true`           | If true, field will be validated when `update:modelValue` event is emitted                                                                                                                                                      |\n| bails                 | `boolean`                      | `true`           | Stops validating as soon as a rule fails the validation                                                                                                                                                                         |\n| label                 | `string`                       | `undefined`      | A different string to override the field `name` prop in error messages, useful for display better or formatted names. The generated message won't be updated if this prop changes, you will need to re-validate the input.      |\n| value                 | `any`                          | `undefined`      | The field's initial value, optional as long as the field type is not `checkbox` or `radio`.                                                                                                                                     |\n| type                  | `string`                       | `undefined`      | The field type, must be provided if you want your field to behave as a `checkbox` or a `radio` input.                                                                                                                           |\n| unchecked-value       | `any`                          | `undefined`      | Only useful when the `type=\"checkbox\"` and the field is a single checkbox field (not bound to an array value). Controls the input's value when it's unchecked.                                                                  |\n| standalone            | `boolean`                      | `false`          | Excludes the field from participating in any `Form` or `useForm` contexts, useful for creating inputs that do contribute to the `values` object. In other words, the form won't pick up or validate fields marked as standalone |\n| keepValue             | `boolean`                      | `undefined`      | If the field value should be kept in the form when it gets unmounted, default follows the form's configuration                                                                                                                  |\n\n### Slots\n\n#### default\n\nThe default slot gives you access to the following props:\n\n<CodeTitle level=\"4\">\n\n`meta: FieldMeta`\n\n</CodeTitle>\n\nContains useful information/flags about the field status.\n\n```ts\ninterface FieldMeta {\n  touched: boolean; // if the field has been blurred (via handleBlur)\n  dirty: boolean; // if the field has been manipulated (via handleChange)\n  valid: boolean; // if the field doesn't have any errors\n  validated: boolean; // if the field has been validated\n  pending: boolean; // if validation is in progress\n  initialValue?: any; // the field's initial value\n}\n```\n\n<DocTip title=\"The valid flag\">\n\nThe `valid` flag on the meta object can be tricky, because by default it stars off with `true` for a few moments, only then it is updated to its proper state.\n\nCombining your `valid` flag checks with `dirty` will yield the expected result based on user interaction.\n\n</DocTip>\n\n<CodeTitle level=\"4\">\n\n`errors: string[]`\n\n</CodeTitle>\n\nAn array containing all error messages for the field.\n\n<CodeTitle level=\"4\">\n\n`value: unknown`\n\n</CodeTitle>\n\nThe current value of the field, useful to compare and do conditional rendering based on the field value. **You should not use it as a target of `v-model` or `:value` binding**. Instead use the `field` prop.\n\n<CodeTitle level=\"4\">\n\n`errorMessage: ComputedRef<string | undefined>`\n\n</CodeTitle>\n\nThe first error in the `errors` array if available, a handy shortcut to display error messages\n\n<CodeTitle level=\"4\">\n\n`resetField: (state?: Partial<FieldState>) => void`\n\n</CodeTitle>\n\nResets the field's validation state, reverts all `meta` object to their default values and clears out the error messages, it will also reset the field value to it's initial value. Note that no error messages will be generated if the initial value is invalid after reset, the `valid` flag will be then set to `true` in that case.\n\nNote that it is unsafe to use this function as an event handler directly, check the following snippet:\n\n```vue-html\n<!-- ⛔️ Unsafe -->\n<button @click=\"resetField\">Reset</button>\n\n<!-- ✅  Safe -->\n<button @click=\"resetField()\">Reset</button>\n```\n\nYou can use `resetField` to update the fields' current value to something other than its initial value,\n\n```vue-html\n<button @click=\"resetField({ value: 'new value' })\">Reset</button>\n```\n\n<CodeTitle level=\"4\">\n\n`handleReset: () => void`\n\n</CodeTitle>\n\nSimilar to `resetField` but it doesn't accept any arguments and can be safely used as an event handler. The values won't be validated after reset.\n\n<CodeTitle level=\"4\">\n\n`validate: () => Promise<{ errors: string[] }>`\n\n</CodeTitle>\n\nValidates the field's current value and returns a promise that resolves with an object containing the error messages emitted by the various rule(s).\n\n```js\nconst { validate } = useField('field', value => !!value);\n\n// trigger validation\nawait validate();\n```\n\n<CodeTitle level=\"4\">\n\n`handleChange: (evt: Event | any, shouldValidate?: boolean) => void`\n\n</CodeTitle>\n\nUpdates the field value, and validates the field by default. Can be used as an event handler to bind on the field. If the passed argument isn't an event object it will be used as the new value for that field.\n\nYou can update the field value without validation by passing `false` as a second argument.\n\n<CodeTitle level=\"4\">\n\n`handleBlur: (evt: Event | any) => void`\n\n</CodeTitle>\n\nValidates the field by default unless explicitly [specified by validation triggers](/guide/components/validation#customizing-validation-triggers). Can be used as an event handler to bind on the field. If the passed argument isn't an event object it will be used as the new value for that field.\n\nIt sets the `touched` meta flag to true\n\nBecause this handler doesn't set the field value, it might not report validation correctly if other events are unspecified or disabled.\n\n<CodeTitle level=\"4\">\n\n`setTouched: (isTouched: boolean) => void`\n\n</CodeTitle>\n\nSets the `touched` meta flag for this field, useful to create your own `blur` handlers\n\n#### `field`\n\nContains a few properties that you can use `v-bind` with to get all vee-validate features on that input. The following is a description of the properties\n\n<CodeTitle level=\"5\">\n\n`field.value: any`\n\n</CodeTitle>\n\nThe field's current value, you can bind it with `value` prop on your inputs to sync both values. Don't use it with `v-model` otherwise your input will freeze.\n\n<CodeTitle level=\"5\">\n\n`field.name: string`\n\n</CodeTitle>\n\nThe field name.\n\n<CodeTitle level=\"5\">\n\n`field.onBlur: (e: Event | unknown) => void`\n\n</CodeTitle>\n\nAn array containing a few listeners for the `blur` event, it involves updating some meta information and triggers validation by default.\n\n<CodeTitle level=\"5\">\n\n`field.onInput: (e: Event | unknown) => void`\n\n</CodeTitle>\n\nAn array containing a few listeners for the `input` event, it involves updating the field value and some meta information.\n\n<CodeTitle level=\"5\">\n\n`field.onChange: (e: Event | unknown) => void`\n\n</CodeTitle>\n\nAn array containing a few listeners for the `change` event, it involves updating the field value and triggering validation.\n\n#### `componentField`\n\nSame as `field`, but provides value as `modelValue` to use with components\n"
  },
  {
    "path": "docs/src/pages/api/form.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Form\ndescription: API reference for the Form component\nmenuTitle: '<Form />'\norder: 2\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport CodeTitle from '@/components/CodeTitle.vue';\n\n# Form\n\n## Form Component\n\nThe `<Form />` component is like its name, a simple HTML form but with a few adjustments and DX improvements, By default it will render a native HTML `form` element.\n\n```vue-html\n<Form>\n  <Field name=\"password\" type=\"password\" />\n</Form>\n```\n\n## Rendering Forms\n\nJust like the `Field` component you can pass whatever you want to render in its place, for example a custom `v-form` component that is registered globally:\n\n```vue-html\n<Form as=\"v-form\">\n  <Field name=\"password\" type=\"password\" />\n</Form>\n```\n\nBy default a `submit` and `reset` listeners are added to the rendered tag specified by the `as` prop.\n\nFor more complex form markup, you can render a `div` and inline your forms in the `Form` component's slots.\n\n```vue-html\n<Form as=\"div\">\n  <h2>Sign up form</h2>\n  <form>\n    <Field name=\"name\" />\n    <Field name=\"email\" type=\"email\" />\n    <Field name=\"password\" type=\"password\" />\n  </form>\n</Form>\n```\n\n<DocTip type=\"danger\" title=\"HTML Case Insensitivity\">\n\nNotice the character-case difference between `Form` and `form`, the uppercased one is the component provided by vee-validate while the lowercased one is the native `form` element, you might run into issues when not using Vue compiler workflow like script tags. In these cases it is recommended to rename the `Form` component to something that will not conflict with native HTML.\n\n```js\n// Using named imports\nimport { Form as ValidationForm } from 'vee-validate';\n\nconst component = {\n  components: {\n    // If you have VeeValidate globally via a CDN script\n    ValidationForm: VeeValidate.Form,\n  },\n};\n```\n\n</DocTip>\n\nLastly, you can use the `Form` component slot props to access various aspects of the form state:\n\n```vue-html\n<Form v-slot=\"{ values }\">\n  <Field name=\"name\" />\n  <Field name=\"email\" type=\"email\" />\n  <Field name=\"password\" type=\"password\" />\n\n  <!-- prints current form values -->\n  <pre>\n    {{ values }}\n  </pre>\n</Form>\n```\n\n## Renderless Forms\n\nWhile not recommended, you can make the `Form` component a renderless component by passing an empty string to the as prop, this is useful if you already need to add a form inside the scoped slot:\n\n```vue-html\n<Form as=\"\" v-slot=\"{ values, submitForm }\">\n  <h2>Sign up form</h2>\n  <form @submit=\"submitForm\">\n    <Field name=\"name\" />\n    <Field name=\"email\" type=\"email\" />\n    <Field name=\"password\" type=\"password\" />\n\n    <!-- prints current form values -->\n    <pre>\n      {{ values }}\n    </pre>\n  </form>\n</Form>\n```\n\n## API Reference\n\n### Props\n\n| Prop             | Type                                 | Default     | Description                                                                                                  |\n| :--------------- | :----------------------------------- | :---------- | :----------------------------------------------------------------------------------------------------------- |\n| as               | `string`                             | `\"form\"`    | The element to render as a root node                                                                         |\n| validationSchema | `Record<string, string \\| Function>` | `undefined` | An object describing a schema to validate fields with, can be a plain object or a `yup` object schema        |\n| initialValues    | `Record<string, any>`                | `undefined` | Initial values to fill the fields with, when provided the fields will be validated on mounted                |\n| initialErrors    | `Record<string, string>`             | `undefined` | Initial form errors to fill the fields with, the errors will be added when the form component is mounted     |\n| initialTouched   | `Record<string, boolean>`            | `undefined` | Initial touched fields, the status will be applied when the form component is mounted                        |\n| validateOnMount  | `boolean`                            | `false`     | If true, the fields currently present in the form will be validated when the `<Form />` component is mounted |\n| keepValues       | `boolean`                            | `false`     | If the fields values should be deleted when they get unmounted, default is false                             |\n| name             | `string`                             | `\"Form\"`      | The name of the form that is displayed in the devtools.                                                      |\n\n### Slots\n\n#### default\n\nThe default slot gives you access to the following props:\n\n<CodeTitle level=\"4\">\n\n`errors: Record<string, string>`\n\n</CodeTitle>\n\nAn object that maps field names to their error messages, it only takes the first error message of each field if multiple exists.\n\nHere is an example of its shape:\n\n```js\n{\n  email: \"this field must be a valid email\",\n  password: \"too short\"\n}\n```\n\nAny fields without error messages will not be included in the object. So you can safely iterate over it with `Object.keys()` knowing all the included fields are invalid.\n\n<CodeTitle level=\"4\">\n\n`errorBag: Record<string, string>`\n\n</CodeTitle>\n\nAn object that maps field names to all of their error messages.\n\nHere is an example of its shape:\n\n```js\n{\n  email: [\"this field is required\", \"this field must be a valid email\"],\n  password: \"too short\"\n}\n```\n\nAny fields without error messages will not be included in the object. So be careful when accessing the errors array for each field\n\n<CodeTitle level=\"4\">\n\n`isSubmitting: boolean`\n\n</CodeTitle>\n\nIndicates if the submission handler is still running, once it resolves/rejects it will be automatically set to `false` again.\n\n<CodeTitle level=\"4\">\n\n`isValidating: boolean`\n\n</CodeTitle>\n\nIndicates if the validate function is still running, once validate function is done it will be automatically set to `false` again.\n\n<CodeTitle level=\"4\">\n\n`meta: FormMeta`\n\n</CodeTitle>\n\nContains an aggregated meta information/flags reflecting the state of all the fields inside the form.\n\n```ts\ninterface FormMeta {\n  touched: boolean; // if at least one field is touched (was blurred)\n  dirty: boolean; // if at least one field is dirty (manipulated)\n  valid: boolean; // if all fields are valid\n  pending: boolean; // if at least one field is pending validation\n  initialValues?: Record<string, any>; // a map of the form's initial values\n}\n```\n\n<CodeTitle level=\"4\">\n\n`values: Record<string, any>`\n\n</CodeTitle>\n\nContains the current form values\n\n<CodeTitle level=\"4\">\n\n`setFieldError: (field: string, message: string) => void`\n\n</CodeTitle>\n\nSets a field's error message, useful for setting messages form an API or that are not available as a validation rule.\n\nIf you try to set an error for a field that doesn't exist, it will be added to the form's errors object and it will change the form's `valid` state\n\n<CodeTitle level=\"4\">\n\n`setErrors: (fields: Record<string, string>) => void`\n\n</CodeTitle>\n\nSets multiple fields error messages, uses `setFieldError` internally.\n\n<CodeTitle level=\"4\">\n\n`setFieldValue: (field: string, value: any) => void`\n\n</CodeTitle>\n\nSets a field's value, if a field does not exist it will not be reflected in the `values` ref. This will trigger validation on the field whose value changed.\n\nIf you try to set a value for a field that doesn't exist, it will be added to the form's values object and will stay there until the next `resetForm` is called.\n\n<CodeTitle level=\"4\">\n\n`setValues: (fields: Record<string, any>) => void`\n\n</CodeTitle>\n\nSets all fields values, will trigger validation for the changed fields.\n\n<CodeTitle level=\"4\">\n\n`setFieldTouched: (field: string, isTouched: boolean) => void`\n\n</CodeTitle>\n\nSets a field's `touched` meta flag, if you set it for a non-existing field it will have no effect.\n\n<CodeTitle level=\"4\">\n\n`setTouched: (fields: Record<string, boolean>) => void`\n\n</CodeTitle>\n\nSets multiple fields `touched` meta flag, does not validate.\n\n<CodeTitle level=\"4\">\n\n`validate: () => Promise<{ valid: boolean; errors: Record<string, string>}>`\n\n</CodeTitle>\n\nValidates all the fields and populates the `errors` object, returns a promise that resolves to an object containing aggregated validation result of all fields.\n\n<CodeTitle level=\"4\">\n\n`validateField: (field: string) => Promise<{ valid: boolean; errors: string[] }>`\n\n</CodeTitle>\n\nValidates a specific field inside the form, returns a promise that resolves to an object containing the validation result.\n\n<CodeTitle level=\"4\">\n\n`handleSubmit: (evt: Event, cb: (values: Record<string, any>, ctx: SubmissionContext) => any) => Promise<void>`\n\n</CodeTitle>\n\nThis can be used as an event handler for `submit` events, it accepts the event object and a callback function that will run if the form is valid. If an event object is provided, `preventDefault` and `stopPropagation` will be automatically called on it.\n\nNote that this is only useful if you are not rendering a form tag on the `<Form />` component. By default the `Form` component uses this handler to handle any `submit` events.\n\n<CodeTitle level=\"4\">\n\n`submitForm: (evt: Event) => void`\n\n</CodeTitle>\n\nThis function can also be used as an event handler for form `submit` event, the different that it will prevent the propagation and submission of the form as long as they are invalid. Once all the fields are valid it will submit the form with the native HTML behavior following the `form` element's `action` and `method` attributes.\n\nThis is useful if you plan to handle form submissions using a backend API like Laravel.\n\n<CodeTitle level=\"4\">\n\n`submitCount: number`\n\n</CodeTitle>\n\nThe number of submission attempts by the user, it increments whenever `submitForm` or `handleSubmit` callback are called.\n\n<CodeTitle level=\"4\">\n\n`handleReset: () => void`\n\n</CodeTitle>\n\nClears error messages, resets the meta state for all fields and reverts their values to their initial state and resets the `submitCount` to `0`. You can use this function as handler for the `reset` events on native form elements.\n\n<CodeTitle level=\"4\">\n\n`resetForm: (state?: Partial<FormState>) => void`\n\n</CodeTitle>\n\nClears error messages, resets the meta state for all fields and reverts their values to their initial state and resets the `submitCount`.\n\nAccepts an optional object containing the new form state, useful if you need to reset the form values to different values other than their initial state.\n\nThis is the shape of the `state` object:\n\n```ts\ninterface FormState {\n  // any error messages\n  errors: Record<string, string>;\n  // touched meta flags\n  touched: Record<string, boolean>;\n  // Form Values\n  values: Record<string, any>;\n  // The form submit attempts count\n  submitCount: number;\n}\n```\n\nIn the following example the form is resetting the `email` field value to another value, this will change the field current value as well as it's initial value. Meaning any future calls of `resetForm` without arguments or `handleReset` will use `example@example.com` as their value. This also applies if fields are reset individually using `resetField` on either `useField` return value or `<Field />` component's slot props.\n\n```vue-html\n<Form v-slot=\"{ resetForm }\">\n  ...\n\n  <button @click=\"resetForm({ values: { email: 'example@example.com' } })\" type=\"button\">Reset</button>\n</Form>\n```\n"
  },
  {
    "path": "docs/src/pages/api/use-field-array.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: useFieldArray\ndescription: API reference for the useFieldArray composition API function\nmenuTitle: useFieldArray()\norder: 7\n---\n\nimport DocBadge from '@/components/DocBadge.vue';\nimport CodeTitle from '@/components/CodeTitle.vue';\n\n# useFieldArray <DocBadge title=\"v4.5\" />\n\n`useFieldArray` is a custom composition API function that allows you to manage repeatable fields and forms entries and provides common operation helpers.\n\nBasic usage:\n\n```vue\n<template>\n  <form @submit=\"onSubmit\" novalidate>\n    <div v-for=\"(field, idx) in fields\" :key=\"field.key\">\n      <Field :name=\"`links[${idx}].url`\" type=\"url\" />\n\n      <button type=\"button\" @click=\"remove(idx)\">Remove</button>\n    </div>\n\n    <button type=\"button\" @click=\"push({ url: '' })\">Add</button>\n\n    <button>Submit</button>\n  </form>\n</template>\n\n<script setup>\nimport { Field, useForm, useFieldArray } from 'vee-validate';\n\nconst { handleSubmit } = useForm({\n  initialValues: {\n    links: [{ id: 1, url: 'https://github.com/logaretm' }],\n  },\n});\n\nconst { remove, push, fields } = useFieldArray('links');\nconst onSubmit = handleSubmit(values => {\n  console.log(JSON.stringify(values, null, 2));\n});\n</script>\n```\n\n## API Reference\n\nThe full signature of the `useFieldArray` function looks like this:\n\n```ts\ninterface FieldEntry<TValue = unknown> {\n  value: Ref<TValue>;\n  key: string | number;\n  isFirst: boolean;\n  isLast: boolean;\n}\n\ninterface FieldArrayContext<TValue = unknown> {\n  fields: Ref<FieldEntry<TValue>[]>;\n  remove(idx: number): void;\n  replace(newArray: TValue[]): void;\n  update(idx: number, value: TValue): void;\n  push(value: TValue): void;\n  swap(indexA: number, indexB: number): void;\n  insert(idx: number, value: TValue): void;\n  prepend(value: TValue): void;\n  move(oldIdx: number, newIdx: number): void;\n}\n\nfunction useFieldArray: (arrayPath: string): FieldArrayContext;\n```\n\n### Composable API\n\nThe following sections documents each available property on the `useFieldArray` composable.\n\n<CodeTitle level=\"4\">\n\n`fields: Ref<FieldArrayEntry<TValue>[]>`\n\n</CodeTitle>\n\nThis is a **read-only** version of your array items, wrapped inside a `FieldArrayEntry` object which has the following interface:\n\n```ts\ninterface FieldEntry<TValue = unknown> {\n  // The actual value of the item as readonly, this is what exists in the form values\n  value: TValue;\n  // a value you can use as a key for iteration, automatically generated\n  key: string | number;\n  // true if this is the first array item\n  isFirst: boolean;\n  // true if this is the last array item\n  isLast: boolean;\n}\n```\n\n```js\n// call composable in component setup to get readable version of links array\nconst { fields } = useFieldArray('links');\n```\n\n<CodeTitle level=\"4\">\n\n`push(item: any)`\n\n</CodeTitle>\n\nAdds an item to the end of the array.\n\n```js\n// get push function from composable in component setup\nconst { push } = useFieldArray('links');\n\n// call push function within custom function\nconst myPushFunction = () => {\n  // adds a new item to the array\n  push({ url: '' });\n};\n```\n\n<CodeTitle level=\"4\">\n\n`prepend(item: any)`\n\n</CodeTitle>\n\nAdds an item to the start of the array.\n\n```js\n// get prepend function from composable in component setup\nconst { prepend } = useFieldArray('links');\n\n// call prepend function within custom function\nconst myPrependFunction = () => {\n  // adds a new item to the array\n  prepend({ url: '' });\n};\n```\n\n<CodeTitle level=\"4\">\n\n`remove(idx: number)`\n\n</CodeTitle>\n\nRemoves the item at the specified index from the array if it exists.\n\n```js\n// get remove function from composable in component setup\nconst { remove } = useFieldArray('links');\n\n// call remove function within custom function\nconst myRemoveFunction = () => {\n  // removes the second item from the array\n  remove(1);\n};\n```\n\n<CodeTitle level=\"4\">\n\n`swap(idxA: number, idxB: number)`\n\n</CodeTitle>\n\nSwaps the items at the given indexes with each other. Both indexes must exist in the array or it won't have an effect.\n\n```js\n// get swap function from composable in component setup\nconst { swap } = useFieldArray('links');\n\n// call swap function within custom function\nconst mySwapFunction = () => {\n  // Swaps the 4th item with the 5th\n  swap(3, 4);\n};\n```\n\n<CodeTitle level=\"4\">\n\n`insert(idx: number, item: any)`\n\n</CodeTitle>\n\nAdds an item at the specified index. If the specified index will place the item out of bounds (i.e: larger than length) the operation will be ignored, you still can add items as the last item of the array.\n\n```js\n// get insert function from composable in component setup\nconst { insert } = useFieldArray('links');\n\n// call insert function within custom function\nconst myInsertFunction = () => {\n  // inserts a new item to the array at the second index\n  insert(1, { url: '' });\n};\n```\n\n<CodeTitle level=\"4\">\n\n`update(idx: number, value: any)`\n\n</CodeTitle>\n\nUpdates the value at the specified index, note that it doesn't merge the values if they are objects. If the specified index is outside the array boundary the operation will be ignored.\n\n```js\n// get update function from composable in component setup\nconst { update } = useFieldArray('links');\n\n// call update function within custom function\nconst myUpdateFunction = () => {\n  // updates the 2nd item value\n  update(1, { url: '' });\n};\n```\n\n<CodeTitle level=\"4\">\n\n`replace(items: any[])`\n\n</CodeTitle>\n\nReplaces the entire array of fields.\n\n```js\n// get replace function from composable in component setup\nconst { replace } = useFieldArray('links');\n\n// call replace function within custom function\nconst myReplaceFunction = () => {\n  // replace the entire array with these items\n  replace([{ url: 'https://google.com' }, { url: 'https://vuejs.org' }]);\n};\n```\n\n<CodeTitle level=\"4\">\n\n`move(oldIdx:number, newIdx: number)`\n\n</CodeTitle>\n\nMoves an array item to a different position within the array.\n\n```js\n// get move function from composable in component setup\nconst { move } = useFieldArray('links');\n\n// call move function within custom function\nconst myMoveFunction = () => {\n  // move array item to a different position\n  move(2, 1);\n};\n```\n"
  },
  {
    "path": "docs/src/pages/api/use-field.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: useField\ndescription: API reference for the useField composition API function\nmenuTitle: useField()\norder: 5\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport CodeTitle from '@/components/CodeTitle.vue';\n\n# useField\n\n`useField` is a custom composition API function that allows you to create data models that's automatically validated that you can then use to build your own custom input components with validation capabilities. It is very useful if you plan to build a UI component library that needs to have validation capabilities. In other words it acts as a primitive to allow you to compose validation logic into your components.\n\nThe most basic usage looks like this:\n\n```vue\n<template>\n  <div>\n    <input v-model=\"value\" />\n    <span>{{ errorMessage }}</span>\n  </div>\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\n// a simple `name` field with basic required validator\nconst { value, errorMessage } = useField('name', inputValue => !!inputValue);\n</script>\n```\n\nWhenever the `value` ref is updated it will be validated and the `errorMessage` ref will be automatically filled with the first error message. Usually you would bind the `value` ref to your inputs using `v-model` or any other means and whenever you want to validate your field you update the `value` binding with the new value.\n\nAdditionally you can use `yup` as a validator:\n\n```vue\n<script setup>\nimport { useField } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst { value, errorMessage } = useField('email', yup.string().email().required());\n</script>\n```\n\nYou are responsible for when the field validates, blurs or when its value changes. This gives you greater control over the `Field` component which may include or implement sensible defaults for most common use cases.\n\n## Usage with TypeScript\n\nYou can use `useField` with typescript and type the field's value type to ensure safety when manipulating it's value. The `useField` function is a generic function that receives the value type and applies it on the various interactions you have with its API.\n\n```ts\nconst { value, resetField } = useField<string>('email', yup.string().email());\n\nvalue.value = 1; // ⛔️  Error\nvalue.value = 'test@example.com'; // ✅\n\nresetField({\n  value: 1, // ⛔️  Error\n});\nresetField({\n  value: 'test@example.com', // ✅\n});\n```\n\nThe validation rules can be either a string, object, function or a yup schema:\n\n```js\n// Globally defined rules with `defineRule`, Laravel-like syntax\nuseField('password', 'required|min:8');\n\n// Globally defined rules object\nuseField('password', { required: true, min: 8 });\n\n// Simple validation function\nuseField('password', value => {\n  if (!value) {\n    return 'password is required';\n  }\n\n  if (value.length < 8) {\n    return 'password must be at least 8 characters long';\n  }\n\n  return true;\n});\n\n// Yup validation\nuseField('password', yup.string().required().min(8));\n```\n\n## API Reference\n\n### Composable API\n\nThe following sections documents each available property on the `useField` composable.\n\n<CodeTitle level=\"4\">\n\n`name: string | Ref<string> | () => string`\n\n</CodeTitle>\n\nThe field name, it can be a string or a reactive ref to a string or a getter than returns a string. It is used to identify the field and specify its value path.\n\n<CodeTitle level=\"4\">\n\n`value: Ref<TValue = unknown>`\n\n</CodeTitle>\n\nA reactive reference to the field's current value, can be changed and will trigger validation by default unless disabled by the `validateOnValueUpdate` option.\n\n```js\nconst { value } = useField('field', value => !!value);\n\nvalue.value = 'hello world'; // sets the value and validates the field\n```\n\nYou can also bind it with `v-model` to get two-way value binding with validation.\n\n<CodeTitle level=\"4\">\n\n`setValue: Ref<TValue = unknown>`\n\n</CodeTitle>\n\nA method to update the fields value.\n\n```js\nconst { setValue } = useField('field', value => !!value);\n\nsetValue('hello world') // sets the value and validates the field\n```\n\n<CodeTitle level=\"4\">\n\n`meta: FieldMeta<TValue = unknown>`\n\n</CodeTitle>\n\nContains useful information/flags about the field status, should be treated as **read only**.\n\n```ts\ninterface FieldMeta {\n  touched: boolean; // if the field has been blurred (via handleBlur)\n  dirty: boolean; // if the field has been manipulated (via handleChange)\n  valid: boolean; // if the field doesn't have any errors\n  pending: boolean; // if validation is in progress\n  initialValue?: any; // the field's initial value\n}\n```\n\n<DocTip title=\"The valid flag\">\n\nThe `valid` flag on the meta object can be tricky, because by default it stars off with `true` for a few moments, only then it is updated to its proper state.\n\nCombining your `valid` flag checks with `dirty` will yield the expected result based on user interaction.\n\n</DocTip>\n\n**usage**\n\n```js\nconst { meta } = useField('field', value => !!value);\n\nmeta; // { valid: true, dirty: true, .... }\n```\n\n<CodeTitle level=\"4\">\n\n`errors: Ref<string[]>`\n\n</CodeTitle>\n\nA reactive reference containing all error messages for the field, should be treated as **read only**\n\n```js\nconst { errors } = useField('field', value => !!value);\n\nerrors.value; // ['field is not valid']\n```\n\n<CodeTitle level=\"4\">\n\n`errorMessage: ComputedRef<string | undefined>`\n\n</CodeTitle>\n\nA computed reference that returns the first error in the `errors` array, a handy shortcut to display error messages\n\n```js\nconst { errorMessage } = useField('field', value => !!value);\n\nerrorMessage.value; // 'field is not valid' or undefined\n```\n\n<CodeTitle level=\"4\">\n\n`resetField: (state?: Partial<FieldState>) => void`\n\n</CodeTitle>\n\nResets the field's validation state, by default it reverts all `meta` object to their default values and clears out the error messages. It also updates the field value to its initial value without validating them.\n\n```js\nconst { resetField } = useField('field', value => !!value);\n\n// reset the field meta and its initial value and clears errors\nresetField();\n\n// reset the meta state, clears errors and updates the field value and its initial value\nresetField({\n  value: 'new value',\n});\n\n// resets the meta state, resets the field to its initial value and sets the errors\nresetField({\n  errors: ['bad field'],\n});\n\n// Marks the field as touched, while resetting its value and errors.\nresetField({\n  touched: true,\n});\n\n// Changes the meta, initial and current values and sets the errors for the field\nresetField({\n  value: 'new value',\n  touched: true,\n  errors: ['bad field'],\n});\n```\n\nNote that it is unsafe to use this function as an event handler directly, check the following snippet:\n\n```vue-html\n<!-- ⛔️ Unsafe -->\n<button @click=\"resetField\">Reset</button>\n\n<!-- ✅  Safe -->\n<button @click=\"resetField()\">Reset</button>\n```\n\nYou can also use `handleReset` which is a safe alternative for `resetField`.\n\n<CodeTitle level=\"4\">\n\n`setErrors: (errors: string | string[]) => void`\n\n</CodeTitle>\n\nSets then field errors, you can pass a single message string or an array of errors.\n\n```js\nconst { setErrors } = useField('field', value => !!value);\n\n// Sets the errors to a single error message\nsetErrors('field is required');\n\n// sets the errors to multiple error messages\nsetErrors(['field is required', 'field must be valid']);\n\n// clears the errors\nsetErrors([]);\n```\n\n<CodeTitle level=\"4\">\n\n`handleReset: () => void`\n\n</CodeTitle>\n\nSimilar to `resetField` but it doesn't accept any arguments and can be safely used as an event handler. The values won't be validated after reset.\n\n```js\nconst { handleReset } = useField('field', value => !!value);\n\n// reset the field validation state and its initial value\nhandleReset();\n```\n\n<CodeTitle level=\"4\">\n\n`validate: () => Promise<{ errors: string[] }>`\n\n</CodeTitle>\n\nValidates the field's current value and returns a promise that resolves with an object containing the error messages emitted by the various rule(s).\n\n```js\nconst { validate } = useField('field', value => !!value);\n\n// trigger validation\nawait validate();\n```\n\n<CodeTitle level=\"4\">\n\n`handleChange: (evt: Event | any) => void`\n\n</CodeTitle>\n\nUpdates the field value, and validates the field. Can be used as an event handler to bind on the field. If the passed argument isn't an event object it will be used as the new value for that field.\n\nIt sets the `dirty` meta flag to `true`\n\n```vue\n<template>\n  <input @change=\"handleChange\" type=\"text\" />\n</template>\n\n<script setup>\nconst { handleChange } = useField('field');\n\nhandleChange('new value'); // update field value and validate it\nhandleChange('new value 2', false); // update field value without validating it (you have to turn off validateOnValueUpdate)\n</script>\n```\n\n<CodeTitle level=\"4\">\n\n`handleBlur: (evt: Event | any) => void`\n\n</CodeTitle>\n\nSets the `touched` meta flag to `true`\n\n```vue\n<template>\n  <input @blur=\"handleBlur\" type=\"text\" />\n</template>\n\n<script setup>\nconst { handleBlur } = useField('field');\n</script>\n```\n\n<CodeTitle level=\"4\">\n\n`setTouched: (isTouched: boolean) => void`\n\n</CodeTitle>\n\nSets the `touched` meta flag for this field, useful to create your own `blur` handlers\n\n```js\nconst { setTouched } = useField('field', value => !!value);\n\n// mark the field as touched\nsetTouched(true);\n```\n\n<CodeTitle level=\"4\">\n\n`checked: ComputedRef<boolean> | undefined`\n\n</CodeTitle>\n\nA computed property that indicates if the field should be checked or unchecked, only available if `type=checkbox` or `type=radio` in field options. Useful if you are creating [custom checkboxes](/examples/custom-checkboxes).\n\n```js\nconst { checked } = useField('field', ..., {\n  type: 'checkbox',\n  valueProp: 'Checkbox value'\n});\n\nchecked.value; // true or false\n```\n\nFor more information on how you might use the `checked` property, check the [custom checkboxes example](/examples/custom-checkboxes).\n\n## Additional options\n\nTo pass additional configuration to your fields you can use more options.\n\n```vue\n<template>\n  <div>\n    <input v-model=\"value\" />\n    <span>{{ errorMessage }}</span>\n  </div>\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\n// a simple `company` field with some options passed into it\nconst { value, errorMessage } = useField('company', ..., {\n  label: 'Your company',\n  initialValue: ''\n});\n</script>\n```\n\n| Field options                          |\n| -------------------------------------- |\n| `type`                                 |\n| `label`                                |\n| `initialValue`                         |\n| `validateOnMount`                      |\n| `bails `                               |\n| `standalone`                           |\n| `validateOnValueUpdate`                |\n| `keepValueOnUnmount`                   |\n| `syncVModel`                           |\n| `checkedValue` (checkbox/radio only)   |\n| `uncheckedValue` (checkbox/radio only) |\n"
  },
  {
    "path": "docs/src/pages/api/use-form.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: useForm\ndescription: API reference for the useForm composition API function\nmenuTitle: useForm()\norder: 6\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport CodeTitle from '@/components/CodeTitle.vue';\nimport DocBadge from '@/components/DocBadge.vue';\n\n# useForm\n\n`useForm` is a custom composition API function that allows you to group fields created by `useField` and aggregates their state. It should be used to create logical forms or custom form components similar to the `<Form/>` component which is just a consumer of `useForm`.\n\n<DocTip type=\"warn\">\n\nNote that you can only have one `useForm` per component. See this issue: https://github.com/logaretm/vee-validate/issues/4550\n\n</DocTip>\n\n## Field Types\n\nThe `useForm` function has field typing capabilities if you need it, getting type information for your fields and their values can be very powerful when building complex forms.\n\nBy unlocking the field type you automatically get more strict information for the various properties/methods exposed by `useForm` like `setErrors` and `setTouched`. There are two ways you can get the advanced typing information for your fields, the first is to provide a generic type to `useForm`.\n\n```ts\nimport { useForm } from 'vee-validate';\n\ninterface LoginForm {\n  email: string;\n  password: string;\n}\n\n// in your setup\nconst { errors } = useForm<LoginForm>();\n```\n\nOr simply provide initial values to `useForm` and it will automatically pick up the type of `initialValues` and use it for the field types.\n\n```ts\nimport { useForm } from 'vee-validate';\n\nconst { errors, setErrors, setFieldValue } = useForm({\n  initialValues: {\n    email: '',\n    password: '',\n  },\n});\n```\n\nAlternatively, you can use a [standard schema](https://standardschema.dev/) to infer the form types from the validation schema if you are using yup or zod.\n\nWhichever approach you prefer, you get full type information for your fields for all the functions exposed by `useForm`, here are a few examples.\n\n```ts\nimport { useForm } from 'vee-validate';\n\ninterface LoginForm {\n  email: string;\n  password: string;\n}\n\n// in your setup\nconst { errors, setErrors, setFieldValue } = useForm<LoginForm>();\n\nerrors.value; // typed as { email?: string; password?: string }\n\nsetErrors({\n  email: 'This field is invalid', // auto-complete for `email` and `password`\n});\n\nsetFieldValue('email', 'example@gmail.com'); // auto-complete for the field name and its value type\n```\n\nFor example if you were to do this in the previous example:\n\n```ts\nsetFieldValue('age', 5); // ⛔️ TypeScript error\nsetFieldValue('email', 5); // ⛔️ TypeScript error\n```\n\nIt will error out because `age` is not defined in the `LoginForm` type you defined. The second line errors out because the `email` field is typed as a `string`.\n\n## API Reference\n\n### Arguments\n\n<CodeTitle level=\"4\">\n\n`validationSchema?: any`\n\n</CodeTitle>\n\nEnables form-level validation, uses the specified schema to validate the fields. The schema can be either valid vee-validate global validators or functions or a yup object schema.\n\n<CodeTitle level=\"4\">\n\n`initialValues?: Record<string, any>`\n\n</CodeTitle>\n\nThe initial values for the form.\n\n```js\nconst { ... } = useForm({\n  initialValues: {\n    email: 'example@gmail.com',\n    password: 'p@$$w0rd',\n  }\n});\n```\n\n<CodeTitle level=\"4\">\n\n`initialErrors?: Record<string, string>`\n\n</CodeTitle>\n\nThe initial errors for the fields, useful for non hydrated SSR applications like Laravel, errors are applied on mounted.\n\n```js\nconst { ... } = useForm({\n  initialErrors: {\n    email: 'This email is invalid',\n    password: 'Password too short',\n  }\n});\n```\n\n<CodeTitle level=\"4\">\n\n`initialTouched?: Record<string, any>`\n\n</CodeTitle>\n\nThe initial touched status for the form fields, applied on mounted.\n\n```js\nconst { ... } = useForm({\n  initialTouched: {\n    email: true, // touched\n    password: false, // non-touched\n  }\n});\n```\n\n<CodeTitle level=\"4\">\n\n`validateOnMount?: boolean`\n\n</CodeTitle>\n\nIf true, it will trigger validation for all fields once the form component is mounted.\n\n<CodeTitle level=\"4\">\n\n`name?: string`\n\n</CodeTitle>\n\nIf set, it will be used as the form's name in the devtools.\n\n```js\nconst { ... } = useForm({\n  name: 'LoginForm', // Defaults to \"Form\"\n});\n```\n\n### Composable API\n\nThe following sections documents each available property on the `useForm` composable.\n\n<CodeTitle level=\"4\">\n\n`errors: Ref<Record<string, string>>`\n\n</CodeTitle>\n\nAn object that maps field names to their error messages, it only takes the first error message of each field if multiple exists.\n\n```js\nconst { errors } = useForm();\n\nerrors.value; // access the errors value\n```\n\n<CodeTitle level=\"4\">\n\n`errorBag: Ref<Record<string, string>>`\n\n</CodeTitle>\n\nAn object that maps field names to all of their error messages.\n\n```js\nconst { errorBag } = useForm();\n\nerrorBag.value.email; // email field errors\n```\n\nHere is an example of its shape:\n\n```js\n{\n  email: [\"this field is required\", \"this field must be a valid email\"],\n  password: \"too short\"\n}\n```\n\nAny fields without error messages will not be included in the object. So you can safely iterate over it with `Object.keys()` knowing all the included fields are invalid.\n\n<CodeTitle level=\"4\">\n\n`isSubmitting: Ref<boolean>`\n\n</CodeTitle>\n\nIndicates if the submission handler is still running, once it resolves/rejects it will be automatically set to false again.\n\n```js\nconst { isSubmitting } = useForm();\n\nisSubmitting.value; // true or false\n```\n\n<CodeTitle level=\"4\">\n\n`isValidating: Ref<boolean>`\n\n</CodeTitle>\n\nIndicates if the validate function is still running, once validate function is done it will be automatically set to `false` again.\n\n```js\nconst { isValidating } = useForm();\n\nisValidating.value; // true or false\n```\n\n<CodeTitle level=\"4\">\n\n`meta: ComputedRef<FormMeta>`\n\n</CodeTitle>\n\nA computed property that contains an aggregated meta information/flags reflecting the state of all the fields inside the form.\n\n```ts\ninterface FormMeta {\n  touched: boolean; // if at least one field is touched (was blurred)\n  dirty: boolean; // if at least one field is dirty (manipulated)\n  valid: boolean; // if the form doesn't have any error messages\n  pending: boolean; // if at least one field is pending validation\n  initialValues?: Record<string, any>; // a map of the form's initial values\n}\n```\n\n**usage**\n\n```js\nconst { meta } = useForm();\n\nmeta.value; // { valid: false, invalid: true, dirty: true, .... }\n```\n\n<CodeTitle level=\"4\">\n\n`values: Record<string, any>`\n\n</CodeTitle>\n\nA reactive property that contains the current form values, you should not try to mutate it directly.\n\n```js\nconst { values } = useForm();\n\nvalues; // { email: 'something@gmail.com', .... }\n```\n\n<CodeTitle level=\"4\">\n\n`setFieldError: (field: string, message: string | undefined) => void`\n\n</CodeTitle>\n\nSets a field's error message, useful for setting messages form an API or that are not available as a validation rule. Setting the message to `undefined` or an empty string clears the errors and marks the field as valid.\n\n```js\nconst { setFieldError } = useForm();\n\nsetFieldError('email', 'this email is already taken');\n\n// Mark field as valid\nsetFieldError('email', undefined);\n```\n\nIf you try to set an error for a field that doesn't exist, it will be added to the form's errors object and it will change the form's `valid` state\n\n<CodeTitle level=\"4\">\n\n`setErrors: (fields: Record<string, string | undefined>) => void`\n\n</CodeTitle>\n\nSets multiple fields error messages, uses `setFieldError` internally.\n\n```js\nconst { setErrors } = useForm();\n\nsetErrors({\n  email: 'this email is already taken',\n  password: 'someone already has this password 🤪',\n  firstName: undefined, // clears errors and marks the field as valid\n});\n```\n\n<DocTip>\n\nAny missing fields you didn't pass to `setErrors` will be unaffected and their state will not change\n\n</DocTip>\n\n<CodeTitle level=\"4\">\n\n`setFieldValue: (field: string, value: any) => void`\n\n</CodeTitle>\n\nSets a field's value, if a field does not exist it will not be reflected in the `values` ref. This will trigger validation on the field whose value changed.\n\n```js\nconst { setFieldValue } = useForm();\n\nsetFieldValue('email', 'example@gmail.com');\n```\n\nIf you try to set a value for a field that doesn't exist, it will be added to the form's values object and will stay there until the next `resetForm` is called.\n\n<CodeTitle level=\"4\">\n\n`setValues: (fields: Record<string, any>) => void`\n\n</CodeTitle>\n\nSets all fields values, will trigger validation for the changed fields.\n\n```js\nconst { setValues } = useForm();\n\nsetValues({\n  email: 'example@gmail.com',\n  password: 'p@a$$W0rD',\n});\n```\n\n<CodeTitle level=\"4\">\n\n`setFieldTouched: (field: string, isTouched: boolean) => void`\n\n</CodeTitle>\n\nSets a field's `touched` meta flag, if you set it for a non-existing field it will have no effect.\n\n```js\nconst { setFieldTouched } = useForm();\n\nsetFieldTouched('email', true);\n```\n\n<CodeTitle level=\"4\">\n\n`setTouched: (fields: Record<string, boolean>) => void`\n\n</CodeTitle>\n\nSets multiple fields `touched` meta flag, does not validate.\n\n```js\nconst { setTouched } = useForm();\n\nsetTouched({\n  email: true,\n  password: false,\n});\n```\n\n<CodeTitle level=\"4\">\n\n`validate: () => Promise<{ valid: boolean; errors: Record<string, string>}>`\n\n</CodeTitle>\n\nValidates all the fields and populates the `errors` object, returns a promise that resolves to an object containing aggregated validation result of all fields.\n\n```js\nconst { validate } = useForm();\n\nconst { valid, errors } = await validate();\n```\n\n<CodeTitle level=\"4\">\n\n`validateField: (field: string) => Promise<{ valid: boolean; errors: string[] }>`\n\n</CodeTitle>\n\nValidates a specific field inside the form, returns a promise that resolves to an object containing the validation result.\n\n```js\nconst { validateField } = useForm();\n\nconst { valid, errors } = await validateField('email');\n```\n\n<CodeTitle level=\"4\">\n\n`handleSubmit: (cb: SubmissionHandler) => (evt?: Event) => Promise<void>`\n\n</CodeTitle>\n\nThis is a higher order function used to create `submit` event handlers, You shouldn't use it as a handler for the events directly but rather use it to create those handlers.\n\nThe handlers created using this function will automatically prevent form submission and stop the propagation of the submit event.\n\nIt accepts a function which runs after validating the form and if all fields are valid. The callback you pass will receive the form values as the first argument, which is an object containing the fields' values.\n\n```vue\n<template>\n  <form @submit=\"onSubmit\"></form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { handleSubmit } = useForm();\n\n// use `onSubmit` as an event handler for your forms\nconst onSubmit = handleSubmit(values => {\n  // pretty print the values object\n  alert(JSON.stringify(values, null, 2));\n});\n</script>\n```\n\nFor advanced forms, you may need to trigger various actions on the form in the `submit` handler. Your callback receives a `FormActions` object as part of the second argument along with the event object that triggered the submission if available.\n\n```js\nconst { handleSubmit } = useForm();\n\nconst onSubmit = handleSubmit((values, actions) => {\n  // Send data to API\n  alert(JSON.stringify(values, null, 2));\n\n  // the form object contains useful methods\n  // set a single field value\n  actions.setFieldValue('field', 'hello');\n  // set multiple fields values\n  actions.setValues({ email: 'value', password: 'hi' });\n  // set a single field error\n  actions.setFieldError('field', 'this field is bad');\n  // set multiple fields errors\n  actions.setErrors({ email: 'bad email', password: 'bad password' });\n  // reset the form\n  actions.resetForm();\n});\n```\n\n`handleSubmit` contains a `withControlled` function that you can use to only submit fields controlled by `useField` or `useFieldModel`. Read the [guide](/guide/composition-api/handling-forms) for more information.\n\n```vue\n<template>\n  <form @submit=\"onSubmit\"></form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { handleSubmit } = useForm();\n\nconst onSubmit = handleSubmit.withControlled(values => {\n  // Send only controlled values to the API\n  // Only fields declared with `useField` or `useFieldModel` will be printed\n  alert(JSON.stringify(values, null, 2));\n});\n</script>\n```\n\n<DocTip title=\"Virtual Forms\">\n\nYou can use `handleSubmit` to submit **virtual forms** that may use `form` elements or not. As you may have noticed the snippet above doesn't really care if you are using forms or not.\n\n</DocTip>\n\n<CodeTitle level=\"4\">\n\n`submitForm: (evt: Event) => void`\n\n</CodeTitle>\n\nUnlike `handleSubmit` this function can be used as an event handler for form `submit` event, it will prevent the propagation and submission of the forms using it as long as they are invalid. Once all the fields are valid it will submit the form with the native HTML behavior following the `form` element's `action` and `method` attributes.\n\nThis is useful if you plan to handle form submissions using a backend API like Laravel or whatever.\n\n```vue\n<template>\n  <form @submit=\"submitForm\" action=\"/api/login\" method=\"post\">\n    <!-- ... -->\n  </form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { submitForm } = useForm();\n</script>\n```\n\n<CodeTitle level=\"4\">\n\n`submitCount: number`\n\n</CodeTitle>\n\nThe number of submission attempts by the user, it increments whenever `submitForm` or `handleSubmit` callback are called.\n\n<CodeTitle level=\"4\">\n\n`resetForm: (state?: Partial<FormState>, opts?: ResetFormOpts) => void`\n\n</CodeTitle>\n\nClears error messages, resets the meta state for all fields and reverts their values to their initial state as well as the `submitCount` state. Accepts an optional object containing the new form state, useful if you need to reset the form values to different values other than their initial state.\n\nThis is the `FormState` interface:\n\n```ts\ntype TouchedFlags = { [k: string]: boolean };\n\ninterface FormState {\n  // any error messages\n  errors: Record<string, string>;\n  // touched meta flags\n  touched: TouchedFlags;\n  // Form Values\n  values: Record<string, any>;\n  // The form submit attempts count\n  submitCount: number;\n}\n```\n\nIn this example, the `resetForm` function is updating the fields current values to the ones provided, these values will be used as the new initial values for future `resetForm` or `handleReset` calls. This also applies if the `Field` component or `useField` used their individual `resetField` function.\n\n```js\nconst { resetForm } = useForm();\n\n// ...\nfunction onSubmit(values) {\n  // send values to the API\n  // ...\n\n  // Reset the form values\n  resetForm({\n    values: {\n      firstName: '',\n      lastName: '',\n      email: '',\n      password: '',\n    },\n  });\n}\n```\n\nBy default `resetForm` merges the previous initial values with the new one provided, meaning only the provided ones will be overwritten. You can overwrite all the fields by passing `force: true` in the second argument.\n\n```js\nconst { values, resetForm } = useForm({\n  initialValues: { fname: '123', lname: '456' },\n});\n\n// values: { fname: 'test', lname: '456' }\nresetForm({ values: { fname: 'test' } });\n\n// values: { fname: 'test' }\nresetForm({ values: { fname: 'test' } }, { force: true });\n```\n\n<CodeTitle level=\"4\">\n\n`handleReset: () => void`\n\n</CodeTitle>\n\nClears error messages, resets the meta state for all fields and reverts their values to their initial state as well as the `submitCount` state. you can use this function as handler for the `reset` events on native form elements.\n\n```vue\n<template>\n  <form @reset=\"handleReset\">\n    <!-- ... -->\n  </form>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { handleReset } = useForm();\n\n// you can use it in your code\nhandleReset();\n</script>\n```\n\n<CodeTitle level=\"4\">\n\n`useFieldModel`\n\n</CodeTitle>\n\n<DocTip>\n\nThis is deprecated, please use `defineField` instead.\n\n</DocTip>\n\nThis creates a bindable two-way model value for the specified fields, there are a couple of signatures for `useFieldModel`. Must be called in the `setup` function.\n\n`useFieldModel` accepts either a single field path or multiple via an array. You can use either root field paths or nested paths like `some.user.path` with dot notation.\n\n```vue\n<template>\n  <input name=\"email\" v-model=\"email\" />\n  <span>{{ errors.email }}</span>\n\n  <input name=\"password\" v-model=\"password\" type=\"password\" />\n  <span>{{ errors.password }}</span>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { errors, useFieldModel } = useForm();\n\nconst email = useFieldModel('email');\nconst password = useFieldModel('password');\n\n// or multiple models at once\nconst [email, password] = useFieldModel(['email', 'password']);\n</script>\n```\n\n<CodeTitle level=\"4\">\n\n`defineInputBinds`\n\n</CodeTitle>\n\n<DocTip>\n\nThis is deprecated, please use `defineField` instead.\n\n</DocTip>\n\nThis creates a bindable object for the specified field. The bindable object only works with native HTML input elements, for components use `defineComponentBinds` instead.\n\nThe `defineInputBinds` must be called in the `setup` function.\n\n`defineInputBinds` accepts a single field path, You can use either root field paths or nested paths like `some.user.path` with dot notation.\n\n```vue\n<template>\n  <input v-bind=\"email\" />\n  <span>{{ errors.email }}</span>\n\n  <input v-bind=\"password\" type=\"password\" />\n  <span>{{ errors.password }}</span>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { errors, defineInputBinds } = useForm();\n\nconst email = defineInputBinds('email');\nconst password = defineInputBinds('password');\n</script>\n```\n\n<CodeTitle level=\"4\">\n\n`defineComponentBinds`\n\n</CodeTitle>\n\n<DocTip>\n\nThis is deprecated, please use `defineField` instead.\n\n</DocTip>\n\nThis creates a bindable object for the specified field. The bindable object only works with components, for native HTML input elements use `defineInputBinds` instead.\n\nThe `defineComponentBinds` must be called in the `setup` function.\n\n`defineComponentBinds` accepts a single field path, You can use either root field paths or nested paths like `some.user.path` with dot notation.\n\n```vue\n<template>\n  <MyTextInput v-bind=\"email\" />\n  <span>{{ errors.email }}</span>\n\n  <MyTextInput v-bind=\"password\" type=\"password\" />\n  <span>{{ errors.password }}</span>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\nimport MyTextInput from '@/components/MyTextInput.vue';\n\nconst { errors, defineComponentBinds } = useForm();\n\nconst email = defineComponentBinds('email');\nconst password = defineComponentBinds('password');\n</script>\n```\n\n<CodeTitle level=\"4\">\n\n`defineField`\n\n</CodeTitle>\n\nThis function returns a model and a props/attributes pair.\n\nThe `defineField` must be called in the `setup` function.\n\n`defineField` accepts a single field path, You can use either root field paths or nested paths like `some.user.path` with dot notation.\n\n```vue\n<template>\n  <input v-model=\"email\" v-bind=\"emailProps\" />\n  <span>{{ errors.email }}</span>\n\n  <input v-model=\"password\" v-bind=\"passwordProps\" type=\"password\" />\n  <span>{{ errors.password }}</span>\n</template>\n\n<script setup>\nimport { useForm } from 'vee-validate';\n\nconst { errors, defineField } = useForm();\n\nconst [email, emailProps] = defineField('email');\nconst [password, passwordProps] = defineField('password');\n</script>\n```\n\nThis function also works with custom components.\n\nYou can configure the props/attributes that are bound to the component by passing a second argument to `defineField`. You can use this configuration to adjust the `field` validation behavior and more with the individual elements you are using or the component library of your choice. Check the [UI library examples](/examples/ui-libraries) for live examples.\n\n```ts\nconst [field, props] = defineField('field', {\n  // A getter that computes and adds any additional props to the component\n  // It receives the current field state as an argument\n  props(state) {\n    // This is just an example, by default this is an empty object\n    return {\n      'aria-invalid': state.errors.length > 0 ? 'true' : 'false',\n    };\n  },\n  // A label for the field, only used with global validation rules\n  label: 'a label',\n  // Validates when `blur` event is emitted from the element/component\n  validateOnBlur: true,\n  // Validates when `change` event is emitted from the element/component\n  validateOnChange: true,\n  // Validates when `input` event is emitted from the element/component\n  validateOnInput: false,\n  // Validates when the returned model value changes\n  validateOnModelUpdate: true,\n});\n```\n\nYou can also have a lazy configuration by passing a function that returns the configuration object. The only difference is `props` is now a plain object instead of a getter function.\n\nThis means you can change any of the configuration based on the field state:\n\n```ts\nconst [field, props] = defineField('field', state => {\n  return {\n    // A getter that computes and adds any additional props to the component\n    props: {\n      // This is just an example, by default this is an empty object\n      'aria-invalid': state.errors.length > 0 ? 'true' : 'false',\n    },\n    // Validates when `blur` event is emitted from the element/component\n    validateOnBlur: true,\n    // Validates when `change` event is emitted from the element/component\n    validateOnChange: true,\n    // Validates when `input` event is emitted from the element/component\n    validateOnInput: false,\n    // Validates when the returned model value changes\n    validateOnModelUpdate: true,\n  };\n});\n```\n"
  },
  {
    "path": "docs/src/pages/examples/array-fields.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Array Fields\ndescription: How to implement array fields in vee-validate\norder: 5\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Array Fields\n\nThis example shows how to implement array fields in vee-validate\n\n<LiveExample client:visible id=\"vee-validate-v4-array-fields\" />\n"
  },
  {
    "path": "docs/src/pages/examples/async-validation.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Async Validation\ndescription: Using async validation with vee-validate\norder: 3\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Async Validation\n\nThis is an example of field that uses an async rule to check if an email is available.\n\n<LiveExample client:visible id=\"vee-validate-v4-async-validation\" />\n"
  },
  {
    "path": "docs/src/pages/examples/checkboxes-and-radio.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Checkbox and Radio Inputs\ndescription: Validating checkboxes and Radio inputs\norder: 1\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Checkbox and Radio Inputs\n\nThe documentation has so far avoided using `type=\"radio\"` and `type=\"checkbox\"` inputs because of their complex nature, however vee-validate supports both HTML checkboxes and radio inputs as well as your custom components that act as such (with caveats).\n\nThe only requirements are that the fields:\n\n<div class=\"features\">\n\n- Must be inside a `Form` component or a [derivative (using useForm)](/api/use-form#creating-custom-form-components)\n- Must Have the same `name` prop\n- Should have a `type` attribute\n\n</div>\n\n<DocTip title=\"Slot props and custom components\">\n\nWhen using `Field` slot props with checkbox/radio components, you still need to provide the `type` and `value` props to the `Field` node itself.\n\n```vue-html\n<Field v-slot=\"{ field }\" name=\"terms\" type=\"checkbox\" :value=\"true\" :unchecked-value=\"false\">\n  <label>\n    <input type=\"checkbox\" name=\"terms\" v-bind=\"field\" :value=\"true\" />\n    I agree\n  </label>\n</Field>\n```\n\nThe same caveat applies if you are rendering another component with `as` prop:\n\n```vue-html\n<Field as=\"my-checkbox\" name=\"terms\" type=\"checkbox\" :value=\"true\" />\n```\n\n</DocTip>\n\n## Validating Radio Inputs\n\nvee-validate handles radio input groups as long as they have the `type=\"radio\"` and the same `name` prop value. The selected value will be present in the `values` object.\n\n<LiveExample client:visible id=\"vee-validate-v4-radio\" />\n\n## Validating Checkbox Inputs\n\nvee-validate handles checkboxes as long as they have the `type=\"checkbox\"` prop and the same `name` prop value. The selected values will be collected in an array similar to what `v-model` does.\n\n<LiveExample client:visible id=\"vee-validate-v4-checkboxes\" />\n\nIf there is only one checkbox then its value will be directly assigned in the `values` object without binding it in an array.\n"
  },
  {
    "path": "docs/src/pages/examples/cross-field-validation.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Cross-Field Validation\ndescription: Validating input values depending on other inputs' values\norder: 4\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Cross-Field Validation\n\nThis example shows how to create a password-confirmation-like rules using either `yup` or global validators.\n\n<LiveExample client:visible id=\"vee-validate-v4-cross-field-validation\" />\n"
  },
  {
    "path": "docs/src/pages/examples/custom-checkboxes.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Custom Checkboxes\ndescription: Creating validatable checkbox inputs\norder: 6\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Custom Checkboxes\n\nCheckboxes are more complex than regular text inputs, because there is always two states to keep track of which can be confusing at first. Mainly you should keep track of:\n\n- Each individual input's value\n- Which inputs are current selected\n\nTo make this easier, remember that native checkboxes behave as a group while each input maintains it's own value. Then a checkbox said to be checked when either:\n\n- It's value is the one currently selected\n- It's value is included in the ones selected\n\nThis is because of the nature of checkboxes behaving as **\"multi-value\"** form inputs, so you need to keep track of each input's value and the currently selected one(s).\n\nWith all of that in mind, vee-validate offers simple abstractions for checkboxes. You can build your own checkboxes with vee-validate's `useField` function which gives you the full capabilities of validation in a composable fashion.\n\nBecause `useField` isn't aware of what kind of input will be composed with it, you will need to specify that the input is of type `checkbox` and pass a `checkedValue` as well which represents that single field's value. By doing so, you gain access to `checked` prop which tells you if the checkbox should be selected.\n\n```js\nimport { useField } from 'vee-validate';\n\nexport default {\n  props: {\n    // The group's value\n    modelValue: {\n      type: null,\n    },\n    // Field's own value\n    value: {\n      type: null,\n    },\n    name: {\n      type: String,\n    },\n    rules: {\n      type: String,\n      default: undefined,\n    },\n  },\n  setup(props) {\n    // We pass a function to make sure the name stays reactive\n    const { checked, handleChange } = useField(() => props.name, props.rules, {\n      // 👇 These are important\n      type: 'checkbox',\n      checkedValue: props.value,\n    });\n\n    // select/unselect the input\n    handleChange(props.value);\n\n    return {\n      checked, // readonly\n      handleChange,\n    };\n  },\n};\n```\n\nvee-validate handles some of the complexities of the checkbox inputs nature, by default if a checkbox field is registered it will be treated as a single input until another checkbox with the same name is registered. Then they will be treated as a group, and their values will affect the group value when they are selected or not.\n\nHere is a live example of a custom checkbox input:\n\n<LiveExample client:visible id=\"vee-validate-v4-custom-checkboxes\" />\n\n<DocTip>\n\nYou can also specify a custom `uncheckedValue` which sets the input value to when it is unchecked.\n\n```js\nconst { checked, handleChange } = useField('toa', undefined, {\n  // Will make the checkbox set its value to true/false if it was checked or not\n  type: 'checkbox',\n  checkedValue: true,\n  uncheckedValue: false,\n});\n```\n\n</DocTip>\n"
  },
  {
    "path": "docs/src/pages/examples/custom-inputs.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Custom Inputs\ndescription: Building custom inputs with useField()\norder: 2\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Custom Inputs\n\nMore often than not, you will have complex requirements for your inputs. Like a custom design, multiple UI states, validation and more. You can easily build your custom components with `useField()` composable function. While it is possible to build your inputs with `<Field />` component it is not recommended as you won't have access to many of the underlying features to manage your UI state and you would rely on scoped slot props which is only available in the template.\n\n`useField` allows you to hook into the many underlying features of the `Field` component in a composable manner that you can easily integrate it in your UI, and on top of that your custom components will work seamlessly with `<Form />` component or `useForm` without any intervention on your part.\n\nIn the following example we have a complex `TextInput` component that we use for many types of fields.\n\n<LiveExample client:visible id=\"vee-validate-v4-custom-inputs\" />\n"
  },
  {
    "path": "docs/src/pages/examples/dynamic-validation-triggers.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Dynamic validation triggers\ndescription: Dynamic interaction for your inputs\norder: 11\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Dynamic validation triggers\n\nIn previous versions of vee-validate you could configure what events trigger the validation based on the field state. This feature was called \"interaction modes\". In vee-validate v4 this feature was removed because it is now possible to implement it with the composition API.\n\nThis example should help you figure out how to migrate this feature from older vee-validate versions.\n\n<LiveExample client:visible id=\"vee-validate-v4-dynamic-validation-triggers\" />\n"
  },
  {
    "path": "docs/src/pages/examples/multistep-form-wizard.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Multi-step Form Wizard\ndescription: a multi-step form wizard\norder: 7\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Multi-step Form Wizard\n\nThese examples showcases a simple multi-step form (form wizard), with `next` and `previous` step navigation.\n\n## Higher Order Components\n\nThis example uses the higher-order components only.\n\n<LiveExample client:visible id=\"vee-validate-v4-hoc-multi-step-form\" />\n\n## Composition API\n\nThis example uses the composition API to construct a system of `<FormStep>` and `<FormWizard>` components to make building form steps easier.\n\n<LiveExample client:visible id=\"vee-validate-v4-multi-step-form-composition\" />\n"
  },
  {
    "path": "docs/src/pages/examples/ui-libraries.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Popular UI Libraries\ndescription: Validating popular Vue.js UI libraries with examples\norder: 10\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\n\n# UI Libraries Examples\n\nMost popular Vue.js UI libraries come with their own built-in form logic and some may tackle a lot of what vee-validate tackles. If you find yourself not satisfied with said library's logic, you can add vee-validate power up these components.\n\nvee-validate is UI-agnostic, it doesn't offer any special treatment for the elements/components as long as they emit the right events.\n\nIntegrating vee-validate can be different for each UI library, it mostly depends on the library's ability to outsource the form logic to 3rd party logic and how it tracks the form field values.\n\nIn the next few examples you will find examples on how to do that in various ways with the most popular Vue.js libraries in no particular order.\n\n## Shadcn Vue\n\n> Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.\n\nShadCN has an official guide on how to use vee-validate with their components, check it out [here](https://www.shadcn-vue.com/docs/components/form).\n\n## Vuetify\n\n> [Vuetify](https://vuetifyjs.com/en/) is a no design skills required UI Library with beautifully handcrafted Vue Components.\n\n<LiveExample client:visible id=\"vee-validate-v4-vuetify\" click-to-load preview-only />\n\nCheck their [official example here](https://vuetifyjs.com/en/components/forms/#vee-validate).\n\n## PrimeVue\n\n> [PrimeVue](https://primevue.org/) is a rich set of open source UI Components for Vue.\n\n<LiveExample client:visible id=\"vee-validate-v4-prime-vue\" click-to-load preview-only />\n\nCheck their [official example here](https://primevue.org/inputtext/#veevalidate).\n\n## Quasar\n\n[Quasar framework](https://quasar.dev/) aims to:\n\n> Effortlessly build high-performance & high-quality Vue 3 user interfaces in record time\n\n<LiveExample client:visible id=\"vee-validate-v4-quasar-framework\" click-to-load preview-only />\n\n## Element Plus\n\n> [Element Plus](https://element-plus.org/#/en-US), a Vue 3.0 based component library for developers, designers and product managers\n\n<LiveExample client:visible id=\"vee-validate-v4-element-plus\" click-to-load preview-only />\n\n## Headless UI\n\n> [Headless UI](https://headlessui.dev/), a completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.\n\n<LiveExample client:visible id=\"vee-validate-v4-headless-ui\" click-to-load preview-only />\n\n## Ionic Framework\n\n> [Ionic Framework](https://ionicframework.com/), An open source mobile toolkit for building high quality, cross-platform native and web app experiences.\n\nThis example is originally forked from another example created by [Aaron Saunders](https://twitter.com/aaronksaunders).\n\n<LiveExample client:visible id=\"vee-validate-v4-ionic\" click-to-load preview-only />\n\n## Ant Design\n\n> [Ant Design](https://next.antdv.com/) provides plenty of UI components to enrich your web applications, and we will improve components experience consistently.\n\n<LiveExample client:visible id=\"vee-validate-v4-ant-design\" click-to-load preview-only />\n\n## Nuxt UI\n\n> [Nuxt UI](https://ui.nuxtlabs.com/) is a Fully styled and customizable components for Nuxt.js\n\n<LiveExample client:visible id=\"nuxtlabs-ui-vee-validate-v4\" click-to-load preview-only />\n\n## Naive UI\n\n> [Naïve UI](https://www.naiveui.com/en-US/os-theme) Fairly Complete, Theme Customizable, Uses TypeScript, Fast, Kinda Interesting\n\n<LiveExample client:visible id=\"vee-validate-v4-naive-ui\" click-to-load preview-only />\n\n## Bootstrap Vue\n\n> With [BootstrapVue](https://bootstrap-vue.org/) you can build responsive, mobile-first, and ARIA accessible projects on the web using Vue.js and the world's most popular front-end CSS library\n\n<LiveExample client:visible id=\"vee-validate-v4-bootstrap-vue\" click-to-load preview-only />\n\n## Request a UI library\n\nCan't find your favorite UI library here? You can request adding an example for it by creating an [issue here](https://github.com/logaretm/vee-validate/issues/new/choose) and we will consider adding it here.\n"
  },
  {
    "path": "docs/src/pages/examples/using-stores.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: State Stores\ndescription: using vee-validate with state stores\norder: 8\nnew: true\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Stores\n\nIf you want to integrate vee-validate with state management solutions you can do that with the composition API.\n\n## Pinia\n\n[Pinia](https://pinia.esm.dev/) is a data store for Vue.js and it is the recommended solution to your Vue.js state management.\n\nThe example integrates a form state into the store by utilizing a setup function when defining a store. This makes vee-validate act as a state provider for the form where the form values become your store state and submit function becomes your store action.\n\n<DocTip type=\"warn\">\n\nUsing `useForm` inside Pinia stores may cause unwanted behavior as lifecycle hooks only execute against the component that first initialized the store.\n\n</DocTip>\n\n<LiveExample client:visible id=\"vee-validate-v4-pinia\" />\n"
  },
  {
    "path": "docs/src/pages/examples/value-formatting.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Value formatting and Masks\ndescription: using vee-validate with masked and formatted inputs\norder: 9\nnew: true\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Value Formatting and Masks\n\nSome inputs may have a mask applied to them, that is their value is displayed in a different way than the actual value to make it more friendly towards the user.\n\nFor example, a currency input could insert a thousand separator to make it easier for the user to enter and read large numbers.\n\n```sh\n# hard to read\n10000000\n\n# Much easier\n10,000,000\n```\n\nIt can be confusing as to how would you run your numeric validation rules on such inputs. The following examples show you how to handle such inputs by separating the \"display value\" from the actual value.\n\n## Currency Format Example\n\nThe following example integrates [`vue-currency-input`](https://github.com/dm4t2/vue-currency-input) using the composition API. While it is still possible to do it with the `<Field />` component, it is significantly easier to work with the composition API in this case.\n\nThe main key to getting this right is to sync the value in multiple formats, the formatted one, and the non-formatted value.\n\nIdeally, vee-validate should be synced with the non-formatted one, you can do this by updating the value manually using `setValue` or `handleChange`.\n\n<LiveExample client:visible id=\"vee-validate-v4-input-masks\" />\n"
  },
  {
    "path": "docs/src/pages/guide/components/handling-forms.mdx",
    "content": "---\nlayout: ../../../layouts/PageLayout.astro\ntitle: Handling Forms\ndescription: Handling form state and submissions\norder: 3\nnext:\n  path: guide/components/nested-objects-and-arrays\n  title: Nested Objects and Arrays\n  description: Structuring forms in nested paths in objects or arrays\n---\n\nimport DocTip from '@/components/DocTip.vue';\n\n# Handling Forms\n\nvee-validate offers many helpers to handle form submissions, resets, and DX to make your forms much easier to reason about and less of a burden to maintain. The `Form` component handles the following form cases:\n\n<div class=\"features\">\n\n- Submitting forms with JavaScript listeners (AJAX)\n- Submitting forms using the classic/native approach (page reload)\n- Handling form resets\n\n</div>\n\n## Form Values\n\nSo far you probably noticed we didn't use `v-model` once in the examples. This is because in most cases you don't need the model values until you submit them to your API or not at all if you are submitting an HTML form without JavaScript.\n\nHaving to create models just to be able to reference them later is redundant and vee-validate goes around this by creating an internal model for the `<Field />` field component instances and tracks them and keeps them in sync with the input. You can still use `v-model` if you need it but vee-validate doesn't require it.\n\nYou may access your form's values using the `values` scoped slot prop on the `Form` component:\n\n```vue\n<template>\n  <Form v-slot=\"{ values }\">\n    <Field name=\"email\" type=\"email\" />\n    <Field name=\"password\" type=\"password\" />\n\n    <!-- print form values -->\n    <pre>{{ values }}</pre>\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field } from 'vee-validate';\n</script>\n```\n\nYou will rarely need to access the form values inside the template, but it is there if you ever need it. What's interesting is that vee-validate follows the assumption that most likely you will need the form values at the submission phase.\n\nSo if you were to add a `submit` handler on the `<Form />` component, vee-validate will automatically pass the form values to your handler as the first argument.\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\" :validation-schema=\"schema\">\n    <Field name=\"email\" type=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" type=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().required().email(),\n  password: yup.string().required().min(8),\n});\n\nfunction onSubmit(values) {\n  // Submit values to API...\n  alert(JSON.stringify(values, null, 2));\n}\n</script>\n```\n\n## Handling Submissions\n\nvee-validate exposes useful defaults to help you handle form submissions whether you submit them using JavaScript or native HTML submissions, in most cases, you would like to make sure all your fields are valid before you submit the form, this is done for you by default.\n\nConsider the last example, if you tried submitting the form, it won't be submitted unless all fields are valid. When rendering a form using the `as` prop, vee-validate will automatically listen for the `submit` event and prevent the execution of any `submit` listener you may have on the form.\n\nIf you have a `submit` listener on the `Form` component, vee-validate assumes you will be handling submissions via JavaScript (AJAX) and automatically calls `event.preventDefault()` for you and once the form is finished validating and turned out to be valid it will pass all the values of the `<Field />` components.\n\nBut in the case when you don't have a `submit` listener on your form, vee-validate assumes that the form will be submitted using the native HTML submission that causes the page to \"reload\". However vee-validate will make sure the form is not submitted unless all fields are valid, here is an example:\n\n```vue-html\n<Form method=\"post\" action=\"/api/users\" :validation-schema=\"schema\">\n  <Field name=\"email\" type=\"email\" />\n  <Field name=\"name\" />\n  <Field name=\"password\" type=\"password\" />\n\n  <button>Submit</button>\n</Form>\n```\n\n## Manually Handling Submissions\n\nIf you have complex markup requirements in your forms, you can use any of those `<Form />` component slot props:\n\n- `handleSubmit`: automatically prevents native submission at all times, use for AJAX submissions\n- `submitForm`: prevents native submissions as long as the form is invalid, use for native submissions\n- `validate`: triggers validation on all fields belonging to the form\n\n### Using handleSubmit\n\nThe `handleSubmit` slot prop is probably the most common method you will use to handle form submissions manually, it accepts a callback that will be executed with the form values if the form is valid.\n\n```vue\n<template>\n  <VeeForm v-slot=\"{ handleSubmit }\" :validation-schema=\"schema\" as=\"div\">\n    <form @submit=\"handleSubmit($event, onSubmit)\">\n      <Field name=\"email\" type=\"email\" />\n      <ErrorMessage name=\"email\" />\n\n      <Field name=\"password\" type=\"password\" />\n      <ErrorMessage name=\"password\" />\n\n      <button>Submit</button>\n    </form>\n  </VeeForm>\n</template>\n\n<script setup>\nimport { Form as VeeForm, Field, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().required().email(),\n  password: yup.string().required().min(8),\n});\n\nfunction onSubmit(values) {\n  // Submit values to API...\n  alert(JSON.stringify(values, null, 2));\n}\n</script>\n```\n\n### Using submitForm\n\nAlternatively if you plan to submit forms natively which will cause a page \"reload\" then use `submitForm` as an event handler:\n\n```vue\n<template>\n  <VeeForm v-slot=\"{ submitForm }\" :validation-schema=\"schema\" as=\"div\">\n    <form @submit=\"submitForm\" method=\"post\" action=\"/api/users/\">\n      <Field name=\"email\" type=\"email\" />\n      <ErrorMessage name=\"email\" />\n\n      <Field name=\"password\" type=\"password\" />\n      <ErrorMessage name=\"password\" />\n\n      <button>Submit</button>\n    </form>\n  </VeeForm>\n</template>\n\n<script setup>\nimport { Form as VeeForm, Field, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().required().email(),\n  password: yup.string().required().min(8),\n});\n</script>\n```\n\nThis will prevent submitting the form until all fields are valid.\n\n### Using validate()\n\nYou can validate the form without submissions using the `validate()` slot prop function:\n\n```vue-html\n<Form v-slot=\"{ validate }\" :validation-schema=\"schema\">\n  <Field name=\"email\" type=\"email\" />\n  <ErrorMessage name=\"email\" />\n\n  <Field name=\"password\" type=\"password\" />\n  <ErrorMessage name=\"password\" />\n\n  <button type=\"button\" @click=\"validate\">Submit</button>\n</Form>\n```\n\nThat form doesn't render a `form` tag, so vee-validate doesn't handle submissions for that group of fields. But you can still validate them using the `validate` function present on the `Form` component slot props.\n\n## Submission Progress\n\nQuite often you need to show your users a submission indicator, or you might want to disable the submit button entirely until the submission attempt is done. The `Form` component offers an `isSubmitting` slot prop that you can use to show such UI indicators.\n\nThe `isSubmitting` state will be set to `true` once the validation of the form starts (as a result of a submit event) and will keep track of the submission handler you passed to either `onSubmit` or until it calls `submitForm`. If the submission handler throws any errors or completes successfully it will be set to `false` afterward.\n\nHere is small example:\n\n<p\n  class=\"codepen\"\n  data-height=\"265\"\n  data-theme-id=\"light\"\n  data-default-tab=\"html,result\"\n  data-user=\"logaretm\"\n  data-slug-hash=\"xxVZOGX\"\n  style=\"height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;\"\n  data-pen-title=\"vee-validate v4 isSubmitting\"\n>\n  <span>\n    See the Pen <a href=\"https://codepen.io/logaretm/pen/xxVZOGX\">vee-validate v4 isSubmitting</a> by Abdelrahman Awad (\n    <a href=\"https://codepen.io/logaretm\">@logaretm</a>) on <a href=\"https://codepen.io\">CodePen</a>.\n  </span>\n</p>\n\n<DocTip title=\"isSubmitting and validate()\">\n\nNote that calling `validate` from the `Form` slot props will not cause the `isSubmitting` state to change, it will only change if either `submitForm` or `handleSubmit` are called or when a submit event is triggered.\n\n</DocTip>\n\n<DocTip title=\"submitCount\">\n\nThe `Form` component exposes a `submitCount` state that you can use to track the number of submission attempts done by the user. For more information check the [API Reference](/api/form).\n\n</DocTip>\n\n## Handling Invalid Submissions\n\nIn case you want to perform some logic after a form fails to submit due to validation errors (e.g: focusing the first invalid field), you can listen for the `onInvalidSubmit` event emitted by the `<Form />` component.\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\" :validation-schema=\"schema\" @invalid-submit=\"onInvalidSubmit\">\n    <Field name=\"email\" type=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" type=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().required().email(),\n  password: yup.string().required().min(8),\n});\n\nfunction onSubmit(values) {\n  // Submit values to API...\n  alert(JSON.stringify(values, null, 2));\n}\n\nfunction onInvalidSubmit({ values, errors, results }) {\n  console.log(values); // current form values\n  console.log(errors); // a map of field names and their first error message\n  console.log(results); // a detailed map of field names and their validation results\n}\n</script>\n```\n\nSpecifying a `onInvalidSubmit` prop or `@invalid-submit` will run your handler if you submit your form using either `handleSubmit` or the regular form submit event but not the `submitForm` function.\n\n## Initial Values\n\nSince with vee-validate you don't have to use `v-model` to track your values, the `Form` component allows you to define the starting values for your fields, by default all fields start with `undefined` as a value.\n\nUsing the `initialValues` prop you can send an object that contains the field names as keys and their values:\n\n```vue\n<template>\n  <Form :validation-schema=\"schema\" :initial-values=\"formValues\">\n    <Field name=\"email\" type=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" type=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button type=\"Submit\">Submit</button>\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().required().email(),\n  password: yup.string().required().min(8),\n});\n\n// Initial values\nconst formValues = {\n  email: 'example@example.com',\n  password: 'P@$$w0Rd',\n};\n</script>\n```\n\nDoing so will trigger initial validation on the form and it will generate messages for fields that fail the initial validation. You can still use `v-model` on your fields to define model-based initial values.\n\nYou can use `validateOnMount` prop present on the `<Form />` component to force an initial validation when the component is mounted.\n\nNote that **only the non-dirty fields will be updated**. In other words, **only the fields that were not manipulated by the user will be updated**. For information on how to set the values for all fields regardless of their dirty status check the following [Setting Form Values section](#setting-form-values)\n\n<DocTip>\n\nIt's generally recommended that you provide the `initialValues`, this is because vee-validate cannot assume a reasonable initial value for your fields other than `undefined` which may cause unexpected behavior when using a 3rd-party validator that does not deal with `undefined`.\n\n</DocTip>\n\n## Setting Form Values\n\nYou can set any field's value using either `setFieldValue` or `setValues`, both methods are exposed on the `<Form />` component scoped slot props, and as component instance methods.\n\nYou can call them with template `$refs` and for an added convenience you can call them in the submit handler callback.\n\n**Using scoped slot props**\n\n```vue-html\n<Form v-slot=\"{ setFieldValue, setValues }\">\n  <Field name=\"email\"  />\n  <ErrorMessage name=\"email\" />\n\n  <Field name=\"password\"  />\n  <ErrorMessage name=\"password\" />\n\n  <button type=\"button\" @click=\"setFieldValue('email', 'test')\">Set Field Value</button>\n  <button type=\"button\" @click=\"setValues({ email: 'test', password: 'test12' })\">\n    Set Multiple Values\n  </button>\n</Form>\n```\n\n**Using submit callback**\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\">\n    <Field name=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nfunction onSubmit(values, actions) {\n  // Submit the values...\n\n  // set single field value\n  actions.setFieldValue('email', 'ummm@example.com');\n\n  // set multiple values\n  actions.setValues({\n    email: 'ummm@example.com',\n    password: 'P@$$w0Rd',\n  });\n}\n</script>\n```\n\n**Using template `$refs`**\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\" ref=\"myForm\">\n    <Field name=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nfunction onSubmit(values) {\n  // Submit the values...\n\n  // set single field value\n  this.$refs.myForm.setFieldValue('email', 'ummm@example.com');\n\n  // set multiple values\n  this.$refs.myForm.setValues({\n    email: 'ummm@example.com',\n    password: 'P@$$w0Rd',\n  });\n}\n</script>\n```\n\nNote that setting any field's value using this way will trigger validation\n\n## Submission Behavior\n\nvee-validate does the following when you submit a form rendered by `<Form />` or when calling either `handleSubmit` or `submitForm`:\n\n### Before validation stage\n\n- Sets all fields `touched` meta to `true`\n- Sets `isSubmitting` form state to `true`\n- Increments the `submitCount` form state by `1`\n\n### Validation stage\n\n- Sets form and individual fields meta `pending` to `true` to indicate validation is in progress\n- Runs the validation function/schema/rule against the current form values asynchronously\n- Checks for any errors in the validation result\n  - If there are errors then it will skip the next stage and update the validation state (meta, errors) for the form and fields\n  - If there aren't any errors then it will set the `pending` meta flag to `false` and proceed to the next stage\n\n### After validation stage\n\n- Calls the `@submit` handler you specified, or calls the `handleSubmit` callback you provided.\n- After the callbacks in either method finish (it will wait if the result is asynchronous), then it will set `isSubmitting` to `false`\n\nNote that there isn't a need to have `isSubmitting` set back to false if you've used `submitForm`, as this submission method will perform a full-page refresh (native forms behavior).\n\n## Handling Resets\n\nvee-validate also handles form resets in a similar way to submissions. When resetting the form, all fields' errors and meta flags will be reset to their original state, including the fields' values.\n\nForm reset is handled automatically if you are using the `as` prop to render a `form` element, like shown in this example:\n\n```vue\n<template>\n  <Form :validation-schema=\"schema\">\n    <Field name=\"email\" type=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" type=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button type=\"Submit\">Submit</button>\n    <button type=\"reset\">Reset</button>\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().required().email(),\n  password: yup.string().required().min(8),\n});\n</script>\n```\n\nAlternatively if you plan to use the scoped slot for complex markup, you can use the `handleReset` slot prop function to trigger the reset manually:\n\n```vue-html\n<Form v-slot=\"{ handleReset }\" :validation-schema=\"schema\">\n  <Field name=\"email\" type=\"email\" />\n  <ErrorMessage name=\"email\" />\n\n  <Field name=\"password\" type=\"password\" />\n  <ErrorMessage name=\"password\" />\n\n  <button type=\"button\" @click=\"handleReset\">Reset</button>\n</Form>\n```\n\n### Resetting Forms After Submit\n\nUsually you will reset your forms after a successful submission, the `onSubmit` handler receives an additional `FormActions` object in the second argument that allows you do some actions on the form after submissions, this is the shape of the `FormActions` object:\n\n```ts\nexport interface FormActions {\n  setFieldValue: (field: T, value: any) => void;\n  setFieldError: (field: string, message: string | undefined) => void;\n  setErrors: (fields: Partial<Record<string, string | undefined>>) => void;\n  setValues: (fields: Partial<Record<T, any>>) => void;\n  setFieldTouched: (field: string, isTouched: boolean) => void;\n  setTouched: (fields: Partial<Record<string, boolean>>) => void;\n  resetForm: (state?: Partial<FormState>) => void;\n}\n```\n\nThis is an example of using the form actions object to reset the form:\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\" :validation-schema=\"schema\">\n    <!-- fields ... -->\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  // ...\n});\n\nfunction onSubmit(values, { resetForm }) {\n  console.log(values); // send data to API\n  // reset the form and the field values to their initial values\n  resetForm();\n}\n</script>\n```\n\nThe `resetForm` accepts an optional `state` object that allows you to specify the new initial values for any of the fields state, this is the shape of the `FormState` object:\n\n```ts\ninterface FormState {\n  // any error messages\n  errors: Record<string, string>;\n  // dirty meta flags\n  dirty: Record<string, boolean>;\n  // touched meta flags\n  touched: Record<string, boolean>;\n  // Form Values\n  values: Record<string, any>;\n}\n```\n\nIn the following snippet, `resetForm` is used to update the form values to specific ones other than their original values. This is useful if your receive your form state asynchronously\n\n```js\nresetForm({\n  values: {\n    email: 'example@example.com',\n    password: '',\n  },\n});\n```\n\nYou can also use template `$refs` to reset the form whenever you need:\n\n```vue\n<template>\n  <Form ref=\"form\" @submit=\"onSubmit\" :validation-schema=\"schema\">\n    <!-- fields ... -->\n\n    <button type=\"Submit\">Submit</button>\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  // ...\n});\n\nfunction onSubmit(values) {\n  console.log(values); // send data to API\n\n  // reset the form\n  this.$refs.form.resetForm();\n}\n</script>\n```\n\n## Initial Errors\n\nIf you are building a non-SPA application it is very common to pre-fill form errors using server-side rendering, frameworks like Laravel make this very easy to do. vee-validate supports filling the errors initially before any validation is done using the `initialErrors` prop which is present on the `<Form />` component scoped slot props.\n\nThe `initialErrors` property accepts an object containing the field names as keys with their corresponding error message string.\n\n```vue\n<template>\n  <Form :initial-errors=\"initialErrors\">\n    <Field name=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nconst initialErrors = {\n  email: 'This email is already taken',\n  password: 'The password is too short',\n};\n</script>\n```\n\n<DocTip>\n\n`initialErrors` are applied once the `Form` component is mounted and is ignored after, so any changes to the `initialErrors` props won't affect the messages.\n\nSee the next section for setting errors manually.\n\n</DocTip>\n\n## Setting Errors Manually\n\nQuite often you will find yourself unable to replicate some validation rules on the client-side due to natural limitations. For example, `unique` email validation is complex to implement on the client-side, which is why the `<Form />` component allows you to set errors manually.\n\nYou can set messages for fields by using either `setFieldError` which sets an error message for one field at a time, and the `setErrors` function which allows you to set error messages for multiple fields at once.\n\nBoth functions are available on the `Form` component scoped slot props, and also on the `Form` component instance which enables you to use it with template `$refs`, and also for added convenience on the `submit` event handler since it would be the most common place for its usage.\n\nHere are a few snippets showcasing its usage in these various scenarios:\n\n**Using scoped slot props (recommended)**\n\n```vue-html\n<Form v-slot=\"{ setFieldError, setErrors }\">\n  <Field name=\"email\"  />\n  <ErrorMessage name=\"email\" />\n\n  <Field name=\"password\"  />\n  <ErrorMessage name=\"password\" />\n\n  <button type=\"button\" @click=\"setFieldError('email', 'nope')\">Set Single Error</button>\n  <button type=\"button\" @click=\"setErrors({ email: 'nope', password: 'wrong' })\">\n    Set Multiple Errors\n  </button>\n</Form>\n```\n\n**Using submit callback (recommended)**\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\">\n    <Field name=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nfunction onSubmit(values, actions) {\n  // Submit the values...\n\n  // set single field error\n  actions.setFieldError('email', 'this email is already taken');\n\n  // set multiple errors\n  actions.setErrors({\n    email: 'this field is already taken',\n    password: 'someone already has this password',\n  });\n}\n</script>\n```\n\n**Using template `$refs`**\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\" ref=\"myForm\">\n    <Field name=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nfunction onSubmit(values) {\n  // Submit the values...\n\n  // if API returns errors\n  this.$refs.myForm.setFieldError('email', 'this email is already taken');\n  this.$refs.myForm.setErrors({\n    email: 'this field is already taken',\n    password: 'someone already has this password',\n  });\n}\n</script>\n```\n\n<DocTip title=\"Avoid Template $refs\" type=\"warn\">\n\nAlways try to avoid using the template `$refs` to gain access to the `<Form />` component methods, template `$refs` are designed to be an escape hatch of sorts when all else fails.\n\nSo treat them as such and don't reach out for template `$refs` if you can help it.\n\n</DocTip>\n\n<script async src=\"https://static.codepen.io/assets/embed/ei.js\"></script>\n"
  },
  {
    "path": "docs/src/pages/guide/components/nested-objects-and-arrays.mdx",
    "content": "---\nlayout: ../../../layouts/PageLayout.astro\ntitle: Nested Objects and Arrays\ndescription: Structuring forms in nested paths in objects or arrays\norder: 4\nnext:\n  path: guide/global-validators\n  title: Global Validators\n  description: Defining global rules to be used throughout your web app\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport DocBadge from '@/components/DocBadge.vue';\n\n# Nested Objects and Arrays\n\nvee-validate supports nested objects and arrays, using field name syntax to indicate a field's path. This allows you to structure forms easily to make data mapping straightforward without having to deal with flat form values.\n\n## Nested Objects\n\nYou can specify a field to be nested in an object using dot paths, like what you would normally do in JavaScript to access a nested property. The field `name` prop acts as the path for that field:\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\">\n    <Field name=\"links.twitter\" type=\"url\" />\n    <Field name=\"links.github\" type=\"url\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nfunction onSubmit(values) {\n  alert(JSON.stringify(values, null, 2));\n}\n</script>\n```\n\nSubmitting the previous form would result in the following values being passed to your handler:\n\n```js\n{\n  \"links\": {\n    \"twitter\": \"https://twitter.com/logaretm\",\n    \"github\": \"https://github.com/logaretm\"\n  }\n}\n```\n\nYou are not limited to a specific depth, you can nest as much as you like.\n\n## Nested Arrays\n\nSimilar to objects, you can also nest your values in an array, using square brackets just like how you would do it in JavaScript.\n\nHere is the same example as above but in array format:\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\">\n    <Field name=\"links[0]\" type=\"url\" />\n    <Field name=\"links[1]\" type=\"url\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nfunction onSubmit(values) {\n  alert(JSON.stringify(values, null, 2));\n}\n</script>\n```\n\nSubmitting the previous form would result in the following values being passed to your handler:\n\n```js\n{\n  \"links\": [\n    \"https://twitter.com/logaretm\",\n    \"https://github.com/logaretm\"\n  ]\n}\n```\n\n<DocTip type=\"warn\">\n\nvee-validate will only create nested arrays if the path expression is a complete number, for example, paths like `some.nested[0path]` will not create any arrays because the `0path` key is not a number. However `some.nested[0].path` will create the array with an object as the first item.\n\n</DocTip>\n\n## Avoiding Nesting\n\nIf your fields' names are using the dot notation and you want to avoid the nesting behavior which is enabled by default, all you need to do is wrap your field names in square brackets (`[]`) to disable nesting for those fields.\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\">\n    <Field name=\"[links.twitter]\" type=\"url\" />\n    <Field name=\"[links.github]\" type=\"url\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nfunction onSubmit(values) {\n  alert(JSON.stringify(values, null, 2));\n}\n</script>\n```\n\nSubmitting the previous form would result in the following values being passed to your handler:\n\n```js\n{\n  \"links.twitter\": \"https://twitter.com/logaretm\",\n  \"links.github\": \"https://github.com/logaretm\"\n}\n```\n\n## Field Arrays <DocBadge title=\"v4.5\" />\n\nField arrays are a special type of nested array fields, they are often used to collect repeatable pieces of data or repeatable forms. They are often called \"repeatable fields\".\n\nWhen dealing with those fields it is better to use `<FieldArray />` component which gives you a few helpers you can use to manage the array fields.\n\nHere is a small example that shows how easy it is to create a repeatable `URL` field:\n\n```vue\n<template>\n  <Form @submit=\"onSubmit\" :initial-values=\"initialValues\">\n    <FieldArray name=\"links\" v-slot=\"{ fields, push, remove }\">\n      <div v-for=\"(entry, idx) in fields\" :key=\"entry.key\">\n        <Field :name=\"`links[${idx}]`\" type=\"url\" />\n\n        <button type=\"button\" @click=\"remove(idx)\">Remove</button>\n      </div>\n\n      <button type=\"button\" @click=\"push('')\">Add</button>\n    </FieldArray>\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nconst initialValues = {\n  links: ['https://github.com/logaretm'],\n};\n\nfunction onSubmit(values) {\n  alert(JSON.stringify(values, null, 2));\n}\n</script>\n```\n\n<DocTip title=\"Form Context\" type=\"warn\">\n\nThe `<FieldArray />` component requires being used inside a `Form` component or a `useForm` to be called at its parent tree.\n\n</DocTip>\n\n### Field Array Paths\n\nWhen planning to use `<FieldArray />` you need to provide a `name` prop which is the path of the array starting from the root form value, you can use dot notation for object paths or indices for array paths.\n\nHere are a few examples:\n\n_*Iterate over the `users` array:*_\n\n```vue-html\n<Form>\n  <FieldArray name=\"users\" v-slot=\"{ fields }\">\n    <div v-for=\"(entry, idx) in fields\" :key=\"entry.key\">\n      <Field :name=\"`users[${idx}].name`\" />\n    </div>\n  </FieldArray>\n</Form>\n```\n\n_*Iterate over the `domains` inside `settings.dns` object:*_\n\n```vue-html\n<Form>\n  <FieldArray name=\"settings.dns.domains\" v-slot=\"{ fields }\">\n    <div v-for=\"(entry, idx) in fields\" :key=\"entry.key\">\n      <Field :name=\"`settings.dns.domains[${idx}]`\" />\n    </div>\n  </FieldArray>\n</Form>\n```\n\n_*Iterate over both `users` and `links`:*_\n\n```vue-html\n<Form>\n  <FieldArray name=\"users\" v-slot=\"{ fields: users }\">\n    <div v-for=\"(userEntry, userIdx) in users\">\n      <FieldArray :name=\"`users[${userIdx}].links`\" v-slot=\"{ fields: links }\">\n        <div v-for=\"(entry, idx) in fields\" :key=\"entry.key\">\n          <Field :name=\"`users[${userIdx}].links[${idx}]`\" />\n        </div>\n      </FieldArray>\n    </div>\n  </FieldArray>\n</Form>\n```\n\n### Iteration Keys\n\nThe `FieldArrayEntry` item exposes a `key` property, this property is unique and is auto-generated for you so you can use it as an iteration key.\n\n```vue-html\n<FieldArray name=\"users\" v-slot=\"{ fields }\">\n  <div v-for=\"(entry, idx) in fields\" :key=\"entry.key\">\n    <Field :name=\"`users[${idx}].name`\" />\n  </div>\n</FieldArray>\n```\n\nThis auto-generated `key` property is very convenient as you no longer have to provide your own unique key for each item.\n\n<DocTip type=\"warn\">\n\nThe `key` property is not an index. It is a unique identifier for the array item that is independent of the array index, so you should not be using it to reference field names.\n\n</DocTip>\n\n### Array Helpers\n\nThe `<FieldArray />` slot provides the following properties and functions:\n\n- `fields`: a **read-only** version of your array field items, it includes some useful properties like `key`, `isFirst` and `isLast`, the actual item value is inside `.value` property. You should use it to iterate with `v-for`.\n- `push(item: any)`: adds an item to the end of the array.\n- `insert(idx: number, item: any)`: Inserts an array item at the specified index.\n- `prepend(item: any)`: adds an item to the start of the array.\n- `remove(idx: number)`: removes the item with the given index from the array.\n- `swap(idxA: number, idxB: number)`: Swaps two array elements by their indexes.\n- `replace(items: any[])`: Replaces the entire array values with the given items.\n- `update(idx: number, value: any)`: Updates an array item value at the specified index.\n- `move(oldIdx: number, newIdx: number)`: Moves an array item to a different position within the array.\n\n[Read the API reference](/api/field-array) for more information.\n\n## Caveats\n\n### Paths creation and destruction\n\nvee-validate creates the paths inside the form data automatically but lazily, so initially, your form values won't contain the values of the fields unless you provide initial values for them. It might be worthwhile to provide initial data for your forms with nested paths.\n\nWhen fields get unmounted like in the case of conditional rendered fields with `v-if` or `v-for`, their path will be destroyed just as it was created if they are the last field in that path. So you need to be careful while accessing the nested field in `values` inside your submission handler or the `Form` component `values` slot prop.\n\nPath destruction can be annoying when dealing with multi-step forms or tabbed forms where you want all the values to be available even when the fields are unmounted. You can control this behavior by passing `keepValue` prop to the `<Field />` component or you can do it for all the fields by passing `keepValues` to the `<Form />` component.\n\nNote that the priority of this configuration follows the field config first then it fallbacks to the form's config.\n\n```vue\n<template>\n  <!-- All fields values will be kept -->\n  <Form keep-values v-slot=\"{ values }\">\n    <!-- This field value will be kept -->\n    <Field v-if=\"showFields\" name=\"email\" />\n\n    <!-- This field value will be removed -->\n    <Field v-if=\"showFields\" name=\"name\" :keep-value=\"false\" />\n\n    <button @click=\"showFields = !showFields\" type=\"button\">Show/Hide fields</button>\n    <button>Submit</button>\n\n    <pre>{{ values }}</pre>\n  </Form>\n</template>\n\n<script>\nexport default {\n  data: () => ({\n    showFields: true,\n  }),\n};\n</script>\n```\n\n### Referencing Errors\n\nWhen referencing errors using `errors` object on the `Form` slot props or the `ErrorMessage` component, make sure to reference the field name in the same way you set it on the `name` prop for that field. So even if you avoid nesting you should always include the square brackets. In other words `errors` do not get nested, they are always flat.\n\n### Nested Fields With Validation Schema\n\nSince vee-validate supports [form-level validation](/guide/components/validation#form-level-validation), referencing the nested fields may vary depending on how you are specifying the schema.\n\nIf you are using yup, you can utilize the nested `yup.object` or `yup.array` schemas to provide validation for your nested fields, here is a quick example:\n\n```vue\n<template>\n  <Form v-slot=\"{ errors }\" :validation-schema=\"schema\" @submit=\"onSubmit\">\n    <Field name=\"user.name\" />\n    <span>{{ errors['user.name'] }}</span>\n    <Field name=\"user.addresses[0]\" />\n    <span>{{ errors['user.addresses[0]'] }}</span>\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  user: yup.object({\n    name: yup.string().required(),\n    addresses: yup.array().of(yup.string().required()),\n  }),\n});\n\nfunction onSubmit(values: any) {\n  fn(values);\n}\n</script>\n```\n\nYou can [visit this link](/examples/array-fields) for a practical example using nested arrays.\n"
  },
  {
    "path": "docs/src/pages/guide/components/validation.mdx",
    "content": "---\nlayout: ../../../layouts/PageLayout.astro\ntitle: Validation\ndescription: Field-level and form-level validation and validation behavior and error messages\norder: 2\nnext:\n  path: guide/components/handling-forms\n  title: Handling Forms\n  description: Handling form state and submissions\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Validation\n\nvee-validate handles complex validations in a very easy way, it supports synchronous and asynchronous validation and allows defining rules on the field-level or the form level using validation schemas with built-in support for [yup](https://github.com/jquense/yup).\n\nYou will be using the following components to validate your forms:\n\n- A `Field` component represents a single form input and can be used to render any kind of HTML elements or Vue components.\n- A `Form` component that renders a form. Do not confuse the `<Form>` tag with the HTML `<form>` tag.\n- An `ErrorMessage` component that displays an error message for a field, you don't have to use it as there are many ways to render error messages.\n\nHere is the most simple example in action:\n\n<p\n  class=\"codepen\"\n  data-height=\"265\"\n  data-theme-id=\"light\"\n  data-default-tab=\"js,result\"\n  data-user=\"logaretm\"\n  data-slug-hash=\"rNxbMzq\"\n  style=\"height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;\"\n  data-pen-title=\"Basic Example\"\n>\n  <span>\n    See the Pen <a href=\"https://codepen.io/logaretm/pen/rNxbMzq\">Basic Example</a> by Abdelrahman Awad (\n    <a href=\"https://codepen.io/logaretm\">@logaretm</a>) on <a href=\"https://codepen.io\">CodePen</a>.\n  </span>\n</p>\n\n<DocTip>\n\nFrom this point forwards, the docs will assume basic knowledge of [Vue's SFC components](https://v3.vuejs.org/guide/single-file-component.html) and will demonstrate examples as such and will be using ES6+ code snippets. So be sure to brush up on these if you haven't already.\n\n</DocTip>\n\n## Field-level Validation\n\nYou can define validation rules for your fields using the `Field` component, your rules can be as simple as a function that accepts the current value and returns an error message.\n\n```vue\n<template>\n  <Form>\n    <Field name=\"field\" :rules=\"isRequired\" />\n    <ErrorMessage name=\"field\" />\n  </Form>\n</template>\n\n<script setup>\nimport { Field, Form, ErrorMessage } from 'vee-validate';\n\nfunction isRequired(value) {\n  if (value && value.trim()) {\n    return true;\n  }\n\n  return 'This is required';\n}\n</script>\n```\n\n### Validating fields with yup\n\n[`yup`](https://github.com/jquense/yup) is a very popular, simple and powerful data validation library for JavaScript, you can use it in combination with vee-validate, You can use `yup` to define your validation rules for that field:\n\n```vue{3,10,20}\n<template>\n  <Form>\n    <Field name=\"password\" type=\"password\" :rules=\"passwordRules\" />\n    <ErrorMessage name=\"password\" />\n  </Form>\n</template>\n\n<script setup>\nimport { Field, Form, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst passwordRules = yup.string().required().min(8);\n</script>\n```\n\nFor more information on the `Field` component, read [the API reference](/api/field).\n\n## Form-level Validation\n\nvee-validate supports using a validation schema to define all your validations on your fields beforehand so you don't have to define them individually on your fields.\nForm-level validation is convenient if you are building large forms and want to keep your templates cleaner.\n\nA simple validation schema can be an object containing field names as keys and validation functions as the value for those keys:\n\n```vue\n<template>\n  <Form @submit=\"submit\" :validation-schema=\"simpleSchema\">\n    <Field name=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" type=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field, ErrorMessage } from 'vee-validate';\n\nconst simpleSchema = {\n  email(value) {\n    // validate email value...\n  },\n  name(value) {\n    // validate name value...\n  },\n  // If you defined global rules you can also use them\n  password: 'required|min:8',\n  // ...\n};\n</script>\n```\n\n### Validation schemas with yup\n\nFortunately there is already a very neat way to build validation schemas for your forms by using `yup`, it allows you create validation objects like this:\n\n```js\nconst schema = yup.object({\n  email: yup.string().required().email(),\n  name: yup.string().required(),\n  password: yup.string().required().min(8),\n});\n```\n\nvee-validate has built-in support for yup schemas, You can pass your schemas to the `<Form />` component using the `validation-schema` prop:\n\n```vue\n<template>\n  <Form @submit=\"submit\" :validation-schema=\"schema\">\n    <Field name=\"email\" />\n    <ErrorMessage name=\"email\" />\n\n    <Field name=\"password\" type=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().required().email(),\n  password: yup.string().required().min(8),\n});\n</script>\n```\n\nFor more information on the `Form` component, read [the API reference](/api/form).\n\n### Reactive Form Schema\n\nYou can have reactive form schemas using `computed` if you are looking to create dynamic schemas using either `yup` or a validation object.\n\n```js\nimport * as yup from 'yup';\n\nexport default {\n  data: () => ({\n    min: 6,\n  }),\n  computed: {\n    schema() {\n      return yup.object({\n        password: yup.string().min(this.min),\n      });\n    },\n  },\n};\n```\n\n```vue\n<template>\n  <Form @submit=\"submit\" :validation-schema=\"schema\">\n    <Field name=\"password\" type=\"password\" />\n    <ErrorMessage name=\"password\" />\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script>\nimport { Form, Field, ErrorMessage } from 'vee-validate';\nimport * as yup from 'yup';\n\nexport default {\n  components: {\n    Form,\n    Field,\n    ErrorMessage,\n  },\n  data: () => ({\n    min: 6,\n  }),\n  computed: {\n    schema() {\n      return yup.object({\n        password: yup.string().min(this.min),\n      });\n    },\n  },\n};\n</script>\n```\n\nWhen the validation schema changes, only the fields that were validated at least once will be re-validated, the other fields won't be validated to avoid aggressive validation behavior.\n\n## Validation Behavior\n\nBy default vee-validate runs validation in these scenarios:\n\n**After field value change**\n\n- When a `change` event is dispatched/emitted\n- value changed externally (model update or others)\n\nNote that `input` event is not considered to be a trigger because it would make it too aggressive, you can configure the triggers in the next section to suit your needs.\n\n**After Rules change**\n\n- Only if the field was validated before via user interaction\n\n**After field is blurred**\n\n- Field has been blurred (`blur` event was emitted)\n\n**After form submissions**\n\n- When the form has been submitted with either `handleSubmit` or `submitForm` on the `<Form />` component slot props\n\n### Customizing Validation Triggers\n\nBy default vee-validate adds multiple event listeners to your fields:\n\n- **input:** Adds a `handleChange` handler that updates the field value, and it may validate if configured to do so (may update `meta.dirty` flag if the value changed).\n- **change:** Adds a `handleChange` handler that updates the field value and validates the field (may update `meta.dirty` flag if the value changed).\n- **blur:** Adds a `handleBlur` handler that updates the `meta.touched` flag.\n- **update:modelValue** Adds a `handleChange` handler to components emitting the `update:modelValue` event\n\nNotice that in all of these, the `handleChange` handler is the only one that triggers validation. You can configure if a handler should validate by using the `configure` helper:\n\n```js\nimport { configure } from 'vee-validate';\n\n// Default values\nconfigure({\n  validateOnBlur: true, // controls if `blur` events should trigger validation with `handleChange` handler\n  validateOnChange: true, // controls if `change` events should trigger validation with `handleChange` handler\n  validateOnInput: false, // controls if `input` events should trigger validation with `handleChange` handler\n  validateOnModelUpdate: true, // controls if `update:modelValue` events should trigger validation with `handleChange` handler\n});\n```\n\nNote that configuring any of these options to `false` will not remove all the events, they only control if each event triggers a validation check or not.\n\nThis might not be flexible enough for your needs, which is why you can define the same config per `Field` component instance:\n\n```vue-html\n<!-- Turns off validation events -->\n<Field name=\"email\" :validateOnBlur=\"false\" :validateOnChange=\"false\" :validateOnInput=\"false\" />\n```\n\nAdditionally if you need to use different events or have specific needs in mind, you can control which events to listen to by using the scoped-slot `handleChange` prop of the `<Field />` component and binding it to the desired event:\n\n```vue-html\n<!-- Listen to all events, this is the default behavior -->\n<Field v-slot=\"{ field }\">\n  <input v-bind=\"field\" />\n</Field>\n\n<!-- Only validate when the change event is dispatched -->\n<Field v-slot=\"{ field, handleChange }\">\n  <input @change=\"handleChange\" :value=\"field.value\" />\n</Field>\n```\n\nIn addition to those events, you can also validate when the `<Field />` or `<Form />` components are mounted with `validateOnMount` prop present on both components:\n\n```vue-html\n<!-- Trigger validation when this field is mounted (initial validation) -->\n<Field name=\"name\" validate-on-mount />\n\n<!-- Trigger validation on all fields inside this form when the form is mounted -->\n<Form validate-on-mount>\n  <Field name=\"email\" />\n  <Field name=\"password\" />\n</Form>\n```\n\nYou can also specify if a `handleChange` call should trigger validation or not by providing the second argument:\n\n```vue-html\n<!-- Only update field value without validating it -->\n<Field v-slot=\"{ field, handleChange }\">\n  <input @change=\"$event => handleChange($event, false)\" :value=\"field.value\" />\n</Field>\n```\n\n<DocTip title=\"Vue components validation triggers\">\n\nWhen applying `v-bind=\"field\"` to a Vue component, be careful that the listeners will both be applied for Vue and native DOM events, meaning you might trigger validation unintentionally.\n\nAn example of that could be `input[type=\"file\"]` inputs, because you cannot bind the `value` attribute to a file instance which means two-way binding won't work there. In that case, only listing to handful of events makes more sense:\n\n```vue-html\n<Field name=\"file\" v-slot=\"{ handleChange, handleBlur }\">\n  <input type=\"file\" @change=\"handleChange\" @blur=\"handleBlur\" />\n</Field>\n```\n\nFor custom components, it is recommended that you listen to the proper events when using `v-bind` with custom components, the following sample uses `modelValue` events.\n\n```vue-html\n<Field name=\"custom\" v-slot=\"{ handleChange, value }\">\n  <CustomInput :modelValue=\"value\" @update:modelValue=\"handleChange\" />\n</Field>\n```\n\nFor 3rd party components you may consult their documentation to figure which events to trigger validation for. Here are a few examples for the common UI frameworks [here](/examples/ui-libraries).\n\n</DocTip>\n\n## Displaying Error Messages\n\n### Using the Field slot-props\n\nIf you intend to use the scoped slot on the `Field` component, you can access `errors` or `errorMessage` on the scoped slot props to render your messages:\n\n```vue-html\n<Field name=\"field\" :rules=\"rules\" v-slot=\"{ field, errors, errorMessage }\">\n  <input v-bind=\"field\" type=\"text\" />\n  <span>{{ errors[0] }}</span>\n  <!-- Or -->\n  <span>{{ errorMessage }}</span>\n</Field>\n```\n\nThis is convenient if you have a complex markup for your input and would like to keep everything contained within, it also allows you to create input components with built-in validation.\n\n### Using the Form slot-props\n\nAs you noticed the `<Form />` component gives you access to the `errors` on its scoped-slot props which you can use to display any error messages for any `<Field />` within that form:\n\n```vue-html\n<Form v-slot=\"{ errors }\">\n  <Field name=\"field\" :rules=\"rules\" />\n  {{ errors.field }}\n</Form>\n```\n\nand if you would like, you could display all error messages for your fields by iterating over the `errors` object:\n\n```vue-html\n<Form v-slot=\"{ errors }\">\n  <template v-if=\"Object.keys(errors).length\">\n    <p>Please correct the following errors</p>\n    <ul>\n      <li v-for=\"(message, field) in errors\" :key=\"field\">\n        {{ message }}\n      </li>\n    </ul>\n  </template>\n\n  <Field name=\"name\" :rules=\"rules\" />\n  <Field name=\"email\" :rules=\"rules\" />\n  <Field name=\"password\" :rules=\"rules\" />\n</Form>\n```\n\n### Using ErrorMessage component\n\nYou've seen how the `ErrorMessage` works in the previous examples, by default the `ErrorMessage` component renders a `span` but you can specify any kind of HTML element or global component to the `as` prop.\n\n```vue-html\n<Form>\n  <Field name=\"field\" :rules=\"rules\" />\n  <!-- Render the error message as a div element -->\n  <ErrorMessage name=\"field\" as=\"div\" />\n</Form>\n```\n\nThe `<ErrorMessage />` component is very flexible and you can customize its render output with scoped slots to build complex messages markup, read the [ErrorMessage API reference](/api/error-message) for more information.\n\n### Custom Field Labels\n\nMore often than not, your fields will have names with underscores or shorthands which isn't very nice when showing in error messages, for example, you might have specific encoding to your field names because they might be generated by the backend. Ideally, you want to avoid having messages like:\n\n```txt\nThe down_p is required\n```\n\nAnd instead, show something more meaningful to the user\n\n```txt\nThe down payment is required\n```\n\nYou can do this in two ways depending on which validators you are using (yup or [global validators](/guide/global-validators)).\n\nWith yup it is very straightforward, you just need to call `label()` after defining your field's validations either in field level or form level:\n\n```js\nconst schema = Yup.object({\n  email_addr: Yup.string().email().required().label('Email Address'),\n  acc_pazzword: Yup.string().min(5).required().label('Your Password'),\n});\n```\n\nHere is a live example:\n\n<LiveExample client:visible id=\"vee-validate-v4-friendly-labels-with-yup\" />\n\nIf you are interested in how to do the same for global validators check the [i18n guide](/guide/i18n#custom-labels)\n\n## Validation Metadata\n\n### Field-level Meta\n\nEach field has metadata associated with it, the `meta` property available on the `<Field />` component contains additional information about the field:\n\n- `valid`: The current field validity, automatically updated for you.\n- `touched`: If the field was blurred (unfocused), can be updated with the `handleBlur` function or `setTouched` on the field's slot scope props.\n- `dirty`: If the field value was updated, you cannot change its value.\n- `pending`: If the field's validations are still running, useful for long-running async validation.\n- `initialValue`: The field's initial value, is `undefined` if you didn't specify any.\n\n```vue-html\n<Field name=\"email\" type=\"email\" :rules=\"validateEmail\" v-slot=\"{ field, meta }\">\n  <input v-bind=\"field\" />\n  <pre>{{ meta }}</pre>\n</Field>\n```\n\nThis is the typescript interface for a field's meta-object value\n\n```ts\ninterface FieldMeta {\n  dirty: boolean;\n  pending: boolean;\n  touched: boolean;\n  valid: boolean;\n  initialValue: any;\n}\n```\n\n<DocTip title=\"Field Dirty Flag and Initial Values\">\n\nThe default value is `undefined` unless specified which may cause unexpected `meta.dirty` results. To get accurate results for the `meta.dirty` flag, you must provide an initial value to your field even if the values are empty.\n\n```vue-html\n<Field name=\"email\" value=\"\" type=\"email\" v-slot=\"{ field, meta }\">\n  <input v-bind=\"field\" />\n  <pre>{{ meta }}</pre>\n</Field>\n```\n\nTo reduce the verbosity of adding a `value` prop to each field, you could provide the `initial-values` prop to your `<Form />` component instead.\n\n</DocTip>\n\n<DocTip title=\"Valid Flag Combinations\">\n\nSince the `meta.valid` flag is initially `true` (because it just means there are no errors yet), it would cause problems if you have a \"success\" UI state an indicator.\n\nTo avoid this case you could combine the `valid` flag with either `meta.dirty` or `meta.touched` to get accurate representation:\n\n```vue-html\n<Field name=\"email\" type=\"email\" :rules=\"validateEmail\" v-slot=\"{ field, errorMessage, meta }\">\n  <input v-bind=\"field\" />\n  <span v-if=\"errorMessage\">⛔️ {{ errorMessage }}</span>\n  <span v-if=\"meta.valid && meta.touched\">✅ Field is valid</span>\n</Field>\n```\n\n</DocTip>\n\n### Form-level Meta\n\nForms also have their own `meta` value containing useful information about the form, it is an aggregation of the metadata for the fields inside that form.\n\nThe form's metadata properties are:\n\n- `valid`: The form's validity status, will be `true` if the errors array is empty. After the form is mounted, vee-validate will update the flag to its accurate state\n- `touched`: If at least one field was blurred (unfocused) inside the form.\n- `dirty`: If at least one field's value was updated.\n- `pending`: If at least one field's validation is still pending.\n- `initialValues`: All fields' initial values, packed into an object where the keys are the field names.\n\n```vue-html\n<Form v-slot=\"{ meta }\">\n  <!-- Some fields -->\n  <pre>{{ meta }}</pre>\n</Form>\n```\n\nHere is a similar example where we disable the form's submit button if no value was changed, we will check the `dirty` flag on the form's scoped slot props which should tell us if the form values have changed or not.\n\n```vue\n<template>\n  <Form v-slot=\"{ meta }\" :initial-values=\"initialValues\">\n    <Field name=\"email\" />\n\n    <button :disabled=\"!meta.dirty\">Submit</button>\n  </Form>\n</template>\n\n<script>\nimport { Field, Form } from 'vee-validate';\n\nexport default {\n  components: {\n    Field,\n    Form,\n  },\n  data() {\n    return {\n      initialValues: { email: '' },\n    };\n  },\n};\n</script>\n```\n\n<DocTip title=\"Form Dirty Flag and Initial Values\">\n\nNotice that the `initial-values` in the previous example were provided, like mentioned for the `meta.dirty` accuracy for fields, to get accurate results for the `meta.dirty` flag, you must provide initial values to your forms even if the values are empty.\n\n</DocTip>\n\n<DocTip title=\"Valid Flag Combinations\">\n\nForms `meta.valid` flag is also initially `true` (because it just means there are no errors yet), it would cause problems if you have a \"success\" UI state or an indicator.\n\nTo avoid this case you could combine the form's `valid` flag with either `meta.dirty` or `meta.touched` to get accurate representation:\n\n```vue-html\n<Form v-slot=\"{ meta, errors }\">\n  <Field name=\"email\" type=\"email\" :rules=\"validateEmail\" />\n  <span v-if=\"errors.email\">⛔️ {{ errors.email }}</span>\n  <span v-if=\"meta.valid && meta.touched\">✅ Form is valid</span>\n</Form>\n```\n\n</DocTip>\n\n<script async src=\"https://static.codepen.io/assets/embed/ei.js\"></script>\n"
  },
  {
    "path": "docs/src/pages/guide/composition-api/caveats.mdx",
    "content": "---\nlayout: ../../../layouts/PageLayout.astro\ntitle: Caveats and best practices\ndescription: Things to watch out for when using the composition API\norder: 7\nmenuTitle: Best practices\n---\n\n# Composition API Caveats\n\nWhen using the composition API, there are a few things that are not clear when first starting to use it. This page will contain these topics and help you understand how to workaround or address them.\n\n## Function Field Names with `useField`\n\nYou might've noticed that some examples in the docs pass the field name as a function to `useField`:\n\n```js\nimport { useField } from 'vee-validate';\n\nexport default {\n  props: {\n    name: String,\n  },\n  setup(props) {\n    const { value, errorMessage } = useField(() => props.name);\n  },\n};\n```\n\nThis is mainly because the `props` in Vue.js is a reactive object, meaning if you access or destruct any of its properties they will lose the reactivity aspect. Let's say you did the following:\n\n```js\nimport { useField } from 'vee-validate';\n\nexport default {\n  props: {\n    name: String,\n  },\n  setup(props) {\n    // ❌ Don't do this in custom input components\n    const { value, errorMessage } = useField(props.name);\n  },\n};\n```\n\nThe implications are that vee-validate is no longer able to tell when the field name changes, which is crucial for syncing values when they do.\n\nA common example where field names change frequently is in a array field where `v-for` loops field names use the index or the iterated value to generate the field name\n\n```vue{4}\n<CustomTextField\n  v-for=\"(user, idx) in users\"\n  :key=\"user.id\"\n  :name=\"`users[${idx}].name`\"\n></CustomTextField>\n```\n\nTo address this issue, you need to get a reactive reference to the `name` property. Vue offers a few ways to do this, so you can use any of the following methods:\n\n```js\nimport { toRef, toRefs, computed } from 'vue';\n\n// ✅ using a function that returns the name\nconst { value, errorMessage } = useField(() => props.name);\n\n// ✅ using `toRef`\nconst { value, errorMessage } = useField(toRef(props, 'name'));\n\n// ✅ using `toRefs`\nconst { name } = toRefs(props);\nconst { value, errorMessage } = useField(name);\n\n// ✅ using `computed`\nconst name = computed(() => props.name);\nconst { value, errorMessage } = useField(name);\n```\n\n## Destructing composable\n\nThe composition API examples in the docs have always used the left-hand side destructing syntax when assigning component data with any of the composable functions vee-validate offers. To quickly refresh your memory:\n\n```js\nconst { value } = useField('field');\nconst { handleChange } = useForm();\nconst { fields } = useFieldArray('users');\n```\n\nThis is required by default, because each of these functions assumes you might never need the entire features each one provides and such each state/function is exposed independently as a `Ref` or a `Function`.\n\nThis means if you try the following, it won't work as expected when used in your template:\n\n```vue\n<script setup>\nimport { useField, useForm, useFieldArray } from 'vee-validate';\n\nexport default {\n  setup() {\n    const form = useForm();\n    const field = useField('field');\n    const fieldArray = useFieldArray('users');\n\n    return {\n      form,\n      field,\n      fieldArray,\n    };\n  },\n};\n</script>\n\n<template>\n  <!-- ❌ Doesn't work -->\n  <input v-model=\"field.value\" />\n\n  <!-- ❌ Doesn't work -->\n  <pre>{{ form.meta.valid }}</pre>\n\n  <!-- ❌ Doesn't work -->\n  <div v-for=\"item in fieldArray.fields\"></div>\n</template>\n```\n\nThis is because the `setup` function doesn't recursively expose the refs inside of these objects. If you prefer to use the composition API like shown above, then you can fix most of the issues by wrapping the function calls with `reactive()`.\n\n```vue\n<script setup>\nimport { reactive } from 'vue';\nimport { useField, useForm, useFieldArray } from 'vee-validate';\n\nconst form = reactive(useForm());\nconst field = reactive(useField('field'));\nconst fieldArray = reactive(useFieldArray('users'));\n</script>\n\n<template>\n  <!-- ❌  Still Doesn't work because it is a writeable computed ref -->\n  <input v-model=\"field.value\" />\n\n  <!-- ✅  Works if unwrapped manually -->\n  <input v-model=\"field.value.value\" />\n\n  <!-- ✅  Works -->\n  <pre>{{ form.meta.valid }}</pre>\n\n  <!-- ✅  Works -->\n  <div v-for=\"item in fieldArray.fields\"></div>\n</template>\n```\n\nYou can read more on that behavior in [Vue.js docs](https://vuejs.org/guide/reusability/composables.html#conventions-and-best-practices). Note that once you wrap the composable calls with `reactive` you no longer can destruct them and preserve the reactivity.\n"
  },
  {
    "path": "docs/src/pages/guide/composition-api/custom-inputs.mdx",
    "content": "---\nlayout: ../../../layouts/PageLayout.astro\ntitle: Custom inputs\ndescription: Field-level and form-level validation and validation behavior and error messages with composition API\norder: 4\nnext:\n  path: guide/composition-api/helpers\n  title: Composable Helpers\n  description: Access any field or form state within child components with these composable helpers.\n  intro: |\n    You've learned to build your form, your custom inputs. Now it is a quick one to figure out how to build special components like submission buttons, reset buttons, error displays and more with these composable helpers.\n---\n\n# Building Custom inputs\n\nimport DocTip from '@/components/DocTip.vue';\nimport Repl from '@/components/MdxRepl.vue';\n\n## Imperative vs Declarative\n\nSo far we've been using `useForm` to create forms and use `defineField` to create field-binding objects to integrate them with our fields. However, that usually requires a lot of boilerplate code to create the binding object and the field component.\n\nFor example, this is how a 5-field form looks like with `useForm` and `defineField`:\n\n```js\nconst { defineField } = useForm();\n\nconst email = defineField('email');\nconst firstName = defineField('firstName');\nconst lastName = defineField('lastName');\nconst password = defineField('password');\nconst passwordConfirm = defineField('passwordConfirm');\n```\n\nThis can get ugly very quickly especially if you have a lot of field arrays or nested fields involved. This is one of the downsides of using an imperative API, but with `useField` you can switch to declarative API and get rid of all that boilerplate code.\n\n`useField` is a composition function that is similar to `useForm`. it makes it easier to create and manage input components. You should use it when creating custom input components and that means you've made the choice that vee-validate will be an integral part of your input component system.\n\n## Creating a custom input component\n\nLet's start with a simple example, we will create a `InputText` component that represents a text field. It can be as simple as this:\n\n```vue\n<template>\n  <input v-model=\"value\" />\n  {{ errorMessage }}\n</template>\n\n<script setup>\nimport { useField } from 'vee-validate';\n\nconst props = defineProps({\n  name: String,\n});\n\n// The `name` is returned in a function because we want to make sure it stays reactive\n// If the name changes you want `useField` to be able to pick it up\nconst { value, errorMessage } = useField(() => props.name);\n</script>\n```\n\nThis works exactly the same way as with `defineField`, but now since you have a vee-validate field component, you can use it directly in any component with a form context and it will just work:\n\nHere is a live example:\n\n<Repl files={{ 'App.vue': 'CompositionCustomField01', 'InputText.vue': 'CustomInputFieldBasic' }} client:visible />\n\nNotice how much of the burden of defining fields went away as soon as switched to the declarative approach. This is where `useField` really shines, but that's just us getting started. Follow along in this guide to make the most out of `useField`.\n\n## Validation\n\nAll previous examples have used the form's validation schema to validate the individual fields, however, you can also define a validation schema for each field individually.\n\n### Validating with yup\n\nYou can use Yup schemas to validate fields individually by passing the schema as the second argument to `useField`.\n\n<Repl files={{ 'App.vue': 'CompositionInputFieldYup' }} client:visible />\n\n### Validating with Zod\n\nYou can use [Zod](https://github.com/colinhacks/zod) directly with vee-validate.\n\n<Repl files={{ 'App.vue': 'CompositionInputFieldZod' }} client:visible />\n\n### Validating with Valibot\n\nYou can use [Valibot](https://valibot.dev/) to validate your fields.\n\n<Repl files={{ 'App.vue': 'CompositionInputFieldValibot' }} client:visible />\n\n### Other validation providers\n\n#### Standard Schema\n\nvee-validate supports [standard schema](https://standardschema.dev/) libraries, which includes all the previous validation providers and more.\n\n#### Validating with global validators\n\nAnother option is using `@vee-validate/rules` which have been historically bundled with past versions of vee-validate. It includes rules that can be defined globally and then used anywhere using Laravel-like string expressions.\n\nYou can refer to the full guide on global rules [here](/guide/global-validators).\n\n#### Validating with functions\n\nAnother option is to just use any 3rd party validation tool you prefer.\n\n<Repl files={{ 'App.vue': 'CompositionInputFieldFn' }} client:visible />\n\n### Triggers\n\n#### Default Behavior\n\nBy default, vee-validate runs validation whenever the `value` ref changes whether it was bound by a `v-model` or changed in your code:\n\n```js\nconst { value } = useField('fieldName', yup.string().required());\n\n// validation WILL be triggered\nvalue.value = 'something';\n```\n\nYou can disable that behavior by passing a `validateOnValueUpdate` option set to `false`:\n\n```js\nconst { value } = useField('fieldName', yup.string().required(), {\n  validateOnValueUpdate: false,\n});\n\n// validation WILL NOT trigger\nvalue.value = 'something';\n```\n\n#### Handling Events\n\n`useField()` composition function is not concerned with any events, it only validates whenever the `value` ref changes. However, it gives you everything you need to set up your own validation experience.\n\nThe `useField` function exposes some handler functions, each handling a specific aspect of the validation experience:\n\n- `handleChange`: Updates the field value, can be configured to trigger validation or silently update the value\n- `handleBlur`: Updates the `meta.touched` flag, doesn't trigger validation.\n\n```js\nconst { handleChange, handleBlur } = useField('someField');\n```\n\nIn this example, we are validating on the `input` event (when the user types), which would make the validation aggressive:\n\n<Repl files={{ 'App.vue': 'CompositionCustomField03', 'InputText.vue': 'CustomInputFieldAggressive' }} client:visible />\n\nWith a slight adjustment we can make our validation lazy by changing the listener to `@change` (validates when the user leaves the control):\n\n```vue-html\n<div>\n  <input @change=\"handleChange\" :value=\"value\" type=\"text\" />\n  <span>{{ errorMessage }}</span>\n</div>\n```\n\nNote that `handleChange` can be called anywhere, not just in the template, and not as just an event handler. You can use it to mutate the field value whenever you want, as an added bonus you can choose if `handleChange` should trigger a validation or not.\n\n```js\nconst { handleChange } = useField('someField');\n\n// validates by default\nhandleChange('new value');\n// validates\nhandleChange('new value', true);\n// Doesn't validate\nhandleChange('new value', false);\n```\n\nLet's say you want to validate on `blur` instead. You can use the `handleBlur` in a similar way. The main differences are:\n\n- `handleBlur` doesn't mutate the `value` of the field. It only sets the `meta.touched` to `true`.\n- `handleBlur` does not validate the current value by default, you have to pass `true` as a second argument to trigger validation.\n\nWith that info in mind, you can validate on `blur` like so:\n\n```vue-html\n<div>\n  <input\n    :value=\"value\"\n    type=\"text\"\n    @change=\"handleChange\"\n    @blur=\"handleBlur($event, true)\"\n  />\n  <span>{{ errorMessage }}</span>\n</div>\n```\n\nAs you can see, the `useField` doesn't care which events you use `handleChange` for. This allows for greater flexibility that's not possible with the `<Field>` component, not as straightforward at least.\n\nConsider this validation experience:\n\n- Validate on Change/Blur initially (when the user leaves the control), let's call this lazy mode.\n- If the field is invalid, switch the validation to validate on input (when the user types), let's call this aggressive mode.\n- If the field is valid, go back to \"lazy\" mode, otherwise, be \"aggressive\".\n\nImplementing this requires some knowledge about how the `v-on` (we can bind objects on it) handler works.\n\n```js\nconst { errorMessage, value, handleChange } = useField(() => props.name, undefined, {\n  validateOnValueUpdate: false,\n});\n\nconst validationListeners = {\n  blur: evt => handleBlur(evt, true),\n  change: handleChange,\n  input: evt => handleChange(evt, !!errorMessage.value),\n};\n```\n\nThen in your template, you can use `v-on` to add your listener object:\n\n```vue-html\n<input :value=\"value\" v-on=\"validationListeners\" type=\"text\" />\n```\n\nHere is a full example:\n\n<Repl files={{ 'App.vue': 'CompositionCustomField03', 'InputText.vue': 'CustomInputFieldEager' }} client:visible />\n\n## v-model Support\n\nThe `useField` function can automatically manage `v-model` integration for you. Usually, you will need to do this in every component you create:\n\n```js\nconst props = defineProps({\n  modelValue: String,\n});\n\nconst emit = defineEmits(['update:modelValue']);\n```\n\nInstead, you can let `useField` do that for you by telling it to enable `v-model` syncing:\n\n```js\nconst props = defineProps({\n  modelValue: String,\n});\n\nconst { value, errorMessage } = useField('fieldName', undefined, {\n  syncVModel: true,\n});\n```\n\nNow whenever `value` changes, you will emit an `update:modelValue` event with the new value. This is useful when you want to use `v-model` with your custom input component:\n\n<Repl files={{ 'App.vue': 'CompositionCustomField02', 'InputText.vue': 'CustomInputFieldVModel' }} client:visible />\n\nYou can also use different prop names for the `modelValue`, for example, `v-model:text` can be implemented by passing the model name directly to `syncVModel`.\n\n```js\nconst props = defineProps({\n  text: String,\n});\n\nconst { value, errorMessage } = useField('fieldName', undefined, {\n  syncVModel: 'text',\n});\n```\n\nThis will emit `onUpdate:text` instead of `onUpdate:modelValue` whenever the `value` changes.\n\n## Displaying Error Messages\n\nYou've already seen how to display errors with `useForm`. With `useField` you can use `errorMessage` ref:\n\n```js\nconst { errorMessage, value } = useField('fieldName', yup.string().required());\n\n// contains the error message if available\nerrorMessage.value;\n```\n\nIn addition to this, you can get all errors for the field using the `errors` ref which contains multiple error messages if applicable:\n\n```js\nconst { errors, value } = useField('fieldName', yup.string().required());\n\n// contains an array of error messages, otherwise empty array\nerrors.value;\n```\n\nHere is an example where each field displays its entire range of error messages:\n\n<Repl\n  files={{ 'App.vue': 'CompositionCustomField04', 'InputText.vue': 'CustomInputFieldMultiErrors' }}\n  client:visible\n/>\n\n### Custom Field Labels\n\nMore often than not, your fields will have names with underscores or shorthands which isn't very nice when showing in error messages, for example, you might have specific encoding to your field names because they might be generated by the backend. Ideally, you want to avoid having messages like:\n\n```txt\nThe down_p is required\n```\n\nAnd instead show something more meaningful to the user\n\n```txt\nThe down payment is required\n```\n\nYou can do this in two ways depending on which validators you are using (yup or [global validators](/guide/global-validators)).\n\n#### Custom Labels with Yup\n\nWith yup it is very straightforward, you just need to call `label()` after defining your field's validations either at the field level or form level:\n\n```js\nconst schema = Yup.object({\n  email_addr: Yup.string().email().required().label('Email Address'),\n  acc_password: Yup.string().min(5).required().label('Your Password'),\n});\n```\n\n#### Custom Labels with Zod\n\nZod does not have a built-in `label` method, but you can override the default error messages by passing a custom message to the chained validator.\n\n```js\nconst schema = z.object({\n  email_addr: z.string().email({ message: 'Email Address be a valid email address' });\n  acc_password: z.string().min(5, { message: 'Password be at least 5 characters long' });\n});\n```\n\nIf you are interested in how to do the same for global validators check the [i18n guide](/guide/i18n#custom-labels)\n\n## Field-level Meta\n\nEach field has metadata associated with it, the `meta` property returned from `useField` contains information about the field:\n\n- `valid`: The current field validity, is automatically updated for you.\n- `touched`: If the field was **touched**, can be updated with `setTouched` on `useField`'s return value.\n- `dirty`: If the field value was updated, you cannot change its value.\n- `pending`: If the field's validations are still running, useful for long-running async validation.\n- `initialValue`: The field's initial value, is `undefined` if you didn't specify any.\n\n```js\nconst { meta } = useField('fieldName');\n\nmeta.dirty;\nmeta.pending;\nmeta.touched;\nmeta.valid;\nmeta.initialValue;\n```\n\nThis is the typescript interface for a field's meta value\n\n```ts\ninterface FieldMeta {\n  dirty: boolean;\n  pending: boolean;\n  touched: boolean;\n  valid: boolean;\n  initialValue: any;\n}\n```\n\nJust like how the form's `meta` is read-only, this is also read-only and you cannot change it directly. Actually, only the `touched` meta value can be mutated using `handleBlur`, all other meta values are automatically updated for you as the field validates or when it changes its value.\n\n```js\nconst { meta, handleBlur } = useField('fieldName');\n\n// updates meta.touched = true\nhandleBlur();\n```\n\n<DocTip title=\"Valid Flag Combinations\">\n\nSince the `meta.valid` flag is initially `true` (because it just means there are no errors yet), it would cause problems if you have a \"success\" UI state as an indicator.\n\nTo avoid this case you should combine the `valid` flag with either `meta.dirty` or `meta.touched` to get an accurate representation. You will see that in action in the next example.\n\n</DocTip>\n\nIn the following example, we the various meta information flags to style the input with some styling.\n\n<Repl files={{ 'App.vue': 'CompositionCustomField05', 'InputText.vue': 'CustomInputFieldMeta' }} client:visible />\n\n<DocTip title=\"Field Dirty Flag and Initial Values\">\n\nNotice in the previous example, we passed an `initialValue`, this is because the default field value is `undefined` which may cause unexpected `meta.dirty` results.\n\nTo get accurate results for the `meta.dirty` flag, you must provide an initial value to your field even if the values are empty.\n\nTo reduce the verbosity of adding an `initialValue` prop to each field, you could provide the `initialValues` prop to your `useForm` call instead.\n\n</DocTip>\n\n## Building checkboxes\n\nCheckboxes are a hard type of input to implement, mainly because of the expectations about how it should mutate the form's value. For example, a checkbox can be used to toggle between `true` or `false` values which is common with single checkboxes. But it can also be used in a group to act as a multi-select between multiple options. In that case, it adds or removes its own \"checked\" value to the group value.\n\nThis means checkboxes have three states to maintain:\n\n- It's own checked value. In HTML this is done with the `value` attribute for native `input[type=\"checkbox\"]` elements.\n- The current form value and if it is a checkbox group or a single checkbox. This is usually the `modelValue` prop for components.\n- Whether it's checked or not, if the checked value equals or is in the form value then it is checked. This should be computed based on the previous fact.\n\nAll of this can be hard to wrap your head around. However, `useField` makes this easy as it already handles the nuances of checkboxes.\n\nThe `useField` function accepts a `type` option that you can use to tell vee-validate that the input type is a checkbox and also accepts a `checkedValue` option.\n\n```ts\nconst { handleChange, checked } = useField('myCheckbox', undefined, {\n  type: 'checkbox',\n  checkedValue: 'opt1',\n});\n```\n\nA simple integration with an input element would look like this:\n\n<Repl\n  files={{ 'App.vue': 'CompositionCustomFieldCheckbox', 'CustomCheckbox.vue': 'CustomCheckboxInputBasic' }}\n  client:only\n/>\n\nNote that we are not using `v-model` with the `value` returned from `useField` here. This is because `handleChange` is better suited for checkboxes as it handles toggling the value on or off and is also aware of the form has other checkboxes so it also handles whether the value should be an array or a single value.\n\nYou can find a more advanced example of checkboxes on [this page](/examples/custom-checkboxes/).\n"
  },
  {
    "path": "docs/src/pages/guide/composition-api/getting-started.mdx",
    "content": "---\nlayout: ../../../layouts/PageLayout.astro\ntitle: Getting started\ndescription: Field-level and form-level validation and validation behavior and error messages with composition API\norder: 1\nnext:\n  path: guide/composition-api/handling-forms\n  title: Handling forms\n  description: Submissions, resets and form state\n  intro: |\n    Now that you've learned how to use forms to define fields, collect their values and validate them. Next, you will learn how to handle submissions and implement advanced patterns with forms.\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport DocBadge from '@/components/DocBadge.vue';\nimport LiveExample from '@/components/LiveExample.vue';\nimport Repl from '@/components/MdxRepl.vue';\n\n# Getting started\n\nvee-validate is built from the ground up with the composition API through a collection of functions, mainly the `useField` and `useForm` functions. Internally the `<Form />` and `<Field />` components actually use the composition functions under the hood.\n\nMeaning you can create your own custom input and form components and they will be treated the same as `<Form />` and `<Field />` components. You can mix them together and use a `Form` component with any other custom component that uses `useField` and vice versa.\n\nvee-validate supports synchronous and asynchronous validation and allows defining rules on the field level or the form level using validation schemas. vee-validate has first-class support for:\n\n- [Standard Schema](https://standardschema.dev/) libraries like zod, valibot, yup and more.\n- [Global validators](/guide/global-validators) (Laravel-like syntax) through `@vee-validate/rules`.\n\nvee-validate has historically been a declarative validation library, and while the composition API changes things a bit, it still follows the same mindset of declarative validation. vee-validate optimizes for building fields and forms, not values.\n\n## When to use composition API\n\nWhile vee-validate offers both declarative components and composition functions to supercharge your forms, it is always up to you to decide which one to use. However, the composition API is easier to integrate and more flexible. You can build custom components with it or integrate it with any UI library. It is generally recommended to use the composition API.\n\nOn this page, you will learn how to declare forms and how to hook your elements and components into vee-validate forms and achieve value tracking, validation, and more.\n\n## Declaring Forms\n\n### Form context\n\nYou can declare forms with the `useForm` function exported from the `vee-validate` core package. This is a composition API function that marks the current component as a form.\n\n```vue\n<script setup>\nimport { useForm } from 'vee-validate';\n\n// Creates a form context\n// This component now acts as a form\n// Usually you will destruct the form context to get what you need\nconst { values } = useForm();\n</script>\n\n<template>\n  <pre>{{ values }}</pre>\n</template>\n```\n\nCalling `useForm` creates a form context in the component and provides it for any child component that injects it. This means you should stick to calling `useForm` once in a component.\n\nCreating a form context does a few things:\n\n- Acts as a value collector for all the fields you will declare as child components.\n- Validates the fields and aggregates the errors.\n- Aggregates the validity, touched, and dirty states of all the fields.\n\n### Field binds\n\nWith `useForm` declared, you are now ready to integrate the form with your elements and components. vee-validate is agnostic to the UI you are using.\n\nYou will learn how to associate your components and elements with the form and how to get value collection, validation, and error messages working.\n\n### HTML Inputs\n\n`useForm` provides a function called `defineField`. This function accepts a field path and returns a value model and an object containing the bindings for the input element. The field path is a string that represents the path to the field in the form context.\n\nFor example, if you have a field called `email` in the form context, the field path will be `email`.\n\n```ts\nconst { defineField } = useForm();\n\nconst [email, emailAttrs] = defineField('email');\n```\n\nNote that `defineField` generates a pair of values, the first one is the value model and the second one is the attributes/props object. The props object contain attributes or event listeners that are useful to have on the input control or component which enables custom validation triggers and more.\n\nHere is a basic example of how to use `defineField` with a simple input element:\n\n<Repl files={{ 'App.vue': 'CompositionInputBindsBasic01' }} client:visible />\n\nNotice that as you type in the input, the `values` are automatically updated with the value changes.\n\nLet's quickly add a validation schema on the form to see some errors on the form. We will be using `yup` throughout the examples, but you can use `zod` or any other supported validation library you want.\n\nTo add a `yup` schema or any kind of form schema, you pass it to the `validationSchema` option when calling `useForm`. Naturally, form schemas are almost always an `object` or a `shape` schema.\n\n```ts{1,3-5,8}\nimport * as yup from 'yup';\n\nconst schema = yup.object({\n  email: yup.string().required().email(),\n});\n\nconst { defineField } = useForm({\n  validationSchema: schema,\n});\n\nconst [email, emailAttrs] = defineField('email');\n```\n\nHere is a full running example:\n\n<Repl files={{ 'App.vue': 'CompositionInputBindsBasic02' }} client:visible />\n\nNotice as you type into the input, the validation is then triggered and the errors are populated. By default `defineField` optimizes for aggressive validation, meaning the validation will be triggered whenever the model changes.\n\nYou can change that behavior. For example, you can make it \"lazy\" by passing a configuration to `defineField` to disable validation on model updates with `validateOnModelUpdate` config.\n\n<Repl files={{ 'App.vue': 'CompositionInputBindsBasic03' }} client:visible />\n\nNow as you type in the field, the input is not immediately validated. You can do more with dynamic configurations.\n\n### Components\n\nSimilarly to HTML inputs, you can achieve the same results with the same `defineField` function.\n\nFollowing the previous examples we can achieve value tracking like this:\n\n<Repl files={{ 'App.vue': 'CompositionComponentBindsBasic01', 'CustomInput.vue': 'CustomInputBasic' }} client:visible />\n\nAs you type into the input, notice that the `values` are being updated.\n\nLet's add validation to the previous example:\n\n<Repl files={{ 'App.vue': 'CompositionComponentBindsBasic02', 'CustomInput.vue': 'CustomInputBasic' }} client:visible />\n\nNotice that for components, validations are executed immediately. This is intended because component implementations are not standardized across the Vue ecosystem as there is no guarantee it will emit the same range of events as the native HTML elements. However, you can customize the validation trigger if you know the components you are using are emitting the right events to support the behavior.\n\n<Repl files={{ 'App.vue': 'CompositionComponentBindsBasic03', 'CustomInput.vue': 'CustomInputBasic' }} client:visible />\n\n### Mapping attributes and props\n\nBut aside from the attributes and listeners that vee-validate adds to those binding objects, you can also map the attributes and props of the in. This is useful when you want to:\n\n- Map the attributes/props to a different name.\n- Pass new attributes/props to the component/element based on the field state.\n\nYou can use `props` to include any additional props or attributes you need to add to the component/element.\n\n```ts\nconst { defineField } = useForm({\n  // ...\n});\n\nconst [email, emailProps] = defineField('email', { props: state => ({ error: state.errors[0] }) });\n```\n\nIn the following example, we have a component that accepts an `error` string prop and shows that message if it is not empty. This is common in many UI libraries as they try not to lock you into a specific validation library.\n\n<Repl\n  files={{ 'App.vue': 'CompositionComponentBindsBasic04', 'CustomInput.vue': 'CustomInputBasicError' }}\n  client:only\n/>\n\n<DocTip>\n\nThe `state` object contains a lot of useful information about the field, it is fully typed so you can explore it with your IDE or visit the [source reference](https://github.com/logaretm/vee-validate/blob/main/packages/vee-validate/src/types/forms.ts#L255-L258) for more information.\n\n</DocTip>\n\nNotice that `form` also gives you access to `errors` so you can reference them anywhere in the component.\n\n### Dynamic configuration\n\nInstead of passing a static configuration object `defineField`, you could pass a function that returns different configuration values. This is useful when you want the configuration to be dynamic based on the field state.\n\nHere is an example that shows how to make the validation behavior \"eager\". Meaning if the field does not have any errors then it will only validate on `change`.\n\nBut once it is invalid, it validates on each input event, making it \"eager\" for success.\n\n<Repl files={{ 'App.vue': 'CompositionComponentBindsBasic05' }} client:visible />\n\n## Form Schema\n\nAs you have seen in the previous examples, the `useForm` function accepts a `validationSchema` that is used to validate the form. We've been using yup to define the schema however you can use `zod` or any 3rd-party validators.\n\n### Validating with Yup\n\nYou can pass yup schemas directly as you've seen previously.\n\n<Repl files={{ 'App.vue': 'CompositionYupBasic' }} client:visible />\n\n### Validating with Zod\n\nYou can use [Zod](https://github.com/colinhacks/zod) in a very similar manner to how we've been using yup in the past examples.\n\n```ts\nimport { useForm } from 'vee-validate';\nimport { z } from 'zod';\n\nconst schema = z.object({\n  email: z.string().nonempty().email(),\n});\n\nconst { errors, values } = useForm({\n  validationSchema: schema,\n});\n```\n\nHere is a full example using zod with `useForm`:\n\n<Repl files={{ 'App.vue': 'CompositionZodBasic' }} client:visible />\n\n<DocTip title=\"refine/superRefine\">\n\nThere is a known issue with Zod's `refine` and `superRefine` not executing whenever some object keys are missing which is common with forms. This is not an issue with vee-validate as it is a design choice in Zod at the moment. Refer to [this issue](https://github.com/logaretm/vee-validate/issues/4338) for explanations and further reading.\n\n</DocTip>\n\n### Validating with Valibot\n\nYou can also use [Valibot](https://valibot.dev/) which is is a schema library with bundle size, type safety and developer experience in mind. It is a great alternative to Yup and Zod if bundle size is a concern.\n\n```ts\nimport { useForm } from 'vee-validate';\nimport * as v from 'valibot';\n\nconst schema = v.object({\n  email: v.pipe(v.string(), v.email('Invalid email'), v.nonEmpty('required')),\n});\n\nconst { errors, values } = useForm({\n  validationSchema: schema,\n});\n```\n\nHere is a full example using valibot with `useForm`:\n\n<Repl files={{ 'App.vue': 'CompositionValibotBasic' }} client:visible />\n\n### Other validation providers and options\n\n#### Global Rules\n\nAnother option is using `@vee-validate/rules` which have been historically bundled with past versions of vee-validate. It includes rules that can be defined globally and then used anywhere using Laravel-like string expressions.\n\nYou can refer to the full guide on global rules [here](/guide/global-validators).\n\n#### Validating with functions\n\nAnother option is to just use any 3rd party validation tool you prefer, something like [`validator.js`](https://github.com/validatorjs/validator.js/). Here is a quick example:\n\n<Repl files={{ 'App.vue': 'CompositionValidateFnBasic' }} client:visible />\n\nOr you could use any custom function.\n\n<DocTip>\n\nSchema libraries like zod and yup are great at defining schemas especially with nested values so it is recommended that you use any [standard schema](https://standardschema.dev/) library to get full benefits. As an added bonus, you get full typescript support with any compatible library.\n\n</DocTip>\n\n### Dynamic Form Schemas\n\nThere are a few ways you can create dynamic schemas (reactive) where it changes the validation rules based on some state. The first way to do that is with `computed`.\n\n<Repl files={{ 'App.vue': 'CompositionDynamicSchemaComputed' }} client:visible />\n\nWhen the validation schema value changes, only the fields that were validated at least once will be re-validated, the other fields won't be validated to avoid aggressive validation behavior.\n\nThere are other ways depending on which validation library you are using. For example, with `yup` you can achieve the same with `yup.lazy` or `zod.lazy`:\n\n<Repl files={{ 'App.vue': 'CompositionDynamicSchemaYupLazy' }} client:visible />\n"
  },
  {
    "path": "docs/src/pages/guide/composition-api/handling-forms.mdx",
    "content": "---\nlayout: ../../../layouts/PageLayout.astro\ntitle: Handling Forms\ndescription: Handling form state and submissions\norder: 2\nnext:\n  path: guide/composition-api/nested-objects-and-arrays\n  title: Nested Objects and Arrays\n  description: Structuring form values in nested paths in objects or arrays\n  intro: |\n    So far we've only dealt with flat form values, what about nested objects and arrays? In the next guide you will learn how to use path names to structure your values and nest them declaratively.\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport Repl from '@/components/MdxRepl.vue';\n\n# Handling Forms\n\nvee-validate makes it easy to handle form submissions, resets, and DX to make your forms much easier to reason about and less of a burden to maintain. The `useForm` function allows you to easily handle:\n\n<div class=\"features\">\n\n- Form state (valid/dirty/touched/pending).\n- Submitting forms and handling invalid submissions.\n- Handling form resets.\n\n</div>\n\n## Form Metadata\n\nForms have a `meta` object value containing useful information about the form, it acts as an aggregation of the metadata for the fields inside that form.\n\n```js\nconst { meta } = useForm();\n\nmeta.value.dirty;\nmeta.value.pending;\nmeta.value.touched;\nmeta.value.valid;\nmeta.value.initialValues;\n```\n\n- `valid`: The form's validity status, will be `true` if the errors array is empty initially, but will be updated once the form is mounted.\n- `touched`: If at least one field was blurred (unfocused) inside the form.\n- `dirty`: If at least one field's value was updated.\n- `pending`: If at least one field's validation is still pending.\n- `initialValues`: All fields' initial values, this is an object where the keys are the field names.\n\nHere is a simple example where we disable the form's submit button unless a field was touched.\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms01' }} client:visible />\n\n## Handling Submissions\n\nvee-validate exposes useful defaults to help you handle form submissions whether you submit them using JavaScript or native HTML submissions.\n\n### JavaScript Submissions (AJAX)\n\nTo handle submissions, you can use the `handleSubmit` function to create submission handlers for your forms, the `handleSubmit` function accepts a callback that receives the final form values.\n\n```js\nconst { handleSubmit } = useForm({\n  validationSchema: yup.object({\n    email: yup.string().email().required(),\n    password: yup.string().min(6).required(),\n  }),\n});\n\n// Creates a submission handler\n// It validates all fields and doesn't call your function unless all fields are valid\n// You can bind `onSubmit` to a form element's submit event, or call it directly to submit the current data.\nconst onSubmit = handleSubmit(values => {\n  alert(JSON.stringify(values, null, 2));\n});\n```\n\nHere is an example that makes use of `handleSubmit` to validate before submitting the form.\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms02' }} client:visible />\n\nThe `handleSubmit` function will only execute your callback once the returned function (`onSubmit` in the example) if all fields are valid, meaning you don't have to handle if the form is invalid in your logic.\n\nYou can call the returned function either manually or via an event like `@submit` and it will validate all the fields and execute the callback if everything passes validation.\n\nAs a bonus, when the returned function is used as an event handler (like in the previous example) it will automatically prevent the default submission of the form so you don't need to use the `prevent` modifier like you normally would.\n\n### Full-Page Submissions (non-AJAX)\n\nFor non-ajax submissions that trigger a full page reload, you can use the `submitForm` function instead of `handleSubmit`. You normally would use this if you are not building a single-page application. In the following example, we submit the form to another tab using the `get` form method.\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms13' }} client:visible />\n\nIn that case **YOU MUST** use `submitForm` as an event handler for the `submit` event for a native `form` element, otherwise, it would have no effect.\n\n### Handling Invalid Submissions\n\nSometimes you want to perform some logic after a form fails to submit due to validation errors (e.g. focusing the first invalid field), you can pass a callback as the second argument to the `handleSubmit` function.\n\n```js\nconst { handleSubmit } = useForm();\n\nfunction onSuccess(values) {\n  alert(JSON.stringify(values, null, 2));\n}\n\nfunction onInvalidSubmit({ values, errors, results }) {\n  console.log(values); // current form values\n  console.log(errors); // a map of field names and their first error message\n  console.log(results); // a detailed map of field names and their validation results\n}\n\n// This handles both valid and invalid submissions\nconst onSubmit = handleSubmit(onSuccess, onInvalidSubmit);\n```\n\nHere is a quick example of how to scroll to and focus the first invalid field after a failed submission attempt.\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms03' }} client:visible />\n\n### Submission Progress\n\nQuite often you need to show your users a submission indicator, or you might want to disable the submit button entirely until the submission attempt is done. The `useForm` function exposes an `isSubmitting` ref that you can use.\n\nThe `isSubmitting` state will be set to `true` once the validation of the form starts (as a result of a submit event) and will keep track of the submission handler you passed to either `onSubmit` or until it calls `submitForm`. If the submission handler throws any errors or completes successfully it will be set to `false` afterward.\n\n```js\nconst { isSubmitting } = useForm();\n```\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms04' }} client:visible />\n\n### Submit Count\n\nThe `useForm` function also exposes a `submitCount` ref that you can use to track the number of submissions attempted by the user. The count is incremented regardless of the validation result.\n\n```js\nconst { submitCount } = useForm();\n```\n\nMaybe you want to lock the form if too many attempts were made, or you want to show a message after the first submission attempt.\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms05' }} client:visible />\n\n### Submission Behavior\n\nvee-validate does the following when calling submission handlers created by `handleSubmit` or when calling `submitForm` as a result of the user submitting the form.\n\n#### Before validation stage\n\n- Sets all fields `touched` meta to `true`\n- Sets `isSubmitting` form state to `true`\n- Increments the `submitCount` form state by `1`\n\n#### Validation stage\n\n- Sets form and individual fields meta `pending` to `true` to indicate validation is in progress\n- Runs the validation function/schema/rule against the current form values asynchronously\n- Checks for any errors in the validation result\n  - If there are errors then it will skip the next stage and update the validation state (meta, errors) for the form and fields\n  - If there aren't any errors then it will set the `pending` meta flag to `false` and proceed to the next stage\n\n#### After validation stage\n\n- Calls the `handleSubmit` handler you passed\n- After the callback finishes (it will wait if the result is asynchronous), then it will set `isSubmitting` to `false`\n\nNote that there isn't a need to have `isSubmitting` set back to false if you've used `submitForm`, as this submission method will perform a full-page refresh (native forms behavior).\n\n## Form Values\n\nYou may have noticed in the earlier examples that you can access all fields' values using the `values` reactive object returned by `useForm`.\n\n```js\nconst { values } = useForm();\n```\n\nThe `values` object is read-only and should not be mutated with a `v-model` or by assigning a value to it. This is because all mutations are done through the vee-validate API, this is because mutations to form state need to have a context.\n\nFor example:\n\n```js\nconst { values } = useForm();\n\n// ❌ Do not do that!\nvalues.email = '';\n```\n\nIn order for the form UX to be stable, we need to understand why the email value was set to `''`. Was it being reset? Should we run validation again? This is the type of small differences that are a result of vee-validate's design choice based on fields and forms, not values.\n\n### Initial Values\n\nSince you don't have to use `v-model` to track your values, the `useForm` function allows you to define the starting values for your fields, by default all fields start with `undefined` as a value.\n\nUsing the `initialValues` option you can send an object that contains the field names as keys and their values:\n\n```js\nconst { defineInputBinds } = useForm({\n  initialValues: {\n    email: 'test@example.com',\n    password: 'p@$$w0rd',\n  },\n});\n```\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms06' }} client:visible />\n\n<DocTip>\n\nIt's generally recommended that you provide the `initialValues`, this is because vee-validate cannot assume a reasonable initial value for your fields other than `undefined` which may cause unexpected behavior when using a 3rd-party validator that does not deal with `undefined`.\n\n</DocTip>\n\nYou can reset initial values at [any time using the `resetForm`](#handling-resets) function returned by `useForm`.\n\n### Manually Setting Form Values\n\nYou can set any field's value using either `setFieldValue` or `setValues` returned by `useForm`.\n\n```js\nconst { setFieldValue, setValues } = useForm();\n\n// Sets a value of a specific field in the form values\nsetFieldValue('fieldName', 'value');\n\n// Merges the given object with the current form values\nsetValues({\n  fieldName: 'value',\n});\n```\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms07' }} client:visible />\n\n### Controlled Values\n\nThe form values can be categorized into two categories:\n\n- Controlled values: values that have a form input controlling them via `defineInputBinds` or `defineComponentBinds` or `useField` or `<Field />`.\n- Uncontrolled values: values that are inserted dynamically with `setFieldValue` or inserted initially with initial values.\n\nSometimes you maybe only interested in controlled values. For example, your initial data contains noisy extra properties from your API and you wish to ignore them when submitting them back to your API.\n\nWhen accessing `values` from `useForm` result or the submission handler you get all the values, both controlled and uncontrolled values. To get access to only the controlled values you can use `controlledValues` from the `useForm` result:\n\n```js\nconst { handleSubmit, controlledValues } = useForm();\n\nconst onSubmit = handleSubmit(async () => {\n  // Send only controlled values to the API\n  const response = await client.post('/users/', controlledValues.value);\n});\n```\n\nAlternatively, for less verbosity, you can create submission handlers with only the controlled values with `handleSubmit.withControlled` which has the same API as `handleSubmit`:\n\n```js\nconst { handleSubmit } = useForm();\n\nconst onSubmit = handleSubmit.withControlled(async values => {\n  // Send only controlled values to the API\n  const response = await client.post('/users/', values);\n});\n```\n\nHere is an example that filters out some noisy initial values when submitting the form using the `withControlled` modifier.\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms12' }} client:visible />\n\n### Setting initial values asynchronously\n\nSometimes your data is fetched asynchronously from an API and you want to set the initial values or the current values after the data is fetched. You can do that by using `resetForm` to set both current and initial data.\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms14' }} client:visible />\n\nYou could alternatively use `setValues` but note that `setValues` can trigger validation and do not reset the meta state for the fields like `dirty` or `touched`.\n\n## Handling Resets\n\nvee-validate also handles form resets in a similar way to submissions. When resetting the form, all fields' errors will be cleared, meta info will be reset to defaults and the values will be reset to their original or initial values.\n\nTo reset forms you can use the `resetForm` function returned by `useForm`. You can also reset the form to a new state by passing a `FormState` object to the `resetForm` function. You can then set errors, `touched` meta, and the values.\n\n```js\nconst { resetForm } = useForm();\n\n// Resets the form\nresetForm();\n\n//\nresetForm({\n  touched: {\n    email: false,\n  },\n  errors: {\n    email: 'custom error',\n  },\n  values: {\n    email: 'newvalue@email.com',\n  },\n});\n```\n\nThis is the shape of the `FormState` object:\n\n```ts\ninterface FormState {\n  // any error messages\n  errors: Record<string, string>;\n  // touched meta flags\n  touched: Record<string, boolean>;\n  // Form Values\n  values: Record<string, any>;\n}\n```\n\nHere is an example where a full form is being reset:\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms08' }} client:visible />\n\n### Resetting Forms After Submit\n\nUsually, you will reset your forms after successful submission. For convenience, the `onSubmit` handler receives an additional `FormActions` object in the second argument that allows you to do some actions on the form after submissions, this is the shape of the `FormActions` object:\n\n```ts\nexport interface FormActions {\n  setFieldValue: (field: T, value: any) => void;\n  setFieldError: (field: string, message: string | undefined) => void;\n  setErrors: (fields: Partial<Record<string, string | undefined>>) => void;\n  setValues: (fields: Partial<Record<T, any>>) => void;\n  setFieldTouched: (field: string, isTouched: boolean) => void;\n  setTouched: (fields: Partial<Record<string, boolean>>) => void;\n  resetForm: (state?: Partial<FormState>) => void;\n}\n```\n\nThis is an example of using the form actions object to reset the form:\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms09' }} client:visible />\n\n## Errors\n\nAs you have previously seen in some examples, you have access to `errors` with `useForm` that contains a mapping of each field's path and its error message.\n\n```js\nconst { errors } = useForm();\n```\n\nHowever, if you want to display multiple errors for your fields then you can use `errorBag` which is a mapping of each field's path and an array of error messages for that field.\n\n```js\nconst { errorBag } = useForm();\n```\n\nHere is an example that displays multiple errors for a field:\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms10' }} client:visible />\n\n### Initial Errors\n\nIf you are building a non-SPA application it is very common to pre-fill form errors using server-side rendering, frameworks like Laravel and Rails make this very easy to do. vee-validate supports filling the errors initially before any validation is done using the `initialErrors` option.\n\nThe `initialErrors` option accepts an object containing the field names as keys with their corresponding error message string.\n\n```js\nuseForm({\n  initialErrors: {\n    email: 'This email is already taken',\n    password: 'The password is too short',\n  },\n});\n```\n\n<DocTip>\n\n`initialErrors` are applied once the component that called `useForm` is mounted and is ignored after, so any changes to the `initialErrors` props won't affect the messages.\n\n</DocTip>\n\n### Setting Errors Manually\n\nQuite often you will find yourself unable to replicate some validation rules on the client-side due to natural limitations. For example, `unique` email validation is complex to implement on the client side. So the ability to set errors manually can be useful.\n\nYou can set messages for fields by using either `setFieldError` which sets an error message for one field at a time, or by using the `setErrors` function which allows you to set error messages for multiple fields at once.\n\nBoth functions are available as a return value from `useForm`. In the following example, we check if the server response contains any validation errors and we set them on the fields:\n\n```js\nconst { handleSubmit, setFieldError, setErrors } = useForm();\n\nconst onSubmit = handleSubmit(async values => {\n  // Send data to the API\n  const response = await client.post('/users/', values);\n\n  // all good\n  if (!response.errors) {\n    return;\n  }\n\n  // set single field error\n  if (response.errors.email) {\n    setFieldError('email', response.errors.email);\n  }\n\n  // set multiple errors, assuming the keys are the names of the fields\n  // and the key's value is the error message\n  setErrors(response.errors);\n});\n```\n\nAlternatively, you can use the `FormActions` passed as the second argument to the `handleSubmit` callback which contains both functions for convenience:\n\n```js\nconst onSubmit = handleSubmit(async (values, actions) => {\n  // Send data to the API\n  const response = await client.post('/users/', values);\n  // ...\n\n  // set single field error\n  if (response.errors.email) {\n    actions.setFieldError('email', response.errors.email);\n  }\n\n  // set multiple errors, assuming the keys are the names of the fields\n  // and the values is the error message\n  actions.setErrors(response.errors);\n});\n```\n\nHere is an example that sets form errors after submission, usually you will have a backend API that returns the errors:\n\n<Repl files={{ 'App.vue': 'CompositionHandlingForms11' }} client:visible />\n"
  },
  {
    "path": "docs/src/pages/guide/composition-api/helpers.mdx",
    "content": "---\nlayout: ../../../layouts/PageLayout.astro\ntitle: Composition Helpers\ndescription: Composition API helpers\nmenuTitle: Helpers\norder: 5\n---\n\nAside from `useField` and `useForm` and `useFieldArray`, these are a collection of simple functions that you can use to opt-in specific parts of vee-validate features like form state and various actions you can perform on fields and forms.\n\nHere are a few examples of what you can build with these functions:\n\n- A custom submission progress component\n- A custom error message component.\n- A form validity indicators\n- reset buttons or submit buttons\n\nHere is a list of the functions available that you can use:\n\n- `useFieldError` Gives access to a single field's first error message\n- `useFormErrors` Gives access to the entire error bag of the form\n- `useIsFieldDirty` If a field is dirty\n- `useIsFormDirty` If the form is dirty (form contains at least one dirty field)\n- `useIsFieldTouched` If a field is touched\n- `useIsFormTouched` If the form is touched (form contains at least one touched field)\n- `useIsFieldValid` If a field is valid\n- `useIsFormValid` If all fields are **validated and valid**\n- `useValidateField` Returns a function that validates a specific field\n- `useValidateForm` Returns a function that validates the entire form\n- `useResetForm` Resets the form to its initial state\n- `useSubmitForm` Creates a submission function that validates and submits the form (even if no `form` element is involved)\n- `useIsSubmitting` If the form is currently submitting\n- `useIsValidating` If the form is currently validating by validate function\n- `useSubmitCount` The number of times the user attempted to submit the form\n- `useFieldValue` Returns a specific fields' current value\n- `useFormValues` Returns the current form field values\n\nFor more information about the functions, you can head over to the [API reference and check them out](/api/composition-helpers).\n"
  },
  {
    "path": "docs/src/pages/guide/composition-api/nested-objects-and-arrays.mdx",
    "content": "---\nlayout: ../../../layouts/PageLayout.astro\ntitle: Nested Objects and Arrays\ndescription: Structuring form values in nested paths in objects or arrays\norder: 3\nnext:\n  path: guide/composition-api/custom-inputs\n  title: Custom Inputs\n  description: Building input components with the composition API\n  intro: |\n    You've learned a lot about forms so far, but that's not all. Just like how vee-validate makes it easy to build forms, it also offers tools to help you build custom input components with the composition API. Enter `useField()`.\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport DocBadge from '@/components/DocBadge.vue';\nimport Repl from '@/components/MdxRepl.vue';\n\n# Nested Objects and Arrays\n\nvee-validate supports nested objects and arrays by using field path syntax to indicate a field's path. This allows you to structure forms easily to make data mapping straightforward without having to deal with flat form values.\n\n## Nested Objects\n\nYou can specify a field to be nested in an object using dot paths, like what you would normally do in JavaScript to access a nested property. The field's `name` acts as the path for that field in the form values:\n\n```js\nconst { defineInputBinds } = useForm();\n\nconst twitterLink = defineInputBinds('links.twitter');\nconst githubLink = defineInputBinds('links.github');\n```\n\nSubmitting the previous form would result in the following values being passed to your handler:\n\n```js\n{\n  \"links\": {\n    \"twitter\": \"https://twitter.com/logaretm\",\n    \"github\": \"https://github.com/logaretm\"\n  }\n}\n```\n\nHere is a live example so you can see it in action.\n\n<Repl files={{ 'App.vue': 'CompositionNested01' }} client:visible />\n\nYou are not limited to a specific depth, you can nest as much as you like.\n\n## Nested Arrays\n\nSimilar to objects, you can also nest your values in an array, using square brackets just like how you would do it in JavaScript.\n\n```js\nconst { defineInputBinds } = useForm();\n\nconst twitterLink = defineInputBinds('links[0]');\nconst githubLink = defineInputBinds('links[1]');\n```\n\nHere is the same example as above but in array format:\n\n<Repl files={{ 'App.vue': 'CompositionNested02' }} client:visible />\n\nSubmitting the previous form would result in the following values being passed to your handler:\n\n```js\n{\n  \"links\": [\n    \"https://twitter.com/logaretm\",\n    \"https://github.com/logaretm\"\n  ]\n}\n```\n\n<DocTip type=\"warn\">\n\nvee-validate will only create nested arrays if the path expression is a complete number, for example, paths like `some.nested[0path]` will not create any arrays because the `0path` key is not a number. However `some.nested[0].path` will create the array with an object as the first item.\n\n</DocTip>\n\n## Avoiding Nesting\n\nIf your fields' names are using the dot notation and you want to avoid the nesting behavior which is enabled by default, all you need to do is wrap your field names in square brackets (`[]`) to disable nesting for those fields.\n\n```js\nconst { defineInputBinds } = useForm();\n\nconst twitter = defineInputBinds('[links.twitter]');\nconst github = defineInputBinds('[links.github]');\n```\n\nSubmitting the previous form would result in the following values being passed to your handler:\n\n```js\n{\n  \"links.twitter\": \"https://twitter.com/logaretm\",\n  \"links.github\": \"https://github.com/logaretm\"\n}\n```\n\nHere is a live example on that:\n\n<Repl files={{ 'App.vue': 'CompositionNested03' }} client:visible />\n\n## Field Arrays\n\nField arrays are a special type of nested array fields, they are often used to collect repeatable pieces of data or repeatable forms. They are often called \"repeatable fields\".\n\nTo set up a repeatable block of the form, you can use `useFieldArray` to help you manage the array values and operations. It requires a form context to be present so `useForm` must be called before you use `useFieldArray` either in parent component or in the same component.\n\n```js\nimport { useForm, useFieldArray } from 'vee-validate';\n\nuseForm();\n\nconst { remove, push, fields } = useFieldArray('users');\n```\n\nThe `useFieldArray` exposes a few properties and functions to help you manage the array fields, the most special one is the `fields` array which contains the array items and represents their current value in the form. You will use `fields` as an iteration source to render the array items.\n\nHere is an example of a repeatable block of fields, we mutate the field value with `v-model` directly on the iteration item value.\n\n<Repl files={{ 'App.vue': 'CompositionNested04' }} client:visible />\n\nNotice that we used `field.key` as the key of the iteration, this is because vee-validate generates a unique key for each array item so you can rely it on without having to generate them yourself.\n\n<DocTip type=\"warn\">\n\nThe `key` property generated on array items is not an index. It is a unique identifier for the array item that is independent of the array index, so you should not be using it to reference field names.\n\n</DocTip>\n\n### Field Array Paths\n\nWhen calling `useFieldArray` you need to provide a `name` prop which is the path of the array starting from the root form value, you can use dot notation for object paths or indices for array paths.\n\nHere are a few examples:\n\n_*Iterate over the `users` array:*_\n\n```js\nconst { remove, push, fields } = useFieldArray('users');\n```\n\n_*Iterate over the `domains` inside `settings.dns` object:*_\n\n```js\nconst { remove, push, fields } = useFieldArray('settings.dns.domains');\n```\n\n### Array Helpers\n\nThe `<useFieldArray />` function provides the following properties and functions:\n\n- `fields`: a **read-only** version of your array field items, it includes some useful properties like `key`, `isFirst` and `isLast`, the actual item value is inside `.value` property. You should use it to iterate with `v-for`.\n- `push(item: any)`: adds an item to the end of the array.\n- `prepend(item: any)`: adds an item to the start of the array.\n- `insert(idx: number, item: any)`: Inserts an array item at the specified index.\n- `remove(idx: number)`: removes the item with the given index from the array.\n- `swap(idxA: number, idxB: number)`: Swaps two array elements by their indexes.\n- `replace(items: any[])`: Replaces the entire array values with the given items.\n- `update(idx: number, value: any)`: Updates an array item value at the specified index.\n- `move(oldIdx: number, newIdx: number)`: Moves an array item to a different position within the array.\n\n[Read the API reference](/api/use-field-array) for more information.\n\n## Caveats\n\n### Paths creation and destruction\n\nvee-validate creates the paths inside the form data automatically but lazily, so initially, your form values won't contain the values of the fields unless you provide initial values for them. It might be worthwhile to provide initial data for your forms with nested paths.\n\nWhen fields get unmounted like in the case of conditional rendered fields with `v-if` or `v-for`, their path will be destroyed just as it was created if they are the last field in that path. So you need to be careful while accessing the nested field in `values` inside your submission handler.\n\nPath destruction can be annoying when dealing with multi-step forms or tabbed forms where you want all the values to be available even when the fields are unmounted. You can control this behavior by passing `keepValueOnUnmount` prop to the `useField` function or you can do it for all the fields by passing `keepValuesOnUnmount` to the `useForm` function.\n\nNote that the priority of this configuration follows the field config first then it fallbacks to the form's config.\n\n```js\nimport { useForm } from 'vee-validate';\n\n// keep all values when their fields get unmounted\nconst { values } = useForm({\n  keepValuesOnUnmount: true,\n});\n```\n\n```js\nimport { useField } from 'vee-validate';\n\n// this field value will be removed\nconst field = useField('field', undefined, {\n  keepValueOnUnmount: false,\n});\n```\n\n### Referencing Errors\n\nWhen referencing errors using `errors` object returned from the `useForm` function. Make sure to reference the field name in the same way you set it on the `name` argument for that field. So even if you avoid nesting you should always include the square brackets. In other words `errors` do not get nested, they are always flat.\n\nSince vee-validate supports `yup` and `zod` schemas, referencing the nested fields may vary depending on how you are specifying the schema.\n\nIf you are using yup, you can utilize the nested `yup.object` or `yup.array` schemas to provide validation for your nested fields, here is an example:\n\n<Repl files={{ 'App.vue': 'CompositionNested05' }} client:visible />\n\nYou can [visit this link](/examples/array-fields) for a practical example using nested arrays.\n"
  },
  {
    "path": "docs/src/pages/guide/devtools.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Devtools Plugin\ndescription: Using the vee-validate Vue.js devtools plugin\norder: 7\nnext:\n  path: guide/testing\n  title: Testing\n  description: Testing form validation in your apps\nnew: true\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport DocBadge from '@/components/DocBadge.vue';\n\n# Devtools Plugin <DocBadge title=\"v4.5\" />\n\nvee-validate ships with a Vue.js devtools plugin that allows you to inspect your forms. The terms \"devtools plugin\" or \"plugin\" in this page will refer to vee-validate's devtools plugin from now on.\n\nThe devtools plugin is useful for debugging and inspecting your forms. A common situation is not having any clues on why a form isn't submitting, the devtools plugin exposes to you all of the validation state giving you insight for your forms behavior.\n\nSince vee-validate doesn't require any app configuration, the devtools plugin is auto installed when you use `useField` or `useForm` or their component counterpart `<Field />` and `<Form />`.\n\n<DocTip type=\"warn\">\n\nNote that the plugin won't be installed in the following cases:\n\n- You are using the umd builds via CDN\n- Your `process.env.NODE_ENV` is set to `production` or `test`\n\nThat means the plugin is only available to the workflows that employ either webpack or vite where `process.env.NODE_ENV` is available.\n\n</DocTip>\n\n## The Inspector\n\nThe devtools plugin adds a new \"vee-validate\" inspector that allows you to view your form state, at the moment all the properties are read only.\n\nTo use the vee-validate inspector, switch from the `components` inspector to the `vee-validate` inspector:\n\n<video src=\"/v5/video/inspector.mp4\" autoplay muted loop loading=\"lazy\"></video>\n\n<DocTip type=\"tip\" title=\"Form Name\">\n  When working with multiple forms, you can distinguish between them by their name. The name of the form can be set\n  using the `name` prop on the `<Form />` component or the `useForm` composable.\n</DocTip>\n\n## Disabling the plugin\n\nIf the plugin is causing you issues, you can disable it explicitly from the vue-devtools plugin page.\n\nAlso please don't forget to report the issue [here](https://github.com/logaretm/vee-validate/issues/new?assignees=&labels=&template=bug_report.yaml).\n\nThis short video shows how to disable the vee-validate devtools plugin:\n\n<video src=\"/v5/video/disable-plugin.mp4\" autoplay muted loop loading=\"lazy\"></video>\n"
  },
  {
    "path": "docs/src/pages/guide/global-validators.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Global Validators\ndescription: Defining global rules to be used throughout your web app\norder: 5\nnext:\n  path: guide/i18n\n  title: Localization (i18n)\n  description: Localization support with the first party module and other providers\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\nimport DocTip from '@/components/DocTip.vue';\n\n# Global Validators\n\nSometimes you are building an application that is form-heavy and needs to validate forms frequently, like an admin dashboard or a form-based application. importing validation rules every time you need them can be quite tedious.\n\nVeeValidate allows you to define validation rules globally on the app-level which in turn can allow you to express your rules in a minimal syntax that is inspired by the [Laravel framework's validation syntax](https://laravel.com/docs/validation).\n\n## Defining Global Validators\n\nYou can define a global validator using the `defineRule` function exported by vee-validate:\n\n```js\nimport { defineRule } from 'vee-validate';\n```\n\nThe `defineRule` function accepts a rule name that acts as an identifier for that validation rule, the second argument is the validator function that will verify the field value. Here is an example of a simple `required` and an `email` rule:\n\n```js\nimport { defineRule } from 'vee-validate';\n\ndefineRule('required', value => {\n  if (!value || !value.length) {\n    return 'This field is required';\n  }\n\n  return true;\n});\n\ndefineRule('email', value => {\n  // Field is empty, should pass\n  if (!value || !value.length) {\n    return true;\n  }\n\n  // Check if email\n  if (!/[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}/.test(value)) {\n    return 'This field must be a valid email';\n  }\n\n  return true;\n});\n```\n\nThe validator function is a simple function that receives the current field value as the first argument, and it should return:\n\n- `true` if the validation passed\n- `string` if the validation failed and there is an error message to display\n- `false` if validation fails, in that case, vee-validate will try to generate an error message using `config.defaultMessage`\n- `Promise` if you have an asynchronous rule, the promise must either resolve to `string` or `true`\n\n<DocTip title=\"Rules Placement\">\n\nYou should make the `defineRule` calls in your application entry-point file to make sure your forms have access to them, otherwise, you may risk a form not being able to use some global rules because they weren't defined then. Here are some common entry points:\n\n- In vue-cli applications that would be the `src/main.js` file\n- In a Nuxt application, you need to create a `plugins/vee-validate.js` file and register it in `nuxt.config.js`\n\n</DocTip>\n\n### Using Global Validators\n\nNow that you've defined your validators, for example, the `email` and `required` rules. You can pass them directly to `<Field />` component's `rules` prop like this:\n\n```vue-html\n<Field name=\"name\" rules=\"required\" />\n\n<Field name=\"email\" rules=\"required|email\" />\n```\n\nNotice that to define multiple rules you have to place a `|` (pipe) character between your rules as a separator.\n\n## Configuring Global Validators\n\nSometimes your rules require more information to work properly, for example, if we want to define a `minLength` rule it won't be very useful to hard code the character limit, instead, it should receive it per field.\n\nVeeValidate passes rules arguments or (configuration) as the second argument to the validator function which is often an array containing the arguments in the same order they were passed in. Here is an example defining a `minLength` rule:\n\n```js\nimport { defineRule } from 'vee-validate';\n\ndefineRule('minLength', (value, [limit]) => {\n  // The field is empty so it should pass\n  if (!value || !value.length) {\n    return true;\n  }\n\n  if (value.length < limit) {\n    return `This field must be at least ${limit} characters`;\n  }\n\n  return true;\n});\n```\n\nAnd then you can use it on the `Field` component like this:\n\n```vue-html\n<Field name=\"password\" type=\"password\" rules=\"required|minLength:8\" />\n```\n\nNote that to pass arguments to rules, you need to place a colon `:` character to signify the beginning of rules. You can pass multiple arguments as a comma-separated list. Here is an example for a `minMax` rule:\n\n```js\nimport { defineRule } from 'vee-validate';\n\ndefineRule('minMax', (value, [min, max]) => {\n  // The field is empty so it should pass\n  if (!value || !value.length) {\n    return true;\n  }\n  const numericValue = Number(value);\n  if (numericValue < min) {\n    return `This field must be greater than ${min}`;\n  }\n\n  if (numericValue > max) {\n    return `This field must be less than ${max}`;\n  }\n\n  return true;\n});\n```\n\nThen you can use it like this:\n\n```vue-html\n<Field name=\"longitude\" type=\"number\" rules=\"required|minMax:-180,180\" />\n```\n\n## Schema Validation\n\nThe [Form-level validation](/guide/components/validation#form-level-validation) feature isn't limited to `yup` validators, you can define your global validators and define them in the same way as the previous examples in the `Form` component `validation-schema` prop.\n\nHere is an example that uses all the rules we've defined prior in this page in a form validation schema:\n\n```vue\n<template>\n  <Form @submit=\"submit\" :validation-schema=\"schema\" v-slot=\"{ errors }\">\n    <Field name=\"email\" />\n    <span>{{ errors.email }}</span>\n\n    <Field name=\"password\" type=\"password\" />\n    <span>{{ errors.password }}</span>\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script setup>\nimport { Form, Field } from 'vee-validate';\n\nconst schema = {\n  email: 'required|email',\n  password: 'required|minLength:8',\n};\n</script>\n```\n\nThis makes vee-validate extremely compatible with Laravel's Request validation and potentially opens the door to make your forms completely API-driven, eliminating the maintenance burden of syncing validation rules between frontend and backend.\n\n## Cross-Field Validation\n\nAssuming you want to create a rule that verifies that a field matches another, like a password confirmation scenario. Because globally defined rules do not have scope access to other values you may have in the component, vee-validate sends a third argument to your global validators which is a `ValidationContext` that carries useful information about the form and field being validated.\n\nSo assuming you want to build a `confirmed` rule, you would make it configurable by accepting the `target` field name and you can use the `ValidationContext.form` object to access its value:\n\n```js\nimport { defineRule } from 'vee-validate';\n\ndefineRule('confirmed', (value, [target], ctx) => {\n  if (value === ctx.form[target]) {\n    return true;\n  }\n\n  return 'Passwords must match';\n});\n```\n\nHere is an example of the two fields using that rule:\n\n```vue-html\n<Field name=\"password\" rules=\"required\" />\n\n<Field name=\"confirmation\" rules=\"required|confirmed:password\" />\n```\n\nThere is a shorthand for this using `@` prefix before specifying arguments, this tells vee-validate to automatically swap the specified field value in the arguments array:\n\n```js\nimport { defineRule } from 'vee-validate';\n\ndefineRule('confirmed', (value, [target]) => {\n  if (value === target) {\n    return true;\n  }\n\n  return 'Passwords must match';\n});\n```\n\n```vue-html\n<Form>\n  <Field name=\"password\" type=\"password\" />\n\n  <Field name=\"confirmation\" type=\"password\" rules=\"confirmed:@password\" />\n</Form>\n```\n\nThis allows you to create more concise rules, you can reference any number of fields using this way.\n\n## Object Expressions\n\nThere is another way to use global validators which is more expressive by using JavaScript objects to describe the validation for your fields. For example this:\n\n```js\n'required|between:0,10';\n```\n\nCould be rewritten as an object like this\n\n```js\n{ required: true, between: [0, 10] }\n```\n\nThis makes defining rules more expressive and less limited by the string format.\n\nFor dynamic expressions, you can use computed properties in the same way to define dynamic validation rules.\n\n## @vee-validate/rules\n\nVeeValidate offers a wide range of common validators that you can use as global validators, they are packed in a separate package under the `@vee-validate/rules` namespace\n\n```sh\nyarn add @vee-validate/rules\n\n# or with npm\nnpm install @vee-validate/rules\n```\n\nYou can then start importing and defining rules globally:\n\n```js\nimport { defineRule } from 'vee-validate';\nimport { required, email, min } from '@vee-validate/rules';\n\ndefineRule('required', required);\ndefineRule('email', email);\ndefineRule('min', min);\n```\n\nOr you can globally define all the available rules in the `@vee-validate/rules` package:\n\n```js\nimport { defineRule } from 'vee-validate';\nimport { all } from '@vee-validate/rules';\n\nObject.entries(all).forEach(([name, rule]) => {\n  defineRule(name, rule);\n});\n```\n\n## Caveats\n\n- Be careful of having too many global rules as this can slow down your initial website load time due to the large initial bundle size\n- It is recommended to treat your validation rules as pure functions, meaning they only operate with the information given to them\n- Having small, pure global validations is preferable to allow reusing them across the app\n- You could possibly trigger an infinite render-loop when using the [object expressions](/guide/global-validators#object-expressions) to define your validations for a field, read the [linked section](/guide/global-validators#object-expressions) for a workaround\n\n## Available Rules\n\n<ul class=\"grid grid-cols-2 col-gap-4 lg:grid-cols-3 lg:col-gap-8 text-accent-800\">\n  <li>\n    <a href=\"/v5/guide/global-validators#alpha\">alpha</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#alpha_dash\">alpha_dash</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#alpha_num\">alpha_num</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#alpha_spaces\">alpha_spaces</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#between\">between</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#confirmed\">confirmed</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#digits\">digits</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#dimensions\">dimensions</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#email\">email</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#not_one_of\">not_one_of</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#ext\">ext</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#image\">image</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#one_of\">one_of</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#integer\">integer</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#is\">is</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#is_not\">is_not</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#length\">length</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#max\">max</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#max_value\">max_value</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#mimes\">mimes</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#min\">min</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#min_value\">min_value</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#numeric\">numeric</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#regex\">regex</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#required\">required</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#size\">size</a>\n  </li>\n  <li>\n    <a href=\"/v5/guide/global-validators#url\">url</a>\n  </li>\n</ul>\n\n### Playground\n\nHere is a live demo where you can view and test all the global validators live\n\n<LiveExample client:visible id=\"vee-validate-v4-global-rules\" preview-only />\n\n#### alpha\n\nThe field under validation may only contain alphabetic characters.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"alpha\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ alpha: true }\" />\n```\n\n#### alpha_dash\n\nThe field under validation may contain alphabetic characters, numbers, dashes, or underscores.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"alpha_dash\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ alpha_dash: true }\" />\n```\n\n#### alpha_num\n\nThe field under validation may contain alphabetic characters or numbers.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"alpha_num\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ alpha_num: true }\" />\n```\n\n#### alpha_spaces\n\nThe field under validation may contain alphabetic characters or spaces.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"alpha_spaces\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ alpha_spaces: true }\" />\n```\n\n#### between\n\nThe field under validation must have a numeric value bounded by a minimum value and a maximum value.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"between:1,10\" />\n\n<!-- object format with shorthand array -->\n<Field name=\"field\" :rules=\"{ between: [1, 10] }\" />\n\n<!-- object format with named arguments -->\n<Field name=\"field\" :rules=\"{ between: { min: 1, max: 10 } }\" />\n```\n\n| Param Name | Required? | Description        |\n| ---------- | --------- | ------------------ |\n| `min`      | **yes**   | The minimum value. |\n| `max`      | **yes**   | The maximum value. |\n\n#### confirmed\n\nThe field under validation must have the same value as the confirmation field.\n\n```vue-html\n<Form>\n  <Field name=\"password\" type=\"password\" />\n\n  <Field name=\"confirmation\" type=\"password\" rules=\"confirmed:@password\" />\n</Form>\n```\n\n| Param Name | Required? | Description                                                                  |\n| ---------- | --------- | ---------------------------------------------------------------------------- |\n| `target`   | **yes**   | The other field's `name` value, must use `@` to prefix the target field name |\n\n<DocTip type=\"danger\">\n\nAny fields defined to have this rule must have a `<Form />` parent in their hierarchy or `useForm()` called on their parent hierarchy.\n\n</DocTip>\n\n#### digits\n\nThe field under validation must be numeric and have the specified number of digits.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"digits:3\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ digits: 3 }\" />\n```\n\n| Param Name | Required? | Description                   |\n| ---------- | --------- | ----------------------------- |\n| `length`   | **yes**   | The number of digits allowed. |\n\n#### dimensions\n\nThe file added to the field under validation must be an image (jpg,svg,jpeg,png,bmp,gif) having the exact specified dimension.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" type=\"file\" rules=\"dimensions:120,120\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ dimensions: [120, 120] }\" />\n\n<!-- object format with named arguments -->\n<Field name=\"field\" :rules=\"{ dimensions: { width: 120, height: 120 } }\" />\n```\n\n| Param Name | Required? | Description           |\n| ---------- | --------- | --------------------- |\n| `width`    | **yes**   | The width in pixels.  |\n| `height`   | **yes**   | The height in pixels. |\n\n#### email\n\nThe field under validation must be a valid email.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"email\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ email: true }\" />\n```\n\n#### not_one_of\n\nThe field under validation must have a value that is not in the specified list. **Uses double equals** for checks.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"not_one_of:1,3\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ not_one_of: [1, 3] }\" />\n```\n\n`not_one_of` accepts an infinite number of params, each is a value that is disallowed.\n\n#### ext\n\nThe file added to the field under validation must have one of the extensions specified.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"ext:jpg,png\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ ext: ['jpg', 'png'] }\" />\n```\n\n`ext` accepts an infinite number of arguments representing extensions. ex: `ext:jpg,png,bmp,svg`.\n\n#### image\n\nThe file added to the field under validation must have an image mime type (image/\\*).\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"image\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ image: true }\" />\n```\n\n#### integer\n\nThe field under validation must be a valid integer value. Doesn't accept exponential notation.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"integer\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ integer: true }\" />\n```\n\n#### is\n\nThe field under validation must match the given value, uses strict equality.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"is:hello\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ is: 'hello' }\" />\n```\n\n| Param Name | Required? | Description                                                 |\n| ---------- | --------- | ----------------------------------------------------------- |\n| `value`    | **yes**   | A value of any type to be compared against the field value. |\n\n#### is_not\n\nThe field under validation must not match the given value, uses strict equality.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"is_not:world\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ is_not: 'world' }\" />\n```\n\n| Param Name | Required? | Description                                                 |\n| ---------- | --------- | ----------------------------------------------------------- |\n| `value`    | **yes**   | A value of any type to be compared against the field value. |\n\n#### length\n\nThe field under validation must exactly have the specified number of items, only works for iterables.\n\nAllowed Iterable values are `string`, `array`, and any object that can be used with `Array.from`.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"length:5\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ length: 5 }\" />\n```\n\n| Param Name | Required? | Description                                                                   |\n| ---------- | --------- | ----------------------------------------------------------------------------- |\n| `length`   | **yes**   | A numeric value representing the exact number of items the value can contain. |\n\n#### max\n\nThe field under validation length may not exceed the specified length.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"max:10\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ max: 10 }\" />\n```\n\n| Param Name | Required? | Description                                                    |\n| ---------- | --------- | -------------------------------------------------------------- |\n| `length`   | **yes**   | A numeric value representing the maximum number of characters. |\n\n#### max_value\n\nThe field under validation must be a numeric value and must not be greater than the specified value.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"max_value:10\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ max_value: 10 }\" />\n```\n\n| Param Name | Required? | Description                                              |\n| ---------- | --------- | -------------------------------------------------------- |\n| `max`      | **yes**   | A numeric value representing the greatest value allowed. |\n\n#### mimes\n\nThe file type added to the field under validation should have one of the specified mime types.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"mimes:image/jpeg\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ mimes: ['image/jpeg'] }\" />\n```\n\n`mimes` accepts an infinite number of arguments that are formatted as file types. EG: `mimes:image/jpeg,image/png`.\n\n<DocTip>\n\nYou can use '\\*' to specify a wild card, something like `mimes:image/*` will accept all image types.\n\n</DocTip>\n\n#### min\n\nThe field under validation length should not be less than the specified length.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"min:3\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ min: 3 }\" />\n```\n\n| Param Name | Required? | Description                                                    |\n| ---------- | --------- | -------------------------------------------------------------- |\n| `length`   | **yes**   | A numeric value representing the minimum number of characters. |\n\n#### min_value\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"min_value:5\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ min_value: 5 }\" />\n```\n\nThe field under validation must be a numeric value and must not be less than the specified value.\n\n| Param Name | Required? | Description                                              |\n| ---------- | --------- | -------------------------------------------------------- |\n| `min`      | **yes**   | A numeric value representing the smallest value allowed. |\n\n#### numeric\n\nThe field under validation must only consist of numbers.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"numeric\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ numeric: true }\" />\n```\n\n#### one_of\n\nThe field under validation must have a value that is in the specified list. **Uses double equals** for checks.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"one_of:1,2,3\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ one_of: [1, 2, 3] }\" />\n```\n\n`one_of` takes an infinite number of params, each is a value that is allowed.\n\n#### regex\n\nThe field under validation must match the specified regular expression.\n\n```vue-html\n<!-- string format: NOT RECOMMENDED -->\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ regex: /^[0-9]+$/ }\" />\n```\n\n| Param Name | Required? | Description                                               |\n| ---------- | --------- | --------------------------------------------------------- |\n| `pattern`  | **yes**   | A regular expression instance or string representing one. |\n\n<DocTip type=\"warn\">\n\nYou should not use the pipe '|' or commas ',' within your regular expression when using the string rules format as it will cause a conflict with how validators parsing works. You should use the object format of the rules instead as shown in the last snippet\n\n</DocTip>\n\n<DocTip type=\"warn\" title=\"The g flag\">\n\nWhen using the `regex` rule, using the `g` flag may result in unexpected falsy validations. This is because vee-validate uses the same instance across validation attempts.\n\n</DocTip>\n\n#### required\n\nThe field under validation must have a non-empty value. By default, all validators pass the validation if they have \"empty values\" unless they are required. Those empty values are empty strings, `undefined`, `null`, `false`, and empty arrays.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" rules=\"required\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ required: true }\" />\n```\n\n#### size\n\nThe file size added to the field under validation must not exceed the specified size in kilobytes.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" type=\"file\" rules=\"size:250\" />\n\n<!-- object format -->\n<Field name=\"field\" :rules=\"{ size: 250 }\" />\n```\n\n| Param Name | Required? | Description                         |\n| ---------- | --------- | ----------------------------------- |\n| `size`     | **yes**   | The maximum file size in kilobytes. |\n\n#### url\n\nThe field under validation must be a valid url. You can pass a `pattern` if you need the url to be more restricted.\n\n```vue-html\n<!-- string format -->\n<Field name=\"field\" type=\"url\" rules=\"url\" />\n\n<!-- object format -->\n<Field name=\"field\" type=\"text\" :rules=\"{ url: 'https://.*' }\" />\n```\n\n| Param Name | Required? | Description                                               |\n| ---------- | --------- | --------------------------------------------------------- |\n| `pattern`  | **no**    | A regular expression instance or string representing one. |\n"
  },
  {
    "path": "docs/src/pages/guide/i18n.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Localization (i18n)\ndescription: Localization support with the first party module and other providers\norder: 6\nnext:\n  path: guide/devtools\n  title: Devtools Plugin\n  description: Using the vee-validate Vue.js devtools plugin\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\nimport DocTip from '@/components/DocTip.vue';\n\n# Localization (i18n)\n\nThis guide only addresses generating error messages for [globally defined validators](/guide/global-validators) using vee-validate's own `@vee-validate/i18n` plugin.\n\nIf you are using vee-validate with yup, then you should check out [yup's localization guide](https://github.com/jquense/yup#localization-and-i18n). If you are using another library for data validation, check their i18n capabilities.\n\n## Global Message Generator\n\nvee-validate exposes a global config called `generateMessage` which is a function that should return a string. Whenever any globally defined rule returns a falsy value the `generateMessage` will be called and its result will be used as an error message for that rule.\n\nThe message generator function has the following type:\n\n```ts\ninterface FieldContext {\n  field: string; // The field's name or label (see next section)\n  value: any; // the field's current value\n  form: Record<string, any>; // other values in the form\n  rule: {\n    name: string; //the rule name\n    params?: any[]; // any params sent to it\n  };\n}\n\ntype ValidationgenerateMessage = (ctx: FieldContext) => string;\n```\n\nWith this information, you could create message handlers with any kind of 3rd party libraries. To register a message generator use the `configure` function exposed by vee-validate:\n\n```js\nimport { configure } from 'vee-validate';\n\nconfigure({\n  generateMessage: context => {\n    return `The field ${context.field} is invalid`;\n  },\n});\n```\n\n### Custom Labels\n\nIf you want to display different field names in your error messages, the `<Field />` component accepts a `label` prop which allows you to display better names for your fields in their generated messages. Here is an example:\n\n```vue-html\n<Form>\n  <Field name=\"_bad_field_name\" label=\"nice name\" rules=\"required|email\" />\n  <ErrorMessage name=\"_bad_field_name\" />\n</Form>\n```\n\nThe generated message will use `nice name` instead of the badly formatted one.\n\n## Using @vee-validate/i18n\n\n### Overview\n\nThe `@vee-validate/i18n` contains a simple message generator function that you can use to generate localized messages from JSON objects:\n\nFirst, you need to install the `@vee-validate/i18n` package:\n\n```sh\nyarn add @vee-validate/i18n\n\n# or with npm\nnpm install @vee-validate/i18n\n```\n\nImport the `localize()` function from `@vee-validate/i18n` which returns a message generator function:\n\n```js\nimport { defineRule, configure } from 'vee-validate';\nimport { required } from '@vee-validate/rules';\nimport { localize } from '@vee-validate/i18n';\n\n// Define the rule globally\ndefineRule('required', required);\n\nconfigure({\n  // Generates an English message locale generator\n  generateMessage: localize('en', {\n    messages: {\n      required: 'This field is required',\n    },\n  }),\n});\n```\n\nIf you have multiple locales in your application, you can add them like this:\n\n```js\nimport { defineRule, configure } from 'vee-validate';\nimport { required } from '@vee-validate/rules';\nimport { localize } from '@vee-validate/i18n';\n\n// Define the rule globally\ndefineRule('required', required);\n\nconfigure({\n  generateMessage: localize({\n    en: {\n      messages: {\n        required: 'This field is required',\n      },\n    },\n    ar: {\n      messages: {\n        required: 'هذا الحقل مطلوب',\n      },\n    },\n  }),\n});\n```\n\nYou can change the locale using `setLocale` function exported by the `@vee-validate/i18n` anywhere in your application:\n\n```js\nimport { setLocale } from '@vee-validate/i18n';\n\nsetLocale('ar');\n```\n\nTo save you a lot of time translating `@vee-validate/rules` messages to your language, the awesome community around vee-validate already contributed over 40+ languages that you can use directly in your application and get started quickly. The localized files include localized messages for all the [global rules provided by @vee-validate/rules package](/guide/global-validators#available-rules).\n\nYou can import the needed locale from the `@vee-validate/i18n/dist/locale/{localeCode}.json` and they can be passed directly to the localize function. This snippet adds the English and Arabic localized messages for all the rules of `@vee-validate/rules` package into the message generator function:\n\n```js\nimport { configure } from 'vee-validate';\nimport { localize } from '@vee-validate/i18n';\nimport en from '@vee-validate/i18n/dist/locale/en.json';\nimport ar from '@vee-validate/i18n/dist/locale/ar.json';\n\nconfigure({\n  generateMessage: localize({\n    en,\n    ar,\n  }),\n});\n```\n\n### Localizing Field Names\n\nTo localize the field name with the `@vee-validate/i18n` package, you can add a `names` property to your dictionaries containing the translated names of the fields.\n\n```js\nimport { configure } from 'vee-validate';\nimport { localize } from '@vee-validate/i18n';\n\nconfigure({\n  generateMessage: localize({\n    en: {\n      names: {\n        age: 'Age',\n      },\n    },\n    ar: {\n      age: 'السن',\n    },\n  }),\n});\n```\n\nThen whenever a message is generated for a global rule, vee-validate will try to match the field name with the `names` property found in the active locale.\n\nThis is such an example:\n\n<LiveExample client:visible id=\"vee-validate-v4-localizing-field-names\" />\n\n## Custom messages for specific fields\n\nYou may want to override specific rule messages for specific fields, you can do this by calling `localize` with the specific messages object:\n\n```js\nimport { localize } from '@vee-validate/i18n';\n\nlocalize('en', {\n  fields: {\n    password: {\n      required: 'Hey! Password cannot be empty',\n    },\n  },\n});\n\n// Or update multiple languages\nlocalize({\n  en: {\n    fields: {\n      password: {\n        required: 'Hey! Password cannot be empty',\n      },\n    },\n  },\n});\n```\n\nYou can call `localize` anywhere in your component initialization, ideally before any error is generated so either `mounted` or `setup` should be safe to call `localize`.\n\n### Placeholder Interpolation\n\nYour messages can be more complex than `required`, for example a `between` rule would need access to the params values to be able to produce a meaningful error message, the `@vee-validate/i18n` plugin comes with interpolation support for various placeholders, consider this example:\n\n```js\nimport { defineRule, configure } from 'vee-validate';\nimport { between } from '@vee-validate/rules';\nimport { localize } from '@vee-validate/i18n';\n\n// Define the rule globally\ndefineRule('between', between);\n\nconfigure({\n  // Generates an English message locale generator\n  generateMessage: localize('en', {\n    messages: {\n      between: 'The {field} value must be between 0:{min} and 1:{max}',\n    },\n  }),\n});\n```\n\nThe `{field}` placeholder will be replaced with the field name, and `0:{min}` and `1:{max}` will be replaced with the rule arguments. Note that the indices that prefix each param name are recommended because the interpolation will need to know the order of the arguments because you may define your global rules in one of `object` or `array` or `string` formats, and thus the interpolation process needs to know both argument names and their order if array params or strings are used.\n\nYou can also interpolate the other fields in the form by using their names as placeholders.\n\nHere is an example that show cases interpolation for different cases:\n\n<LiveExample client:visible id=\"vee-validate-v4-i18n-interpolation\" />\n\n#### Custom Interpolation Prefix and Suffix\n\nYou also have the ability to customize the `prefix` and `suffix` of the interpolated values, by default they are `{` and `}` respectively.\n\nConfigure them by passing a third parameter of `InterpolateOptions` to the `localize` function:\n\n```js\nimport { defineRule, configure } from 'vee-validate';\nimport { between } from '@vee-validate/rules';\nimport { localize } from '@vee-validate/i18n';\n\n// Define the rule globally\ndefineRule('between', between);\n\nconfigure({\n  // Generates an English message locale generator\n  generateMessage: localize(\n    'en',\n    {\n      messages: {\n        // use double `{{` and `}}` i18next-like curly braces for the interpolated values, instead of the default `{` and `}`\n        between: `The {{field}} field must be between 0:{{min}} and 1:{{max}}`,\n      },\n    },\n    {\n      prefix: '{{',\n      suffix: '}}',\n    },\n  ),\n});\n```\n\n### Loading Locale From CDN\n\nIf you are using Vue.js over CDN, you can still load the locale files without having to copy them to your code, the `@vee-validate/i18n` library exposes a `loadLocaleFromURL` function that accepts a URL to a locale file.\n\n```html\n<script src=\"path/to/vee-validate.js\"></script>\n<script src=\"path/to/@vee-validate/rules.js\"></script>\n<script src=\"path/to/@vee-validate/i18n.js\"></script>\n\n<script>\n  // Install all rules\n  Object.keys(VeeValidateRules).forEach(rule => {\n    VeeValidate.defineRule(rule, VeeValidateRules[rule]);\n  });\n\n  // Downloads and merges the locale from URL\n  VeeValidateI18n.loadLocaleFromURL('https://unpkg.com/@vee-validate/i18n@4.0.2/dist/locale/ar.json');\n\n  // Activate the locale\n  VeeValidate.configure({\n    generateMessage: VeeValidateI18n.localize('ar'),\n  });\n</script>\n```\n\nHere is an example of the previous snippet:\n\n<LiveExample client:visible id=\"vee-validate-v4-localize-from-cdn\" />\n"
  },
  {
    "path": "docs/src/pages/guide/migration.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Migration Guide\ndescription: How to migrate from vee-validate v4 to v5\norder: 10\n---\n\n# Migrating from v4 to v5\n\nvee-validate v5 is a major release that brings support to [standard schema](https://standardschema.dev/) libraries like zod, valibot, yup, and more.\n\nThis means most of the companion packages like `@vee-validate/zod`, `@vee-validate/yup`, `@vee-validate/valibot` are no longer needed and are now deprecated.\n\n## Changes to Nuxt Module\n\nThe nuxt module won't suggest installing any packages anymore since most providers that were supported in v4 are now supported in v5 via standard schema API.\n\n## Changes to schema behavior\n\nSince vee-validate v5 is considered schema agnostic, you lose some features that were previously possible with each dedicated validation provider.\n\n- Resolving `required` meta flag is no longer supported from schemas.\n- Using defaults to initialize the form values is no longer supported from schemas.\n\nWhile these features are critical to many apps, the standard schema spec does not provide a way to do that at the moment. Alternatives are being considered via external packages at the moment.\n\n## Replace Typed Schema calls\n\nTyped schemas were a way for vee-validate v4 to support a common interface for multiple validation providers. However, there is a community driven package called [standard schema](https://standardschema.dev/) that provides a common interface for multiple validation providers that is becoming very popular and is already supported by the most popular validation providers.\n\nSo in v5 we now introduced support for standard schema libraries, which means you can use any of the most popular validation providers with vee-validate v5 without installing any resolvers or adapter packages. This includes almost all the previous providers like zod, yup, and valibot.\n\nThe only needed step is to remove all calls to `toTypedSchema` and replace them with the standard schema library of your choice.\n\n### Zod\n\nvee-validate is compatible with zod 3.24.0 and above.\n\n```ts\nimport { z } from 'zod';\n\n// v4\nconst schema = toTypedSchema(z.object({ name: z.string().min(1) }));\n\n// v5 - remove the call to `toTypedSchema`\nconst schema = z.object({ name: z.string().min(1) });\n\nconst { value, errorMessage } = useForm({ validationSchema: schema });\n```\n\n### Yup\n\nYou will need to upgrade `yup` to 1.7.0 or above since the standard schema support was added in that version.\n\n#### If you are using `@vee-validate/yup`\n\n```ts\nimport * as yup from 'yup';\n\n// v4\nconst schema = toTypedSchema(yup.object({ name: yup.string().min(1) }));\n\n// v5 - remove the call to `toTypedSchema`\nconst schema = yup.object({ name: yup.string().min(1) });\n\nconst { value, errorMessage } = useForm({ validationSchema: schema });\n```\n\n#### If you are using yup directly\n\nContinue using your yup schema as you've been doing in the past. You will start getting type safety features out of the box, just make sure you are using yup 1.7.0 or above.\n\n### Valibot\n\nvee-validate is compatible with valibot 1.0 and above.\n\n```ts\nimport * as v from 'valibot';\n\n// v4\nconst schema = toTypedSchema(v.object({ email: v.pipe(v.string(), v.email()) }));\n\n// v5 - remove the call to `toTypedSchema`\nconst schema = v.object({ email: v.pipe(v.string(), v.email()) });\n\nconst { value, errorMessage } = useForm({ validationSchema: schema });\n```\n\n### Joi\n\nvee-validate is compatible with Joi v18.0.0 and above.\n\n```ts\nimport * as Joi from 'joi';\n\n// v4\nconst schema = toTypedSchema(Joi.object({ email: Joi.string().email() }));\n\n// v5 - remove the call to `toTypedSchema`\nconst schema = Joi.object({ email: Joi.string().email() });\n\nconst { value, errorMessage } = useForm({ validationSchema: schema });\n```\n"
  },
  {
    "path": "docs/src/pages/guide/overview.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Overview\ndescription: Getting started with VeeValidate\norder: 1\n---\n\nimport DocTip from '@/components/DocTip.vue';\n\n# Why vee-validate\n\n\"Forms\" is a difficult subject in frontend development. Not only do you have to deal with ensuring that correct values are submitted, but you should also provide a pleasant UX for your users.\n\nBuilding forms from scratch is a lot of work and you probably won't cover all your future needs as your requirements change over time, and as you add more features.\n\n**The time you spend working on a custom form solution is better spent building your application logic**.\n\nMost form libraries will save you a lot of time, but `vee-validate` tackles the major pain points of forms and then gets out of your way, some of those are:\n\n- Form state and value tracking\n- UX\n- Synchronous and Asynchronous Validation\n- Handling submissions\n\nvee-validate tries to handle all of the above and more by providing abstractions to these problems without any UI. This could be viewed as a double-edged sword, however, overriding UI and styles was the downfall of many component libraries and design languages.\n\nBecause of that, vee-validate abstracts away the hard parts into pure logic compositions that you can add to your existing UI and component. There is nothing to override, there is no hidden cost. You can also use vee-validate to power your components internally, and as a result you can build up your form library without having to think about the hard parts.\n\nA great showcase of this approach is how vee-validate seamlessly [integrate with almost every component UI library](/examples/ui-libraries/) for Vue.js out there without any special treatment or hacks.\n\n## Getting Started\n\nvee-validate makes use of two flavors to add validation to your forms.\n\n- **Composition API**: This is the best way to use vee-validate as it allows seamless integrations with your existing UI, or any 3rd party component library.\n- **Higher-order components (HOC)**: This approach is easy to use and is strictly used within the template, you can use it if you have simple forms and don't want to write a lot of JavaScript.\n\nWhichever approach you prefer to use, both flavors can be used interchangeably. So you can mix and match between the two approaches as needed.\n\n<DocTip title=\"Setup SFC\">\n\nMost examples in the docs use the new [script setup](https://vuejs.org/api/sfc-script-setup.html#script-setup) SFC syntax for brevity. In case you're having difficulty following along, take some time to learn about it.\n\n</DocTip>\n\n### Using a package manager\n\nFor a more modern workflow with a bundler, you can install vee-validate using a package manager like `yarn`, `npm` or `pnpm`:\n\n```sh\nyarn add vee-validate\n# or\nnpm i vee-validate --save\n# or\npnpm add vee-validate\n```\n\n### Using a script tag\n\nYou can use vee-validate with a script tag and a CDN, import the library like this:\n\n```html\n<script src=\"https://unpkg.com/vee-validate\"></script>\n```\n\nThis will inject a `VeeValidate` global object, which you will use to access the various components and functions exposed by vee-validate.\n"
  },
  {
    "path": "docs/src/pages/guide/testing.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Testing\ndescription: Testing form validation in your apps\norder: 8\n---\n\n# Testing\n\nvee-validate has many tests of its own that cover almost every functionality, but if you find yourself needing to test vee-validate integration with your forms and fields, this guide should offer some guidance into the best practices and the caveats of doing that.\n\n## Waiting for async validation\n\nvee-validate does all of the work asynchronously. This means whenever you trigger a validation using explicit `validate()` calls or form submissions or `change` events, you still need to \"flush\" the promises to assert the state you expect.\n\nFor example, the following test will fail\n\n```js\nimport { useField } from 'useField';\n\nconst SomeComponent = {\n  template: `\n    <input v-model=\"value\" type=\"text\">\n    <span>{{ errorMessage }}</span>\n  `,\n  setup() {\n    const { value, errorMessage } = useField('name', value => {\n      return value ? true : 'field is required';\n    });\n\n    return {\n      value,\n      errorMessage,\n    };\n  },\n};\n\ntest('it validates', async () => {\n  // assuming you have a mounting helper\n  mount(SomeComponent);\n  const input = document.querySelector('input');\n  input.value = '';\n  input.dispatchEvent(new Event('change'));\n\n  // ❌ Fails\n  expect(document.querySelector('span').textContent).toBe('Field is required');\n});\n```\n\nTo wait for the validation to execute and render the error message, you can use the `flush-promises` npm package to wait for all promises to fulfill and also coupled with `wait-for-expect`.\n\n```js\nimport flushPromises from 'flush-promises';\nimport waitForExpect from 'wait-for-expect';\n\ntest('it validates', async () => {\n  // assuming you have a mounting helper\n  mount(SomeComponent);\n  const input = document.querySelector('input');\n  input.value = '';\n  input.dispatchEvent(new Event('change'));\n\n  // wait for the promises to fulfill\n  await flushPromises();\n  await waitForExpect(() => {\n    // ✅ Now passes\n    expect(document.querySelector('span').textContent).toBe('Field is required');\n  });\n});\n```\n\nvee-validate may run validation in batches to improve performance which isn't always detected by `flush-promises`, so using both is recommended here.\n\n## Testing error messages\n\nMessages can change for the simplest of reasons, for example, grammar or punctuation changes could break your tests if you test against the literal contents of the message.\n\nIdeally, you shouldn't rely on validation messages staying the same for your tests to pass, in any of the iterations when you work on your product you don't want your tests to fail just because of that.\n\nSo instead of testing the literal messages, you want to test if they get any kind of validation message regardless of their content. There are a few suggestions to remedy that:\n\n### Testing message existence\n\nYou can test if the error field contains any message at all, this is useful if you rely on error messages from 3rd party, like the `@vee-validate/i18n` package which changes its messages frequently due to constant updates and fixes by the awesome contributors from all over the world.\n\n```js\n// ❌ Breaks easily\nexpect(errorElement.textContent).toBe('Field is required');\n\n// ✅\nexpect(errorElement.textContent).toBeTruthy();\n```\n\n### Testing partial contents\n\nAnother approach is to test that the messages contain the critical information needed for the user to understand how to fix their input. This assumes you have some idea of the contents of the message:\n\n```js\n// ❌ Breaks easily\nexpect(errorElement.textContent).toBe('Field is required');\n\n// ✅ use `toContain` or similar matching assertions\nexpect(errorElement.textContent).toContain('required');\n```\n\nOf course, this can break easily but still is more flexible than the full literal check.\n\n### Testing actual contents\n\nThis approach relies on the fact that you organize your app user-facing strings in dictionary files, meaning messages are deterministic and not sprinkled across your component's code.\n\n```js\nimport messages from 'strings/validation.js';\n\n// ✅\nexpect(errorElement.textContent).toBe(messages.required);\n```\n\n## Mocking Form and Field Contexts\n\nWhile this is extremely rare you may need to mock the `FormContext` object or the `FieldContext` object, one of the reasons is to unit test some component that relies on those objects being provided with the `provide/inject` API.\n\nYou can import the injection keys for those objects from vee-validate and manually inject your fields/forms.\n\n```js\nimport { provide } from 'vue';\nimport { FormContextKey, FieldContextKey } from 'vee-validate';\n\nprovide(FormContextKey, MockedForm);\nprovide(FieldContextKey, MockedField);\n```\n\nTo learn more about the mock details you should check the source code and see the typescript interfaces for [`FormContext`](https://github.com/logaretm/vee-validate/blob/main/packages/vee-validate/src/types.ts#L145) and [`FieldContext`](https://github.com/logaretm/vee-validate/blob/main/packages/vee-validate/src/types.ts#L66) objects and implement them as mocks.\n"
  },
  {
    "path": "docs/src/pages/index.astro",
    "content": "---\nimport HomeLayout from '@/layouts/HomeLayout.astro';\nimport SponsorButton from '@/components/SponsorButton.vue';\nimport Icon from '@/components/Icon.vue';\nimport MainPageExample from '@/components/MainPageExample.vue';\nimport StarCount from '@/components/StarCount.vue';\nimport FeatureCard from '@/components/FeatureCard.vue';\nimport { features } from '@/constants';\nimport UiLibraries from '@/components/UiLibraries.vue';\n\nconst highlights = [\n  {\n    title: 'Flexible',\n    details:\n      'Offers both declarative components or composable functions API.<br><br>vee-validate sets up the foundation for you to <span title=\"pun intended\">form</span> in whatever style you prefer.',\n  },\n  {\n    title: 'Incremental',\n    details:\n      'vee-validate can do a lot if you let it. Like tracking values, validation, handling submissions and more. <br><br> You may opt-in or out to all of these aspects. You are in control of how much form code you write.',\n  },\n  {\n    title: 'Great DX',\n    details:\n      'Vue.js devtools support.<br><br> vee-validate makes debugging forms much easier and less of a wild goose chase every time that form does not submit.',\n  },\n];\n---\n\n<HomeLayout>\n  <div class=\"mt-6 md:mt-16 grid grid-cols-1 md:grid-cols-2 max-w-6xl mx-auto\">\n    <div class=\"flex flex-col items-start justify-center\">\n      <h1\n        class=\"text-4xl md:text-6xl font-bold font-display bg-clip-text bg-gradient-to-r from-emerald-600 to-emerald-400 text-transparent leading-tight\"\n      >\n        VeeValidate\n      </h1>\n      <p class=\"text-3xl md:text-5xl font-bold font-display\">\n        Painless <span\n          class=\"bg-clip-text bg-gradient-to-r from-emerald-600 to-emerald-400 text-transparent leading-tight\"\n          >Vue\n        </span>\n        forms\n      </p>\n      <p class=\"mt-4 text-lg text-white-800 font-display\">\n        VeeValidate is the most popular Vue.js form library. It takes care of value tracking, validation, errors,\n        submissions and more.\n      </p>\n\n      <div class=\"mt-8 flex items-center gap-4\">\n        <a\n          class=\"flex items-center bg-gradient-to-br from-emerald-500 to-emerald-700 hover:from-emerald-600 hover:to-emerald-800 py-3 px-6 text-white rounded-lg text-center focus:outline-none focus:ring focus:ring-emerald-500 text-sm md:text-base font-medium font-display select-none whitespace-nowrap transition-colors duration-200\"\n          href=\"/v5/guide/overview/\"\n        >\n          Get Started\n\n          <Icon name=\"arrow-right\" class=\"w-5 h-5 ml-2\" />\n        </a>\n\n        <a\n          class=\"bg-gray-200 hover:bg-gray-300 dark:bg-zinc-700 dark:hover:bg-zinc-800 py-3 px-6 rounded-lg text-center focus:outline-none whitespace-nowrap focus:ring focus:ring-emerald-500 font-medium font-display select-none text-sm md:text-base transition-colors duration-200\"\n          href=\"/v5/examples/checkboxes-and-radio/\"\n        >\n          Live Examples\n        </a>\n\n        <div class=\"hidden md:block\">\n          <StarCount client:idle />\n        </div>\n      </div>\n    </div>\n\n    <img src=\"/v5/logo.png\" width=\"300\" height=\"300\" class=\"hidden md:block ml-auto\" alt=\"\" />\n  </div>\n\n  <section class=\"mt-12 md:mt-24 grid grid-cols-1 md:grid-cols-3 gap-5 mx-auto min-w-0 max-w-6xl\">\n    {highlights.map(feature => <FeatureCard feature={feature} client:visible />)}\n  </section>\n\n  <section class=\"mt-24 flex flex-col mx-auto items-center\">\n    <h2 class=\"text-center text-gray-500 dark:text-gray-200 font-display font-bold text-2xl md:text-4xl mb-8\">\n      Works with your favorite UI framework\n    </h2>\n\n    <UiLibraries />\n\n    <p class=\"mt-10 text-sm mx-auto\">\n      <span class=\"opacity-75 font-display\">\n        Listed libraries are ones with official examples, find more UI frameworks and libraries</span\n      >\n      <a href=\"/v5/examples/ui-libraries/\" class=\"text-emerald-500 cursor-pointer\">here</a>.\n    </p>\n  </section>\n\n  <section class=\"mt-24 flex flex-col mx-auto items-center\">\n    <h2 class=\"text-center text-gray-500 dark:text-gray-200 font-display font-bold text-2xl md:text-4xl mb-6\">\n      Sponsors\n    </h2>\n\n    <object\n      data=\"https://sponsors.logaretm.com/sponsors.svg\"\n      type=\"image/svg+xml\"\n      class=\"max-w-full\"\n      aria-label=\"Sponsors Image\"></object>\n\n    <p class=\"mt-8 font-display text-gray-600 dark:text-gray-400 text-center\">\n      You can also help this this project and my other projects by donating one time or by sponsoring via the following\n      link\n    </p>\n\n    <br />\n\n    <div class=\"mt-5 flex justify-center items-center\">\n      <SponsorButton size=\"lg\" />\n    </div>\n  </section>\n\n  <section class=\"mt-24 md:mt-48 max-w-6xl mx-auto\">\n    <h2 class=\"text-center text-gray-500 dark:text-gray-200 font-display font-bold text-2xl md:text-4xl\">Features</h2>\n    <ul\n      class=\"mt-16 grid grid-flow-row md:grid-rows-4 min-w-0 mx-auto text-lg font-display font-semibold gap-x-20 gap-y-3 md:grid-flow-col justify-center features\"\n    >\n      {features.map(feature => <li class=\"flex items-center\">{feature.title}</li>)}\n    </ul>\n  </section>\n\n  <section class=\"mt-24 md:mt-48 mx-auto max-w-4xl\">\n    <h2 class=\"text-center text-gray-500 dark:text-gray-200 font-display font-bold text-2xl md:text-4xl\">\n      Do more with less\n    </h2>\n    <p class=\"mt-4 text-center text-gray-300 text-lg font-display\">\n      In this example, value tracking, validation and submissions are handled in just a few lines of code\n    </p>\n\n    <MainPageExample client:visible />\n  </section>\n</HomeLayout>\n"
  },
  {
    "path": "docs/src/pages/integrations/nuxt.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Nuxt integration\ndescription: VeeValidate Nuxt module\norder: 3\n---\n\nimport DocTip from '@/components/DocTip.vue';\n\n# @vee-validate/nuxt\n\n<div class=\"mb-10 w-full flex items-center justify-center\">\n  <img class=\"h-40\" src=\"https://github.com/logaretm/vee-validate/raw/main/logo.png\" />\n\n  <a class=\"ml-20\" href=\"https://nuxt.com/\" target=\"_blank\">\n    <img class=\"h-40\" src=\"https://nuxt.com/assets/design-kit/logo/icon-green.svg\" />\n  </a>\n</div>\n\n<p align=\"center\">\n  <a href=\"https://github.com/sponsors/logaretm\">\n    <img src=\"https://sponsors.logaretm.com/sponsors.svg\" />\n  </a>\n</p>\n\nOfficial vee-validate's Nuxt module\n\n## Features\n\n- Auto import of vee-validate components\n- Auto import of vee-validate composables\n\n<DocTip type=\"warn\">\n\nNo types are exposed by default to avoid having conflicts with other libraries, aside from vee-validate's main API components/composables. You can still import them via `vee-validate`.\n\n</DocTip>\n\n## Getting Started\n\nIn your nuxt project install the vee-validate nuxt module:\n\n```sh\n# npm\nnpm i @vee-validate/nuxt\n\n# pnpm\npnpm add @vee-validate/nuxt\n\n# yarn\nyarn add @vee-validate/nuxt\n```\n\nThen add the module to your `modules` config in `nuxt.config.ts`:\n\n```ts\nexport default defineNuxtConfig({\n  // ...\n  modules: [\n    //...\n    '@vee-validate/nuxt',\n  ],\n});\n```\n\n## Configuration\n\nYou can configure a few aspects of the `@vee-validate/nuxt` module. Here is the config interface:\n\n```ts{3-19}\nexport default defineNuxtConfig({\n  // ...\n  modules: [\n    //...\n    [\n      '@vee-validate/nuxt',\n      {\n        // disable or enable auto imports\n        autoImports: true,\n        // Use different names for components\n        componentNames: {\n          Form: 'VeeForm',\n          Field: 'VeeField',\n          FieldArray: 'VeeFieldArray',\n          ErrorMessage: 'VeeErrorMessage',\n        },\n      },\n    ],\n  ],\n});\n```\n\nYou can also use the `veeValidate` config key instead of the array syntax:\n\n```ts{7-16}\nexport default defineNuxtConfig({\n  // ...\n  modules: [\n    //...\n    '@vee-validate/nuxt',\n  ],\n  veeValidate: {\n    // disable or enable auto imports\n    autoImports: true,\n    // Use different names for components\n    componentNames: {\n      Form: 'VeeForm',\n      Field: 'VeeField',\n      FieldArray: 'VeeFieldArray',\n      ErrorMessage: 'VeeErrorMessage',\n    },\n  },\n});\n```\n"
  },
  {
    "path": "docs/src/pages/resources.mdx",
    "content": "---\nlayout: ../layouts/PageLayout.astro\ntitle: Resources\ndescription: Articles, Tutorials, and Products on VeeValidate\norder: 1\n---\n\n# Resources\n\n## Talks\n\n- [What's new in vee-validate v4](https://youtu.be/_r6PjzFLbqw) by [Abdelrahman Awad](https://twitter.com/logaretm) - Jul 18, 2020\n- [Vue Form Validation w/ VeeValidate](https://www.youtube.com/watch?v=KN1ij6hWVDs) by [Aaron Saunders](https://twitter.com/aaronksaunders) - Apr 30, 2021\n\n## Community Videos\n\n- [Managing Form Validation with Custom Form Components And Vee-Validate Composition API](https://www.youtube.com/watch?v=2ET7IH57XwQ) by [Aaron Saunders](https://twitter.com/aaronksaunders)\n\n## Products\n\nCreative-Tim are using vee-validate in their Vue dashboards, head over to [creative-tim](https://www.creative-tim.com/templates/vuejs?ref=vee-validate) and check their offerings.\n\n<div class=\"mt-8 grid grid-cols-2 gap-x-4 gap-y-4\">\n<a class=\"block dark:bg-black bg-gray-100 p-4 rounded-lg overflow-hidden\" href=\"https://www.creative-tim.com/product/vue-argon-dashboard-pro?ref=vee-validate\" target=\"_blank\" rel=\"noopener\">\n  <div class=\"relative w-full h-64\">\n    <img src=\"https://s3.amazonaws.com/creativetim_bucket/products/159/original/opt_adp_vue_thumbnail.jpg?1557130295\" class=\"w-full h-full inset-0 absolute object-contain\" />\n  </div>\n  <p class=\"text-lg font-bold text-center mt-4\">Vue Argon Dashboard Pro</p>\n</a>\n\n<a\n  class=\"block dark:bg-black bg-gray-100 p-4 rounded-lg overflow-hidden\"\n  href=\"https://www.creative-tim.com/product/vue-white-dashboard-pro?ref=vee-validate\"\n  target=\"_blank\"\n  rel=\"noopener\"\n>\n  <div class=\"relative w-full h-64\">\n    <img\n      src=\"https://s3.amazonaws.com/creativetim_bucket/products/261/original/opt_wdp_vue_thumbnail.jpg?1576152737\"\n      class=\"w-full h-full inset-0 absolute object-contain\"\n    />\n  </div>\n  <p class=\"text-lg font-bold text-center mt-4\">Vue White Dashboard Pro</p>\n</a>\n\n<a\n  class=\"block dark:bg-black bg-gray-100 p-4 rounded-lg overflow-hidden\"\n  href=\"https://www.creative-tim.com/product/vue-light-bootstrap-dashboard-pro?ref=vee-validate\"\n  target=\"_blank\"\n  rel=\"noopener\"\n>\n  <div class=\"relative w-full h-64\">\n    <img\n      src=\"https://s3.amazonaws.com/creativetim_bucket/products/69/original/opt_lbdp_vue_thumbnail.jpg?1534959576\"\n      class=\"w-full h-full inset-0 absolute object-contain\"\n    />\n  </div>\n  <p class=\"text-lg font-bold text-center mt-4\">Vue Light Bootstrap Dashboard PRO</p>\n</a>\n\n<a\n  class=\"block dark:bg-black bg-gray-100 p-4 rounded-lg overflow-hidden\"\n  href=\"https://www.creative-tim.com/product/vue-black-dashboard-pro?ref=vee-validate\"\n  target=\"_blank\"\n  rel=\"noopener\"\n>\n  <div class=\"relative w-full h-64\">\n    <img\n      src=\"https://s3.amazonaws.com/creativetim_bucket/products/135/original/opt_bdp_vue_thumbnail_%285%29.jpg?1571054798\"\n      class=\"w-full h-full inset-0 absolute object-contain\"\n    />\n  </div>\n  <p class=\"text-lg font-bold text-center mt-4\">Vue Black Dashboard Pro</p>\n</a>\n\n  <a class=\"block dark:bg-black bg-gray-100 p-4 rounded-lg overflow-hidden\" href=\"https://www.creative-tim.com/product/vue-now-ui-dashboard-pro?ref=vee-validate\" target=\"_blank\" rel=\"noopener\">\n    <div class=\"relative w-full h-64\">\n      <img src=\"https://s3.amazonaws.com/creativetim_bucket/products/79/original/opt_nudp_vue_thumbnail.jpg?1534959600\" class=\"w-full h-full inset-0 absolute object-contain\" />\n    </div>\n    <p class=\"text-lg font-bold text-center mt-4\">Vue Now UI Dashboard PRO</p>\n  </a>\n</div>\n"
  },
  {
    "path": "docs/src/pages/submit-target.astro",
    "content": "---\nimport LogQueryStr from '@/components/LogQueryStr.vue';\n---\n\n<html lang=\"en\">\n  <head>\n    <title>Submit target</title>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" type=\"image/x-icon\" href=\"/v5/img/favicon.ico\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, viewport-fit=cover\" />\n  </head>\n\n  <body>\n    <LogQueryStr client:load />\n  </body>\n</html>\n"
  },
  {
    "path": "docs/src/pages/tutorials/basics.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Validation Basics\ndescription: Build a newsletter form with vee-validate\norder: 1\n---\n\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Validation Basics\n\nVeeValidate offers many ways to do form validation, this tutorial will teach you how to do basic form validation using the simplest approach.\n\n## What are we building\n\nIn this tutorial, we will be building a \"sign up newsletter\" form where the user would have to fill a field to complete their sign-up.\n\n## Prerequisites\n\nThis tutorial assumes you know:\n\n- Modern JavaScript features like arrow functions and ES modules.\n- Vue's [SFC file syntax](https://v3.vuejs.org/guide/single-file-component.html#introduction).\n\n## Setup\n\nIt is preferable to use a local development environment to follow along, make sure to have the following:\n\n1. Prepare a Vue 3.x project using the [`vue-cli`](https://cli.vuejs.org/)\n\n<details>\n\n<summary>Detailed Steps</summary>\n\nIf not already prepared, install the New Vue CLI\n\n```sh\nnpm install -g @vue/cli@next\n```\n\nUsing the `vue-cli`, create a new project and choose Vue 3 template:\n\n```sh\nvue create vee-validate-tutorial\n```\n\n</details>\n\n2. Add `vee-validate` to your project\n\n```sh\nyarn add vee-validate\n\n# or\n\nnpm install vee-validate --save\n```\n\n3. Cleanup the contents of `App.vue`, it should look like the following:\n\n```vue\n<template>\n  <div id=\"app\"></div>\n</template>\n\n<script>\nexport default {};\n</script>\n```\n\nAnd that's it, now you have an empty Vue project and vee-validate installed.\n\n## Building the Form\n\n<div class=\"tutorial-step is-first\">\n\nFirst, start by adding some markup, you can start by having a `form` wrapping a few `input` elements.\n\n</div>\n\n```vue\n<template>\n  <div id=\"app\">\n    <form novalidate>\n      <input type=\"email\" name=\"email\" />\n\n      <button>Sign up for newsletter</button>\n    </form>\n  </div>\n</template>\n\n<script>\nexport default {};\n</script>\n```\n\nSo far so good, try filling the `email` field with a dummy value like `hello`. Then click the submit button once and see what happens.\n\nYou will notice that the form submits and you should see `?email=` added in your URL in the address bar, it should have the same value that you entered in the `email` field.\n\nThis is the native HTML form submission behavior. Usually, in modern applications, you don't want that and you prefer to handle submission with JavaScript.\n\nThe `novalidate` attribute on the `<form>` element is meant to disable the native HTML form validation, we will get to validating the form by the end of this tutorial.\n\n<div class=\"tutorial-step\">\n\nAdd a `submit` event handler that prevents the native form submission, we will use `onSubmit` function to handle our form submission.\n\n</div>\n\n```vue{3,13-17}\n<template>\n  <div id=\"app\">\n    <form novalidate @submit.prevent=\"onSubmit\">\n      <input type=\"email\" name=\"email\" />\n\n      <button>Sign up for newsletter</button>\n    </form>\n  </div>\n</template>\n\n<script>\nexport default {\n  methods: {\n    onSubmit() {\n      console.log('Submitted');\n    },\n  },\n};\n</script>\n```\n\nNow type anything in the `email` field and click submit. You will notice a couple of things:\n\n1. The word \"Submitted\" being logged to the console.\n2. The value you entered wasn't added to the address bar, this means you've prevented the default submission behavior.\n\nSo far so good, but the form isn't that useful unless it takes the correct data from the user. So let's add validation to the form.\n\n## Adding Validation\n\nVeeValidate exposes 2 components that you will be using regularly, the `<Field>` and `<Form>` are components that will help you validate your forms and inputs.\n\n<div class=\"tutorial-step\">\n\nImport them and register them on the Vue component, then replace the following elements with the vee-validate component:\n\n- Replace `<input>` with `<Field />` while keeping the same attributes.\n- Replace `<form>` with `<Form />` but remove both the `.prevent` modifier and the `novalidate` attribute.\n\n</div>\n\n```vue{3,4,7,12,15-18}\n<template>\n  <div id=\"app\">\n    <Form @submit=\"onSubmit\">\n      <Field name=\"email\" type=\"email\" />\n\n      <button>Sign up for newsletter</button>\n    </Form>\n  </div>\n</template>\n\n<script>\nimport { Form, Field } from 'vee-validate';\n\nexport default {\n  components: {\n    Form,\n    Field,\n  },\n  methods: {\n    onSubmit() {\n      console.log('Submitting :(');\n    },\n  },\n};\n</script>\n```\n\n<div class=\"tutorial-step\">\n\nChange the `onSubmit` method so it receives an argument called `values` and logs it\n\n</div>\n\n```js{7-9}\nexport default {\n  components: {\n    Form,\n    Field,\n  },\n  methods: {\n    onSubmit(values) {\n      console.log(values);\n    },\n  },\n};\n```\n\nTry typing anything into the `email` field and click submit. You will see form values being logged into the console with the value you entered, this means vee-validate extracted the form values for you and passed it to your `onSubmit` handler. Now all that remains is to add the validation rules.\n\nThere are multiple ways to define rules with VeeValidate, the most straightforward way is to use regular Vue methods.\n\n<div class=\"tutorial-step\">\n\nCreate a function called `validateEmail` that receives 1 argument called `value`.\n\n</div>\n\nIt should look like this:\n\n```vue{23-37}\n<template>\n  <div id=\"app\">\n    <Form @submit=\"onSubmit\">\n      <Field name=\"email\" type=\"email\" />\n\n      <button>Sign up</button>\n    </Form>\n  </div>\n</template>\n\n<script>\nimport { Form, Field } from 'vee-validate';\n\nexport default {\n  components: {\n    Form,\n    Field,\n  },\n  methods: {\n    onSubmit(values) {\n      console.log(JSON.stringify(values, null, 2));\n    },\n    validateEmail(value) {\n      // if the field is empty\n      if (!value) {\n        return 'This field is required';\n      }\n\n      // if the field is not a valid email\n      const regex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$/i;\n      if (!regex.test(value)) {\n        return 'This field must be a valid email';\n      }\n\n      // All is good\n      return true;\n    },\n  },\n};\n</script>\n```\n\nThe `validateEmail` function makes sure the `email` field is both required and is a valid email.\n\nNow you need to tell the `<Field name=\"email />` component to use that function as a validation rule.\n\n<div class=\"tutorial-step\">\n\nYou can do that by passing the `validateEmail` function to the `rules` prop on the `Field` component:\n\n</div>\n\n```vue{4}\n<template>\n  <div id=\"app\">\n    <Form @submit=\"onSubmit\">\n      <Field name=\"email\" type=\"email\" :rules=\"validateEmail\" />\n\n      <button>Sign up</button>\n    </Form>\n  </div>\n</template>\n\n<script>\nimport { Form, Field } from 'vee-validate';\n\nexport default {\n  components: {\n    Form,\n    Field,\n  },\n  methods: {\n    onSubmit(values) {\n      console.log(JSON.stringify(values, null, 2));\n    },\n    validateEmail(value) {\n      // if the field is empty\n      if (!value) {\n        return 'This field is required';\n      }\n\n      // if the field is not a valid email\n      const regex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$/i;\n      if (!regex.test(value)) {\n        return 'This field must be a valid email';\n      }\n\n      // All is good\n      return true;\n    },\n  },\n};\n</script>\n```\n\nTry testing these scenarios:\n\n1. Type a random non-email value like `example` into the `email` field and try clicking submit.\n2. Type a valid email like `hello@example.com` into the `email` field and try clicking submit.\n\nIn the first case, you will notice that nothing was logged to the console, while in the second case you will see your form values being logged into the console the same as before.\n\nThis means validation is working and vee-validate is not executing your `onSubmit` handler until the `email` field validation passes.\n\nThe last step is to show error messages that you already return in the `validateEmail` so that your users have a better understanding of what is going on and why the form isn't submitting.\n\n## Displaying Error Messages\n\nTo display the error message, you will use the `ErrorMessage` component.\n\n<div class=\"tutorial-step\">\n\nImport the `ErrorMessage` component from `vee-validate` and register it in your component:\n\n</div>\n\n```js{1,7}\nimport { Field, Form, ErrorMessage } from 'vee-validate';\n\nexport default {\n  components: {\n    Field,\n    Form,\n    ErrorMessage,\n  },\n};\n```\n\n<div class=\"tutorial-step\">\n\nAdd the `<ErrorMessage />` component to your template, passing a `name` prop that matches the `<Field />` name prop which is `\"email\"`.\n\n</div>\n\n```vue{5}\n<template>\n  <div id=\"app\">\n    <Form @submit=\"onSubmit\">\n      <Field name=\"email\" type=\"email\" :rules=\"validateEmail\" />\n      <ErrorMessage name=\"email\" />\n\n      <button>Sign up</button>\n    </Form>\n  </div>\n</template>\n\n<script>\nimport { Form, Field, ErrorMessage } from 'vee-validate';\n\nexport default {\n  components: {\n    Form,\n    Field,\n    ErrorMessage,\n  },\n  methods: {\n    onSubmit(values) {\n      console.log(values, null, 2);\n    },\n    validateEmail(value) {\n      // if the field is empty\n      if (!value) {\n        return 'This field is required';\n      }\n\n      // if the field is not a valid email\n      const regex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$/i;\n      if (!regex.test(value)) {\n        return 'This field must be a valid email';\n      }\n\n      // All is good\n      return true;\n    },\n  },\n};\n</script>\n```\n\nIf you try the form now without entering anything you will see the required error message appear. Try filling anything that's not an email and notice the invalid email message appearing instead.\n\nNow you have successfully created a simple form and implemented validation and submission.\n\nYou can check out the finished code in action:\n\n<LiveExample client:visible id=\"vitejs-vite-2ia3j4\" />\n\nThere is a lot more you can do with vee-validate, there are other ways and features you can use to clean up your form validation logic. Here are a few things that you can do with vee-validate:\n\n- Declare rules globally and use them in a Laravel-like syntax\n- Using 3rd-party libraries like `yup` to validate\n- Doing form-level validation using a validation schema\n- Advanced rendering of your inputs and forms using scoped-slots\n- Component-less validation with the composition API\n- Generating localized messages\n\nYou can visit the [guide section](/guide/overview) to begin learning more about vee-validate.\n"
  },
  {
    "path": "docs/src/pages/tutorials/dynamic-form-generator.mdx",
    "content": "---\nlayout: ../../layouts/PageLayout.astro\ntitle: Build a Form Generator\ndescription: Learn how to build a schema-generated form\norder: 2\n---\n\nimport DocTip from '@/components/DocTip.vue';\nimport LiveExample from '@/components/LiveExample.vue';\n\n# Build a Form Generator\n\nBuilding forms is often a repetitive task and requires a lot of back and forth to maintain. Maybe your client asked to add a field, maybe they asked to remove a field.\n\nFor most cases using static markup is good enough for your form needs but in some cases, it would be great if you had a dynamic form generator that would quickly render your fields based on some javascript object schema.\n\nIn this tutorial, you will learn how to use vee-validate to build a form-generator without external libraries.\n\nLet's quickly recap what you will be building, the component we will be building should:\n\n<div class=\"features\">\n\n- Accept a form schema specifying the fields\n- Render the given schema\n- Use [yup](https://github.com/jquense/yup) to validate our form\n- Show error messages\n\n</div>\n\n<DocTip>\n\nThis guide will cover how to build a basic form generator.\n\nIf you are looking for a more robust solution for form generation, take a look at [Formvuelate](https://formvuelate.js.org/), and it has first-party [vee-validate support](https://formvuelate.js.org/guide/veevalidate.html).\n\n</DocTip>\n\n## Prerequisites\n\nThis tutorial assumes you know:\n\n- Modern JavaScript like arrow functions and ES modules.\n- Vue's [SFC file syntax](https://v3.vuejs.org/guide/single-file-component.html#introduction).\n- Vue's [list rendering with `v-for`](https://v3.vuejs.org/guide/list.html#mapping-an-array-to-elements-with-v-for).\n- Vue's [dynamic components](https://v3.vuejs.org/guide/component-basics.html#dynamic-components).\n\nThis tutorial also assumes you already have an empty Vue-cli project that you will edit as you follow along and that you have installed `vee-validate` already.\n\n## Laying The Foundation\n\nBefore getting to the implementation details to implement a dynamic form generator, you need to have an overview of how it would work.\n\nSo let's assume we have already implemented a component called `DynamicForm` that accepts a `schema` prop that has all the information needed to render the form.\n\nWe have a few requirements to fulfill:\n\n- Should be able to provide the fields.\n- Should be able to specify types (elements) for those fields\n- Should be able to specify validation either on field-level or form-level\n\nAssuming we have such a component, we can imagine using it to be like this:\n\n```vue[App.vue]\n<template>\n  <DynamicForm :schema=\"formSchema\" />\n</template>\n\n<script>\nimport DynamicForm from '@/components/DynamicForm.vue';\n\nexport default {\n  components: {\n    DynamicForm,\n  },\n  data: () => {\n    const formSchema = {\n      fields: [\n        {\n          label: 'Your Name',\n          name: 'name',\n          as: 'input',\n        },\n        {\n          label: 'Your Email',\n          name: 'email',\n          as: 'input',\n        },\n        {\n          label: 'Your Password',\n          name: 'password',\n          as: 'input',\n        },\n      ],\n    };\n\n    return {\n      formSchema,\n    };\n  },\n};\n</script>\n```\n\nThe form schema will contain `fields` property which is an array of the fields we want to render, each field entry will have these properties:\n\n- `label`: a friendly label to display with the input.\n- `name`: a unique name for the field to identify it.\n- `as`: the name of the input element to render, it can be any native HTML element.\n\n## Rendering Fields\n\n<div class=\"tutorial-step is-first\">\n\nThe initial implementation will follow these generic steps:\n\n- Use `Form` component from vee-validate to render the form\n- Iterate over each field in `schema.fields`\n- Render each field as a `Field` component passing all props to it\n\nLet's put that into some code.\n\n</div>\n\n```vue[components/DynamicForm.vue]\n<template>\n  <Form>\n    <div\n      v-for=\"field in schema.fields\" :key=\"field.name\">\n      <label :for=\"field.name\">{{ field.label }}</label>\n      <Field :as=\"field.as\" :id=\"field.name\" :name=\"field.name\" />\n    </div>\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script>\nimport { Form, Field } from 'vee-validate';\n\nexport default {\n  name: 'DynamicForm',\n  components: {\n    Form,\n    Field,\n  },\n  props: {\n    schema: {\n      type: Object,\n      required: true,\n    },\n  },\n};\n</script>\n```\n\nNotice that when you run the example, the `password` field is being rendered as a text field which isn't ideal. We would like to be able to pass the `type` property to the input element as well.\n\n<div class=\"tutorial-step\">\n\nIn the `App.vue` component, add highlighted line:\n\n</div>\n\n```vue{29}[App.vue]\n<template>\n  <DynamicForm :schema=\"formSchema\" />\n</template>\n\n<script>\nimport DynamicForm from '@/components/DynamicForm.vue';\n\nexport default {\n  components: {\n    DynamicForm,\n  },\n  data: () => {\n    const formSchema = {\n      fields: [\n        {\n          label: 'Your Name',\n          name: 'name',\n          as: 'input',\n        },\n        {\n          label: 'Your Email',\n          name: 'email',\n          as: 'input',\n        },\n        {\n          label: 'Your Password',\n          name: 'password',\n          as: 'input',\n          type: 'password'\n        },\n      ],\n    };\n\n    return {\n      formSchema,\n    };\n  },\n};\n</script>\n```\n\n<div class=\"tutorial-step\">\n\nIn the `DynamicForm.vue` component, update the iteration with `v-for` portion to extract the known keys that we expect and collecting the rest in another object using ES6 object rest operator.\n\n</div>\n\n```vue{3-9}[components/DynamicForm.vue]\n<template>\n  <Form>\n    <div\n      v-for=\"{ as, name, label, ...attrs } in schema.fields\"\n      :key=\"name\"\n    >\n      <label :for=\"name\">{{ label }}</label>\n      <Field :as=\"as\" :id=\"name\" :name=\"name\" v-bind=\"attrs\" />\n    </div>\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script>\nimport { Form, Field } from 'vee-validate';\n\nexport default {\n  name: 'DynamicForm',\n  components: {\n    Form,\n    Field,\n  },\n  props: {\n    schema: {\n      type: Object,\n      required: true,\n    },\n  },\n};\n</script>\n```\n\nThe `v-bind` there allows us to bind everything in the `attrs` object which is all the other props we didn't extract explicitly and bind them to the `Field` component.\n\nThe `Field` component will pass down any props that it doesn't accept to whatever gets rendered in its place, effectively passing down other attributes to our `input` tags.\n\n<details>\n\n<summary>Bonus: Adding support for slotted inputs</summary>\n\nThe `select` input introduces an edge case where your field would need to have child elements (i.e: `<option>` elements) inside its slot. Let's tackle this edge case head-on.\n\nAdd a new fourth entry to the form's schema. This new entry will have a new `children` property that contains the options we want to render in the select element.\n\n```vue{16-40}[App.vue]\n<template>\n  <DynamicForm :schema=\"formSchema\" />\n</template>\n\n<script>\nimport DynamicForm from '@/components/DynamicForm.vue';\n\nexport default {\n  components: {\n    DynamicForm,\n  },\n  data: () => {\n    const formSchema = {\n      fields: [\n        // ...\n        {\n          label: 'Favorite Drink',\n          name: 'drink',\n          as: 'select',\n          children: [\n            {\n              tag: 'option',\n              value: '',\n              text: '',\n            },\n            {\n              tag: 'option',\n              value: 'coffee',\n              text: 'Coffeee',\n            },\n            {\n              tag: 'option',\n              value: 'tea',\n              text: 'Tea',\n            },\n            {\n              tag: 'option',\n              value: 'coke',\n              text: 'Coke',\n            },\n          ],\n        },\n      ],\n    };\n\n    return {\n      formSchema,\n    };\n  },\n};\n</script>\n```\n\nSimilar to how we render fields we will iterate on the `children` property if it exists inside the default slot for the `<Field />` component.\n\n```vue{4,9-16}[components/DynamicForm.vue]\n<template>\n  <Form>\n    <div\n      v-for=\"{ as, name, label, children, ...attrs } in schema.fields\"\n      :key=\"name\"\n    >\n      <label :for=\"name\">{{ label }}</label>\n      <Field :as=\"as\" :id=\"name\" :name=\"name\" v-bind=\"attrs\">\n        <template v-if=\"children && children.length\">\n          <component v-for=\"({ tag, text, ...childAttrs }, idx) in children\"\n            :key=\"idx\"\n            :is=\"tag\"\n            v-bind=\"childAttrs\"\n          >\n            {{ text }}\n          </component>\n        </template>\n      </Field>\n    </div>\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script>\nimport { Form, Field } from 'vee-validate';\n\nexport default {\n  name: 'DynamicForm',\n  components: {\n    Form,\n    Field,\n  },\n  props: {\n    schema: {\n      type: Object,\n      required: true,\n    },\n  },\n};\n</script>\n```\n\nThe template started to get a little bit more complex, so we will stop there but now we have support for `select` elements and any other type of inputs you may need.\n\n</details>\n\n## Handling Validation\n\nWe would like each field to have its own validation rules defined on the schema. We will use [`yup`](https://github.com/jquense/yup) for those validation rules.\n\n<div class=\"tutorial-step\">\n\nIn `App.vue`, update the form's schema so that each field has a new `rules` property with sensible validation rules\n\n</div>\n\n```vue{7,20,26,33}[App.vue]\n<template>\n  <DynamicForm :schema=\"formSchema\" />\n</template>\n\n<script>\nimport DynamicForm from '@/components/DynamicForm.vue';\nimport * as Yup from 'yup';\n\nexport default {\n  components: {\n    DynamicForm,\n  },\n  data: () => {\n    const formSchema = {\n      fields: [\n        {\n          label: 'Your Name',\n          name: 'name',\n          as: 'input',\n          rules: Yup.string().required(),\n        },\n        {\n          label: 'Your Email',\n          name: 'email',\n          as: 'input',\n          rules: Yup.string().email().required(),\n        },\n        {\n          label: 'Your Password',\n          name: 'password',\n          as: 'input',\n          type: 'password',\n          rules: Yup.string().min(6).required(),\n        },\n      ],\n    };\n\n    return {\n      formSchema,\n    };\n  },\n};\n</script>\n```\n\nNow that each field has its own validation rules, we will need to display the error messages.\n\n<div class=\"tutorial-step\">\n\nImport and register the `ErrorMessage` component inside the `DynamicForm.vue` component, and add it to the template after the `<Field />`.\n\n</div>\n\n```vue{27,34,19}[components/DynamicForm.vue]\n<template>\n  <Form>\n    <div\n      v-for=\"{ as, name, label, children, ...attrs } in schema.fields\"\n      :key=\"name\"\n    >\n      <label :for=\"name\">{{ label }}</label>\n      <Field :as=\"as\" :id=\"name\" :name=\"name\" v-bind=\"attrs\">\n        <template v-if=\"children && children.length\">\n          <component v-for=\"({ tag, text, ...childAttrs }, idx) in children\"\n            :key=\"idx\"\n            :is=\"tag\"\n            v-bind=\"childAttrs\"\n          >\n            {{ text }}\n          </component>\n        </template>\n      </Field>\n      <ErrorMessage :name=\"name\" />\n    </div>\n\n    <button>Submit</button>\n  </Form>\n</template>\n\n<script>\nimport { Form, Field, ErrorMessage } from 'vee-validate';\n\nexport default {\n  name: 'DynamicForm',\n  components: {\n    Form,\n    Field,\n    ErrorMessage\n  },\n  props: {\n    schema: {\n      type: Object,\n      required: true,\n    },\n  },\n};\n</script>\n```\n\nAnd that's it, you should have validation working now 🎉\n\n## Demo\n\nYou can check a live sample of what we did here.\n\n<LiveExample client:visible id=\"vee-validate-v4-form-generator\" />\n\n## Conclusion\n\nIn this guide, you learned how to use the dynamic rendering capabilities of Vue.js combined with the flexible nature of the vee-validate components. You created a form that renders fields and validates them based on javascript object schema.\n\nWhile the finished product is far from being complete, you can add features as needed to your form generator.\n\n<DocTip>\n\nIf you are looking for a more robust solution for form generation, take a look at [Formvuelate](https://formvuelate.js.org/), and it has first-party [vee-validate support](https://formvuelate.js.org/#vee-validate-plugin).\n\n</DocTip>\n"
  },
  {
    "path": "docs/src/styles/home.css",
    "content": ".App {\n  @apply h-full mx-auto;\n  max-width: 1500px;\n  grid-template-areas:\n    'content'\n    'footer';\n  display: grid;\n  grid-gap: 20px;\n}\n\n.main {\n  @apply py-12 px-6 min-w-0;\n  grid-area: content;\n\n  @screen lg {\n    @apply px-0;\n  }\n}\n\n#ad {\n  @apply hidden;\n\n  @screen md {\n    @apply block !fixed bottom-4 right-4;\n  }\n}\n"
  },
  {
    "path": "docs/src/styles/page.css",
    "content": ".PageApp {\n  @apply h-full mx-auto;\n  max-width: 1600px;\n  grid-template-areas:\n    'content'\n    'footer';\n  display: grid;\n  grid-gap: 50px;\n\n  @screen lg {\n    grid-template-areas:\n      'lside content rside'\n      'footer footer footer';\n    grid-template-columns: 300px 40rem 1fr;\n    column-gap: 24px;\n  }\n\n  @screen xl {\n    grid-template-areas:\n      'lside content rside'\n      'footer footer footer';\n    grid-template-columns: 300px 45rem 1fr;\n    column-gap: 40px;\n  }\n\n  @screen 2xl {\n    grid-template-areas:\n      'lside content rside'\n      'footer footer footer';\n    grid-template-columns: 300px 50rem 1fr;\n    column-gap: 100px;\n  }\n\n  .main {\n    @apply py-12 px-6 min-w-0 lg:px-0;\n  }\n}\n"
  },
  {
    "path": "docs/src/styles/tailwind.css",
    "content": "@import url('https://fonts.googleapis.com/css?family=Montserrat:700,400,600,500|Noto+Sans:400,500,700&display=swap');\n@import 'tailwindcss/base';\n@import 'tailwindcss/components';\n@import 'tailwindcss/utilities';\n\nhtml,\nbody {\n  width: 100%;\n  min-height: 100vh;\n  @apply font-body;\n  scroll-padding-top: 130px;\n}\n\nbody {\n  @apply bg-white text-gray-700 w-full;\n}\n\n.dark {\n  body {\n    @apply bg-dark text-white;\n  }\n}\n\n.lside {\n  grid-area: lside;\n}\n\n.rside {\n  grid-area: rside;\n}\n\n.main {\n  grid-area: content;\n}\n\n.fade-enter-active,\n.fade-leave-active {\n  transition: opacity 0.8s ease-in-out, transform 0.2s ease-in-out;\n}\n.fade-enter,\n.fade-leave-to {\n  opacity: 0;\n  transform: translate3d(40%, 0, 0);\n}\n\n:root {\n  --accent: #09a884;\n\n  --code-foreground: #2c3e50;\n  --code-background: #f6f6f6;\n  --code-token-constant: #c25205;\n  --code-token-operator: #b2085f;\n  --code-token-type: #b92dbc;\n  --code-token-parameter: #2c3e50;\n  --code-token-attribute: #c25205;\n  --code-token-regex: #ff9580;\n  --code-token-string: #0a7a34;\n  --code-token-comment: #848486;\n  --code-line-numbers: #bbbbbb;\n  --code-line-highlight: #f8f4e4;\n  --code-line-highlight-border: #b92dbc;\n  --code-lang-label: #bbbbbb;\n}\n\n.dark {\n  --accent: #09a884;\n\n  --code-foreground: #f8f8f2;\n  --code-background: #22212c;\n  --code-token-constant: #9580ff;\n  --code-token-operator: #ff80bf;\n  --code-token-type: #80ffea;\n  --code-token-parameter: #ffca80;\n  --code-token-attribute: #8aff80;\n  --code-token-regex: #ff9580;\n  --code-token-string: #ffff80;\n  --code-token-comment: #7970a9;\n  --code-line-numbers: #7970a9;\n  --code-line-highlight: #16171d;\n  --code-line-highlight-border: #7970a9;\n  --code-lang-label: #7970a9;\n}\n\nul.features {\n  li {\n    @apply relative antialiased list-none;\n    &:before {\n      @apply w-6 h-6 text-lg absolute rounded-full flex items-center justify-center flex-shrink-0;\n      content: '';\n      background-image: url(\"data:image/svg+xml,%3Csvg fill='none' stroke='%2309a884' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z'%3E%3C/path%3E%3C/svg%3E\");\n      left: -2rem;\n    }\n  }\n}\n"
  },
  {
    "path": "docs/src/utils/examples.ts",
    "content": "import { Project } from '@stackblitz/sdk';\nimport { version } from '../../../packages/vee-validate/package.json';\n\nexport function getViteProjectConfig(files: Record<string, string>): Project {\n  return {\n    template: 'node',\n    title: `vee-validate example`,\n    files: {\n      'package.json': `{\n  \"name\": \"vite-vue-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"vee-validate\": \"^${version}\",\n    \"vue\": \"^3.3.11\",\n    \"yup\": \"latest\",\n    \"zod\": \"latest\",\n    \"valibot\": \"latest\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^4.2.3\",\n    \"vite\": \"^4.3.9\"\n  }\n}`,\n      'index.html': `<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/vite.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Vue</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>`,\n      'src/main.js': `import { createApp } from 'vue'\n      import App from './App.vue'\n\n      createApp(App).mount('#app')\n      `,\n      'vite.config.js': `import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [vue()],\n})\n`,\n      ...Object.fromEntries(Object.entries(files).map(([file, content]) => [`src/${file}`, content])),\n    },\n  };\n}\n"
  },
  {
    "path": "docs/src/utils/github.ts",
    "content": "export function fetchStarCount() {\n  return fetch('https://api.github.com/repos/logaretm/vee-validate')\n    .then(res => res.json())\n    .then(json => {\n      return json.stargazers_count as number;\n    })\n    .catch(err => {\n      // eslint-disable-next-line no-console\n      console.error(err);\n\n      return 0;\n    });\n}\n"
  },
  {
    "path": "docs/src/utils/seo.ts",
    "content": "export function generateSocialImage({\n  title,\n  tagline,\n  cloudName = 'logaretm',\n  imagePublicID,\n  cloudinaryUrlBase = 'https://res.cloudinary.com',\n  version = null,\n  titleFont = 'montserrat',\n  titleExtraConfig = 'bold',\n  taglineExtraConfig = '',\n  taglineFont = 'montserrat',\n  imageWidth = 1280,\n  imageHeight = 669,\n  textAreaWidth = 760,\n  textLeftOffset = 70,\n  titleBottomOffset = 350,\n  taglineTopOffset = 360,\n  textColor = '09a884',\n  taglineColor = 'ffffff',\n  titleFontSize = 64,\n  taglineFontSize = 48,\n}) {\n  // configure social media image dimensions, quality, and format\n  const imageConfig = [`w_${imageWidth}`, `h_${imageHeight}`, 'c_fill', 'q_auto', 'f_auto'].join(',');\n  // configure the title text\n  const titleConfig = [\n    `w_${textAreaWidth}`,\n    'c_fit',\n    `co_rgb:${textColor}`,\n    'g_south_west',\n    `x_${textLeftOffset}`,\n    `y_${titleBottomOffset}`,\n    `l_text:${titleFont}_${titleFontSize}${titleExtraConfig}:${encodeURIComponent(title)}`,\n  ].join(',');\n  // configure the tagline text\n  const taglineConfig = [\n    `w_${textAreaWidth}`,\n    'c_fit',\n    `co_rgb:${taglineColor}`,\n    'g_north_west',\n    `x_${textLeftOffset}`,\n    `y_${taglineTopOffset}`,\n    `l_text:${taglineFont}_${taglineFontSize}${taglineExtraConfig}:${encodeURIComponent(tagline)}`,\n  ].join(',');\n  // combine all the pieces required to generate a Cloudinary URL\n  const urlParts = [\n    cloudinaryUrlBase,\n    cloudName,\n    'image',\n    'upload',\n    imageConfig,\n    titleConfig,\n    taglineConfig,\n    version,\n    imagePublicID,\n  ];\n\n  // remove any falsy sections of the URL (e.g. an undefined version)\n  const validParts = urlParts.filter(Boolean);\n\n  // join all the parts into a valid URL to the generated image\n  return validParts.join('/');\n}\n\nexport function generateMetaTags({ title, description, image, url, keywords }: any) {\n  return [\n    {\n      name: 'description',\n      hid: 'description',\n      content: description,\n    },\n    {\n      name: 'og:description',\n      property: 'og:description',\n      hid: 'og:description',\n      content: description,\n    },\n    {\n      name: 'og:title',\n      hid: 'og:title',\n      property: 'og:title',\n      content: title,\n    },\n    url\n      ? {\n          hid: 'og:url',\n          name: 'og:url',\n          property: 'og:url',\n          content: url,\n        }\n      : undefined,\n    image\n      ? {\n          name: 'og:image',\n          hid: 'og:image',\n          property: 'og:image',\n          content: image,\n        }\n      : undefined,\n    image\n      ? {\n          name: 'image',\n          hid: 'image',\n          property: 'image',\n          content: image,\n        }\n      : undefined,\n    {\n      name: 'twitter:card',\n      hid: 'twitter:card',\n      content: 'summary_large_image',\n    },\n    {\n      hid: 'twitter:title',\n      name: 'twitter:title',\n      property: 'twitter:title',\n      content: title,\n    },\n    {\n      hid: 'twitter:description',\n      name: 'twitter:description',\n      property: 'twitter:description',\n      content: description,\n    },\n    image\n      ? {\n          hid: 'twitter:image',\n          name: 'twitter:image',\n          property: 'twitter:image',\n          content: image,\n        }\n      : undefined,\n    keywords\n      ? {\n          hid: 'keywords',\n          name: 'keywords',\n          property: 'keywords',\n          content: Array.isArray(keywords) ? keywords.join(', ') : keywords,\n        }\n      : undefined,\n  ].filter(Boolean);\n}\n\nexport function generateLinks({ url }) {\n  return [\n    {\n      hid: 'canonical',\n      rel: 'canonical',\n      href: url,\n    },\n  ];\n}\n\nexport interface Frontmatter {\n  title: string;\n  menuTitle?: string;\n  order: number;\n  next?: {\n    title: string;\n    description: string;\n    path: string;\n    intro: string;\n  };\n  description?: string;\n  path?: string;\n}\n\nexport function buildMenu(pages: { url?: string; frontmatter: Frontmatter; children?: any[]; icon?: string }[]) {\n  return [\n    ...pages.sort((a, b) => {\n      return a.frontmatter.order - b.frontmatter.order;\n    }),\n  ].map(p => {\n    return {\n      title: p.frontmatter.title,\n      menuTitle: p.frontmatter.menuTitle,\n      order: p.frontmatter.order,\n      description: p.frontmatter.description,\n      next: p.frontmatter.next,\n      path: p.url || '',\n      children: p.children ? buildMenu(p.children) : undefined,\n      icon: p.icon || undefined,\n    };\n  });\n}\n"
  },
  {
    "path": "docs/tailwind.config.js",
    "content": "/*\n ** TailwindCSS Configuration File\n **\n ** Docs: https://tailwindcss.com/docs/configuration\n ** Default: https://github.com/tailwindcss/tailwindcss/blob/master/stubs/defaultConfig.stub.js\n */\nmodule.exports = {\n  darkMode: 'class',\n  content: [\n    'src/components/**/*.vue',\n    'src/components/**/*.astro',\n    'src/layouts/**/*.vue',\n    'src/layouts/**/*.astro',\n    'src/pages/**/*.mdx',\n    'src/pages/**/*.astro',\n  ],\n  theme: {\n    fontFamily: {\n      display: ['Montserrat', 'sans-serif'],\n      body: ['Atkinson-Hyperlegible', 'Segoe UI', 'Tahoma', 'Geneva', 'Verdana', 'sans-serif'],\n      ui: ['Noto Sans', 'Segoe UI', 'Tahoma', 'Geneva', 'Verdana', 'sans-serif'],\n      mono: [\n        'ui-monospace',\n        'SFMono-Regular',\n        'Menlo',\n        'Monaco',\n        'Consolas',\n        'Liberation Mono',\n        'Courier New',\n        'monospace',\n      ],\n    },\n\n    extend: {\n      colors: {\n        'accent-900': '#009f53',\n        'accent-800': 'var(--accent, #06d77b)',\n        'accent-100': '#7bffc5',\n\n        warning: '#ffa629',\n        error: '#cf6679',\n\n        black: '#000',\n        white: '#fff',\n\n        'gray-800': '#151518',\n        'gray-700': 'hsl(240 6% 9%)',\n        'gray-600': '#333',\n        'gray-500': 'hsl(0 0% 29%)',\n        'gray-400': '#a2a2a2',\n        'gray-300': 'hsl(0 0% 74%)',\n        'gray-200': '#e8e8e8',\n        'gray-100': '#f6f6f6',\n        'dracula-selection': '#454158',\n        background: '#22212C',\n        dark: 'hsl(240 6% 9%)',\n        carbon: '#333',\n      },\n\n      screens: {\n        motion: { raw: '(prefers-reduced-motion: no-preference)' },\n      },\n    },\n  },\n};\n"
  },
  {
    "path": "docs/theme.json",
    "content": "{\n  \"$schema\": \"vscode://schemas/color-theme\",\n  \"name\": \"custom\",\n  \"author\": \"Abdelrahman Awad\",\n  \"maintainers\": [\"Abdelrahman Awad <logaretm@gmail.com>\"],\n  \"colors\": {\n    \"editor.foreground\": \"#F8F8F2\",\n    \"editor.background\": \"#22212C\"\n  },\n  \"tokenColors\": [\n    {\n      \"scope\": [\"emphasis\"],\n      \"settings\": {\n        \"fontStyle\": \"italic\"\n      }\n    },\n    {\n      \"scope\": [\"strong\"],\n      \"settings\": {\n        \"fontStyle\": \"bold\"\n      }\n    },\n    {\n      \"scope\": [\"header\"],\n      \"settings\": {\n        \"foreground\": \"#9580ff\"\n      }\n    },\n    {\n      \"scope\": [\"meta.diff\", \"meta.diff.header\"],\n      \"settings\": {\n        \"foreground\": \"#7970a9\"\n      }\n    },\n    {\n      \"scope\": [\"markup.inserted\"],\n      \"settings\": {\n        \"foreground\": \"#8aff80\"\n      }\n    },\n    {\n      \"scope\": [\"markup.deleted\"],\n      \"settings\": {\n        \"foreground\": \"#ff9580\"\n      }\n    },\n    {\n      \"scope\": [\"markup.changed\"],\n      \"settings\": {\n        \"foreground\": \"#ffca80\"\n      }\n    },\n    {\n      \"scope\": [\"invalid\"],\n      \"settings\": {\n        \"foreground\": \"#ff9580\",\n        \"fontStyle\": \"underline italic\"\n      }\n    },\n    {\n      \"scope\": [\"invalid.deprecated\"],\n      \"settings\": {\n        \"foreground\": \"#f8f8f2\",\n        \"fontStyle\": \"underline italic\"\n      }\n    },\n    {\n      \"scope\": [\"entity.name.filename\"],\n      \"settings\": {\n        \"foreground\": \"#ffff80\"\n      }\n    },\n    {\n      \"scope\": [\"markup.error\"],\n      \"settings\": {\n        \"foreground\": \"#ff9580\"\n      }\n    },\n    {\n      \"name\": \"Underlined markup\",\n      \"scope\": [\"markup.underline\"],\n      \"settings\": {\n        \"fontStyle\": \"underline\"\n      }\n    },\n    {\n      \"name\": \"Bold markup\",\n      \"scope\": [\"markup.bold\"],\n      \"settings\": {\n        \"fontStyle\": \"bold\",\n        \"foreground\": \"#ffca80\"\n      }\n    },\n    {\n      \"name\": \"Markup headings\",\n      \"scope\": [\"markup.heading\"],\n      \"settings\": {\n        \"fontStyle\": \"bold\",\n        \"foreground\": \"#9580ff\"\n      }\n    },\n    {\n      \"name\": \"Markup italic\",\n      \"scope\": [\"markup.italic\"],\n      \"settings\": {\n        \"foreground\": \"#ffff80\",\n        \"fontStyle\": \"italic\"\n      }\n    },\n    {\n      \"name\": \"Bullets, lists (prose)\",\n      \"scope\": [\n        \"beginning.punctuation.definition.list.markdown\",\n        \"beginning.punctuation.definition.quote.markdown\",\n        \"punctuation.definition.link.restructuredtext\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"Inline code (prose)\",\n      \"scope\": [\"markup.inline.raw\", \"markup.raw.restructuredtext\"],\n      \"settings\": {\n        \"foreground\": \"#8aff80\"\n      }\n    },\n    {\n      \"name\": \"Links (prose)\",\n      \"scope\": [\"markup.underline.link\", \"markup.underline.link.image\"],\n      \"settings\": {\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"Link text, image alt text (prose)\",\n      \"scope\": [\n        \"meta.link.reference.def.restructuredtext\",\n        \"punctuation.definition.directive.restructuredtext\",\n        \"string.other.link.description\",\n        \"string.other.link.title\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"Blockquotes (prose)\",\n      \"scope\": [\"entity.name.directive.restructuredtext\", \"markup.quote\"],\n      \"settings\": {\n        \"foreground\": \"#ffff80\",\n        \"fontStyle\": \"italic\"\n      }\n    },\n    {\n      \"name\": \"Horizontal rule (prose)\",\n      \"scope\": [\"meta.separator.markdown\"],\n      \"settings\": {\n        \"foreground\": \"#7970a9\"\n      }\n    },\n    {\n      \"name\": \"Code blocks\",\n      \"scope\": [\n        \"fenced_code.block.language\",\n        \"markup.raw.inner.restructuredtext\",\n        \"markup.fenced_code.block.markdown punctuation.definition.markdown\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#8aff80\"\n      }\n    },\n    {\n      \"name\": \"Prose constants\",\n      \"scope\": [\"punctuation.definition.constant.restructuredtext\"],\n      \"settings\": {\n        \"foreground\": \"#9580ff\"\n      }\n    },\n    {\n      \"name\": \"Braces in markdown headings\",\n      \"scope\": [\n        \"markup.heading.markdown punctuation.definition.string.begin\",\n        \"markup.heading.markdown punctuation.definition.string.end\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#9580ff\"\n      }\n    },\n    {\n      \"name\": \"Braces in markdown paragraphs\",\n      \"scope\": [\n        \"meta.paragraph.markdown punctuation.definition.string.begin\",\n        \"meta.paragraph.markdown punctuation.definition.string.end\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#f8f8f2\"\n      }\n    },\n    {\n      \"name\": \"Braces in markdown blockquotes\",\n      \"scope\": [\n        \"markup.quote.markdown meta.paragraph.markdown punctuation.definition.string.begin\",\n        \"markup.quote.markdown meta.paragraph.markdown punctuation.definition.string.end\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#ffff80\"\n      }\n    },\n    {\n      \"name\": \"User-defined class names\",\n      \"scope\": [\"entity.name.type.class\", \"entity.name.class\"],\n      \"settings\": {\n        \"foreground\": \"#80ffea\",\n        \"fontStyle\": \"normal\"\n      }\n    },\n    {\n      \"name\": \"this, super, self, etc.\",\n      \"scope\": [\n        \"keyword.expressions-and-types.swift\",\n        \"keyword.other.this\",\n        \"variable.language\",\n        \"variable.language punctuation.definition.variable.php\",\n        \"variable.other.readwrite.instance.ruby\",\n        \"variable.parameter.function.language.special\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#9580ff\",\n        \"fontStyle\": \"italic\"\n      }\n    },\n    {\n      \"name\": \"Inherited classes\",\n      \"scope\": [\"entity.other.inherited-class\"],\n      \"settings\": {\n        \"fontStyle\": \"italic\",\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"Comments\",\n      \"scope\": [\"comment\", \"punctuation.definition.comment\", \"unused.comment\", \"wildcard.comment\"],\n      \"settings\": {\n        \"foreground\": \"#7970a9\"\n      }\n    },\n    {\n      \"name\": \"JSDoc-style keywords\",\n      \"scope\": [\n        \"comment keyword.codetag.notation\",\n        \"comment.block.documentation keyword\",\n        \"comment.block.documentation storage.type.class\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"JSDoc-style types\",\n      \"scope\": [\"comment.block.documentation entity.name.type\"],\n      \"settings\": {\n        \"foreground\": \"#80ffea\",\n        \"fontStyle\": \"italic\"\n      }\n    },\n    {\n      \"name\": \"JSDoc-style type brackets\",\n      \"scope\": [\"comment.block.documentation entity.name.type punctuation.definition.bracket\"],\n      \"settings\": {\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"JSDoc-style comment parameters\",\n      \"scope\": [\"comment.block.documentation variable\"],\n      \"settings\": {\n        \"foreground\": \"#ffca80\",\n        \"fontStyle\": \"italic\"\n      }\n    },\n    {\n      \"name\": \"Constants\",\n      \"scope\": [\"constant\", \"variable.other.constant\"],\n      \"settings\": {\n        \"foreground\": \"#9580ff\"\n      }\n    },\n    {\n      \"name\": \"Constant escape sequences\",\n      \"scope\": [\"constant.character.escape\", \"constant.character.string.escape\", \"constant.regexp\"],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"HTML tags\",\n      \"scope\": [\"entity.name.tag\"],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"CSS attribute parent selectors ('&')\",\n      \"scope\": [\"entity.other.attribute-name.parent-selector\"],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"HTML/CSS attribute names\",\n      \"scope\": [\"entity.other.attribute-name\"],\n      \"settings\": {\n        \"foreground\": \"#8aff80\",\n        \"fontStyle\": \"italic\"\n      }\n    },\n    {\n      \"name\": \"Function names\",\n      \"scope\": [\n        \"entity.name.function\",\n        \"meta.function-call.generic\",\n        \"meta.function-call.object\",\n        \"meta.function-call.php\",\n        \"meta.function-call.static\",\n        \"meta.method-call.java meta.method\",\n        \"meta.method.groovy\",\n        \"support.function.any-method.lua\",\n        \"keyword.operator.function.infix\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#8aff80\"\n      }\n    },\n    {\n      \"name\": \"Function parameters\",\n      \"scope\": [\n        \"entity.name.variable.parameter\",\n        \"meta.at-rule.function variable\",\n        \"meta.at-rule.mixin variable\",\n        \"meta.function.arguments variable.other.php\",\n        \"meta.selectionset.graphql meta.arguments.graphql variable.arguments.graphql\",\n        \"variable.parameter\"\n      ],\n      \"settings\": {\n        \"fontStyle\": \"italic\",\n        \"foreground\": \"#ffca80\"\n      }\n    },\n    {\n      \"name\": \"Decorators\",\n      \"scope\": [\"meta.decorator variable.other.readwrite\", \"meta.decorator variable.other.property\"],\n      \"settings\": {\n        \"foreground\": \"#8aff80\",\n        \"fontStyle\": \"italic\"\n      }\n    },\n    {\n      \"name\": \"Decorator Objects\",\n      \"scope\": [\"meta.decorator variable.other.object\"],\n      \"settings\": {\n        \"foreground\": \"#8aff80\"\n      }\n    },\n    {\n      \"name\": \"Keywords\",\n      \"scope\": [\"keyword\", \"punctuation.definition.keyword\"],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"Keyword \\\"new\\\"\",\n      \"scope\": [\"keyword.control.new\", \"keyword.operator.new\"],\n      \"settings\": {\n        \"fontStyle\": \"bold\"\n      }\n    },\n    {\n      \"name\": \"Generic selectors (CSS/SCSS/Less/Stylus)\",\n      \"scope\": [\"meta.selector\"],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"Language Built-ins\",\n      \"scope\": [\"support\"],\n      \"settings\": {\n        \"fontStyle\": \"italic\",\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"Built-in magic functions and constants\",\n      \"scope\": [\"support.function.magic\", \"support.variable\", \"variable.other.predefined\"],\n      \"settings\": {\n        \"fontStyle\": \"regular\",\n        \"foreground\": \"#9580ff\"\n      }\n    },\n    {\n      \"name\": \"Built-in functions / properties\",\n      \"scope\": [\"support.function\", \"support.type.property-name\"],\n      \"settings\": {\n        \"fontStyle\": \"regular\"\n      }\n    },\n    {\n      \"name\": \"Separators (key/value, namespace, inheritance, pointer, hash, slice, etc)\",\n      \"scope\": [\n        \"constant.other.symbol.hashkey punctuation.definition.constant.ruby\",\n        \"entity.other.attribute-name.placeholder punctuation\",\n        \"entity.other.attribute-name.pseudo-class punctuation\",\n        \"entity.other.attribute-name.pseudo-element punctuation\",\n        \"meta.group.double.toml\",\n        \"meta.group.toml\",\n        \"meta.object-binding-pattern-variable punctuation.destructuring\",\n        \"punctuation.colon.graphql\",\n        \"punctuation.definition.block.scalar.folded.yaml\",\n        \"punctuation.definition.block.scalar.literal.yaml\",\n        \"punctuation.definition.block.sequence.item.yaml\",\n        \"punctuation.definition.entity.other.inherited-class\",\n        \"punctuation.function.swift\",\n        \"punctuation.separator.dictionary.key-value\",\n        \"punctuation.separator.hash\",\n        \"punctuation.separator.inheritance\",\n        \"punctuation.separator.key-value\",\n        \"punctuation.separator.key-value.mapping.yaml\",\n        \"punctuation.separator.namespace\",\n        \"punctuation.separator.pointer-access\",\n        \"punctuation.separator.slice\",\n        \"string.unquoted.heredoc punctuation.definition.string\",\n        \"support.other.chomping-indicator.yaml\",\n        \"punctuation.separator.annotation\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"Brackets, braces, parens, etc.\",\n      \"scope\": [\n        \"keyword.operator.other.powershell\",\n        \"keyword.other.statement-separator.powershell\",\n        \"meta.brace.round\",\n        \"meta.function-call punctuation\",\n        \"punctuation.definition.arguments.begin\",\n        \"punctuation.definition.arguments.end\",\n        \"punctuation.definition.entity.begin\",\n        \"punctuation.definition.entity.end\",\n        \"punctuation.definition.tag.cs\",\n        \"punctuation.definition.type.begin\",\n        \"punctuation.definition.type.end\",\n        \"punctuation.section.scope.begin\",\n        \"punctuation.section.scope.end\",\n        \"storage.type.generic.java\",\n        \"string.template meta.brace\",\n        \"string.template punctuation.accessor\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#f8f8f2\"\n      }\n    },\n    {\n      \"name\": \"Variable interpolation operators\",\n      \"scope\": [\n        \"meta.string-contents.quoted.double punctuation.definition.variable\",\n        \"punctuation.definition.interpolation.begin\",\n        \"punctuation.definition.interpolation.end\",\n        \"punctuation.definition.template-expression.begin\",\n        \"punctuation.definition.template-expression.end\",\n        \"punctuation.section.embedded.begin\",\n        \"punctuation.section.embedded.coffee\",\n        \"punctuation.section.embedded.end\",\n        \"punctuation.section.embedded.end source.php\",\n        \"punctuation.section.embedded.end source.ruby\",\n        \"punctuation.definition.variable.makefile\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"Keys (serializable languages)\",\n      \"scope\": [\n        \"entity.name.function.target.makefile\",\n        \"entity.name.section.toml\",\n        \"entity.name.tag.yaml\",\n        \"variable.other.key.toml\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"Dates / timestamps (serializable languages)\",\n      \"scope\": [\"constant.other.date\", \"constant.other.timestamp\"],\n      \"settings\": {\n        \"foreground\": \"#ffca80\"\n      }\n    },\n    {\n      \"name\": \"YAML aliases\",\n      \"scope\": [\"variable.other.alias.yaml\"],\n      \"settings\": {\n        \"fontStyle\": \"italic underline\",\n        \"foreground\": \"#8aff80\"\n      }\n    },\n    {\n      \"name\": \"Storage\",\n      \"scope\": [\n        \"storage\",\n        \"meta.implementation storage.type.objc\",\n        \"meta.interface-or-protocol storage.type.objc\",\n        \"source.groovy storage.type.def\"\n      ],\n      \"settings\": {\n        \"fontStyle\": \"regular\",\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"Types\",\n      \"scope\": [\n        \"entity.name.type\",\n        \"keyword.primitive-datatypes.swift\",\n        \"keyword.type.cs\",\n        \"meta.protocol-list.objc\",\n        \"meta.return-type.objc\",\n        \"source.go storage.type\",\n        \"source.groovy storage.type\",\n        \"source.java storage.type\",\n        \"source.powershell entity.other.attribute-name\",\n        \"storage.class.std.rust\",\n        \"storage.type.attribute.swift\",\n        \"storage.type.c\",\n        \"storage.type.core.rust\",\n        \"storage.type.cs\",\n        \"storage.type.groovy\",\n        \"storage.type.objc\",\n        \"storage.type.php\",\n        \"storage.type.haskell\",\n        \"storage.type.ocaml\"\n      ],\n      \"settings\": {\n        \"fontStyle\": \"italic\",\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"Generics, templates, and mapped type declarations\",\n      \"scope\": [\n        \"entity.name.type.type-parameter\",\n        \"meta.indexer.mappedtype.declaration entity.name.type\",\n        \"meta.type.parameters entity.name.type\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#ffca80\"\n      }\n    },\n    {\n      \"name\": \"Modifiers\",\n      \"scope\": [\"storage.modifier\"],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"RegExp string\",\n      \"scope\": [\n        \"string.regexp\",\n        \"constant.other.character-class.set.regexp\",\n        \"constant.character.escape.backslash.regexp\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#ffff80\"\n      }\n    },\n    {\n      \"name\": \"Non-capture operators\",\n      \"scope\": [\"punctuation.definition.group.capture.regexp\"],\n      \"settings\": {\n        \"foreground\": \"#ff80bf\"\n      }\n    },\n    {\n      \"name\": \"RegExp start and end characters\",\n      \"scope\": [\"string.regexp punctuation.definition.string.begin\", \"string.regexp punctuation.definition.string.end\"],\n      \"settings\": {\n        \"foreground\": \"#ff9580\"\n      }\n    },\n    {\n      \"name\": \"Character group\",\n      \"scope\": [\"punctuation.definition.character-class.regexp\"],\n      \"settings\": {\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"Capture groups\",\n      \"scope\": [\"punctuation.definition.group.regexp\"],\n      \"settings\": {\n        \"foreground\": \"#ffca80\"\n      }\n    },\n    {\n      \"name\": \"Assertion operators\",\n      \"scope\": [\"punctuation.definition.group.assertion.regexp\", \"keyword.operator.negation.regexp\"],\n      \"settings\": {\n        \"foreground\": \"#ff9580\"\n      }\n    },\n    {\n      \"name\": \"Positive lookaheads\",\n      \"scope\": [\"meta.assertion.look-ahead.regexp\"],\n      \"settings\": {\n        \"foreground\": \"#8aff80\"\n      }\n    },\n    {\n      \"name\": \"Strings\",\n      \"scope\": [\"string\"],\n      \"settings\": {\n        \"foreground\": \"#ffff80\"\n      }\n    },\n    {\n      \"name\": \"String quotes (temporary vscode fix)\",\n      \"scope\": [\"punctuation.definition.string.begin\", \"punctuation.definition.string.end\"],\n      \"settings\": {\n        \"foreground\": \"#ffff80\"\n      }\n    },\n    {\n      \"name\": \"Property quotes (temporary vscode fix)\",\n      \"scope\": [\"punctuation.support.type.property-name.begin\", \"punctuation.support.type.property-name.end\"],\n      \"settings\": {\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"Docstrings\",\n      \"scope\": [\n        \"string.quoted.docstring.multi\",\n        \"string.quoted.docstring.multi.python punctuation.definition.string.begin\",\n        \"string.quoted.docstring.multi.python punctuation.definition.string.end\",\n        \"string.quoted.docstring.multi.python constant.character.escape\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#7970a9\"\n      }\n    },\n    {\n      \"name\": \"Variables and object properties\",\n      \"scope\": [\n        \"variable\",\n        \"constant.other.key.perl\",\n        \"support.variable.property\",\n        \"variable.other.constant.js\",\n        \"variable.other.constant.ts\",\n        \"variable.other.constant.tsx\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#f8f8f2\"\n      }\n    },\n    {\n      \"name\": \"Destructuring / aliasing reference name (LHS)\",\n      \"scope\": [\n        \"meta.import variable.other.readwrite\",\n        \"meta.object-binding-pattern-variable variable.object.property\",\n        \"meta.variable.assignment.destructured.object.coffee variable\"\n      ],\n      \"settings\": {\n        \"fontStyle\": \"italic\",\n        \"foreground\": \"#ffca80\"\n      }\n    },\n    {\n      \"name\": \"Destructuring / aliasing variable name (RHS)\",\n      \"scope\": [\n        \"meta.import variable.other.readwrite.alias\",\n        \"meta.export variable.other.readwrite.alias\",\n        \"meta.variable.assignment.destructured.object.coffee variable variable\"\n      ],\n      \"settings\": {\n        \"fontStyle\": \"normal\",\n        \"foreground\": \"#f8f8f2\"\n      }\n    },\n    {\n      \"name\": \"GraphQL keys\",\n      \"scope\": [\"meta.selectionset.graphql variable\"],\n      \"settings\": {\n        \"foreground\": \"#ffff80\"\n      }\n    },\n    {\n      \"name\": \"GraphQL function arguments\",\n      \"scope\": [\"meta.selectionset.graphql meta.arguments variable\"],\n      \"settings\": {\n        \"foreground\": \"#f8f8f2\"\n      }\n    },\n    {\n      \"name\": \"GraphQL fragment name (definition)\",\n      \"scope\": [\"entity.name.fragment.graphql\", \"variable.fragment.graphql\"],\n      \"settings\": {\n        \"foreground\": \"#80ffea\"\n      }\n    },\n    {\n      \"name\": \"Edge cases (foreground color resets)\",\n      \"scope\": [\n        \"constant.other.symbol.hashkey.ruby\",\n        \"keyword.operator.dereference.java\",\n        \"keyword.operator.navigation.groovy\",\n        \"meta.scope.for-loop.shell punctuation.definition.string.begin\",\n        \"meta.scope.for-loop.shell punctuation.definition.string.end\",\n        \"meta.scope.for-loop.shell string\",\n        \"storage.modifier.import\",\n        \"punctuation.section.embedded.begin.tsx\",\n        \"punctuation.section.embedded.end.tsx\",\n        \"punctuation.section.embedded.begin.jsx\",\n        \"punctuation.section.embedded.end.jsx\",\n        \"punctuation.separator.list.comma.css\",\n        \"constant.language.empty-list.haskell\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#f8f8f2\"\n      }\n    },\n    {\n      \"name\": \"Shell variables prefixed with \\\"$\\\" (edge case)\",\n      \"scope\": [\"source.shell variable.other\"],\n      \"settings\": {\n        \"foreground\": \"#9580ff\"\n      }\n    },\n    {\n      \"name\": \"Powershell constants mistakenly scoped to `support`, rather than `constant` (edge)\",\n      \"scope\": [\"support.constant\"],\n      \"settings\": {\n        \"fontStyle\": \"normal\",\n        \"foreground\": \"#9580ff\"\n      }\n    },\n    {\n      \"name\": \"Makefile prerequisite names\",\n      \"scope\": [\"meta.scope.prerequisites.makefile\"],\n      \"settings\": {\n        \"foreground\": \"#ffff80\"\n      }\n    },\n    {\n      \"name\": \"SCSS attribute selector strings\",\n      \"scope\": [\"meta.attribute-selector.scss\"],\n      \"settings\": {\n        \"foreground\": \"#ffff80\"\n      }\n    },\n    {\n      \"name\": \"SCSS attribute selector brackets\",\n      \"scope\": [\n        \"punctuation.definition.attribute-selector.end.bracket.square.scss\",\n        \"punctuation.definition.attribute-selector.begin.bracket.square.scss\"\n      ],\n      \"settings\": {\n        \"foreground\": \"#f8f8f2\"\n      }\n    },\n    {\n      \"name\": \"Haskell Pragmas\",\n      \"scope\": [\"meta.preprocessor.haskell\"],\n      \"settings\": {\n        \"foreground\": \"#7970a9\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "docs/tsconfig.json",
    "content": "// Example: starter tsconfig.json for Astro projects\n{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"allowSyntheticDefaultImports\": true,\n    // Enable top-level await and other modern ESM features.\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    // Enable node-style module resolution, for things like npm package imports.\n    \"moduleResolution\": \"node\",\n    // Enable JSON imports.\n    \"resolveJsonModule\": true,\n    // Enable stricter transpilation for better output.\n    \"isolatedModules\": true,\n    // Astro will directly run your TypeScript code, no transpilation needed.\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n    \"paths\": {\n      \"@/*\": [\"src/*\"]\n    }\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.d.ts\", \"src/**/*.tsx\", \"src/**/*.vue\"]\n}\n"
  },
  {
    "path": "eslint.config.js",
    "content": "import eslint from '@eslint/js';\r\nimport globals from 'globals';\r\nimport tseslint from 'typescript-eslint';\r\n\r\nexport default tseslint.config(\r\n  eslint.configs.recommended,\r\n  ...tseslint.configs.recommended,\r\n  {\r\n    languageOptions: {\r\n      sourceType: 'module',\r\n      globals: {\r\n        ...globals.browser,\r\n      },\r\n    },\r\n    rules: {\r\n      '@typescript-eslint/camelcase': 'off',\r\n      '@typescript-eslint/explicit-function-return-type': 'off',\r\n      '@typescript-eslint/no-use-before-define': 'off',\r\n      '@typescript-eslint/explicit-module-boundary-types': 'off',\r\n      '@typescript-eslint/no-explicit-any': 'warn',\r\n      'no-console': 'error',\r\n    },\r\n  },\r\n  {\r\n    files: ['scripts/**/*'],\r\n    languageOptions: {\r\n      sourceType: 'commonjs',\r\n      globals: {\r\n        ...globals.nodeBuiltin,\r\n      },\r\n    },\r\n  },\r\n  {\r\n    files: ['docs/scripts/**/*', 'docs/*.config.js'],\r\n    languageOptions: {\r\n      sourceType: 'commonjs',\r\n      globals: {\r\n        ...globals.node,\r\n      },\r\n    },\r\n  },\r\n  {\r\n    files: ['scripts/**/*', 'packages/**/*.spec.ts'],\r\n    languageOptions: {\r\n      sourceType: 'commonjs',\r\n      globals: {\r\n        ...globals.nodeBuiltin,\r\n      },\r\n    },\r\n    rules: {\r\n      'no-console': 'off',\r\n    },\r\n  },\r\n  {\r\n    ignores: [\r\n      'packages/vee-validate/dist/*',\r\n      'packages/yup/dist/*',\r\n      'packages/zod/dist/*',\r\n      'packages/valibot/dist/*',\r\n      'packages/joi/dist/*',\r\n      'packages/rules/dist/*',\r\n      'packages/i18n/dist/*',\r\n      'packages/nuxt/dist/*',\r\n      'docs/dist/*',\r\n    ],\r\n  },\r\n);\r\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"vee-validate-monorepo\",\n  \"private\": true,\n  \"description\": \"Painless forms for Vue.js\",\n  \"author\": \"Abdelrahman Awad <logaretm1@gmail.com>\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"packageManager\": \"pnpm@9.1.0\",\n  \"homepage\": \"https://vee-validate.logaretm.com\",\n  \"repository\": \"https://github.com/logaretm/vee-validate\",\n  \"scripts\": {\n    \"test\": \"vitest\",\n    \"lint\": \"eslint . '**/*.{js,jsx,ts,tsx}' --fix\",\n    \"format\": \"prettier \\\"./**/*.ts\\\" --write\",\n    \"build\": \"node scripts/build.mjs\",\n    \"cover\": \"vitest run --coverage\",\n    \"postversion\": \"pnpm build\",\n    \"typecheck\": \"pnpm tsc --noEmit --project ./tsconfig.json --skipLibCheck\",\n    \"docs:dev\": \"cd ./docs && pnpm dev && cd -\",\n    \"postinstall\": \"husky install\",\n    \"release\": \"./scripts/release.sh\",\n    \"ci:copy-mds\": \"node scripts/copy-mds.mjs\",\n    \"ci:publish\": \"pnpm build && pnpm publish --provenance --access public -r\",\n    \"ci:version\": \"pnpm changeset version && pnpm ci:copy-mds\",\n    \"ci:tag\": \"node scripts/tag-release.mjs\"\n  },\n  \"devDependencies\": {\n    \"@changesets/cli\": \"^2.29.5\",\n    \"@commitlint/cli\": \"^19.3.0\",\n    \"@commitlint/config-conventional\": \"^19.2.2\",\n    \"@eslint/js\": \"^9.2.0\",\n    \"@rollup/plugin-commonjs\": \"^25.0.7\",\n    \"@rollup/plugin-json\": \"^6.1.0\",\n    \"@rollup/plugin-node-resolve\": \"^15.2.3\",\n    \"@rollup/plugin-replace\": \"^5.0.5\",\n    \"@rollup/plugin-typescript\": \"^11.1.6\",\n    \"@types/node\": \"^20.12.8\",\n    \"@vitest/coverage-v8\": \"^1.6.0\",\n    \"@vue/devtools-api\": \"^7.5.2\",\n    \"@vue/devtools-kit\": \"^7.5.2\",\n    \"chalk\": \"^5.3.0\",\n    \"eslint\": \"^9.2.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"eslint-config-standard\": \"^17.1.0\",\n    \"eslint-plugin-import\": \"^2.29.1\",\n    \"eslint-plugin-n\": \"^17.4.0\",\n    \"eslint-plugin-prettier\": \"^5.1.3\",\n    \"eslint-plugin-promise\": \"^6.1.1\",\n    \"filesize\": \"^10.1.1\",\n    \"flush-promises\": \"^1.0.2\",\n    \"fs-extra\": \"^11.2.0\",\n    \"globals\": \"^15.1.0\",\n    \"gzip-size\": \"^7.0.0\",\n    \"husky\": \"^9.0.11\",\n    \"jsdom\": \"^24.0.0\",\n    \"klona\": \"^2.0.6\",\n    \"lint-staged\": \"^15.2.2\",\n    \"prettier\": \"^3.2.5\",\n    \"prettier-plugin-astro\": \"^0.13.0\",\n    \"raf-stub\": \"^3.0.0\",\n    \"rollup\": \"^4.17.2\",\n    \"rollup-plugin-dts\": \"^6.1.0\",\n    \"terser\": \"^5.31.0\",\n    \"tslint-config-prettier\": \"^1.18.0\",\n    \"type-fest\": \"^4.8.3\",\n    \"typescript\": \"5.3.3\",\n    \"typescript-eslint\": \"^7.8.0\",\n    \"vite-tsconfig-paths\": \"^4.3.2\",\n    \"vitest\": \"^1.6.0\",\n    \"vue\": \"^3.4.26\",\n    \"yup\": \"^1.7.0\",\n    \"zod\": \"^4.0.14\"\n  },\n  \"peerDependencies\": {\n    \"vue\": \"^3.4.26\"\n  },\n  \"lint-staged\": {\n    \"*.ts\": [\n      \"eslint --fix\",\n      \"prettier --write\",\n      \"vitest run related --passWithNoTests\"\n    ],\n    \"*.js\": [\n      \"eslint --fix\",\n      \"vitest run related --passWithNoTests\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/i18n/CHANGELOG.md",
    "content": "# Change Log\n\n## 5.0.0-beta.1\n\n## 5.0.0-beta.0\n\n### Major Changes\n\n- 04ff47c: feat: implement standard schema\n\n## 4.15.1\n\n### Patch Changes\n\n- 0c8a539: fix(i18n): add missing messages for Slovenian locale\n\n## 4.15.0\n\n## 4.14.7\n\n## 4.14.6\n\n## 4.14.5\n\n## 4.14.4\n\n### Patch Changes\n\n- 193a96f: feat: add setFallbackLocale for i18n closes #4872\n- 4f88d85: fix: specify module type on package.json\n\n## 4.14.3\n\n## 4.14.2\n\n## 4.14.1\n\n### Patch Changes\n\n- c118e86: fix: nested exports for the i18n package closes #4899\n\n## 4.14.0\n\n### Minor Changes\n\n- 404cf57: chore: bump release\n\n### Patch Changes\n\n- 97cebd8: chore: add 'exports' field in package.json for all packages\n\n## 4.13.2\n\n## 4.13.1\n\n## 4.13.0\n\n## 4.12.8\n\n## 4.12.7\n\n## 4.12.6\n\n## 4.12.5\n\n## 4.12.4\n\n## 4.12.3\n\n## 4.12.2\n\n## 4.12.1\n\n## 4.12.0\n\n## 4.11.8\n\n## 4.11.7\n\n## 4.11.6\n\n## 4.11.5\n\n## 4.11.4\n\n## 4.11.3\n\n## 4.11.2\n\n## 4.11.1\n\n## 4.11.0\n\n## 4.10.9\n\n## 4.10.8\n\n## 4.10.7\n\n## 4.10.6\n\n## 4.10.5\n\n## 4.10.4\n\n## 4.10.3\n\n## 4.10.2\n\n## 4.10.1\n\n## 4.10.0\n\n### Minor Changes\n\n- 7a548f42: chore: require vue 3.3 and refactor types\n\n## 4.9.6\n\n## 4.9.5\n\n### Patch Changes\n\n- 16580b47: fix: allow labels to be localized with names closes #4268\n\n## 4.9.4\n\n## 4.9.3\n\n## 4.9.2\n\n## 4.9.1\n\n## 4.9.0\n\n## 4.8.6\n\n### Patch Changes\n\n- 6e0b0557: Introduced official nuxt module package\n\n## 4.8.5\n\n### Patch Changes\n\n- 9048a238: fixed zod union issues not showing up as errors closes #4204\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n## [4.8.3](https://github.com/logaretm/vee-validate/compare/v4.8.2...v4.8.3) (2023-03-15)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.8.2](https://github.com/logaretm/vee-validate/compare/v4.8.1...v4.8.2) (2023-03-14)\n\n### Bug Fixes\n\n- do not use name as a default label for useField closes [#4164](https://github.com/logaretm/vee-validate/issues/4164) ([d5acff7](https://github.com/logaretm/vee-validate/commit/d5acff719797c77ba4ff3be5f78c4a45374f9809))\n\n## [4.8.1](https://github.com/logaretm/vee-validate/compare/v4.8.0...v4.8.1) (2023-03-12)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.8.0](https://github.com/logaretm/vee-validate/compare/v4.7.4...v4.8.0) (2023-03-12)\n\n### Features\n\n- Better Yup and Zod typing with output types and input inference ([#4064](https://github.com/logaretm/vee-validate/issues/4064)) ([3820a5b](https://github.com/logaretm/vee-validate/commit/3820a5b8eb3f8c6cd9239057746ccfb4b2e57e76))\n\n## [4.7.4](https://github.com/logaretm/vee-validate/compare/v4.7.3...v4.7.4) (2023-02-07)\n\n### Bug Fixes\n\n- pass the field label as a seperate value closes [#4097](https://github.com/logaretm/vee-validate/issues/4097) ([89f8689](https://github.com/logaretm/vee-validate/commit/89f8689b673be27f0fc221d6c096efa11dacd3e6))\n- wrong and missing RU translations, incorrect order ([#3987](https://github.com/logaretm/vee-validate/issues/3987)) ([1be36ab](https://github.com/logaretm/vee-validate/commit/1be36aba9add96c199f93f8e74f7c422e7e9ae1f))\n\n### Features\n\n- export i18n types closes [#4106](https://github.com/logaretm/vee-validate/issues/4106) ([c65ead8](https://github.com/logaretm/vee-validate/commit/c65ead874323a0bd58f96461f1037cb150cbdc7d))\n\n## [4.7.3](https://github.com/logaretm/vee-validate/compare/v4.7.2...v4.7.3) (2022-11-13)\n\n### Bug Fixes\n\n- rename old excluded with not_one_of closes [#3993](https://github.com/logaretm/vee-validate/issues/3993) ([7fc5077](https://github.com/logaretm/vee-validate/commit/7fc50773275c9c65cdbb0735d0b14dfe7ffca227))\n\n## [4.7.2](https://github.com/logaretm/vee-validate/compare/v4.7.1...v4.7.2) (2022-11-02)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.7.1](https://github.com/logaretm/vee-validate/compare/v4.7.0...v4.7.1) (2022-10-23)\n\n### Bug Fixes\n\n- wrong placeholder in CS localization ([#3959](https://github.com/logaretm/vee-validate/issues/3959)) ([a4603fa](https://github.com/logaretm/vee-validate/commit/a4603fab9647918b6776072b3450aa6e0378660a))\n\n# [4.7.0](https://github.com/logaretm/vee-validate/compare/v4.6.10...v4.7.0) (2022-10-09)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.10](https://github.com/logaretm/vee-validate/compare/v4.6.9...v4.6.10) (2022-09-30)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.9](https://github.com/logaretm/vee-validate/compare/v4.6.8...v4.6.9) (2022-09-19)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.8](https://github.com/logaretm/vee-validate/compare/v4.6.7...v4.6.8) (2022-09-19)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.7](https://github.com/logaretm/vee-validate/compare/v4.6.6...v4.6.7) (2022-08-27)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.6](https://github.com/logaretm/vee-validate/compare/v4.6.5...v4.6.6) (2022-08-16)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.5](https://github.com/logaretm/vee-validate/compare/v4.6.4...v4.6.5) (2022-08-11)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.4](https://github.com/logaretm/vee-validate/compare/v4.6.3...v4.6.4) (2022-08-07)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.3](https://github.com/logaretm/vee-validate/compare/v4.6.2...v4.6.3) (2022-08-07)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.2](https://github.com/logaretm/vee-validate/compare/v4.6.1...v4.6.2) (2022-07-17)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.6.1](https://github.com/logaretm/vee-validate/compare/v4.6.0...v4.6.1) (2022-07-12)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.6.0](https://github.com/logaretm/vee-validate/compare/v4.5.11...v4.6.0) (2022-07-11)\n\n### Bug Fixes\n\n- added argument order for digits rule in ja.json closes [#3780](https://github.com/logaretm/vee-validate/issues/3780) ([9385457](https://github.com/logaretm/vee-validate/commit/938545765c825eead8182202faebfafdebd400c8))\n- sk interpolation for min and digits rules closes [#3788](https://github.com/logaretm/vee-validate/issues/3788) ([778c52e](https://github.com/logaretm/vee-validate/commit/778c52e90afa7b89c6ede07214264b92dec0112a))\n\n### Features\n\n- **locale:** add km (khmer) locale ([#3812](https://github.com/logaretm/vee-validate/issues/3812)) ([b1ee664](https://github.com/logaretm/vee-validate/commit/b1ee664a21db211089a96f76966a6db21c9c7920))\n\n## [4.5.11](https://github.com/logaretm/vee-validate/compare/v4.5.10...v4.5.11) (2022-04-10)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.5.10](https://github.com/logaretm/vee-validate/compare/v4.5.9...v4.5.10) (2022-03-08)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.5.9](https://github.com/logaretm/vee-validate/compare/v4.5.8...v4.5.9) (2022-02-22)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.5.8](https://github.com/logaretm/vee-validate/compare/v4.5.7...v4.5.8) (2022-01-23)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.5.7](https://github.com/logaretm/vee-validate/compare/v4.5.6...v4.5.7) (2021-12-07)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.5.6](https://github.com/logaretm/vee-validate/compare/v4.5.5...v4.5.6) (2021-11-17)\n\n### Bug Fixes\n\n- improved et locale ([#3584](https://github.com/logaretm/vee-validate/issues/3584)) ([60e6f30](https://github.com/logaretm/vee-validate/commit/60e6f307a4039e84721741e31f0148e5b0628696))\n\n## [4.5.5](https://github.com/logaretm/vee-validate/compare/v4.5.4...v4.5.5) (2021-11-01)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.5.4](https://github.com/logaretm/vee-validate/compare/v4.5.3...v4.5.4) (2021-10-20)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.5.3](https://github.com/logaretm/vee-validate/compare/v4.5.2...v4.5.3) (2021-10-17)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.5.2](https://github.com/logaretm/vee-validate/compare/v4.5.1...v4.5.2) (2021-09-30)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.5.1](https://github.com/logaretm/vee-validate/compare/v4.5.0...v4.5.1) (2021-09-29)\n\n### Bug Fixes\n\n- **i18n:** field name in default error message ([#3506](https://github.com/logaretm/vee-validate/issues/3506)) ([f1f5127](https://github.com/logaretm/vee-validate/commit/f1f51279d7cc343e7d3226fda025259e59945cfa))\n\n# [4.5.0](https://github.com/logaretm/vee-validate/compare/v4.4.11...v4.5.0) (2021-09-26)\n\n### Features\n\n- added language specific default ([#3501](https://github.com/logaretm/vee-validate/issues/3501)) ([debdee0](https://github.com/logaretm/vee-validate/commit/debdee032030a3209af8df34f710361150c924c2))\n\n## [4.4.11](https://github.com/logaretm/vee-validate/compare/v4.4.10...v4.4.11) (2021-09-11)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.4.10](https://github.com/logaretm/vee-validate/compare/v4.4.9...v4.4.10) (2021-08-31)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.4.9](https://github.com/logaretm/vee-validate/compare/v4.4.8...v4.4.9) (2021-08-05)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.4.8](https://github.com/logaretm/vee-validate/compare/v4.4.7...v4.4.8) (2021-07-31)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.4.7](https://github.com/logaretm/vee-validate/compare/v4.4.6...v4.4.7) (2021-07-20)\n\n### Features\n\n- expose FieldContext type closes [#3398](https://github.com/logaretm/vee-validate/issues/3398) ([a6e4c0a](https://github.com/logaretm/vee-validate/commit/a6e4c0ac580d4145c72118ac535bfa082c771068))\n\n## [4.4.6](https://github.com/logaretm/vee-validate/compare/v4.4.5...v4.4.6) (2021-07-08)\n\n## [4.4.5](https://github.com/logaretm/vee-validate/compare/v4.4.4...v4.4.5) (2021-06-13)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.4.4](https://github.com/logaretm/vee-validate/compare/v4.4.3...v4.4.4) (2021-06-05)\n\n## [4.4.3](https://github.com/logaretm/vee-validate/compare/v4.4.2...v4.4.3) (2021-06-02)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.4.2](https://github.com/logaretm/vee-validate/compare/v4.4.1...v4.4.2) (2021-05-28)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.4.1](https://github.com/logaretm/vee-validate/compare/v4.4.0...v4.4.1) (2021-05-24)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.4.0](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.2...v4.4.0) (2021-05-23)\n\n### Bug Fixes\n\n- export the URL rule closes [#3310](https://github.com/logaretm/vee-validate/issues/3310) ([50b6b64](https://github.com/logaretm/vee-validate/commit/50b6b64bf0b2b9a905946ed0ef7b8252501b0ccb))\n\n# [4.4.0-alpha.2](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.1...v4.4.0-alpha.2) (2021-05-14)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.4.0-alpha.1](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.0...v4.4.0-alpha.1) (2021-05-14)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.4.0-alpha.0](https://github.com/logaretm/vee-validate/compare/v4.3.6...v4.4.0-alpha.0) (2021-05-14)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.3.6](https://github.com/logaretm/vee-validate/compare/v4.3.5...v4.3.6) (2021-05-08)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.3.5](https://github.com/logaretm/vee-validate/compare/v4.3.4...v4.3.5) (2021-05-01)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.3.4](https://github.com/logaretm/vee-validate/compare/v4.3.3...v4.3.4) (2021-04-27)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.3.3](https://github.com/logaretm/vee-validate/compare/v4.3.2...v4.3.3) (2021-04-22)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.3.2](https://github.com/logaretm/vee-validate/compare/v4.3.1...v4.3.2) (2021-04-21)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.3.1](https://github.com/logaretm/vee-validate/compare/v4.3.0...v4.3.1) (2021-04-18)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.3.0](https://github.com/logaretm/vee-validate/compare/v4.2.4...v4.3.0) (2021-04-07)\n\n### Bug Fixes\n\n- wrong string format in Japanese translation file ([#3257](https://github.com/logaretm/vee-validate/issues/3257)) ([99dbdb2](https://github.com/logaretm/vee-validate/commit/99dbdb288accfe0257d7c1073d4aeaa291eb1d6b))\n\n### Features\n\n- **rules:** add url validator ([#3253](https://github.com/logaretm/vee-validate/issues/3253)) ([1fad5bb](https://github.com/logaretm/vee-validate/commit/1fad5bb5e0f3264386bc8e40beeb4cdae2a832cb))\n\n## [4.2.4](https://github.com/logaretm/vee-validate/compare/v4.2.3...v4.2.4) (2021-03-26)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.2.3](https://github.com/logaretm/vee-validate/compare/v4.2.2...v4.2.3) (2021-03-22)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.2.2](https://github.com/logaretm/vee-validate/compare/v4.2.1...v4.2.2) (2021-03-03)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.2.1](https://github.com/logaretm/vee-validate/compare/v4.2.0...v4.2.1) (2021-02-26)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.2.0](https://github.com/logaretm/vee-validate/compare/v4.1.20...v4.2.0) (2021-02-24)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.1.20](https://github.com/logaretm/vee-validate/compare/v4.1.19...v4.1.20) (2021-02-24)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.1.19](https://github.com/logaretm/vee-validate/compare/v4.1.18...v4.1.19) (2021-02-16)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.1.17](https://github.com/logaretm/vee-validate/compare/v3.2.0...v4.1.17) (2021-02-08)\n\n### Bug Fixes\n\n- add positional information to the zh_CN locale closes [#2898](https://github.com/logaretm/vee-validate/issues/2898) ([f5f44eb](https://github.com/logaretm/vee-validate/commit/f5f44ebb523db0f4d726cb8a07881d7c981c785c))\n- publish the correct i18n typing and json files ([c77b1fc](https://github.com/logaretm/vee-validate/commit/c77b1fcd671fda4d5e975b77bf97a0ee22209c4f))\n- update placeholder format for locales closes [#2871](https://github.com/logaretm/vee-validate/issues/2871) closes [#2875](https://github.com/logaretm/vee-validate/issues/2875) ([1cf8404](https://github.com/logaretm/vee-validate/commit/1cf840465e1fc09b09d8830673176530585de355))\n\n### Features\n\n- added `validateOnMount` prop to `Field` and `Form` components ([#2938](https://github.com/logaretm/vee-validate/issues/2938)) ([3a0d878](https://github.com/logaretm/vee-validate/commit/3a0d878e453163f305acc87c5d4c93812f77f340))\n- added new loadLocaleFromURL function ([e7ba3db](https://github.com/logaretm/vee-validate/commit/e7ba3dbc82bed48d425f10771f4f5d11e767b042))\n- full param interpolation ([#2880](https://github.com/logaretm/vee-validate/issues/2880)) ([0576504](https://github.com/logaretm/vee-validate/commit/0576504bb36d3d2583ecd8c6855a1ab39a4d0c34))\n- invoke generateMessage handler for local functions closes [#2893](https://github.com/logaretm/vee-validate/issues/2893) ([e9fe773](https://github.com/logaretm/vee-validate/commit/e9fe77365877edda51548c9539ec085fff91586b))\n- **i18n:** added setLocale function ([b5a1849](https://github.com/logaretm/vee-validate/commit/b5a184983958e0a537be89b370c9c15ff50b25f6))\n\n# [4.1.0](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.3...@vee-validate/i18n@4.1.0) (2021-02-07)\n\n### Features\n\n- added new loadLocaleFromURL function ([e7ba3db](https://github.com/logaretm/vee-validate/commit/e7ba3dbc82bed48d425f10771f4f5d11e767b042))\n\n## [4.0.3](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.2...@vee-validate/i18n@4.0.3) (2021-02-06)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.0.2](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.1...@vee-validate/i18n@4.0.2) (2020-12-20)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n## [4.0.1](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0...@vee-validate/i18n@4.0.1) (2020-11-25)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.0.0](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-beta.2...@vee-validate/i18n@4.0.0) (2020-11-16)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.0.0-beta.2](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-beta.1...@vee-validate/i18n@4.0.0-beta.2) (2020-11-04)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.0.0-beta.1](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-beta.0...@vee-validate/i18n@4.0.0-beta.1) (2020-10-06)\n\n### Features\n\n- added `validateOnMount` prop to `Field` and `Form` components ([#2938](https://github.com/logaretm/vee-validate/issues/2938)) ([3a0d878](https://github.com/logaretm/vee-validate/commit/3a0d878e453163f305acc87c5d4c93812f77f340))\n\n# [4.0.0-beta.0](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-alpha.7...@vee-validate/i18n@4.0.0-beta.0) (2020-10-01)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.0.0-alpha.7](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-alpha.6...@vee-validate/i18n@4.0.0-alpha.7) (2020-09-15)\n\n### Bug Fixes\n\n- add positional information to the zh_CN locale closes [#2898](https://github.com/logaretm/vee-validate/issues/2898) ([f5f44eb](https://github.com/logaretm/vee-validate/commit/f5f44ebb523db0f4d726cb8a07881d7c981c785c))\n\n### Features\n\n- invoke generateMessage handler for local functions closes [#2893](https://github.com/logaretm/vee-validate/issues/2893) ([e9fe773](https://github.com/logaretm/vee-validate/commit/e9fe77365877edda51548c9539ec085fff91586b))\n\n# [4.0.0-alpha.6](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-alpha.5...@vee-validate/i18n@4.0.0-alpha.6) (2020-08-29)\n\n### Features\n\n- full param interpolation ([#2880](https://github.com/logaretm/vee-validate/issues/2880)) ([0576504](https://github.com/logaretm/vee-validate/commit/0576504bb36d3d2583ecd8c6855a1ab39a4d0c34))\n\n# [4.0.0-alpha.5](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-alpha.4...@vee-validate/i18n@4.0.0-alpha.5) (2020-08-28)\n\n### Bug Fixes\n\n- update placeholder format for locales closes [#2871](https://github.com/logaretm/vee-validate/issues/2871) closes [#2875](https://github.com/logaretm/vee-validate/issues/2875) ([1cf8404](https://github.com/logaretm/vee-validate/commit/1cf840465e1fc09b09d8830673176530585de355))\n\n# [4.0.0-alpha.4](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-alpha.3...@vee-validate/i18n@4.0.0-alpha.4) (2020-07-27)\n\n**Note:** Version bump only for package @vee-validate/i18n\n\n# [4.0.0-alpha.3](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-alpha.2...@vee-validate/i18n@4.0.0-alpha.3) (2020-07-23)\n\n### Bug Fixes\n\n- publish the correct i18n typing and json files ([c77b1fc](https://github.com/logaretm/vee-validate/commit/c77b1fcd671fda4d5e975b77bf97a0ee22209c4f))\n\n# [4.0.0-alpha.2](https://github.com/logaretm/vee-validate/compare/@vee-validate/i18n@4.0.0-alpha.1...@vee-validate/i18n@4.0.0-alpha.2) (2020-07-23)\n\n### Features\n\n- **i18n:** added setLocale function ([b5a1849](https://github.com/logaretm/vee-validate/commit/b5a184983958e0a537be89b370c9c15ff50b25f6))\n\n# 4.0.0-alpha.1 (2020-07-18)\n\n**Note:** Version bump only for package @vee-validate/i18n\n"
  },
  {
    "path": "packages/i18n/README.md",
    "content": "# @vee-validate/i18n\n\n<p align=\"center\">\n  <a href=\"https://vee-validate.logaretm.com/v5/guide/i18n\" target=\"_blank\">\n    <img width=\"150\" src=\"https://github.com/logaretm/vee-validate/blob/main/logo.png\">\n  </a>\n</p>\n\n> Localization module for vee-validate\n\n## What's this\n\nVeeValidate v4 breaks up the parts that made it a popular solution for form validation into it isolated parts. The core `vee-validate` package no longer includes logic for localization.\n\nThis is where this package comes in.\n\n## Installation\n\n```sh\nyarn add @vee-validate/i18n\n\n# or with npm\nnpm install @vee-validate/i18n\n```\n\n## Usage\n\nimport the `localize()` function from `@vee-validate/i18n` which returns a message generator function:\n\n```js\nimport { defineRule, configure } from 'vee-validate';\nimport { required } from '@vee-validate/rules';\nimport { localize } from '@vee-validate/i18n';\n\n// Define the rule globally\ndefineRule('required', required);\n\nconfigure({\n  // Generates an English message locale generator\n  generateMessage: localize('en', {\n    messages: {\n      required: 'This field is required',\n    },\n  }),\n});\n```\n\nIf you have multiple locales in your application, you can add them like this:\n\n```js\nimport { defineRule, configure } from 'vee-validate';\nimport { required } from '@vee-validate/rules';\nimport { localize } from '@vee-validate/i18n';\n\n// Define the rule globally\ndefineRule('required', required);\n\nconfigure({\n  generateMessage: localize({\n    en: {\n      messages: {\n        required: 'This field is required',\n      },\n    },\n    ar: {\n      messages: {\n        required: 'هذا الحقل مطلوب',\n      },\n    },\n  }),\n});\n```\n\nYou can change the locale using `setLocale` function exported by the `@vee-validate/i18n` anywhere in your application:\n\n```js\nimport { setLocale } from '@vee-validate/i18n';\n\nsetLocale('ar');\n```\n\n## Available Languages\n\nTo save you a lot of time translating `@vee-validate/rules` messages to your language, the awesome community around vee-validate already contributed over **40+ languages** that you can use directly in your application and get started quickly. The localized files include localized messages for all the global rules provided by `@vee-validate/rules` package.\n\nYou can import the locales from their JSON directory like this:\n\n```js\nimport { configure } from 'vee-validate';\nimport { localize } from '@vee-validate/i18n';\nimport en from '@vee-validate/i18n/dist/locale/en.json';\nimport ar from '@vee-validate/i18n/dist/locale/ar.json';\n\nconfigure({\n  generateMessage: localize({\n    en,\n    ar,\n  }),\n});\n```\n\nYou can view a list of the available languages by [checking the locale folder](https://github.com/logaretm/vee-validate/tree/main/packages/i18n/src/locale)\n"
  },
  {
    "path": "packages/i18n/package.json",
    "content": "{\n  \"name\": \"@vee-validate/i18n\",\n  \"version\": \"5.0.0-beta.1\",\n  \"description\": \"Localization module for VeeValidate\",\n  \"author\": \"Abdelrahman Awad <logaretm1@gmail.com>\",\n  \"homepage\": \"https://vee-validate.logaretm.com/v5/guide/i18n\",\n  \"license\": \"MIT\",\n  \"module\": \"dist/vee-validate-i18n.mjs\",\n  \"unpkg\": \"dist/vee-validate-i18n.iife.js\",\n  \"main\": \"dist/vee-validate-i18n.mjs\",\n  \"types\": \"dist/vee-validate-i18n.d.ts\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/vee-validate-i18n.d.ts\",\n      \"import\": \"./dist/vee-validate-i18n.mjs\",\n      \"require\": \"./dist/vee-validate-i18n.cjs\"\n    },\n    \"./dist/locale/*.json\": \"./dist/locale/*.json\"\n  },\n  \"sideEffects\": false,\n  \"files\": [\n    \"dist/*.js\",\n    \"dist/*.d.ts\",\n    \"dist/*.cjs\",\n    \"dist/*.mjs\",\n    \"dist/locale/*.json\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/logaretm/vee-validate.git\",\n    \"directory\": \"packages/i18n\"\n  },\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: run tests from root\\\" && exit 1\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/logaretm/vee-validate/issues\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/index.ts",
    "content": "import { isCallable, FieldValidationMetaInfo, ValidationMessageGenerator, merge } from '../../shared';\nimport { InterpolateOptions } from '../../shared/types';\nimport { interpolate } from './utils';\n\nexport { FieldValidationMetaInfo };\n\nexport type ValidationMessageTemplate = ValidationMessageGenerator | string;\n\nexport interface PartialI18nDictionary {\n  name?: string;\n  messages?: Record<string, ValidationMessageTemplate>;\n  names?: Record<string, string>;\n  fields?: Record<string, Record<string, ValidationMessageTemplate>>;\n}\n\nexport type RootI18nDictionary = Record<string, PartialI18nDictionary>;\n\nclass Dictionary {\n  public locale: string;\n  public fallbackLocale?: string;\n\n  private container: RootI18nDictionary;\n  private interpolateOptions: InterpolateOptions;\n\n  public constructor(\n    locale: string,\n    dictionary: RootI18nDictionary,\n    interpolateOptions: InterpolateOptions = { prefix: '{', suffix: '}' },\n  ) {\n    this.container = {};\n    this.locale = locale;\n    this.interpolateOptions = interpolateOptions;\n    this.merge(dictionary);\n  }\n\n  public resolve(ctx: FieldValidationMetaInfo, interpolateOptions?: InterpolateOptions) {\n    let result = this.format(this.locale, ctx, interpolateOptions);\n    if (!result && this.fallbackLocale && this.fallbackLocale !== this.locale) {\n      result = this.format(this.fallbackLocale, ctx, interpolateOptions);\n    }\n\n    return result || this.getDefaultMessage(this.locale, ctx);\n  }\n\n  public getDefaultMessage(locale: string, ctx: FieldValidationMetaInfo) {\n    const { label, name } = ctx;\n    const fieldName = this.resolveLabel(locale, name, label);\n\n    return `${fieldName} is not valid`;\n  }\n\n  public getLocaleDefault(locale: string, field: string): string | ValidationMessageGenerator | undefined {\n    return this.container[locale]?.fields?.[field]?._default || this.container[locale]?.messages?._default;\n  }\n\n  public resolveLabel(locale: string, name: string, label?: string): string {\n    if (label) {\n      return this.container[locale]?.names?.[label] || label;\n    }\n\n    return this.container[locale]?.names?.[name] || name;\n  }\n\n  public format(locale: string, ctx: FieldValidationMetaInfo, interpolateOptions?: InterpolateOptions) {\n    let message!: ValidationMessageTemplate | undefined;\n    const { rule, form, label, name } = ctx;\n    const fieldName = this.resolveLabel(locale, name, label);\n\n    if (!rule) {\n      message = this.getLocaleDefault(locale, name) || '';\n      return isCallable(message)\n        ? message(ctx)\n        : interpolate(message, { ...form, field: fieldName }, interpolateOptions ?? this.interpolateOptions);\n    }\n\n    // find if specific message for that field was specified.\n    message = this.container[locale]?.fields?.[name]?.[rule.name] || this.container[locale]?.messages?.[rule.name];\n    if (!message) {\n      message = this.getLocaleDefault(locale, name) || '';\n    }\n\n    return isCallable(message)\n      ? message(ctx)\n      : interpolate(\n          message,\n          { ...form, field: fieldName, params: rule.params },\n          interpolateOptions ?? this.interpolateOptions,\n        );\n  }\n\n  public merge(dictionary: RootI18nDictionary) {\n    merge(this.container, dictionary);\n  }\n}\n\nconst DICTIONARY: Dictionary = new Dictionary('en', {});\n\nfunction localize(dictionary: RootI18nDictionary): ValidationMessageGenerator;\nfunction localize(locale: string, dictionary?: PartialI18nDictionary): ValidationMessageGenerator;\nfunction localize(\n  locale: string,\n  dictionary?: PartialI18nDictionary,\n  interpolateOptions?: InterpolateOptions,\n): ValidationMessageGenerator;\n\nfunction localize(\n  locale: string | RootI18nDictionary,\n  dictionary?: PartialI18nDictionary,\n  interpolateOptions?: InterpolateOptions,\n) {\n  const generateMessage: ValidationMessageGenerator = ctx => {\n    return DICTIONARY.resolve(ctx, interpolateOptions);\n  };\n\n  if (typeof locale === 'string') {\n    DICTIONARY.locale = locale;\n\n    if (dictionary) {\n      DICTIONARY.merge({ [locale]: dictionary });\n    }\n\n    return generateMessage;\n  }\n\n  DICTIONARY.merge(locale);\n\n  return generateMessage;\n}\n\n/**\n * Sets the locale\n */\nfunction setLocale(locale: string) {\n  DICTIONARY.locale = locale;\n}\n\n/**\n * Sets the fallback locale.\n */\nfunction setFallbackLocale(locale: string) {\n  DICTIONARY.fallbackLocale = locale;\n}\n\n/**\n * Loads a locale file from URL and merges it with the current dictionary\n */\nasync function loadLocaleFromURL(url: string) {\n  try {\n    const locale: { code: string; messages: Record<string, string> } = await fetch(url, {\n      headers: {\n        'content-type': 'application/json',\n      },\n    }).then(res => res.json());\n\n    if (!locale.code) {\n      // eslint-disable-next-line no-console\n      console.error('Could not identify locale, ensure the locale file contains `code` field');\n      return;\n    }\n\n    localize({ [locale.code]: locale });\n  } catch (err) {\n    // eslint-disable-next-line no-console\n    console.error(`Failed to load locale `);\n  }\n}\n\nexport { localize, setLocale, loadLocaleFromURL, setFallbackLocale };\n"
  },
  {
    "path": "packages/i18n/src/locale/ar.json",
    "content": "{\n  \"code\": \"ar\",\n  \"messages\": {\n    \"alpha\": \"{field} يجب ان يحتوي على حروف فقط\",\n    \"alpha_num\": \"{field} قد يحتوي فقط على حروف وارقام\",\n    \"alpha_dash\": \"{field} قد يحتوي على حروف او الرموز - و _\",\n    \"alpha_spaces\": \"{field} قد يحتوي فقط على حروف ومسافات\",\n    \"between\": \"قيمة {field} يجب ان تكون ما بين 0:{min} و 1:{max}\",\n    \"confirmed\": \"{field} لا يماثل التأكيد\",\n    \"digits\": \"{field} يجب ان تحتوي فقط على ارقام والا يزيد عددها عن 0:{length} رقم\",\n    \"dimensions\": \"{field} يجب ان تكون بمقاس 0:{width} بكسل في 1:{height} بكسل\",\n    \"email\": \"{field} يجب ان يكون بريدا اليكتروني صحيح\",\n    \"not_one_of\": \"الحقل {field} غير صحيح\",\n    \"ext\": \"نوع ملف {field} غير صحيح\",\n    \"image\": \"{field} يجب ان تكون صورة\",\n    \"integer\": \"الحقل {field} يجب ان يكون عدداً صحيحاً\",\n    \"length\": \"حقل {field} يجب الا يزيد عن 0:{length}\",\n    \"max_value\": \"قيمة الحقل {field} يجب ان تكون اصغر من 0:{min} او تساويها\",\n    \"max\": \"الحقل {field} يجب ان يحتوي على 0:{length} حروف على الأكثر\",\n    \"mimes\": \"نوع ملف {field} غير صحيح\",\n    \"min_value\": \"قيمة الحقل {field} يجب ان تكون اكبر من 0:{min} او تساويها\",\n    \"min\": \"الحقل {field} يجب ان يحتوي على 0:{length} حروف على الأقل\",\n    \"numeric\": \"{field} يمكن ان يحتوي فقط على ارقام\",\n    \"one_of\": \"الحقل {field} يجب ان يكون قيمة صحيحة\",\n    \"regex\": \"الحقل {field} غير صحيح\",\n    \"required\": \"{field} مطلوب\",\n    \"required_if\": \"حقل {field} مطلوب\",\n    \"size\": \"{field} يجب ان يكون اقل من 0:{size} كيلوبايت\",\n    \"url\": \"حقل {field} ليس رابطاً صحيحاً\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/az.json",
    "content": "{\n  \"code\": \"az\",\n  \"messages\": {\n    \"alpha\": \"{field} yalnız hərflərdən ibarət olmalıdır\",\n    \"alpha_num\": \"{field} yalnız rəqəmlərdən ibarət ola bilər\",\n    \"alpha_dash\": \"{field} yalnız hərflər, rəqəmlər və defisdən ibarət ola bilər\",\n    \"alpha_spaces\": \"{field} yalnız rəqəmlərdən və ara simvolundan (space) ibarət ola bilər\",\n    \"between\": \"{field} yalnız 0:{min} və 1:{max} arası ola bilər\",\n    \"confirmed\": \"{field} təsdiqləməsi yalnışdır\",\n    \"digits\": \"{field} 0:{length} rəqəmdən ibarət olmalıdır\",\n    \"dimensions\": \"{field} ölçüsü 0:{width}x1:{height} piksel olmalıdır\",\n    \"email\": \"{field} düzgün formatda daxil olunmalıdır\",\n    \"not_one_of\": \"{field} göstəricisi yalnışdır\",\n    \"ext\": \"{field} düzgün fayl formatında olmalıdır\",\n    \"image\": \"{field} şəkil olmalıdır\",\n    \"integer\": \"{field} göstəricisi tam ədəd olmalıdır\",\n    \"max_value\": \"{field} göstəricisi ən çox 0:{max} və ya daha az olmalıdır\",\n    \"max\": \"{field} uzunluğu ən çox 0:{length} simvoldan ibarət ola bilər\",\n    \"mimes\": \"{field} formatı yalnışdır\",\n    \"min_value\": \"{field} göstəricisi minimum 0:{min} və ya daha çox olmalıdır\",\n    \"min\": \"{field} uzunluğu ən az 0:{length} simvoldan ibarət olmalıdır\",\n    \"numeric\": \"{field} yalnız rəqəmlərdən ibarət olmalıdır\",\n    \"one_of\": \"{field} göstəricisi yalnışdır\",\n    \"regex\": \"{field} formatı yalnışdır\",\n    \"required\": \"{field} əlavə etmək zəruridir\",\n    \"required_if\": \"{field} əlavə etmək zəruridir\",\n    \"size\": \"{field} həcmi 0:{size}KB və daha az olmalıdır\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/bg.json",
    "content": "{\n  \"code\": \"bg\",\n  \"messages\": {\n    \"alpha\": \"Полето {field} може да съдържа само азбучни знаци\",\n    \"alpha_num\": \"Полето {field} може да съдържа само буквено-цифрови символи\",\n    \"alpha_dash\": \"Полето {field} може да съдържа буквено-цифрови знаци, както и тирета и долни черти\",\n    \"alpha_spaces\": \"Полето {field} може да съдържа само азбучни знаци, както и интервали\",\n    \"between\": \"Полето {field} може да е между 0:{min} и 1:{max}\",\n    \"confirmed\": \"Потвърждението не съвпада за полето {field}\",\n    \"digits\": \"Полето {field} трябва да е цифрово и да съдържа точно 0:{length} цифри\",\n    \"dimensions\": \"Полето {field} трябва да е 0:{width} пиксела по 1:{height} пиксела\",\n    \"email\": \"Полето {field} трябва да е коректен Email адрес\",\n    \"not_one_of\": \"Полето {field} трябва да е с валидна стойност\",\n    \"ext\": \"Полето {field} трябва да е валиден файл\",\n    \"image\": \"Полето {field} трябва да е снимка\",\n    \"integer\": \"Полето {field} трябва да е цяло число\",\n    \"length\": \"Полето {field} трябва да е с дължилна 0:{length} знака\",\n    \"max_value\": \"Полето {field} трябва да бъде 0:{max} или по-малко\",\n    \"max\": \"Полето {field} не може да бъде по-голямо от 0:{length} знака\",\n    \"mimes\": \"Полето {field} трябва да е валиден тип файл\",\n    \"min_value\": \"Полето {field} трябва да бъде минимум 0:{min} или повече\",\n    \"min\": \"Полето {field} трябва да съдържа минимум 0:{length} символа\",\n    \"numeric\": \"Полето {field} може да съдържа само цифри\",\n    \"one_of\": \"Полето {field} трябва да е валидна стойност\",\n    \"regex\": \"Полето {field} съдържа невалиден формат\",\n    \"required\": \"Полето {field} е задължително\",\n    \"required_if\": \"Полето {field} е задължително\",\n    \"size\": \"Размерът на файла за полето {field} трябва да е под 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/bn.json",
    "content": "{\n  \"code\": \"bn\",\n  \"messages\": {\n    \"alpha\": \"এই {field} ক্ষেত্রে কেবলমাত্র অক্ষর থাকতে পারে\",\n    \"alpha_num\": \"এই {field} ক্ষেত্রে কেবলমাত্র অক্ষর, সংখ্যা থাকতে পারে\",\n    \"alpha_dash\": \"এই {field} ক্ষেত্রে কেবলমাত্র অক্ষর, সংখ্যা, ড্যাশ এবং আন্ডারস্কোর থাকতে পারে\",\n    \"alpha_spaces\": \"এই {field} ক্ষেত্রে কেবলমাত্র অক্ষর, সংখ্যা, ড্যাশ এবং আন্ডারস্কোর থাকতে পারে\",\n    \"between\": \"এই {field} ক্ষেত্রটি 0:{min} এবং 1:{max} এর মধ্যে হতে হবে\",\n    \"confirmed\": \"এই {field} ক্ষেত্রটি মিলছে না\",\n    \"digits\": \"এই {field} ক্ষেত্রটি সংখ্যা হতে হবে এবং ঠিক 0:{length} অঙ্ক থাকতে হবে\",\n    \"dimensions\": \"এই {field} ক্ষেত্রটি 0:{width} পিক্সেল 1:{height} পিক্সেল হতে হবে\",\n    \"email\": \"এই {field} ক্ষেত্রটি একটি বৈধ ইমেল হতে হবে\",\n    \"not_one_of\": \"এই {field} ক্ষেত্রটির মান বৈধ না\",\n    \"ext\": \"এই {field} ক্ষেত্রটির ফাইল বৈধ না\",\n    \"image\": \"এই {field} ক্ষেত্রটি একটি চিত্র হতে হবে\",\n    \"integer\": \"এই {field} ক্ষেত্রটি পূর্ণসংখ্যা হতে হবে\",\n    \"length\": \"এই {field} ক্ষেত্রটি 0:{length} দীর্ঘ হতে হবে\",\n    \"max_value\": \"এই {field} ক্ষেত্রটি 0:{max} বা তার চেয়ে কম হতে হবে\",\n    \"max\": \"এই {field} ক্ষেত্রটি 0:{length} অক্ষরের চেয়ে বেশি হওয়া উচিত নয়\",\n    \"mimes\": \"এই {field} ক্ষেত্রের একটি বৈধ ফাইল প্রকার থাকতে হবে\",\n    \"min_value\": \"এই {field} ক্ষেত্রটি 0:{min} বা তার বেশি হতে হবে\",\n    \"min\": \"এই {field} ক্ষেত্রটি কমপক্ষে 0:{length} অক্ষর হতে হবে\",\n    \"numeric\": \"এই {field} ক্ষেত্রে কেবলমাত্র সংখ্যা থাকতে পারে\",\n    \"one_of\": \"এই {field} ক্ষেত্রটির মান বৈধ না\",\n    \"regex\": \"এই {field} ক্ষেত্রটির বিন্যাস বৈধ না\",\n    \"required_if\": \"এই {field} ক্ষেত্রটি অবশ্যক\",\n    \"required\": \"এই {field} ক্ষেত্রটি অবশ্যক\",\n    \"size\": \"এই {field} ক্ষেত্রের আকার 0:{size}KB এর চেয়ে কম হওয়া উচিত\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ca.json",
    "content": "{\n  \"code\": \"ca\",\n  \"messages\": {\n    \"alpha\": \"El camp {field} només ha de contenir lletres\",\n    \"alpha_num\": \"El camp {field} només ha de contenir lletres i números\",\n    \"alpha_dash\": \"El camp {field} només ha de contenir lletres, números i guions\",\n    \"alpha_spaces\": \"El camp {field} només ha de contenir lletres i espais\",\n    \"between\": \"El camp {field} ha d'estar entre 0:{min} i 1:{max}\",\n    \"confirmed\": \"El camp {field} no coincideix amb el camp {target}\",\n    \"digits\": \"El camp {field} ha de ser numèric i contenir exactament 0:{length} dígits\",\n    \"dimensions\": \"El camp {field} ha de ser de 0:{width} píxels per 1:{height} píxels\",\n    \"email\": \"El camp {field} ha de ser un correu electrònic vàlid\",\n    \"not_one_of\": \"El camp {field} ha de ser un valor vàlid\",\n    \"ext\": \"El camp {field} ha de ser un fitxer vàlid\",\n    \"image\": \"El camp {field} ha de ser una imatge\",\n    \"max_value\": \"El camp {field} ha de ser de 0:{max} o menys\",\n    \"max\": \"El camp {field} no ha de ser major a 0:{length} caràcters\",\n    \"mimes\": \"El camp {field} ha de ser un tipus de fitxer vàlid\",\n    \"min_value\": \"El camp {field} ha de ser de 0:{min} o superior\",\n    \"min\": \"El camp {field} ha de tenir almenys 0:{length} caràcters\",\n    \"numeric\": \"El camp {field} ha de contenir només caràcters numèrics\",\n    \"one_of\": \"El camp {field} ha de ser un valor vàlid\",\n    \"regex\": \"El format del camp {field} no és vàlid\",\n    \"required\": \"El camp {field} és obligatori\",\n    \"required_if\": \"El camp {field} és obligatori\",\n    \"size\": \"El camp {field} ha de ser menor a 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ckb.json",
    "content": "{\n  \"code\": \"ckb\",\n  \"messages\": {\n    \"_default\": \"{field}ەکە دروست نییە\",\n    \"alpha\": \" {field} دەکرێت تەنها کاراکتەرە ئەلفابێتیکەکانی تێدا بێت\",\n    \"alpha_num\": \"{field} پێویستە تەنها کاراکتەری ئەلفابێتیکی ژمارەیی بێت\",\n    \"alpha_dash\": \"{field} پێویستە تەنها ژمارەی یاخود داش و ئەندەرسکۆر بێت\",\n    \"alpha_spaces\": \"{field} پێویستە تەنها کاراکتەری ئەلفابێتیک و بۆشایی لەخۆبگرێت\",\n    \"between\": \"بەهای {field} پێویستە لە نێوان 0:{min} و 1:{max} بێت\",\n    \"confirmed\": \"دووپاتکردنەوەی {field} پەسەند نەکراوە\",\n    \"digits\": \"بەهای {field} پێویستە ژمارە بێت و  0:{length} دیجیت بێت\",\n    \"dimensions\": \"{field} پێویستە 0:{width} پیکسڵ بە 1:{height} پیکسڵ بێت\",\n    \"email\": \"{field} پێویستە لە جۆری ئیمەیڵی دروست بێت\",\n    \"not_one_of\": \"الحقل {field} غير صحيح\",\n    \"ext\": \"جۆری {field} لە فایلێکی دروست نییە\",\n    \"image\": \"{field} پێویستە لە جۆری وێنە بێت\",\n    \"integer\": \"بەهای {field} پێویستە ژمارە بێت\",\n    \"length\": \"درێژی {field} پێویستە 0:{length} بێت\",\n    \"max_value\": \"بەهای {field} پێویستە 0:{length} یان کەمتر بێت\",\n    \"max\": \"بەهای {field} نابێت زیاتر بێت لە 0:{length} کاراکتەر\",\n    \"mimes\": \"{field} پێویستە جۆرێک لە فایلە دروستەکان بێت\",\n    \"min_value\": \"بەهای {field} پێویستە 0:{min} یان زیاتر بێت\",\n    \"min\": \"درێژی {field} پێویستە کەمتر نەبێت لە 0:{length} کاراکتەر\",\n    \"numeric\": \"{field} پێویستە تەنها ژمارە لەخۆبگرێت\",\n    \"oneOf\": \"{field} یەکێک نییە لە بەها دروستەکان\",\n    \"regex\": \"جۆری {field} دروست نییە\",\n    \"required\": \"{field} داواکراوە\",\n    \"required_if\": \"{field} داواکراوە\",\n    \"size\": \"{field} پێویستە لە 0:{size}KB کەمتربێت\",\n    \"url\": \"{field} URL ێکی دروست نییە\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/cs.json",
    "content": "{\n  \"code\": \"cs\",\n  \"messages\": {\n    \"_default\": \"Pole {field} není platné\",\n    \"alpha\": \"Pole {field} může obsahovat pouze písmena\",\n    \"alpha_num\": \"Pole {field} může obsahovat pouze alfanumerické znaky\",\n    \"alpha_dash\": \"Pole {field} může obsahovat pouze alfanumerické znaky, pomlčky nebo podtržítka\",\n    \"alpha_spaces\": \"Pole {field} může obsahovat pouze alfanumerické znaky a mezery\",\n    \"between\": \"Pole {field} musí být mezi 0:{min} a 1:{max}\",\n    \"confirmed\": \"Kontrola pole {field} se neshoduje\",\n    \"digits\": \"Pole {field} musí být číslo a musí obshovat přesně 0:{length} číslic\",\n    \"dimensions\": \"{field} musí mít 0:{width} pixelů na 1:{height} pixelů\",\n    \"email\": \"Pole {field} musí být validní email\",\n    \"not_one_of\": \"{field} musí být správná hodnota\",\n    \"ext\": \"{field} musí být validní soubor\",\n    \"image\": \"{field} musí být obrázek\",\n    \"integer\": \"Pole {field} musí být celé číslo\",\n    \"length\": \"Pole {field} musí mít délku 0:{length}\",\n    \"max_value\": \"Pole {field} musí být 0:{max}, nebo mensí\",\n    \"max\": \"{field} nesmí být delší než 0:{length} znaků\",\n    \"mimes\": \"Pole {field} musí být správný typ souboru\",\n    \"min_value\": \"Pole {field} musí být 0:{min}, nebo více\",\n    \"min\": \"Pole {field} musí obsahovat alespoň 0:{length} znaků\",\n    \"numeric\": \"Pole {field} může obsahovat pouze číslice\",\n    \"one_of\": \"{field} musí být správná hodnota\",\n    \"regex\": \"Pole {field} není vyplněno správně\",\n    \"required_if\": \"Pole {field} je povinné\",\n    \"required\": \"Pole {field} je povinné\",\n    \"size\": \"Soubor {field} musí být menší než 0:{size}KB\",\n    \"url\": \"Pole {field} není platná adresa URL\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/cy.json",
    "content": "{\n  \"code\": \"cy\",\n  \"messages\": {\n    \"alpha\": \"Gall {field} ond gynnwys llythrennau'r wyddor\",\n    \"alpha_num\": \"Gall {field} ond gynnwys llythrennau'r wyddor a rhifau\",\n    \"alpha_dash\": \"Gall {field} ond gynnwys llythrennau'r wyddor a chysylltnod\",\n    \"alpha_spaces\": \"Gall {field} ond gynnwys llythrennau'r wyddor a gofod\",\n    \"between\": \"Mae'n rhaid i {field} fod rhwng 0:{min} a 1:{max}\",\n    \"confirmed\": \"Dyw {field} ddim yn gyfatebol\",\n    \"digits\": \"Mae'n rhaid i {field} fod yn ddigidau 0:{length} o hyd\",\n    \"dimensions\": \"Mae'n rhaid i {field} fod yn 0:{width} pixel llydan, a 1:{height} pixel o uchder\",\n    \"email\": \"Mae'n rhaid i {field} fod yn ebost ddilys\",\n    \"not_one_of\": \"Dyw {field} ddim yn fewnbwn ddilys\",\n    \"ext\": \"Dyw {field} ddim yn ffeil dilys\",\n    \"image\": \"Mae'n rhaid i {field} fod yn lun\",\n    \"integer\": \"Mae'n rhaid i {field} fod yn gyfanrif\",\n    \"length\": \"Mae'n rhaid i {field}\",\n    \"max_value\": \"Mae'n rhaid i {field} fod yn 0:{max} o hyd neu'n llai\",\n    \"max\": \"Mae'n rhaid i {field} fod yn 0:{length} o hyd neu'n fwy\",\n    \"mimes\": \"Mae'n rhaid i {field} fod yn ffeil ddilys\",\n    \"min_value\": \"Mae'n rhaid i {field} fod yn 0:{min} o hyd neu'n fwy\",\n    \"min\": \"Mae'n rhaid i {field} fod yn 0:{length} o hyd neu'n fwy\",\n    \"numeric\": \"Mae'n rhaid i {field} fod yn rhif\",\n    \"one_of\": \"Dyw {field} ddim yn fewnbwn dilys\",\n    \"regex\": \"Dyw {field} ddim yn fformat dilys\",\n    \"required_if\": \"Mae {field} yn angenrheidiol\",\n    \"required\": \"Mae {field} yn angenrheidiol\",\n    \"size\": \"Mae'n rhaid i faint {field} for yn llai na 0:{size}KB\",\n    \"url\": \"Dyw {field} ddim yn URL dilys\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/da.json",
    "content": "{\n  \"code\": \"da\",\n  \"messages\": {\n    \"_default\": \"{field} er ikke gyldigt\",\n    \"alpha\": \"{field} må kun indeholde bogstaver\",\n    \"alpha_num\": \"{field} må kun indeholde tal og bogstaver\",\n    \"alpha_dash\": \"{field} må kun indeholde tal, bogstaver, bindestreger og underscores\",\n    \"alpha_spaces\": \"{field} må kun indeholde bogstaver og mellemrum\",\n    \"between\": \"{field} skal være mellem 0:{min} og 1:{max}\",\n    \"confirmed\": \"{field} skal matche {target}\",\n    \"digits\": \"{field} skal være et tal på 0:{length} cifre\",\n    \"dimensions\": \"{field} skal være 0:{width} pixels gange 1:{height} pixels\",\n    \"email\": \"{field} skal være en gyldig email\",\n    \"not_one_of\": \"{field} skal være en gyldig værdi\",\n    \"ext\": \"{field} skal være en gyldig filtype\",\n    \"image\": \"{field} skal være et billede\",\n    \"integer\": \"{field} skal være et heltal\",\n    \"length\": \"{field} skal være 0:{length} karakterer langt\",\n    \"max_value\": \"{field} må maksimalt være 0:{max} karakterer eller mindre\",\n    \"max\": \"{field} må maksimalt være 0:{length} karakterer\",\n    \"mimes\": \"{field} skal være en gyldig filtype\",\n    \"min_value\": \"{field} skal minimum være 0:{min} karakterer eller mere\",\n    \"min\": \"{field} skal minimum være 0:{length} karakterer\",\n    \"numeric\": \"{field} skal være numerisk\",\n    \"one_of\": \"{field} skal være en gyldig værdi\",\n    \"regex\": \"{field} skal have et gyldigt format\",\n    \"required_if\": \"{field} skal udfyldes\",\n    \"required\": \"{field} skal udfyldes\",\n    \"size\": \"{field} må maksimalt have en størrelse på 0:{size}KB\",\n    \"url\": \"{field} er ikke en gyldig URL\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/de.json",
    "content": "{\n  \"code\": \"de\",\n  \"messages\": {\n    \"_default\": \"{field} ist ungültig\",\n    \"alpha\": \"{field} darf nur alphabetische Zeichen enthalten\",\n    \"alpha_dash\": \"{field} darf alphanumerische Zeichen sowie Striche und Unterstriche enthalten\",\n    \"alpha_num\": \"{field} darf nur alphanumerische Zeichen enthalten\",\n    \"alpha_spaces\": \"{field} darf nur alphanumerische Zeichen und Leerzeichen enthalten\",\n    \"between\": \"{field} muss zwischen 0:{min} und 1:{max} liegen\",\n    \"confirmed\": \"Die Bestätigung von {field} stimmt nicht überein\",\n    \"digits\": \"{field} muss numerisch sein und exakt 0:{length} Ziffern enthalten\",\n    \"dimensions\": \"{field} muss 0:{width} x 1:{height} Bildpunkte groß sein\",\n    \"email\": \"{field} muss eine gültige E-Mail-Adresse sein\",\n    \"not_one_of\": \"{field} muss ein gültiger Wert sein\",\n    \"ext\": \"{field} muss eine gültige Datei sein\",\n    \"image\": \"{field} muss eine Grafik sein\",\n    \"one_of\": \"{field} muss ein gültiger Wert sein\",\n    \"integer\": \"{field} muss eine ganze Zahl sein\",\n    \"length\": \"Die Länge von {field} muss 0:{length} sein\",\n    \"max\": \"{field} darf nicht länger als 0:{length} Zeichen sein\",\n    \"max_value\": \"{field} darf maximal 0:{max} sein\",\n    \"mimes\": \"{field} muss einen gültigen Dateityp haben\",\n    \"min\": \"{field} muss mindestens 0:{length} Zeichen lang sein\",\n    \"min_value\": \"{field} muss mindestens 0:{min} sein\",\n    \"numeric\": \"{field} darf nur numerische Zeichen enthalten\",\n    \"regex\": \"Das Format von {field} ist ungültig\",\n    \"required\": \"{field} ist ein Pflichtfeld\",\n    \"required_if\": \"{field} ist ein Pflichtfeld\",\n    \"size\": \"{field} muss kleiner als 0:{size}KB sein\",\n    \"url\": \"{field} ist keine gültige URL\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/el.json",
    "content": "{\n  \"code\": \"el\",\n  \"messages\": {\n    \"alpha\": \"{field} πρέπει να περιέχει μόνο αλφαβητικούς χαρακτήρες\",\n    \"alpha_num\": \"{field} πρέπει να περιέχει μόνο αλφαριθμητικούς χαρακτήρες\",\n    \"alpha_dash\": \"{field} μπορεί να περιέχει αλφαριθμητικούς χαρακτήρες, παύλες και κάτω παύλες\",\n    \"alpha_spaces\": \"{field} μπορεί να περιέχει μόνο αλφαβητικούς χαρακτήρες και κενά\",\n    \"between\": \"{field} πρέπει να είναι μεταξύ 0:{min} καί 1:{max}\",\n    \"confirmed\": \"{field} δεν ταιριάζει με {target}\",\n    \"digits\": \"{field} πρέπει να είναι αριθμός και να περιέχει 0:{length} ψηφία\",\n    \"dimensions\": \"{field} πρέπει να είναι 0:{width} pixels επί 1:{height} pixels\",\n    \"email\": \"{field} πρέπει να είναι έγκυρο email\",\n    \"not_one_of\": \"{field} πρέπει να είναι έγκυρη τιμή\",\n    \"ext\": \"{field} πρέπει να είναι έγκυρο αρχείο\",\n    \"image\": \"{field} πρέπει να είναι εικόνα\",\n    \"integer\": \"{field} πρέπει να είναι ακέραιος αριθμός\",\n    \"length\": \"{field} πρέπει να είναι 0:{length} χαρακτήρες\",\n    \"max_value\": \"{field} πρέπει να είναι 0:{max} ή λιγότερο\",\n    \"max\": \"{field} δεν πρέπει να υπερβαίνει τους 0:{length} χαρακτήρες\",\n    \"mimes\": \"{field} πρέπει να είναι έγκυρο αρχείο ΜΙΜΕ\",\n    \"min_value\": \"{field} πρέπει να είναι 0:{min} ή περισσότερο\",\n    \"min\": \"{field} πρέπει να είναι τουλάχιστον 0:{length} χαρακτήρες\",\n    \"numeric\": \"{field} πρέπει να περιέχει μόνο αριθμούς\",\n    \"one_of\": \"{field} πρέπει να είναι έγκυρη τιμή\",\n    \"regex\": \"{field} δεν είναι έγκυρο\",\n    \"required\": \"{field} δεν έχει συμπληρωθεί\",\n    \"required_if\": \"{field} δεν έχει συμπληρωθεί\",\n    \"size\": \"{field} πρέπει να μην υπερβαίνει τα 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/en.json",
    "content": "{\n  \"code\": \"en\",\n  \"messages\": {\n    \"_default\": \"The {field} is not valid\",\n    \"alpha\": \"The {field} field may only contain alphabetic characters\",\n    \"alpha_num\": \"The {field} field may only contain alpha-numeric characters\",\n    \"alpha_dash\": \"The {field} field may contain alpha-numeric characters as well as dashes and underscores\",\n    \"alpha_spaces\": \"The {field} field may only contain alphabetic characters as well as spaces\",\n    \"between\": \"The {field} field must be between 0:{min} and 1:{max}\",\n    \"confirmed\": \"The {field} field confirmation does not match\",\n    \"digits\": \"The {field} field must be numeric and exactly contain 0:{length} digits\",\n    \"dimensions\": \"The {field} field must be 0:{width} pixels by 1:{height} pixels\",\n    \"email\": \"The {field} field must be a valid email\",\n    \"not_one_of\": \"The {field} field is not a valid value\",\n    \"ext\": \"The {field} field is not a valid file\",\n    \"image\": \"The {field} field must be an image\",\n    \"integer\": \"The {field} field must be an integer\",\n    \"length\": \"The {field} field must be 0:{length} long\",\n    \"max_value\": \"The {field} field must be 0:{max} or less\",\n    \"max\": \"The {field} field may not be greater than 0:{length} characters\",\n    \"mimes\": \"The {field} field must have a valid file type\",\n    \"min_value\": \"The {field} field must be 0:{min} or more\",\n    \"min\": \"The {field} field must be at least 0:{length} characters\",\n    \"numeric\": \"The {field} field may only contain numeric characters\",\n    \"one_of\": \"The {field} field is not a valid value\",\n    \"regex\": \"The {field} field format is invalid\",\n    \"required_if\": \"The {field} field is required\",\n    \"required\": \"The {field} field is required\",\n    \"size\": \"The {field} field size must be less than 0:{size}KB\",\n    \"url\": \"The {field} field is not a valid URL\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/es.json",
    "content": "{\r\n  \"code\": \"es\",\r\n  \"messages\": {\r\n    \"alpha\": \"El campo {field} solo debe contener letras\",\r\n    \"alpha_dash\": \"El campo {field} solo debe contener letras, números y guiones\",\r\n    \"alpha_num\": \"El campo {field} solo debe contener letras y números\",\r\n    \"alpha_spaces\": \"El campo {field} solo debe contener letras y espacios\",\r\n    \"between\": \"El campo {field} debe estar entre 0:{min} y 1:{max}\",\r\n    \"confirmed\": \"El campo {field} no coincide\",\r\n    \"digits\": \"El campo {field} debe ser numérico y contener exactamente 0:{length} dígitos\",\r\n    \"dimensions\": \"El campo {field} debe ser de 0:{width} píxeles por 1:{height} píxeles\",\r\n    \"email\": \"El campo {field} debe ser un correo electrónico válido\",\r\n    \"not_one_of\": \"El campo {field} debe ser un valor válido\",\r\n    \"ext\": \"El campo {field} debe ser un archivo válido\",\r\n    \"image\": \"El campo {field} debe ser una imagen\",\r\n    \"one_of\": \"El campo {field} debe ser un valor válido\",\r\n    \"integer\": \"El campo {field} debe ser un entero\",\r\n    \"length\": \"El largo del campo {field} debe ser 0:{length}\",\r\n    \"max\": \"El campo {field} no debe ser mayor a 0:{length} caracteres\",\r\n    \"max_value\": \"El campo {field} debe de ser 0:{max} o menor\",\r\n    \"mimes\": \"El campo {field} debe ser un tipo de archivo válido\",\r\n    \"min\": \"El campo {field} debe tener al menos 0:{length} caracteres\",\r\n    \"min_value\": \"El campo {field} debe ser 0:{min} o superior\",\r\n    \"numeric\": \"El campo {field} debe contener solo caracteres numéricos\",\r\n    \"regex\": \"El formato del campo {field} no es válido\",\r\n    \"required\": \"El campo {field} es obligatorio\",\r\n    \"required_if\": \"El campo {field} es obligatorio\",\r\n    \"size\": \"El campo {field} debe ser menor a 0:{size}KB\"\r\n  }\r\n}\r\n"
  },
  {
    "path": "packages/i18n/src/locale/et.json",
    "content": "{\n  \"code\": \"et\",\n  \"messages\": {\n    \"_default\": \"{field} on sobimatu\",\n    \"alpha\": \"{field} võib sisaldada ainult tähti\",\n    \"alpha_num\": \"{field} võib sisaldada ainult tähti ja numbreid\",\n    \"alpha_dash\": \"{field} võib sisaldada ainult tähti, numbreid, kriipse ja alakriipse\",\n    \"alpha_spaces\": \"{field} võib sisaldada ainult tähti ja tühikuid\",\n    \"between\": \"{field} peab jääma vahemikku 0:{min} kuni 1:{max}\",\n    \"confirmed\": \"{field} on kontrollist erinev\",\n    \"digits\": \"{field} peab koosnema täpselt 0:{length}-st numbrist\",\n    \"dimensions\": \"{field} peab olema 0:{width} korda 1:{height} pikslit suur\",\n    \"email\": \"{field} peab olema e-maili aadress\",\n    \"not_one_of\": \"{field} ei oma sobivat väärtust\",\n    \"ext\": \"{field} peab olema sobiv fail\",\n    \"image\": \"{field} peab olema pilt\",\n    \"integer\": \"{field} peab olema täisarv\",\n    \"is\": \"{field} peab olema 0:{other}\",\n    \"is_not\": \"{field} ei tohi olla 0:{other}\",\n    \"length\": \"{field} peab olema 0:{length} ühikut pikk\",\n    \"max_value\": \"{field} peab olema 0:{max} või väiksem\",\n    \"max\": \"{field} ei tohi olla pikem kui 0:{length} tähemärki\",\n    \"mimes\": \"{field} peab olema sobivat tüüpi fail\",\n    \"min_value\": \"{field} peab olema 0:{min} või suurem\",\n    \"min\": \"{field} peab olema vähemalt 0:{length} tähemärki pikk\",\n    \"numeric\": \"{field} võib sisaldada ainult numbreid\",\n    \"one_of\": \"{field} ei oma sobivat väärtust\",\n    \"regex\": \"{field} pole sobival kujul\",\n    \"required\": \"{field} on nõutud väli\",\n    \"required_if\": \"{field} on nõutud väli\",\n    \"size\": \"{field} peab olema väiksem kui 0:{size}KB\",\n    \"url\": \"{field} pole sobiv URL\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/eu.json",
    "content": "{\n  \"code\": \"eu\",\n  \"messages\": {\n    \"alpha\": \"{field} eremuak soilik karaktere alfabetikoak eduki ditzake\",\n    \"alpha_dash\": \"{field} eremuak karaktere alfanumerikoak, marrak eta azpimarrak eduki ditzake\",\n    \"alpha_num\": \"{field} eremuak soilik karaktere alfanumerikoak eduki ditzake\",\n    \"alpha_spaces\": \"{field} eremuak soilik karaktere alfanumerikoak eta zuriuneak eduki ditzake\",\n    \"between\": \"{field} eremuak 0:{min} eta 1:{max} artean egon behar du\",\n    \"confirmed\": \"{field} berrespenak ez datoz bat\",\n    \"digits\": \"{field} eremuak zenbakizkoa izan behar du eta zehazki 0:{length} digitu izan behar ditu\",\n    \"dimensions\": \"{field} eremuak 0:{width} pixel bider 1:{height} pixel izan behar du\",\n    \"email\": \"{field} eremuak baliozko helbide elektroniko bat izan behar du\",\n    \"not_one_of\": \"{field} eremuak baliozko balio bat izan behar du\",\n    \"ext\": \"{field} eremuak baliozko fitxategi bat izan behar du\",\n    \"image\": \"{field} eremuak irudi bat izan behar du\",\n    \"integer\": \"{field} eremuak zenbaki oso bat izan behar du\",\n    \"length\": \"{field}(r)en luzerak 0:{length} izan behar du\",\n    \"max_value\": \"{field} eremuak 0:{max} edo gutxiago izan behar du\",\n    \"max\": \"{field} eremuak ezin ditu 0:{length} karaktere baino gehiago izan\",\n    \"mimes\": \"{field} eremuak baliozko fitxategi-mota bat izan behar du\",\n    \"min_value\": \"{field} eremuak 0:{min} edo gehiago izan behar du\",\n    \"min\": \"{field} eremuak gutxienez 0:{length} karaktere izan behar ditu\",\n    \"numeric\": \"{field} eremuak zenbakizko karaktereak soilik izan ditzake\",\n    \"one_of\": \"{field} eremuak baliozko balio bat izan behar du\",\n    \"regex\": \"{field} eremuaren formatua baliogabea da\",\n    \"required\": \"{field} eremua derrigorrezkoa da\",\n    \"required_if\": \"{field} eremua derrigorrezkoa da\",\n    \"size\": \"{field}(e)n tamainak 0:{size}KB baino txikiagoa izan behar du\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/fa.json",
    "content": "{\n  \"code\": \"fa\",\n  \"messages\": {\n    \"alpha\": \"{field} فقط می تواند از حروف تشکیل شود\",\n    \"alpha_num\": \"{field} فقط میتواند از حروف و اعداد تشکیل شود\",\n    \"alpha_dash\": \"{field} فقط می تواند از حروف، اعداد، خط فاصله و زیرخط تشکیل شود\",\n    \"alpha_spaces\": \"{field} فقط می تواند از حروف و فاصله تشکیل شود\",\n    \"between\": \"{field} باید بین 0:{min} و 1:{max} کارکتر باشد\",\n    \"confirmed\": \"{field} با تاییدیه اش مطابقت ندارد\",\n    \"digits\": \"{field} باید یک مقدار عددی و دقیقاً 0:{length} رقم باشد\",\n    \"dimensions\": \"{field} باید در اندازه 0:{width} پیکسل عرض و 1:{height} پیکسل ارتفاع باشد\",\n    \"email\": \"{field} باید یک پست الکترونیک معتبر باشد\",\n    \"not_one_of\": \"{field}باید یک مقدار معتبر باشد\",\n    \"ext\": \"{field} باید یک فایل معتبر باشد\",\n    \"image\": \"{field} باید یک تصویر باشد\",\n    \"integer\": \"{field} باید یک عدد صحیح باشد\",\n    \"length\": \"{field} باید دقیقا 0:{length} کاراکتر باشد\",\n    \"max_value\": \"مقدار {field} باید 0:{max} یا کمتر باشد\",\n    \"max\": \"{field} نباید بیشتر از 0:{length} کارکتر باشد\",\n    \"mimes\": \"{field} باید از نوع معتبر باشد\",\n    \"min_value\": \"مقدار {field} باید 0:{min} یا بیشتر باشد\",\n    \"min\": \"{field} باید حداقل 0:{length} کارکتر باشد\",\n    \"numeric\": \"{field} فقط می تواند عددی باشد\",\n    \"one_of\": \"{field} باید یک مقدار معتبر باشد\",\n    \"regex\": \"قالب {field} قابل قبول نیست\",\n    \"required_if\": \"{field} الزامی است\",\n    \"required\": \"{field} الزامی است\",\n    \"size\": \"حجم {field} کمتر از 0:{size}KB باشد\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/fi.json",
    "content": "{\n  \"code\": \"fi\",\n  \"messages\": {\n    \"alpha\": \"{field} voi sisältää vain kirjaimia\",\n    \"alpha_dash\": \"{field} voi sisältää vain kirajimia, numeroita, ja tavu-, tai alaviivoja\",\n    \"alpha_num\": \"{field} voi sisältää vain kirjaimia ja numeroita\",\n    \"between\": \"Kentän {field} tulee olla 0:{min} ja 1:{max} väliltä\",\n    \"confirmed\": \"{field} ei vastannut {target}\",\n    \"digits\": \"{field} tulee olla numeerinen ja tarkalleen 0:{length} merkkiä\",\n    \"dimensions\": \"{field} tulee olla 0:{width} pikseliä kertaa 1:{height} pikseliä\",\n    \"email\": \"{field} tulee olla kelvollinen sähköpostiosoite\",\n    \"not_one_of\": \"{field} tulee olla kelvollinen arvo\",\n    \"ext\": \"{field} tulee olla kelvollinen tiedosto\",\n    \"image\": \"{field} tulee olla kelvollinen kuva\",\n    \"max\": \"{field} ei saa olla pidempi kuin 0:{length} merkkiä\",\n    \"mimes\": \"{field} tulee olla kelvollinen tiedostotyyppi\",\n    \"min\": \"{field} tulee olla vähintään 0:{length} merkkiä\",\n    \"numeric\": \"{field} voi sisältää vain numeroita\",\n    \"one_of\": \"{field} tulee olla kelvollinen arvo\",\n    \"regex\": \"{field} tulee olla kelvollinen säännöllinen lauseke\",\n    \"required\": \"{field} on pakollinen kenttä\",\n    \"required_if\": \"{field} on pakollinen kenttä\",\n    \"size\": \"{field} tulee olla vähemmän kuin 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/fr.json",
    "content": "{\n  \"code\": \"fr\",\n  \"messages\": {\n    \"_default\": \"Le champ {field} est invalide\",\n    \"alpha\": \"Le champ {field} ne peut contenir que des lettres\",\n    \"alpha_num\": \"Le champ {field} ne peut contenir que des caractères alpha-numériques\",\n    \"alpha_dash\": \"Le champ {field} ne peut contenir que des caractères alpha-numériques, tirets ou soulignés\",\n    \"alpha_spaces\": \"Le champ {field} ne peut contenir que des lettres ou des espaces\",\n    \"between\": \"Le champ {field} doit être compris entre 0:{min} et 1:{max}\",\n    \"confirmed\": \"Le champ {field} ne correspond pas\",\n    \"digits\": \"Le champ {field} doit être un nombre entier de 0:{length} chiffres\",\n    \"dimensions\": \"Le champ {field} doit avoir une taille de 0:{width} pixels par 1:{height} pixels\",\n    \"email\": \"Le champ {field} doit être une adresse e-mail valide\",\n    \"not_one_of\": \"Le champ {field} doit être une valeur valide\",\n    \"ext\": \"Le champ {field} doit être un fichier valide\",\n    \"image\": \"Le champ {field} doit être une image\",\n    \"integer\": \"Le champ {field} doit être un entier\",\n    \"length\": \"Le champ {field} doit contenir 0:{length} caractères\",\n    \"max_value\": \"Le champ {field} doit avoir une valeur de 0:{max} ou moins\",\n    \"max\": \"Le champ {field} ne peut pas contenir plus de 0:{length} caractères\",\n    \"mimes\": \"Le champ {field} doit avoir un type MIME valide\",\n    \"min_value\": \"Le champ {field} doit avoir une valeur de 0:{min} ou plus\",\n    \"min\": \"Le champ {field} doit contenir au minimum 0:{length} caractères\",\n    \"numeric\": \"Le champ {field} ne peut contenir que des chiffres\",\n    \"one_of\": \"Le champ {field} doit être une valeur valide\",\n    \"regex\": \"Le champ {field} est invalide\",\n    \"required\": \"Le champ {field} est obligatoire\",\n    \"required_if\": \"Le champ {field} est obligatoire lorsque {target} possède cette valeur\",\n    \"size\": \"Le champ {field} doit avoir un poids inférieur à 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/he.json",
    "content": "{\n  \"code\": \"he\",\n  \"messages\": {\n    \"alpha\": \"השדה {field} יכול להכיל רק אותיות\",\n    \"alpha_num\": \"השדה {field} יכול להכיל רק אותיות ומספרים.\",\n    \"alpha_dash\": \"השדה {field} יכול להכיל רק אותיות, מספרים ומקפים\",\n    \"alpha_spaces\": \"השדה {field} יכול להכיל רק אותיות ורווחים\",\n    \"between\": \"הערך {field} חייב להיות בין 0:{min} ל- 1:{max}\",\n    \"confirmed\": \"הערכים של {field} חייבים להיות זהים\",\n    \"digits\": \"השדה {field} חייב להיות מספר ולהכיל 0:{length} ספרות בדיוק\",\n    \"dimensions\": \"השדה {field} חייב להיות 0:{width} פיקסלים על 1:{height} פיקסלים\",\n    \"email\": \"השדה {field} חייב להכיל כתובת אימייל תקינה\",\n    \"not_one_of\": \"השדה {field} חייב להכיל ערך תקין\",\n    \"ext\": \"השדה {field} חייב להכיל קובץ תקין\",\n    \"image\": \"השדה {field} חייב להכיל תמונה\",\n    \"max_value\": \"השדה {field} יכול להיות 0:{max} לכל היותר\",\n    \"max\": \"השדה {field} לא יכול להכיל יותר מ- 0:{length} תווים\",\n    \"mimes\": \"הקובץ חייב להיות מסוג תקין\",\n    \"min_value\": \"הערך של {field} חייב להיות לפחות 0:{min}\",\n    \"min\": \"השדה {field} חייב להכיל 0:{length} תווים לפחות\",\n    \"numeric\": \"השדה {field} יכול להכיל ספרות בלבד\",\n    \"one_of\": \"השדה {field} חייב להיות בעל ערך תקין\",\n    \"regex\": \"הפורמט של {field} אינו תקין\",\n    \"required\": \"חובה למלא את השדה {field}\",\n    \"required_if\": \"חובה למלא את השדה {field}\",\n    \"size\": \"השדה {field} חייב לשקול פחות מ 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/hr.json",
    "content": "{\n  \"code\": \"hr\",\n  \"messages\": {\n    \"alpha\": \"{field} može sadržavati samo abecedne znakove\",\n    \"alpha_num\": \"{field} može sadržavati samo alfanumeričke znakove\",\n    \"alpha_dash\": \"{field} može sadržavati alfanumeričke znakove kao i crtice i podvlake\",\n    \"alpha_spaces\": \"{field} može sadržavati samo abecedne znakove kao i razmake\",\n    \"between\": \"{field} mora biti između 0:{min} i 1:{max}\",\n    \"confirmed\": \"Potvrda {field} ne odgovara\",\n    \"digits\": \"{field} mora biti numerički i točno sadrživati 0:{length} znamenke\",\n    \"dimensions\": \"{field} mora biti 0:{width} piksela za 1:{height} piksela\",\n    \"email\": \"{field} mora biti važeća e-pošta\",\n    \"not_one_of\": \"Vrijednost {field} mora biti važeća vrijednost\",\n    \"ext\": \"{field} mora biti važeća datoteka\",\n    \"image\": \"{field} mora biti slika\",\n    \"max_value\": \"Vrijednost {field} mora biti 0:{max} ili manje\",\n    \"max\": \"{field} ne smije biti veći od 0:{length} znakova\",\n    \"mimes\": \"{field} mora imati valjanu vrstu datoteke\",\n    \"min_value\": \"Vrijednost {field} mora biti 0:{min} ili više\",\n    \"min\": \"{field} mora biti barem 0:{length} znakova\",\n    \"numeric\": \"{field} može sadrživati samo numeričke znakove\",\n    \"one_of\": \"Vrijednost {field} mora biti važeća vrijednost\",\n    \"regex\": \"Oblik {field} nije važeći\",\n    \"required\": \"Polje {field} je obavezno\",\n    \"required_if\": \"Polje {field} je obavezno\",\n    \"size\": \"{field} mora biti manje od 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/hu.json",
    "content": "{\n  \"code\": \"hu\",\n  \"messages\": {\n    \"alpha\": \"A(z) {field} kizárólag betűket tartalmazhat\",\n    \"alpha_dash\": \"A(z) {field} kizárólag betűket, számokat, kötőjeleket és alulvonásokat tartalmazhat\",\n    \"alpha_num\": \"A(z) {field} kizárólag betűket és számokat tartalmazhat\",\n    \"alpha_spaces\": \"A(z) {field} kizárólag betűket és szóközöket tartalmazhat\",\n    \"between\": \"A(z) {field} 0:{min} és 1:{max} között kell, hogy legyen\",\n    \"confirmed\": \"A(z) {field} nem egyezik a megerősítéssel\",\n    \"digits\": \"A(z) {field} 0:{length} számjegyű kell, hogy legyen\",\n    \"dimensions\": \"A(z) {field} felbontása 0:{width} és 1:{height} pixel között kell, hogy legyen\",\n    \"email\": \"A(z) {field} nem érvényes email formátum\",\n    \"not_one_of\": \"A(z) {field} értéke érvénytelen\",\n    \"ext\": \"A(z) {field} nem érvényes fájl\",\n    \"image\": \"A(z) {field} képfálj kell, hogy legyen\",\n    \"one_of\": \"A kiválaszott {field} érvénytelen\",\n    \"max\": \"A(z) {field} értéke nem lehet hosszabb mint 0:{length}\",\n    \"max_value\": \"A(z) {field} értéke 0:{max} vagy kevesebb lehet\",\n    \"mimes\": \"A(z) {field} kizárólag érvényes fájlformátumok egyike lehet\",\n    \"min\": \"A(z) {field} értéke nem lehet rövidebb mint 0:{length}\",\n    \"min_value\": \"A(z) {field} értéke 0:{min} vagy több lehet\",\n    \"numeric\": \"A(z) {field} értéke szám kell, hogy legyen\",\n    \"regex\": \"A(z) {field} formátuma érvénytelen\",\n    \"required\": \"A(z) {field} megadása kötelező\",\n    \"required_if\": \"A(z) {field} megadása kötelező\",\n    \"size\": \"A(z) {field} méretének 0:{size} kilobájtnál kisebbnek kell lennie\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/id.json",
    "content": "{\n  \"code\": \"id\",\n  \"messages\": {\n    \"alpha\": \"{field} hanya boleh berisi huruf\",\n    \"alpha_num\": \"{field} hanya boleh berisi huruf dan angka\",\n    \"alpha_dash\": \"{field} hanya boleh berisi huruf, angka, tanda hubung, dan garis bawah\",\n    \"alpha_spaces\": \"{field} hanya boleh berisi huruf dan spasi\",\n    \"between\": \"{field} harus bernilai antara 0:{min} dan 1:{max}\",\n    \"confirmed\": \"{field} tidak sesuai dengan {target}\",\n    \"digits\": \"{field} harus terdiri dari 0:{length} digit angka\",\n    \"dimensions\": \"{field} harus berukuran lebar 0:{width}px dan tinggi 1:{height}px\",\n    \"email\": \"{field} harus berupa alamat email yang valid\",\n    \"not_one_of\": \"{field} mengandung nilai yang tidak diperbolehkan\",\n    \"ext\": \"{field} harus berupa file dengan ekstensi yang valid\",\n    \"image\": \"{field} harus berupa gambar\",\n    \"integer\": \"{field} harus berupa bilangan bulat\",\n    \"length\": \"{field} harus terdiri dari tepat 0:{length} karakter\",\n    \"max_value\": \"Nilai {field} tidak boleh lebih dari 0:{max}\",\n    \"max\": \"{field} tidak boleh lebih dari 0:{length} karakter\",\n    \"mimes\": \"{field} harus memiliki tipe file yang valid\",\n    \"min_value\": \"Nilai {field} tidak boleh kurang dari 0:{min}\",\n    \"min\": \"{field} harus memiliki minimal 0:{length} karakter\",\n    \"numeric\": \"{field} harus berupa angka\",\n    \"one_of\": \"{field} harus berisi salah satu nilai yang diizinkan\",\n    \"regex\": \"Format {field} tidak valid\",\n    \"required\": \"{field} wajib diisi\",\n    \"required_if\": \"{field} wajib diisi\",\n    \"size\": \"Ukuran {field} tidak boleh melebihi 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/it.json",
    "content": "{\n  \"code\": \"it\",\n  \"messages\": {\n    \"alpha\": \"Il campo {field} può contenere solo caratteri alfabetici\",\n    \"alpha_num\": \"Il campo {field} può contenere solo caratteri alfanumerici\",\n    \"alpha_dash\": \"Il campo {field} può contenere caratteri alfa-numerici così come lineette e trattini di sottolineatura\",\n    \"alpha_spaces\": \"Il campo {field} può contenere solo caratteri alfanumerici così come spazi\",\n    \"between\": \"Il campo {field} deve essere compreso tra 0:{min} e 1:{max}\",\n    \"confirmed\": \"Il campo {field} non corrisponde\",\n    \"digits\": \"Il campo {field} deve essere numerico e contenere esattamente 0:{length} cifre\",\n    \"dimensions\": \"Il campo {field} deve essere 0:{width} x 1:{height}\",\n    \"email\": \"Il campo {field} deve essere un indirizzo email valido\",\n    \"not_one_of\": \"Il campo {field} deve avere un valore valido\",\n    \"ext\": \"Il campo {field} deve essere un file valido\",\n    \"image\": \"Il campo {field} deve essere un'immagine\",\n    \"integer\": \"Il campo {field} deve essere un numero\",\n    \"is_not\": \"Il campo {field} non è valido\",\n    \"length\": \"La lunghezza del campo {field} deve essere 0:{length}\",\n    \"max_value\": \"Il campo {field} deve essere minore o uguale a 0:{max}\",\n    \"max\": \"Il campo {field} non può essere più lungo di 0:{length} caratteri\",\n    \"mimes\": \"Il campo {field} deve avere un tipo di file valido\",\n    \"min_value\": \"Il campo {field} deve essere maggiore o uguale a 0:{min}\",\n    \"min\": \"Il campo {field} deve avere almeno 0:{length} caratteri\",\n    \"numeric\": \"Il campo {field} può contenere solo caratteri numerici\",\n    \"one_of\": \"Il campo {field} deve avere un valore valido\",\n    \"regex\": \"Il campo {field} non ha un formato valido\",\n    \"required\": \"Il campo {field} è richiesto\",\n    \"required_if\": \"Il campo {field} è richiesto\",\n    \"size\": \"Il campo {field} deve essere inferiore a 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ja.json",
    "content": "{\n  \"code\": \"ja\",\n  \"messages\": {\n    \"_default\": \"{field}は有効な値ではありません\",\n    \"alpha\": \"{field}はアルファベットのみ使用できます\",\n    \"alpha_num\": \"{field}は英数字のみ使用できます\",\n    \"alpha_dash\": \"{field}は英数字とハイフン、アンダースコアのみ使用できます\",\n    \"alpha_spaces\": \"{field}はアルファベットと空白のみ使用できます\",\n    \"between\": \"{field}は 0:{min} から 1:{max} の間でなければなりません\",\n    \"confirmed\": \"{field}が一致しません\",\n    \"digits\": \"{field}は 0:{length}桁の数字でなければなりません\",\n    \"dimensions\": \"{field}は幅 0:{width}px、高さ 1:{height}px 以内でなければなりません\",\n    \"email\": \"{field}は有効なメールアドレスではありません\",\n    \"not_one_of\": \"{field}は不正な値です\",\n    \"ext\": \"{field}は有効なファイル形式ではありません\",\n    \"image\": \"{field}は有効な画像形式ではありません\",\n    \"integer\": \"{field}は整数のみ使用できます\",\n    \"is\": \"{field}が一致しません\",\n    \"length\": \"{field}は 0:{length} 文字でなければなりません\",\n    \"max_value\": \"{field}は 0:{max} 以下でなければなりません\",\n    \"max\": \"{field}は 0:{length} 文字以内にしてください\",\n    \"mimes\": \"{field}は有効なファイル形式ではありません\",\n    \"min_value\": \"{field}は 0:{min} 以上でなければなりません\",\n    \"min\": \"{field}は 0:{length} 文字以上でなければなりません\",\n    \"numeric\": \"{field}は数字のみ使用できます\",\n    \"one_of\": \"{field}は有効な値ではありません\",\n    \"regex\": \"{field}のフォーマットが正しくありません\",\n    \"required\": \"{field}は必須項目です\",\n    \"required_if\": \"{field}は必須項目です\",\n    \"size\": \"{field}は 0:{size}KB 以内でなければなりません\",\n    \"url\": \"{field}は有効なURLではありません\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ka.json",
    "content": "{\n  \"code\": \"ka\",\n  \"messages\": {\n    \"alpha\": \"{field} უნდა შეიცავდეს მხოლოდ ასოებს\",\n    \"alpha_num\": \"{field} უნდა შეიცავდეს მხოლოდ ციფრებს\",\n    \"alpha_dash\": \"{field} უნდა შესაძლებელია შეიცავდეს ციფრებს, ასოებს და პუნქტუაციის ნიშნებს\",\n    \"alpha_spaces\": \"{field} უნდა შეიცავდეს მხოლოდ ასოებსა და ცარიელ სივრცეებს\",\n    \"between\": \"{field} უნდა იყოს 0:{min} და 1:{max}ს შორის\",\n    \"confirmed\": \"{field} არ ემთხვევა {target}(ი)ს\",\n    \"digits\": \"{field} უნდა შეიცავდეს ციფრებს და უნდა იყოს ზუსტად 0:{length}-ნიშნა\",\n    \"dimensions\": \"{field} უნდა იყოს 0:{width}x{height} ზომის (pixel)\",\n    \"email\": \"{field}-ს უნდა ჰქონდეს ელ-ფოსტის სწორი ფორმატი\",\n    \"not_one_of\": \"{field} უნდა იყოს სწორი მნიშვნელობა\",\n    \"ext\": \"{field} უნდა იყოს ფაილი\",\n    \"image\": \"{field} უნდა იყოს სურათი\",\n    \"max_value\": \"{field} უნდა შეიცავდეს 0:{max} სიმბოლოს ან ნაკლებს\",\n    \"max\": \"{field} არ უნდა იყოს 0:{length} სიმბოლოზე მეტი\",\n    \"mimes\": \"{field}ს უნდა ჰქონდეს სწორი ფაილის ფორმატი\",\n    \"min_value\": \"{field} უნდა შეიცავდეს 0:{min} ან მეტ სიმბოლოს\",\n    \"min\": \"{field} უნდა შეიცავდეს მინიმუმ 0:{length} სიმბოლოს\",\n    \"numeric\": \"{field} უნდა შეიცავდეს ციფრებს\",\n    \"one_of\": \"{field} უნდა იყოს სწორი მნიშვნელობა\",\n    \"regex\": \"{field}-(ი)ს ფორმატი არასწორია\",\n    \"required\": \"{field} აუცილებელია\",\n    \"required_if\": \"{field} აუცილებელია\",\n    \"size\": \"{field} უნდა იყოს 0:{size}KB-ზე ნაკლები\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/km.json",
    "content": "{\n  \"code\": \"km\",\n  \"messages\": {\n    \"_default\": \"{field} មិនមែនជាតម្លៃដែលត្រឹមត្រូវទេ\",\n    \"alpha\": \"{field} តម្រូវអោយមានតែអក្សរតែប៉ុណ្ណោះ\",\n    \"alpha_num\": \"{field} តម្រូវអោយមានតែអក្សរ និងលេខប៉ុណ្ណោះ\",\n    \"alpha_dash\": \"{field} តម្រូវអោយមានតែអក្សរ លេខ សហសញ្ញា(-) និងសហសញ្ញា(_)\",\n    \"alpha_spaces\": \"{field} តម្រូវអោយមានតែអក្សរ និងអាចដកឃ្លាបានប៉ុណ្ណោះ\",\n    \"between\": \"{field} ត្រូវស្ថិតក្នុងចន្លោះពី 0:{min} ដល់ 1:{max}\",\n    \"confirmed\": \"{field} មិនត្រូវនឹង {target} ទេ\",\n    \"digits\": \"{field} ត្រូវតែជាលេខ និងមាន 0:{length} ខ្ទង់\",\n    \"dimensions\": \"{field} ត្រូវមានទទឹង 0:{width}px និងបណ្តោល 1:{height}px\",\n    \"email\": \"{field} មិនមែនជាអាសយដ្ឋានអ៊ីមែលដែលត្រឹមត្រូវទេ\",\n    \"not_one_of\": \"{field} មិនមែនជាតម្លៃដែលត្រឹមត្រូវទេ\",\n    \"ext\": \"{field} មិនមែនជាប្រភេទឯកសារដែលត្រឹមត្រូវទេ\",\n    \"image\": \"{field} ត្រូវតែជារូបភាព\",\n    \"integer\": \"{field} ត្រូវតែជាចំនួនគត់\",\n    \"length\": \"{field} ត្រូវតែមានប្រវែងយ៉ាងហោចណាស់ 0:{length}\",\n    \"max_value\": \"{field} ត្រូវតែតិចជាងឬស្មើ 0:{max}\",\n    \"max\": \"{field} មិនអាចលើសពី 0:{length} តួអក្សរទេ\",\n    \"mimes\": \"{field} មិនមែនជាប្រភេទឯកសារដែលត្រូវបានអនុញ្ញាតទេ\",\n    \"min_value\": \"{field} ត្រូវតែធំជាងឬស្មើ 0:{min}\",\n    \"min\": \"{field} ត្រូវតែមានយ៉ាងហោចណាស់ 0:{length} តួអក្សរ\",\n    \"numeric\": \"{field} ត្រូវតែជាលេខប៉ុណ្ណោះ\",\n    \"one_of\": \"{field} មិនមែនជាតម្លៃដែលត្រឹមត្រូវទេ\",\n    \"regex\": \"{field} មិនត្រឹមត្រូវតាមទម្រង់ដែលបានកំណត់ទេ\",\n    \"required_if\": \"{field} ត្រូវតែមាន\",\n    \"required\": \"{field} ត្រូវតែមាន\",\n    \"size\": \"{field} ត្រូវតែមានទំហំតូចជាង 0:{size}KB\",\n    \"url\": \"{field} មិនមែនជាអាសយដ្ឋាន URL ដែលត្រឹមត្រូវទេ\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ko.json",
    "content": "{\n  \"code\": \"ko\",\n  \"messages\": {\n    \"_default\": \"{field} 항목의 값이 유효하지 않습니다\",\n    \"alpha\": \"{field} 항목에는 영문자만 사용할 수 있습니다\",\n    \"alpha_dash\": \"{field} 항목에는 영문자, 숫자, 대시(-)와 언더스코어(_)만 사용할 수 있습니다\",\n    \"alpha_num\": \"{field} 항목에는 영문자와 숫자만 사용할 수 있습니다\",\n    \"alpha_spaces\": \"{field} 항목에는 영문자와 공백만 사용할 수 있습니다\",\n    \"between\": \"{field} 항목의 값은 0:{min}에서 1:{max} 사이여야 합니다\",\n    \"confirmed\": \"{field} 항목의 값이 일치하지 않습니다\",\n    \"digits\": \"{field} 항목의 값은 0:{length}자리의 숫자여야 합니다\",\n    \"dimensions\": \"{field} 항목의 크기는 가로 0:{width}픽셀, 세로 1:{height}픽셀이어야 합니다\",\n    \"email\": \"{field} 항목의 값은 유효한 이메일 형식이어야 합니다\",\n    \"not_one_of\": \"{field} 항목의 값이 유효하지 않습니다\",\n    \"ext\": \"{field} 항목은 유효한 파일이 아닙니다\",\n    \"image\": \"{field} 항목은 이미지 파일이어야 합니다\",\n    \"integer\": \"{field} 항목의 값은 정수여야 합니다\",\n    \"length\": \"{field} 항목의 길이는 0:{length}글자여야 합니다\",\n    \"max_value\": \"{field} 항목의 값은 0:{max} 이하여야 합니다\",\n    \"max\": \"{field} 항목은 최대 0:{length}글자 이하여야 합니다\",\n    \"mimes\": \"{field} 항목은 유효한 파일 형식이 아닙니다\",\n    \"min_value\": \"{field} 항목의 값은 0:{min} 이상이어야 합니다\",\n    \"min\": \"{field} 항목은 최소 0:{length}글자 이상이어야 합니다\",\n    \"numeric\": \"{field} 항목에는 숫자만 사용할 수 있습니다\",\n    \"one_of\": \"{field} 항목의 값이 유효하지 않습니다\",\n    \"regex\": \"{field} 항목은 형식에 맞지 않습니다\",\n    \"required\": \"{field} 항목은 필수 입력 항목입니다\",\n    \"required_if\": \"{field} 항목은 필수 입력 항목입니다\",\n    \"size\": \"{field} 항목의 크기는 0:{size}KB보다 작아야 합니다\",\n    \"url\": \"{field} 항목은 유효한 URL이 아닙니다\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/kz.json",
    "content": "{\n  \"code\": \"kz\",\n  \"messages\": {\n    \"_default\": \"{field} жолағы дұрыс емес\",\n    \"alpha\": \"{field} жолағына тек әріптер жазуға болады\",\n    \"alpha_num\": \"{field} жолағына тек әріптер және сандар жазуға болады\",\n    \"alpha_dash\": \"{field} жолағына тек әріптер, сандар және дефис жазуға болады\",\n    \"alpha_spaces\": \"{field} жолағына тек әріптер және бос орын жазуға болады\",\n    \"between\": \"{field} жолағы 0:{min} және 1:{max} сандарының арасындағы сан болуға тиіс\",\n    \"confirmed\": \"{field} жолағы басқа жолақпен бірдей емес\",\n    \"digits\": \"{field} жолағы тура 0:{length} цифрдан тұратын сан болуға тиіс\",\n    \"dimensions\": \"{field} жолағы 1:{height} пиксельге 0:{width} пиксель болатын сурет болуға тиіс\",\n    \"email\": \"{field} жолағы қолданыстағы электронды мекенжай болуға тиіс\",\n    \"not_one_of\": \"{field} жолағы рұқсат етілген мән болуға тиіс\",\n    \"ext\": \"{field} жолағы қолданыстағы файл болуға тиіс\",\n    \"image\": \"{field} жолағы сурет болуға тиіс\",\n    \"integer\": \"{field} жолағы бүтін сан болуға тиіс\",\n    \"length\": \"{field} жолағының ұзындығы  мына мәннен ұзын болуға тиіс: 0:{length}\",\n    \"max_value\": \"{field} жолағы 0:{max} не одан кіші сан болуға тиіс\",\n    \"max\": \"{field} жолағы 0:{length} символдан ұзын бола алмайды\",\n    \"mimes\": \"{field} жолағында рұқсат етілген файл типі болуға тиіс\",\n    \"min_value\": \"{field} жолағы 0:{min} не одан үлкен сан болуға тиіс\",\n    \"min\": \"{field} жолағы 0:{length} символдан қысқа болмауға тиіс\",\n    \"numeric\": \"{field} жолағы сан болуға тиіс\",\n    \"one_of\": \"{field} жолағы рұқсат етілген мән болуға тиіс\",\n    \"regex\": \"{field} жолағының форматы дұрыс емес\",\n    \"required_if\": \"{field} жолағын толтыру міндетті\",\n    \"required\": \"{field} жолағын толтыру міндетті\",\n    \"size\": \"{field} жолағы 0:{size}KB-ден кіші болуға тиіс\",\n    \"url\": \"{field} жолағында форматы дұрыс емес сілтеме бар\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/lt.json",
    "content": "{\n  \"code\": \"lt\",\n  \"messages\": {\n    \"alpha\": \"Laukelyje {field} leidžiamos tik raidės\",\n    \"alpha_dash\": \"Laukelyje {field} leidžiamos tik raidės, skaičiai bei brūkšneliai\",\n    \"alpha_num\": \"Laukelyje {field} leidžiamos tik raidės ir skaičiai\",\n    \"alpha_spaces\": \"Laukelyje {field} leidžiamos tik raidės ir tarpai\",\n    \"between\": \"Laukelio {field} reikšmė turi būti tarp 0:{min} ir 1:{max}\",\n    \"confirmed\": \"Laukelio {field} patvirtinimas nesutampa\",\n    \"digits\": \"Laukelio {field} reikšmė turi buti 0:{length} ženklų(-o) skaitmuo\",\n    \"dimensions\": \"{field} turi būti 0:{width} px x 1:{height} px\",\n    \"email\": \"Laukelis {field} turi būti teisinga el. pašto adresas\",\n    \"not_one_of\": \"{field} reikšmė nėra leidžiama\",\n    \"ext\": \"{field} turi būti tinkamas failas\",\n    \"image\": \"{field} turi būti paveikslėlis\",\n    \"one_of\": \"{field} reikšmė nėra leidžiama\",\n    \"max\": \"{field} negali būti ilgesnis nei 0:{length}\",\n    \"max_value\": \"{field} turi būti 0:{max} arba mažiau\",\n    \"mimes\": \"{field}  privalo turėti tinkmą failo tipą\",\n    \"min\": \"{field} ilgis privalo būti bent 0:{length}\",\n    \"min_value\": \"{field} turi būti 0:{min} arba daugiau\",\n    \"numeric\": \"{field} turi būti tik skaitmenys\",\n    \"regex\": \"Laukelio {field} formatas netinkamas\",\n    \"required\": \"Laukelis {field} privalomas\",\n    \"required_if\": \"Laukelis {field} privalomas\",\n    \"size\": \"{field} turi būti mažesnis nei 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/lv.json",
    "content": "{\n  \"code\": \"lv\",\n  \"messages\": {\n    \"alpha\": \" Laukā {field} var ievadīt tikai burtus\",\n    \"alpha_num\": \"Laukā {field} var ievadīt tikai burtus un ciparus\",\n    \"alpha_dash\": \"Laukā {field} var ievadīt tikai burtus, ciparus, domuzīmes un pasvītras\",\n    \"alpha_spaces\": \"Laukā {field} var ievadīt tikai burtus un atstarpes\",\n    \"between\": \"Lauka {field} vērtībai jābūt intervālā starp 0:{min} un 1:{max}\",\n    \"confirmed\": \"Apstiprinājuma lauka {field} vērtība nav korekta\",\n    \"digits\": \"Lauka {field} vērtību veido precīzs 0:{length} ciparu skaits\",\n    \"dimensions\": \"Lauka  {field} izmērs ir 0:{width} pikseļu platumā un 1:{height} pikseļu augstumā\",\n    \"email\": \"Lauka {field} vērtībai jābūt derīgai e-pasta adresei\",\n    \"not_one_of\": \"Laukā {field} jāievada derīga vērtība\",\n    \"ext\": \"Lauka {field} vērtībai jābūt failam\",\n    \"image\": \"Lauka {field} vērtībai jābūt attēlam\",\n    \"integer\": \"Lauka {field} vērtībai jābūt veselam skaitlim\",\n    \"length\": \"Lauka {field} garumam jābūt 0:{length}\",\n    \"max_value\": \"Lauka {field} vērtībai jābūt 0:{max} vai mazākai\",\n    \"max\": \"Laukā {field} nevar ievadīt vairāk nekā 0:{length} rakstzīmes\",\n    \"mimes\": \"Lauka {field} vērtībai jābūt failam\",\n    \"min_value\": \"Laukā {field} izmanto minimālo vērtību 0:{min} vai lielāku\",\n    \"min\": \"Laukā {field} jāievada vismaz 0:{length} rakstzīmes\",\n    \"numeric\": \"Laukā {field} var ievadīt tikai ciparus\",\n    \"one_of\": \"Lauka {field} vērtībai jābūt derīgai\",\n    \"regex\": \"Lauka {field} formāts nav korekts\",\n    \"required\": \"Lauks {field} ir obligāti aizpildāms\",\n    \"required_if\": \"Lauks {field} ir obligāti aizpildāms\",\n    \"size\": \"Lauka {field} lielumam jābut mazākam nekā 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/mn.json",
    "content": "{\n  \"code\": \"mn\",\n  \"messages\": {\n    \"alpha\": \"{field}-н утга зөвхөн үсэг агуулах боломжтой\",\n    \"alpha_num\": \"{field}-н утга зөвхөн тоо болон үсэг агуулах боломжтой\",\n    \"alpha_dash\": \"{field}-н утга зөвхөн үсэг, дундуур зураас, доогуур зураас агуулах боломжтой\",\n    \"alpha_spaces\": \"{field}-н утга зөвхөн үсэг болон зай агуулах боломжтой\",\n    \"between\": \"{field}-н утга зөвхөн 0:{min}-с 1:{max} -ны хооронд байх ёстой\",\n    \"confirmed\": \"{field}-н утга буруу байна\",\n    \"digits\": \"{field}-н утга зөвхөн тоо байх ба яг  0:{length} оронтой байна\",\n    \"dimensions\": \"{field}-н хэмжээ 0:{width}x{height} пикселээс хэтрэх байх шаардлагатай\",\n    \"email\": \"{field}-н утга бодит майл байх ёстой\",\n    \"not_one_of\": \"{field}-н утга {not_one_of} байж болохгүй\",\n    \"ext\": \"{field} заавал файл заавал {ext} форматтай байх ёстой\",\n    \"image\": \"{field} заавал зураг байх ёстой\",\n    \"integer\": \"{field}-н утга тоо байх ёстой\",\n    \"length\": \"{field}-н урт нь 0:{length} байна\",\n    \"max_value\": \"{field}-н утга 0:{max}-с хэтрэхгүй байна\",\n    \"max\": \"{field}-н урт нь хамгийн ихдээ 0:{length} байна\",\n    \"mimes\": \"{field} зөвшөөрөгдөөгүй файл форматтай байна\",\n    \"min_value\": \"{field}-н утга 0:{min}-с багагүй байна\",\n    \"min\": \"{field}-н урт нь хамгийн багадаа 0:{length} байна\",\n    \"numeric\": \"{field}-н утга зөвхөн тоо байна\",\n    \"one_of\": \"{field}-н утга заавал дараахын нэг нь байна. ({one_of})\",\n    \"regex\": \"{field}-н утга буруу форматтай байна\",\n    \"required\": \"{field}-н утга заавал байх ёстой\",\n    \"required_if\": \"{field}-н утга заавал байх ёстой\",\n    \"size\": \"{field} хэмжээ 0:{size}KB-с хэтрэхгүй байна\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ms_MY.json",
    "content": "{\n  \"code\": \"ms_MY\",\n  \"messages\": {\n    \"alpha\": \"{field} hanya boleh mempunyai karakter abjad sahaja\",\n    \"alpha_dash\": \"{field} boleh mempunyai karakter angka-abjad, sengkang dan garis bawah\",\n    \"alpha_num\": \"{field} hanya boleh mempunyai karakter angka-abjad\",\n    \"alpha_spaces\": \"{field} hanya boleh mempunyai karakter abjad termasuklah aksara ruang\",\n    \"between\": \"{field} perlulah di antara 0:{min} dan 1:{max}\",\n    \"confirmed\": \"{field} pengesahan tidak sepadan\",\n    \"digits\": \"{field} perlulah dalam bentuk angka dan mempunyai 0:{length} digit\",\n    \"dimensions\": \"{field} perlulah berdimensi 0:{width} pixel darab 1:{height} pixels\",\n    \"email\": \"{field} perlulah dalam format emel yang sah\",\n    \"not_one_of\": \"{field} perlulah sah\",\n    \"ext\": \"{field} perlulah dalam format fail yang sah\",\n    \"image\": \"{field} perlulah dalam bentuk imej\",\n    \"one_of\": \"{field} perlulah dalam nilai yang sah\",\n    \"integer\": \"{field} perlulah dalam bentuk integer\",\n    \"length\": \"Panjang {field} perlulah bernilai 0:{length}\",\n    \"max\": \"{field} perlulah tidak melebihi 0:{length} karakter\",\n    \"max_value\": \"{field} perlulah bernilai 0:{max} atau kurang\",\n    \"mimes\": \"{field} perlulah mempunyai jenis fail yang sah\",\n    \"min\": \"{field} perlulah sekurang-kurangnya mempunyai 0:{length} karakter\",\n    \"min_value\": \"{field} perlulah bernilai 0:{min} atau lebih\",\n    \"numeric\": \"{field} perlulah mempunyai hanya karakter angka sahaja\",\n    \"regex\": \"Format {field} tidak sah\",\n    \"required\": \"{field} adalah wajib\",\n    \"required_if\": \"{field} adalah wajib\",\n    \"size\": \"Saiz {field} perlulah kurang daripada 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/nb_NO.json",
    "content": "{\n  \"code\": \"nb_NO\",\n  \"messages\": {\n    \"alpha\": \"{field}-feltet kan bare inneholde bokstaver\",\n    \"alpha_dash\": \"{field}-feltet kan bare inneholde alfanumeriske tegn, samt bindestrek og understrek\",\n    \"alpha_num\": \"{field} kan bare inneholde alfanumeriske tegn\",\n    \"alpha_spaces\": \"{field}-feltet kan bare inneholde alfanumeriske tegn og mellomrom\",\n    \"between\": \"{field}-feltet må være imellom 0:{min} og 1:{max}\",\n    \"confirmed\": \"{field}-feltet kan ikke bekreftes\",\n    \"digits\": \"{field}-feltet må være numerisk og inneholde nøyaktig 0:{length} siffer\",\n    \"dimensions\": \"{field}-feltet må være 0:{width} ganger 1:{height} piksler\",\n    \"email\": \"{field}-feltet må være en gyldig e-postadresse\",\n    \"not_one_of\": \"{field}-feltet må være en gyldig verdi\",\n    \"ext\": \"{field}-feltet må være en gyldig fil\",\n    \"image\": \"{field}-feltet må være et bilde\",\n    \"one_of\": \"{field}-feltet må være en gyldig verdi\",\n    \"max\": \"{field}-feltet kan ikke være lengre enn 0:{length} tegn\",\n    \"max_value\": \"{field}-feltet må være 0:{max} eller mindre\",\n    \"mimes\": \"{field}-feltet må ha en gyldig filtype\",\n    \"min\": \"{field}-feltet må være minst 0:{length} tegn\",\n    \"min_value\": \"{field}-feltet må være 0:{min} eller mer\",\n    \"numeric\": \"{field}-feltet kan bare inneholde nummer\",\n    \"regex\": \"{field}-feltet sin formatering er ugyldig\",\n    \"required\": \"{field}-feltet er obligatorisk\",\n    \"required_if\": \"{field}-feltet er obligatorisk\",\n    \"size\": \"{field}-feltet må være mindre enn 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ne.json",
    "content": "{\r\n  \"code\": \"ne\",\r\n  \"messages\": {\r\n    \"alpha\": \"{field} फिल्डमा वर्णमाला अक्षरहरू मात्र समावेश गर्न सकिन्छ।\",\r\n    \"alpha_dash\": \"{field} फिल्डमा वर्णमाला अक्षरहरू साथै रेफ तथा अंडरस्कोर समावेश गर्न सकिन्छ।\",\r\n    \"alpha_num\": \"{field} फिल्डमा संख्या वा अक्षरहरू मात्र समावेश गर्न सकिन्छ।\",\r\n    \"alpha_spaces\": \"{field} फिल्डमा वर्णमाला अक्षरहरू र यिन बीच खाली ठाउँ मात्र समावेश गर्न सकिन्छ।\",\r\n    \"between\": \"{field}को डाटा 0:{min} र 1:{max} को बीच हुनु पर्दछ।\",\r\n    \"confirmed\": \"{field}को मान पुष्टिकरण फिल्डसंग मेल खाँदैन।\",\r\n    \"digits\": \"{field} फिल्डमा अंकहरू समावेश हुनुका साथै ठ्याकै 0:{length}ओटा अंक समावेश हुनु पर्दछ।\",\r\n    \"dimensions\": \"{field} फिल्डमा 0:{width} पिक्सेल चौड़ा र 1:{height} पिक्सेल अग्लो हुनु पर्दछ।\",\r\n    \"email\": \"{field} फिल्डमा मान्य ईमेल हुनु पर्दछ।\",\r\n    \"not_one_of\": \"{field} फिल्डमा मान्य मान हुनु पर्दछ।\",\r\n    \"ext\": \"{field} फिल्डमा मान्य फाइल हुनु पर्दछ।\",\r\n    \"image\": \"{field} फिल्डमा मान्य फोटो हुनु पर्दछ।\",\r\n    \"one_of\": \"{field} फिल्डमा मान्य परिमाण हुनु पर्दछ।\",\r\n    \"integer\": \"{field} फिल्डको मान पूर्णांक संख्या हुनु पर्दछ।\",\r\n    \"length\": \"{field} फिल्डमा लम्बाई 0:{length} हुनु पर्दछ।\",\r\n    \"max\": \"{field} फिल्डमा अक्षरहरू 0:{length}सम्म लामो हुँदा मान्य हुनेछ।\",\r\n    \"max_value\": \"{field} फिल्डमा अंकहरु 0:{max} वा सोभन्दा कम हुनु पर्दछ।\",\r\n    \"mimes\": \"{field} फिल्ड मान्य फाइलको प्रकार हुनु पर्दछ।\",\r\n    \"min\": \"{field} फिल्ड कम्तिमा 0:{length} अक्षर वा अंकहरू हुनु पर्दछ।\",\r\n    \"min_value\": \"{field} फिल्डमा अंकहरु 0:{min} वा बढी हुनु पर्दछ।\",\r\n    \"numeric\": \"{field} फिल्डमा संख्यात्मक अंकहरू मात्र समावेश गर्दा मान्य हुनेछ\",\r\n    \"regex\": \"{field} फिल्डमा मानको ढाँचा स्वीकार-योग्य छैन।\",\r\n    \"required\": \"{field} फिल्ड आवश्यक छ।\",\r\n    \"required_if\": \"{field} फिल्ड आवश्यक छ।\",\r\n    \"size\": \"{field} परिणाम 0:{size}KB भन्दा कम हुनु पर्दछ।\"\r\n  }\r\n}\r\n"
  },
  {
    "path": "packages/i18n/src/locale/nl.json",
    "content": "{\n  \"code\": \"nl\",\n  \"messages\": {\n    \"_default\": \"{field} is ongeldig\",\n    \"alpha\": \"{field} mag alleen letters bevatten\",\n    \"alpha_dash\": \"{field} mag alleen letters, nummers, en streepjes bevatten\",\n    \"alpha_num\": \"{field} mag alleen letters en nummers bevatten\",\n    \"alpha_spaces\": \"{field} mag alleen letters en spaties bevatten\",\n    \"between\": \"{field} moet tussen 0:{min} en 1:{max} liggen\",\n    \"confirmed\": \"{field} bevestiging komt niet overeen\",\n    \"digits\": \"{field} moet een nummer zijn en exact 0:{length} tekens bevatten\",\n    \"dimensions\": \"{field} moet 0:{width} pixels breed zijn en 1:{height} pixels hoog\",\n    \"email\": \"{field} moet een geldig e-mailadres zijn\",\n    \"not_one_of\": \"{field} is ongeldig\",\n    \"ext\": \"{field} moet een geldig bestand zijn\",\n    \"image\": \"{field} moet een afbeelding zijn\",\n    \"one_of\": \"{field} moet een geldige waarde zijn\",\n    \"max\": \"{field} mag niet groter zijn dan 0:{length} karakters\",\n    \"max_value\": \"{field} mag maximaal 0:{max} zijn\",\n    \"mimes\": \"{field} moet een geldig bestandstype hebben\",\n    \"min\": \"{field} moet minimaal 0:{length} karakters zijn\",\n    \"min_value\": \"{field} moet minimaal 0:{min} zijn\",\n    \"numeric\": \"{field} mag alleen nummers bevatten\",\n    \"regex\": \"{field} formaat is ongeldig\",\n    \"required\": \"{field} is verplicht\",\n    \"required_if\": \"{field} is verplicht\",\n    \"size\": \"{field} mag niet groter zijn dan 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/nn_NO.json",
    "content": "{\n  \"code\": \"nn_NO\",\n  \"messages\": {\n    \"alpha\": \"{field}-feltet kan berre innehalde bokstaver\",\n    \"alpha_dash\": \"{field}-feltet kan berre innehalde alfa-numeriske tegn, samt bindestrek og understrek\",\n    \"alpha_num\": \"{field} kan berre innehalde alfanumeriske tegn\",\n    \"alpha_spaces\": \"{field}-feltet kan berre innehalde alfanumeriske tegn og mellomrom\",\n    \"between\": \"{field}-feltet må vere mellom verdiane 0:{min} og 1:{max}\",\n    \"confirmed\": \"{field}-feltet samsvarer ikkje\",\n    \"digits\": \"{field}-feltet må vere numerisk og innehalde nøyaktig 0:{length} siffer\",\n    \"dimensions\": \"{field}-feltet må vere 0:{width} gonger 1:{height} piksler\",\n    \"email\": \"{field}-feltet må innehalde ein gyldig E-post adresse\",\n    \"not_one_of\": \"{field}-feltet må ha ein gyldig verdi\",\n    \"ext\": \"{field}-feltet må innehalde ei gyldig fil\",\n    \"image\": \"{field}-feltet må vere eit bilete\",\n    \"one_of\": \"{field}-feltet må vere ein gyldig verdi\",\n    \"max\": \"{field}-feltet kan ikkje vere lengre enn 0:{length} tegn\",\n    \"max_value\": \"{field} kan ikkje vere lengre enn 0:{max} tegn\",\n    \"mimes\": \"{field}-feltet må ha ein gyldig filtype\",\n    \"min\": \"{field}-feltet må innehalde minst 0:{length} tegn\",\n    \"min_value\": \"{field}-feltet må vere 0:{min} eller mer\",\n    \"numeric\": \"{field}-feltet kan berre innehalde nummer\",\n    \"regex\": \"{field} har ugyldig formatering\",\n    \"required\": \"{field} er eit obligatorisk felt\",\n    \"required_if\": \"{field} er eit obligatorisk felt\",\n    \"size\": \"{field}-feltet må vere mindre enn 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/pl.json",
    "content": "{\n  \"code\": \"pl\",\n  \"messages\": {\n    \"alpha\": \"Pole {field} może zawierać tylko litery\",\n    \"alpha_dash\": \"Pole {field} może zawierać litery, cyfry oraz myślnik lub podkreślnik\",\n    \"alpha_num\": \"Pole {field} może zawierać tylko litery i cyfry\",\n    \"alpha_spaces\": \"Pole {field} może zawierać tylko litery oraz spacje\",\n    \"between\": \"Pole {field} musi być pomiędzy 0:{min} oraz 1:{max}\",\n    \"confirmed\": \"Pole {field} nie zgadza się z polem potwierdzającym {target}\",\n    \"digits\": \"Pole {field} musi być liczbą i dokładnie 0:{length} cyfr\",\n    \"dimensions\": \"Obraz {field} musi być szeroki na 0:{width} pikseli i wysoki na 1:{height} pikseli\",\n    \"email\": \"Pole {field} musi być poprawnym adresem email\",\n    \"not_one_of\": \"Pole {field} musi być poprawną wartością\",\n    \"ext\": \"Plik {field} musi być poprawnym plikiem\",\n    \"image\": \"Pole {field} musi być obrazem\",\n    \"one_of\": \"Pole {field} musi być poprawną wartością\",\n    \"integer\": \"Pole {field} musi być liczbą całkowitą\",\n    \"length\": \"Pole {field} musi mieć długość 0:{length}\",\n    \"max\": \"Pole {field} nie może być dłuższe niż 0:{length}\",\n    \"max_value\": \"Pole {field} musi mieć maksymalną wartość 0:{max}\",\n    \"mimes\": \"Plik {field} musi posiadać poprawne rozszerzenie\",\n    \"min\": \"Pole {field} musi być długie na co najmniej 0:{length}\",\n    \"min_value\": \"Pole {field} musi mieć minimalną wartość 0:{min}\",\n    \"numeric\": \"Pole {field} może zawierać tylko cyfry\",\n    \"regex\": \"Format pola {field} jest nieodpowiedni\",\n    \"required\": \"Pole {field} jest wymagane\",\n    \"required_if\": \"Pole {field} jest wymagane\",\n    \"size\": \"Plik {field} musi być mniejszy niż 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/pt_BR.json",
    "content": "{\n  \"code\": \"pt_BR\",\n  \"messages\": {\n    \"alpha\": \"O campo {field} deve conter somente letras\",\n    \"alpha_dash\": \"O campo {field} deve conter letras, números e traços\",\n    \"alpha_num\": \"O campo {field} deve conter somente letras e números\",\n    \"alpha_spaces\": \"O campo {field} só pode conter caracteres alfabéticos e espaços\",\n    \"between\": \"O campo {field} deve estar entre 0:{min} e 1:{max}\",\n    \"confirmed\": \"A confirmação do campo {field} deve ser igual\",\n    \"digits\": \"O campo {field} deve ser numérico e ter exatamente 0:{length} dígitos\",\n    \"dimensions\": \"O campo {field} deve ter 0:{width} pixels de largura por 1:{height} pixels de altura\",\n    \"email\": \"O campo {field} deve ser um email válido\",\n    \"not_one_of\": \"O campo {field} deve ser um valor válido\",\n    \"ext\": \"O campo {field} deve ser um arquivo válido\",\n    \"image\": \"O campo {field} deve ser uma imagem\",\n    \"integer\": \"O campo {field} deve ser um número inteiro\",\n    \"is\": \"O valor inserido no campo {field} não é válido\",\n    \"one_of\": \"O campo {field} deve ter um valor válido\",\n    \"length\": \"O tamanho do campo {field} deve ser 0:{length}\",\n    \"max\": \"O campo {field} não deve ter mais que 0:{length} caracteres\",\n    \"max_value\": \"O campo {field} precisa ser 0:{max} ou menor\",\n    \"mimes\": \"O campo {field} deve ser um tipo de arquivo válido\",\n    \"min\": \"O campo {field} deve conter pelo menos 0:{length} caracteres\",\n    \"min_value\": \"O campo {field} precisa ser 0:{min} ou maior\",\n    \"numeric\": \"O campo {field} deve conter apenas números\",\n    \"regex\": \"O campo {field} possui um formato inválido\",\n    \"required\": \"O campo {field} é obrigatório\",\n    \"required_if\": \"O campo {field} é obrigatório\",\n    \"size\": \"O campo {field} deve ser menor que 0:{size}KB\",\n    \"url\": \"O campo {field} deve ser uma URL válida\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/pt_PT.json",
    "content": "{\n  \"code\": \"pt_PT\",\n  \"messages\": {\n    \"alpha\": \"O campo {field} deve conter somente letras\",\n    \"alpha_dash\": \"O campo {field} deve conter letras, números e traços\",\n    \"alpha_num\": \"O campo {field} deve conter somente letras e números\",\n    \"alpha_spaces\": \"O {field} só pode conter caracteres alfabéticos e espaços\",\n    \"between\": \"O campo {field} deve estar entre 0:{min} e 1:{max}\",\n    \"confirmed\": \"A confirmação do campo {field} deve ser igual\",\n    \"digits\": \"O campo {field} deve ser numérico e ter 0:{length} dígitos\",\n    \"dimensions\": \"O campo {field} deve ter 0:{width} pixels de largura por 1:{height} pixels de altura\",\n    \"email\": \"O campo {field} deve ser um email válido\",\n    \"integer\": \"O campo {field} deve ser um número inteiro\",\n    \"not_one_of\": \"O campo {field} deve ser um valor válido\",\n    \"ext\": \"O campo {field} deve ser um ficheiro válido\",\n    \"image\": \"O campo {field} deve ser uma imagem\",\n    \"is\": \"O valor inserido no campo {field} não é válido\",\n    \"one_of\": \"O campo {field} deve ter um valor válido\",\n    \"max\": \"O campo {field} não deve ter mais que 0:{length} caracteres\",\n    \"max_value\": \"O campo {field} precisa ser 0:{max} ou menor\",\n    \"mimes\": \"O campo {field} deve ser um tipo de ficheiro válido\",\n    \"min\": \"O campo {field} deve conter pelo menos 0:{length} caracteres\",\n    \"min_value\": \"O campo {field} precisa ser 0:{min} ou maior\",\n    \"numeric\": \"O campo {field} deve conter apenas números\",\n    \"regex\": \"O campo {field} possui um formato inválido\",\n    \"required\": \"O campo {field} é obrigatório\",\n    \"required_if\": \"O campo {field} é obrigatório\",\n    \"size\": \"O campo {field} deve ser menor que 0:{size}KB\",\n    \"url\": \"O campo {field} deve ser uma URL válida\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ro.json",
    "content": "{\n  \"code\": \"ro\",\n  \"messages\": {\n    \"alpha\": \"Câmpul {field} poate conține doar literele alfabetului\",\n    \"alpha_dash\": \"Câmpul {field} poate conține litere și caracterele '-' sau '_'\",\n    \"alpha_num\": \"Câmpul {field} poate conține doar caractere alfanumerice\",\n    \"alpha_spaces\": \"Câmpul {field} poate conține literele și spații\",\n    \"between\": \"Valoare câmpului {field} trebuie să fie între 0:{min} și 1:{max}\",\n    \"confirmed\": \"Câmpul {field} nu coincide\",\n    \"digits\": \"Câmpul {field} trebuie să fie numeric și să conțină exact 0:{length} caractere\",\n    \"dimensions\": \"Câmpul {field} trebuie să fie 0:{width} pixeli lungime și 1:{height} pixeli înălțime\",\n    \"email\": \"Câmpul {field} trebuie să conțină un email valid\",\n    \"not_one_of\": \"Câmpul {field} trebuie să conțină o valoare validă\",\n    \"ext\": \"Câmpul {field} trebuie să fie un nume de fișier valid\",\n    \"image\": \"Câmpul {field} trebuie să fie o imagine\",\n    \"one_of\": \"Câmpul {field} trebuie să conțină o valoare validă\",\n    \"max\": \"Câmpul {field} nu poate conține mai mult de 0:{length} caractere\",\n    \"max_value\": \"Valoarea câmpului {field} trebuie să fie maxim 0:{max}\",\n    \"mimes\": \"Câmpul {field} trebuie să conțină un fișier cu extensie validă\",\n    \"min\": \"Câmpul {field} trebuie să conțină cel puțin 0:{length} caractere\",\n    \"min_value\": \"Valoarea câmpului {field} trebuie să fie mai mare de 0:{min}\",\n    \"numeric\": \"Câmpul {field} poate conține doar valori numerice\",\n    \"regex\": \"Formatul câmpului {field} este invalid\",\n    \"required\": \"Câmpul {field} este obligatoriu\",\n    \"required_if\": \"Câmpul {field} este obligatoriu\",\n    \"size\": \"Câmpul {field} nu trebuie să depășească 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ru.json",
    "content": "{\n  \"code\": \"ru\",\n  \"messages\": {\n    \"_default\": \"Поле {field} некорректно\",\n    \"alpha\": \"Поле {field} может содержать только буквы\",\n    \"alpha_num\": \"Поле {field} может содержать только буквы и цифры\",\n    \"alpha_dash\": \"Поле {field} может содержать только буквы, цифры и дефис\",\n    \"alpha_spaces\": \"Поле {field} может содержать только буквы и пробелы\",\n    \"between\": \"Поле {field} должно быть числом между 0:{min} и 1:{max}\",\n    \"confirmed\": \"Поле {field} не совпадает с другим полем\",\n    \"digits\": \"Поле {field} должно быть числом ровно из 0:{length} цифр\",\n    \"dimensions\": \"Поле {field} должно быть изображением 0:{width} пикселей на 1:{height} пикселей\",\n    \"email\": \"Поле {field} должно быть действительным электронным адресом\",\n    \"not_one_of\": \"Поле {field} должно быть допустимым значением\",\n    \"ext\": \"Поле {field} должно быть действительным файлом\",\n    \"image\": \"Поле {field} должно быть изображением\",\n    \"integer\": \"Поле {field} должно быть целым числом\",\n    \"length\": \"Длина поля {field} должна быть 0:{length}\",\n    \"max_value\": \"Поле {field} должно быть числом 0:{max} или меньше\",\n    \"max\": \"Поле {field} не может быть длиннее 0:{length} символов\",\n    \"mimes\": \"Поле {field} должно иметь допустимый тип файла\",\n    \"min_value\": \"Поле {field} должно быть числом 0:{min} или больше\",\n    \"min\": \"Поле {field} должно быть не короче 0:{length} символов\",\n    \"numeric\": \"Поле {field} должно быть числом\",\n    \"one_of\": \"Поле {field} должно быть допустимым значением\",\n    \"regex\": \"Поле {field} имеет некорректный формат\",\n    \"required_if\": \"Поле {field} обязательно для заполнения\",\n    \"required\": \"Поле {field} обязательно для заполнения\",\n    \"size\": \"Поле {field} должно быть меньше, чем 0:{size}KB\",\n    \"url\": \"Поле {field} содержит ссылку в некорректном формате\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/sk.json",
    "content": "{\n  \"code\": \"sk\",\n  \"messages\": {\n    \"_default\": \"Pole {field} nie je platné\",\n    \"alpha\": \"{field} môže obsahovať len písmená\",\n    \"alpha_num\": \"{field} môže obsahovať len písmená a číslice\",\n    \"alpha_dash\": \"{field} môže obsahovať len písmená, číslice, bodky a podčiarknutie\",\n    \"alpha_spaces\": \"{field} môže obsahovať len písmená, číslice a medzery\",\n    \"between\": \"Položka {field} musí byť medzi 0:{min} a 1:{max}\",\n    \"confirmed\": \"Hodnota položky {field} nie je rovnaká\",\n    \"digits\": \"Položka {field} musí obsahovať 0:{length} čísiel\",\n    \"dimensions\": \"Položka {field} musí mať 0:{width} x 1:{height} pixlov\",\n    \"email\": \"Položka {field} musí obsahovať správnu emailovú adresu\",\n    \"not_one_of\": \"Položka {field} má nesprávnu hodnotu\",\n    \"ext\": \"{field} nie je platný súbor\",\n    \"image\": \"{field} nie je obrázok\",\n    \"integer\": \"Pole {field} musí byť celé číslo\",\n    \"length\": \"Pole {field} musí mať dĺžku 0:{length}\",\n    \"max_value\": \"Položka {field} musí byť maximálne 0:{max}\",\n    \"max\": \"Položka {field} môže obsahovať najviac 0:{length} znakov\",\n    \"mimes\": \"Položka {field} obsahuje nesprávny typ súboru\",\n    \"min_value\": \"Položka {field} musí byť minimálne 0:{min}\",\n    \"min\": \"Položka {field} musí obsahovať minimálne 0:{length} znakov\",\n    \"numeric\": \"Položka {field} môže obsahovať len číslice\",\n    \"one_of\": \"Položka {field} má nesprávnu hodnotu\",\n    \"regex\": \"Formát položky {field} je nesprávny\",\n    \"required_if\": \"Položka {field} je povinná\",\n    \"required\": \"Položka {field} je povinná\",\n    \"size\": \"Súbor {field} musí byť menší ako 0:{size}KB\",\n    \"url\": \"Pole {field} nie je platná adresa URL\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/sl.json",
    "content": "{\n  \"code\": \"sl\",\n  \"messages\": {\n    \"_default\": \"Polje {field} ni veljavno\",\n    \"alpha\": \"Polje {field} lahko vsebuje le črkovne znake\",\n    \"alpha_dash\": \"Polje {field} lahko vsebuje le alfanumerične znake kot tudi vezaje in podčrtaje\",\n    \"alpha_num\": \"Polje {field} lahko vsebuje le alfanumerične znake\",\n    \"alpha_spaces\": \"Polje {field} lahko vsebuje le črkovne znake in presledke\",\n    \"between\": \"Polje {field} mora biti med 0:{min} in 1:{max}\",\n    \"confirmed\": \"Polje {field} se ne ujema\",\n    \"digits\": \"Vrednost polja {field} mora biti numerična in vsebovati natančno 0:{length} številk\",\n    \"dimensions\": \"Slika {field} mora biti široka 0:{width} slikovnih točk in visoka 1:{height} slikovnih točk\",\n    \"email\": \"Vrednost polja {field} mora biti ustrezen e-naslov\",\n    \"not_one_of\": \"Polje {field} mora biti ustrezne vrednosti\",\n    \"ext\": \"Datoteka polja {field} mora biti ustrezna\",\n    \"image\": \"Datoteka polja {field} mora biti slika\",\n    \"one_of\": \"Polje {field} mora biti ustrezne vrednosti\",\n    \"integer\": \"Polje {field} mora biti celo število\",\n    \"is\": \"Vrednost polja {field} se ne ujema\",\n    \"is_not\": \"Polje {field} vsebuje neveljavno vrednost\",\n    \"length\": \"Polje {field} mora biti dolgo 0:{length}\",\n    \"max\": \"Dolžina polja {field} ne sme biti večja od 0:{length} znakov\",\n    \"max_value\": \"Vrednost polja {field} mora biti 0:{max} ali manj\",\n    \"mimes\": \"Datoteka polja {field} mora biti ustreznega tipa\",\n    \"min\": \"Dolžina polja {field} mora biti vsaj 0:{length} znakov\",\n    \"min_value\": \"Vrednost polja {field} mora biti 0:{min} ali več\",\n    \"numeric\": \"Polje {field} lahko vsebuje le numerične znake\",\n    \"regex\": \"Vrednost polja {field} ni v ustreznem formatu\",\n    \"required\": \"Polje {field} je obvezno\",\n    \"required_if\": \"Polje {field} je obvezno\",\n    \"size\": \"Velikost datoteke {field} mora biti manjša kot 0:{size}KB\",\n    \"url\": \"Polje {field} ni veljaven URL\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/so.json",
    "content": "{\n  \"code\": \"so\",\n  \"messages\": {\n    \"alpha\": \"Dhulka {field} dhulku wuxuu lahaan karaa oo keliya xarfaha alifbeetada\",\n    \"alpha_num\": \"Dhulka {field} dhulku wuxuu lahaan karaa oo keliya xarfaha alfa-tirada ah\",\n    \"alpha_dash\": \"Dhismaha {field} waxaa ku jiri kara jilayaasha alfa tiro ahaan ah iyo sidoo kale burburin iyo hoosta\",\n    \"alpha_spaces\": \"The {field} field may only contain alphabetic characters as well as spaces\",\n    \"between\": \"Meesha {field} waa inay u dhexeysa {min} iyo {max}\",\n    \"confirmed\": \"Xaqiijinta garoonka {field} ma lahan\",\n    \"digits\": \"Booska {field} waa inuu ahaadaa lambar\",\n    \"dimensions\": \"Booska {field} waa inuu ahaadaa {width} pixels illaa {height} pixels\",\n    \"email\": \"Booska {field} waa inuu ahaadaa emayl ansax ah\",\n    \"not_one_of\": \"Booska {field} ma ahan qiime sax ah\",\n    \"ext\": \"Booska {field} ma ahan fayl sax ah\",\n    \"image\": \"Meesha {field} waa inay ahaato muuqaal\",\n    \"integer\": \"Booska {field} waa inuu ahaadaa mid isku dhafan\",\n    \"length\": \"Booska {field} waa inuu ahaadaa {length} dherer\",\n    \"max_value\": \"Booska {field} waa inuu ahaadaa {max} ama kayar\",\n    \"max\": \"Booska {field} dhulku kama badnaan karo xarfaha {length}\",\n    \"mimes\": \"Meesha {field} waa inay lahaato nooc fayl oo sax ah\",\n    \"min_value\": \"Booska {field} waa inuu ahaadaa {min} ama in kabadan\",\n    \"min\": \"Booska {field} waa inuu ahaadaa ugu yaraan {max} xarfaha\",\n    \"numeric\": \"Booska {field} waxaa kujiri kara oo keliya xarfaha tirooyinka ah\",\n    \"oneOf\": \"Booska {field} ma ahan qiime sax ah\",\n    \"regex\": \"Qaabka garoonka {field} waa ansax\",\n    \"required_if\": \"Booska {field} waa loo baahan yahay\",\n    \"required\": \"Booska {field} waa loo baahan yahay\",\n    \"size\": \"Baaxadda garoonka {field} waa inay ka yaraato {size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/sq.json",
    "content": "{\n  \"code\": \"sq\",\n  \"messages\": {\n    \"alpha\": \"{field} mund të përmbaj vetëm shkronja\",\n    \"alpha_dash\": \"{field} mund të përmbaj karaktere alfanumerike, shenja si viza dhe shenja të pikësimit\",\n    \"alpha_num\": \"{field} mund të përmbaj vetëm shenja alfanumerike\",\n    \"alpha_spaces\": \"{field} mund të përmbaj vetëm shkronja dhe hapësira\",\n    \"between\": \"{field} duhet të jetë në mes 0:{min} dhe 1:{max}\",\n    \"confirmed\": \"{field} e konfirmimit nuk përputhet\",\n    \"digits\": \"{field} duhet të jetë numerike dhe të përmbaj saktësisht 0:{length} shifra\",\n    \"dimensions\": \"{field} duhet të jetë 0:{width} piksela me 1:{height} piksela\",\n    \"email\": \"{field} duhet të jetë e-mail valid\",\n    \"not_one_of\": \"Vlera {field} duhet të jetë vlerë valide\",\n    \"ext\": \"{field} duhet të jetë fajll valid\",\n    \"image\": \"{field} duhet të jetë fotografi\",\n    \"one_of\": \"Vlera {field} duhet të jetë vlerë valide\",\n    \"max\": \"{field} nuk duhet të jetë më i gjatë se 0:{length} karaktere\",\n    \"max_value\": \"Vlera {field} duhet të jetë 0:{max} ose më e vogël\",\n    \"mimes\": \"{field} duhet të përmbaj llojin e fajllit valid\",\n    \"min\": \"{field} duhet të jetë së paku 0:{length} karakter\",\n    \"min_value\": \"Vlera {field} duhet të jetë së paku 0:{min} ose më shume\",\n    \"numeric\": \"{field} mund të përmbaj vetëm numra\",\n    \"regex\": \"Formati {field} nuk është valid\",\n    \"required\": \"Fusha {field} nuk duhet të jetë e zbrazët\",\n    \"required_if\": \"Fusha {field} nuk duhet të jetë e zbrazët\",\n    \"size\": \"{field} duhet të jetë më e vogël se 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/sr.json",
    "content": "{\n  \"code\": \"sr\",\n  \"messages\": {\n    \"alpha\": \"Поље {field} може садржати само слова\",\n    \"alpha_dash\": \"Поље {field} може садржати алфанумеричке карактере и повлаке\",\n    \"alpha_num\": \"Поље {field} може садржати само алфанумеричке карактере\",\n    \"alpha_spaces\": \"Поље {field} може садржати само алфанумеричке карактере и размаке\",\n    \"between\": \"Поље {field} мора бити између 0:{min} и 1:{max}\",\n    \"confirmed\": \"Потврда поља {field} се не поклапа\",\n    \"digits\": \"Поље {field} мора бити број и садржати тачно 0:{length} цифара\",\n    \"dimensions\": \"Поље {field} мора бити 0:{width} x 1:{height} пиксела\",\n    \"email\": \"Поље {field} мора бити валидан имејл\",\n    \"not_one_of\": \"Поље {field} мора имати валидну вредност\",\n    \"ext\": \"Поље {field} мора бити валидан фајл\",\n    \"image\": \"Поље {field} мора бити слика\",\n    \"one_of\": \"Поље {field} мора бити валидна вредност\",\n    \"max\": \"Поље {field} не сме бити дуже од 0:{length} карактера\",\n    \"max_value\": \"Поље {field} не сме бити веће од 0:{max}\",\n    \"mimes\": \"Поље {field} мора бити валидан тип фајла\",\n    \"min\": \"Поље {field} мора садржати најмање 0:{length} карактера\",\n    \"min_value\": \"Поље {field} не сме бити мање од 0:{min}\",\n    \"numeric\": \"Поље {field} мора бити број\",\n    \"regex\": \"Формат поља {field} није валидан\",\n    \"required\": \"Поље {field} је обавезно\",\n    \"size\": \"Поље {field} мора бити мање од 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/sr_Latin.json",
    "content": "{\n  \"code\": \"sr_Latin\",\n  \"messages\": {\n    \"alpha\": \"Polje {field} može sadržati samo slova\",\n    \"alpha_dash\": \"Polje {field} može sadržati alfanumeričke karaktere i povlake\",\n    \"alpha_num\": \"Polje {field} može sadržati samo alfanumeričke karaktere\",\n    \"alpha_spaces\": \"Polje {field} može sadržati samo alfanumeričke karaktere i razmake\",\n    \"between\": \"Polje {field} mora biti između 0:{min} i 1:{max}\",\n    \"confirmed\": \"Potvrda polja {field} se ne poklapa\",\n    \"digits\": \"Polje {field} mora biti broj i sadržati tačno 0:{length} cifara\",\n    \"dimensions\": \"Polje {field} mora biti 0:{width} x 1:{height} piksela\",\n    \"email\": \"Polje {field} mora biti validan imejl\",\n    \"not_one_of\": \"Polje {field} mora imati validnu vrednost\",\n    \"ext\": \"Polje {field} mora biti validan fajl\",\n    \"image\": \"Polje {field} mora biti slika\",\n    \"one_of\": \"Polje {field} mora biti validna vrednost\",\n    \"max\": \"Polje {field} ne sme biti duže od 0:{length} karaktera\",\n    \"max_value\": \"Polje {field} ne sme biti veće od 0:{max}\",\n    \"mimes\": \"Polje {field} mora biti validan tip fajla\",\n    \"min\": \"Polje {field} mora sadržati najmanje 0:{length} karaktera\",\n    \"min_value\": \"Polje {field} ne sme biti manje od 0:{min}\",\n    \"numeric\": \"Polje {field} mora biti broj\",\n    \"regex\": \"Format polja {field} nije validan\",\n    \"required\": \"Polje {field} je obavezno\",\n    \"required_if\": \"Polje {field} je obavezno\",\n    \"size\": \"Polje {field} mora biti manje od 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/sv.json",
    "content": "{\n  \"code\": \"sv\",\n  \"messages\": {\n    \"_default\": \"Fältet {field} är inte giltigt\",\n    \"alpha\": \"Fältet {field} får bara innehålla alfabetiska tecken\",\n    \"alpha_dash\": \"Fältet {field} får bara innehålla alfanumeriska tecken såväl som snedstreck och understreck\",\n    \"alpha_num\": \"Fältet {field} får bara innehålla alfanumeriska tecken\",\n    \"alpha_spaces\": \"Fältet {field} får bara innehålla alfabetiska tecken och mellanslag\",\n    \"between\": \"Fältet {field} måste vara mellan 0:{min} och 1:{max}\",\n    \"confirmed\": \"Fältet {field} matchar inte {target}\",\n    \"digits\": \"Fältet {field} måste vara numeriskt och innehålla exakt 0:{length} siffor\",\n    \"dimensions\": \"Fältet {field} måste vara 0:{width} pixlar bred och 1:{height} pixlar hög\",\n    \"email\": \"Fältet {field} måste vara en giltig e-postadress\",\n    \"not_one_of\": \"Fältet {field} måste vara ett godkänt alternativ\",\n    \"ext\": \"Fältet {field} måste vara en godkänd fil\",\n    \"image\": \"Fältet {field} måste vara en bildfil\",\n    \"integer\": \"Fältet {field} måste vara ett heltal\",\n    \"length\": \"Fältet {field} måste vara 0:{length} långt\",\n    \"one_of\": \"Fältet {field} måste vara ett godkänt alternativ\",\n    \"max_value\": \"Fältet {field} måste vara 0:{max} eller mindre\",\n    \"max\": \"Fältet {field} får inte vara längre än 0:{length} tecken\",\n    \"mimes\": \"Fältet {field} måste ha en filändelse\",\n    \"min_value\": \"Fältet {field} måste vara 0:{min} eller mer\",\n    \"min\": \"Fältet {field} måste minst vara 0:{length} tecken\",\n    \"numeric\": \"Fältet {field} får bara innehålla numeriska tecken\",\n    \"regex\": \"Fältet {field} har en felaktig formatering\",\n    \"required\": \"Fältet {field} är obligatoriskt\",\n    \"required_if\": \"Fältet {field} är obligatoriskt\",\n    \"size\": \"Fältet {field} måste vara mindre än 0:{size}KB\",\n    \"url\": \"Fältet {field} är inte en giltig webbadress\"\n  }\n}"
  },
  {
    "path": "packages/i18n/src/locale/th.json",
    "content": "{\n  \"code\": \"th\",\n  \"messages\": {\n    \"alpha\": \"{field} ต้องเป็นตัวอักษรเท่านั้น\",\n    \"alpha_dash\": \"{field} สามารถมีตัวอักษร ตัวเลข เครื่องหมายขีดกลาง (-) และเครื่องหมายขีดล่าง (_)\",\n    \"alpha_num\": \"{field} ต้องเป็นตัวอักษร และตัวเลขเท่านั้น\",\n    \"alpha_spaces\": \"{field} ต้องเป็นตัวอักษร และช่องว่างเท่านั้น\",\n    \"between\": \"{field} ต้องเป็นค่าระหว่าง 0:{min} และ 1:{max}\",\n    \"confirmed\": \"การยืนยันข้อมูลของ {field} ไม่ตรงกัน\",\n    \"digits\": \"{field} ต้องเป็นตัวเลขจำนวน 0:{length} หลักเท่านั้น\",\n    \"dimensions\": \"{field} ต้องมีขนาด 0:{width}x{height} px\",\n    \"email\": \"{field} ต้องเป็นรูปแบบอีเมล\",\n    \"not_one_of\": \"{field} ต้องเป็นค่าที่กำหนดเท่านั้น\",\n    \"ext\": \"{field} สกุลไฟล์ไม่ถูกต้อง\",\n    \"image\": \"{field} ต้องเป็นรูปภาพเท่านั้น\",\n    \"one_of\": \"{field} ต้องเป็นค่าที่กำหนดเท่านั้น\",\n    \"integer\": \"{field} ต้องเป็นเลขจำนวนเต็ม\",\n    \"length\": \"{field} ต้องมีความยาว 0:{length}\",\n    \"max\": \"{field} ต้องมีความยาวไม่เกิน 0:{length} ตัวอักษร\",\n    \"max_value\": \"{field} ต้องมีค่าไม่เกิน 0:{max}\",\n    \"mimes\": \"{field} ประเภทไฟล์ไม่ถูกต้อง\",\n    \"min\": \"{field} ต้องมีความยาวอย่างน้อย 0:{length} ตัวอักษร\",\n    \"min_value\": \"{field} ต้องมีค่าตั้งแต่ 0:{min} ขึ้นไป\",\n    \"numeric\": \"{field} ต้องเป็นตัวเลขเท่านั้น\",\n    \"regex\": \"รูปแบบ {field} ไม่ถูกต้อง\",\n    \"required\": \"กรุณากรอก {field}\",\n    \"required_if\": \"กรุณากรอก {field}\",\n    \"size\": \"{field} ต้องมีขนาดไฟล์ไม่เกิน 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/tr.json",
    "content": "{\n  \"code\": \"tr\",\n  \"messages\": {\n    \"alpha\": \"{field} yalnızca harf içerebilir\",\n    \"alpha_dash\": \"{field} alanı harf ve tire (-) ya da alttan tire (_) içerebilir\",\n    \"alpha_num\": \"{field} yalnızca harf ve rakam içerebilir\",\n    \"alpha_spaces\": \"{field} yalnızca harf boşluk (space) içerebilir\",\n    \"between\": \"{field} 0:{min} ile 1:{max} aralığında olmalıdır\",\n    \"confirmed\": \"{field} doğrulaması hatalı\",\n    \"digits\": \"{field} sayısal ve 0:{length} basamaklı olmalıdır\",\n    \"dimensions\": \"{field} alanı 0:{width} piksel ile 1:{height} piksel arasında olmalıdır\",\n    \"email\": \"{field} alanının geçerli bir e-posta olması gerekir\",\n    \"not_one_of\": \"{field} alanına geçerli bir değer giriniz\",\n    \"ext\": \"{field} alanı geçerli bir dosya olmalıdır\",\n    \"image\": \"{field} alanı resim dosyası olmalıdır\",\n    \"integer\": \"{field} alanı bir tamsayı olmalıdır\",\n    \"length\": \"{field} alanı 0:{length} uzunluğunda olmalıdır\",\n    \"one_of\": \"{field} alanına geçerli bir değer giriniz\",\n    \"max\": \"{field} alanı 0:{length} karakterden fazla olmamalıdır\",\n    \"max_value\": \"{field} alanı 0:{max} ya da daha az bir değer olmalıdır\",\n    \"mimes\": \"{field} geçerli bir dosya olmalıdır\",\n    \"min\": \"{field} alanına en az 0:{length} karakter girilmelidir\",\n    \"min_value\": \"{field} alanı 0:{min} ya da daha fazla bir değer olmalıdır\",\n    \"numeric\": \"{field} alanına sayısal bir değer giriniz\",\n    \"regex\": \"{field} formatı geçersiz\",\n    \"required\": \"{field} alanı gereklidir\",\n    \"required_if\": \"{field} alanı gereklidir\",\n    \"size\": \"{field} alanı 0:{size}KB'dan daha az olmalıdır\",\n    \"url\": \"{field} geçerli bir URL değil\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/ug.json",
    "content": "{\n  \"code\": \"ug\",\n  \"messages\": {\n    \"alpha\": \"{field} پەقەت ھەرپ بولۇشى كېرەك\",\n    \"alpha_num\": \"{field} پەقەت ھەرپ ۋە سان بولۇشى كېرەك\",\n    \"alpha_dash\": \"{field} پەقەت ھەرپ، سان، سىزىقچە ۋە ئاستى سىزىق بولۇشى كېرەك\",\n    \"alpha_spaces\": \"{field} پەقەت ھەرپ ۋە بوشلۇق بولۇشى كېرەك\",\n    \"between\": \"{field} چوقۇم 0:{min} بىلەن 1:{max} ئارىسىدا بولۇشى كېرەك\",\n    \"confirmed\": \"{field} نى دەلىللەش ئىناۋەتسىز\",\n    \"digits\": \"{field} چوقۇم 0:{length} خانىلىق سان بولۇشى كېرەك\",\n    \"dimensions\": \"{field} چوقۇم 0:{width} پىكسېلدە 1:{height} پىكسېل بولۇشى كېرەك\",\n    \"email\": \"{field} چوقۇم ئىناۋەتلىك تورخەت بولۇشى كېرەك\",\n    \"not_one_of\": \"{field} ئىناۋەتسىز\",\n    \"ext\": \"{field} ئىناۋەتسىز ھۆججەت\",\n    \"image\": \"{field} چوقۇم رەسىم بولۇشى كېرەك\",\n    \"integer\": \"{field} چوقۇم پۈتۈن سان بولۇشى كېرەك\",\n    \"length\": \"{field} نىڭ ئۇزۇنلۇقى چوقۇم 0:{length} بولۇشى كېرەك\",\n    \"max_value\": \"{field} چوقۇم 0:{max} كە تەڭ ياكى كىچىك بولۇشى كېرەك\",\n    \"max\": \"{field} نىڭ ئۇزۇنلۇقى 0:{length} دىن چوڭ بولماسلىقى كېرەك\",\n    \"mimes\": \"{field} چوقۇم ئىناۋەتلىك ھۆججەت تىپى بولۇشى كېرەك\",\n    \"min_value\": \"{field} چوقۇم 0:{min} كە تەڭ ياكى چوڭ بولۇشى كېرەك\",\n    \"min\": \"{field} نىڭ ئۇزۇنلۇقى 0:{length} دىن كىچىك بولماسلىقى كېرەك\",\n    \"numeric\": \"{field} پەقەت سان بولۇشى كېرەك\",\n    \"oneOf\": \"{field} ئىناۋەتسىز\",\n    \"regex\": \"{field} فورماتى ئىناۋەتسىز\",\n    \"required_if\": \"{field} تەلەپ قىلىنىدۇ\",\n    \"required\": \"{field} تەلەپ قىلىنىدۇ\",\n    \"size\": \"{field} چوڭلۇقى چوقۇم 0:{size}KB دىن كىچىك بولۇشى كېرەك\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/uk.json",
    "content": "{\n  \"code\": \"uk\",\n  \"messages\": {\n    \"alpha\": \"Поле {field} може містити тільки літери\",\n    \"alpha_dash\": \"Поле {field} може містити буквено-цифрові символи, а також тире та підкреслення\",\n    \"alpha_num\": \"Поле {field} може містити тільки літери та цифри\",\n    \"alpha_spaces\": \"Поле {field} може містити тільки літери та пробіли\",\n    \"between\": \"Поле {field} повинно бути між 0:{min} та 1:{max}\",\n    \"confirmed\": \"Поле {field} не співпадає з підтвердженням\",\n    \"digits\": \"Поле {field} повинно бути числовим та точно містити 0:{length} цифри\",\n    \"dimensions\": \"Поле {field} повинно бути 0:{width} пікселів на 1:{height} пікселів\",\n    \"email\": \"В полі {field} повинна бути адреса електронної пошти\",\n    \"not_one_of\": \"Поле {field} повинно мати допустиме значення\",\n    \"ext\": \"Поле {field} повинно бути дійсним файлом\",\n    \"image\": \"В полі {field} має бути зображення\",\n    \"one_of\": \"Поле {field} повинно бути допустимим значенням\",\n    \"max\": \"Поле {field} не може бути більше, ніж 0:{length} символів\",\n    \"max_value\": \"Поле {field} повинно бути 0:{max} або менше\",\n    \"mimes\": \"Поле {field} повиннно мати дійсний тип файлу\",\n    \"min\": \"Поле {field} має бути принаймні 0:{length} символів\",\n    \"min_value\": \"Поле {field} повинно бути 0:{min} або більше\",\n    \"numeric\": \"Поле {field} може містить лише цифри\",\n    \"regex\": \"Поле {field} має невірний формат\",\n    \"required\": \"Поле {field} повинно мати значення\",\n    \"required_if\": \"Поле {field} повинно мати значення\",\n    \"size\": \"Поле {field} повинно бути менше 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/uz.json",
    "content": "{\n  \"code\": \"uz\",\n  \"messages\": {\n    \"alpha\": \"{_field_} maydonida faqat harflar bo'lishi lozim\",\n    \"alpha_dash\": \"{_field_} maydonida faqat harflar, raqamlar va tire (-) bo'lishi lozim\",\n    \"alpha_num\": \"{_field_} maydonida faqat harflar va raqamlar bo'lishi lozim\",\n    \"alpha_spaces\": \"{_field_} maydonida faqat harflar va bo'shliq (space) bo'lishi lozim\",\n    \"between\": \"{_field_} maydoni uzunligi {min} va {max} oralig'ida bo'lishi lozim\",\n    \"confirmed\": \"{_field_} maydoni {target} bilan farq qilayapti\",\n    \"digits\": \"{_field_} maydoni raqam bo'lishi va uning uzunligi {length} ta bo'lishi lozim\",\n    \"dimensions\": \"{_field_} maydoni {width} pikselga {height} piksel bo'lishi lozim\",\n    \"email\": \"{_field_} maydoni haqiqiy elektron pochta bo'lishi lozim\",\n    \"not_one_of\": \"{_field_} maydonida ruhsat etilgan belgi bo'lishi lozim\",\n    \"ext\": \"{_field_} maydonida haqiqiy fayl bo'lishi lozim. ({args})\",\n    \"image\": \"{_field_} maydonida rasm bo'lishi lozim\",\n    \"oneOf\": \"{_field_} maydonida ruhsat etilgan belgi bo'lishi lozim\",\n    \"integer\": \"{_field_} maydonida butun son bo'lishi lozim'\",\n    \"length\": \"{_field_} maydonining uzunligi {length} ta bo'lishi lozim\",\n    \"max\": \"{_field_} maydoni {length} ta belgidan ko'p bo'lishi mumkin emas\",\n    \"max_value\": \"{_field_} maydonining uzunligi {max} ta yoki undan oz bo'lishi lozim\",\n    \"mimes\": \"{_field_} maydonida ruxsat etilgan fayl turi bo'lishi lozim. ({args})\",\n    \"min\": \"{_field_} maydoni uzunligi {length} ta belgidan kam bo'lmasligi lozim\",\n    \"min_value\": \"{_field_} maydonining uzunligi {min} ta yoki undan ko'p bo'lishi lozim\",\n    \"numeric\": \"{_field_} maydonida faqat raqam bo'lishi lozim'\",\n    \"regex\": \"{_field_} maydonida xotolik bor\",\n    \"required\": \"{_field_} maydoni majburiy, to'ldirishingiz lozim\",\n    \"required_if\": \"{_field_} maydoni majburiy to'ldirilishi lozim\",\n    \"size\": \"{_field_} maydoni {size}KB dan kam bo'lishi lozim\",\n    \"double\": \"{_field_} maydoni ruhsat etilgan o'nlik son bo'lishi lozim\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/vi.json",
    "content": "{\n  \"code\": \"vi\",\n  \"messages\": {\n    \"alpha\": \"{field} chỉ có thể chứa các kí tự chữ\",\n    \"alpha_dash\": \"{field} có thể chứa các kí tự chữ (A-Z a-z), số (0-9), gạch ngang (-) và gạch dưới (_)\",\n    \"alpha_num\": \"{field} chỉ có thể chứa các kí tự chữ và số\",\n    \"alpha_spaces\": \"{field} chỉ có thế chứa các kí tự và khoảng trắng\",\n    \"between\": \"{field} phải có giá trị nằm trong khoảng giữa 0:{min} và 1:{max}\",\n    \"confirmed\": \"{field} khác với {target}\",\n    \"digits\": \"Trường {field} chỉ có thể chứa các kí tự số và bắt buộc phải có độ dài là 0:{length}\",\n    \"dimensions\": \"{field} phải có chiều rộng 0:{width} pixels và chiều cao 1:{height} pixels\",\n    \"email\": \"{field} phải là một địa chỉ email hợp lệ\",\n    \"not_one_of\": \"{field} phải chứa một giá trị hợp lệ\",\n    \"ext\": \"{field} phải là một tệp\",\n    \"image\": \"Trường {field} phải là một ảnh\",\n    \"one_of\": \"{field} phải là một giá trị\",\n    \"max\": \"{field} không thể có nhiều hơn 0:{length} kí tự\",\n    \"max_value\": \"{field} phải nhỏ hơn hoặc bằng 0:{max}\",\n    \"mimes\": \"{field} phải chứa kiểu tệp phù hợp\",\n    \"min\": \"{field} phải chứa ít nhất 0:{length} kí tự\",\n    \"min_value\": \"{field} phải lớn hơn hoặc bằng 0:{min}\",\n    \"numeric\": \"{field} chỉ có thể có các kí tự số\",\n    \"regex\": \"{field} có định dạng không đúng\",\n    \"required\": \"{field} là bắt buộc\",\n    \"required_if\": \"{field} là bắt buộc\",\n    \"size\": \"{field} chỉ có thể chứa tệp nhỏ hơn 0:{size}KB\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/zh_CN.json",
    "content": "{\n  \"code\": \"zh_CN\",\n  \"messages\": {\n    \"_default\": \"{field}不是一个有效值\",\n    \"alpha\": \"{field}只能包含字母字符\",\n    \"alpha_dash\": \"{field}能够包含字母数字字符、破折号和下划线\",\n    \"alpha_num\": \"{field}只能包含字母数字字符\",\n    \"alpha_spaces\": \"{field}只能包含字母字符和空格\",\n    \"between\": \"{field}必须在0:{min}与1:{max}之间\",\n    \"confirmed\": \"{field}不能和0:{target}匹配\",\n    \"digits\": \"{field}必须是数字，且精确到0:{length}位数\",\n    \"dimensions\": \"{field}必须在0:{width}像素与1:{height}像素之间\",\n    \"email\": \"{field}不是一个有效的邮箱\",\n    \"not_one_of\": \"{field}不是一个有效值\",\n    \"ext\": \"{field}不是一个有效的文件\",\n    \"image\": \"{field}不是一张有效的图片\",\n    \"one_of\": \"{field}不是一个有效值\",\n    \"integer\": \"{field}必须是整数\",\n    \"length\": \"{field}长度必须为0:{length}\",\n    \"max\": \"{field}不能超过0:{length}个字符\",\n    \"max_value\": \"{field}必须小于或等于0:{max}\",\n    \"mimes\": \"{field}不是一个有效的文件类型\",\n    \"min\": \"{field}必须至少有0:{length}个字符\",\n    \"min_value\": \"{field}必须大于或等于0:{min}\",\n    \"numeric\": \"{field}只能包含数字字符\",\n    \"regex\": \"{field}格式无效\",\n    \"required\": \"{field}是必须的\",\n    \"required_if\": \"{field}是必须的\",\n    \"size\": \"{field}必须小于0:{size}KB\",\n    \"url\": \"{field}不是一个有效的URL\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/locale/zh_TW.json",
    "content": "{\n  \"code\": \"zh_TW\",\n  \"messages\": {\n    \"_default\": \"{field} 的值無效\",\n    \"alpha\": \"{field} 須以英文組成\",\n    \"alpha_dash\": \"{field} 須以英數、破折號及底線組成\",\n    \"alpha_num\": \"{field} 須以英數組成\",\n    \"alpha_spaces\": \"{field} 須以英文及空格組成\",\n    \"between\": \"{field} 須介於 0:{min} 至 1:{max}之間\",\n    \"confirmed\": \" {field} 不一致\",\n    \"digits\": \"{field} 須為 0:{length} 位數字\",\n    \"dimensions\": \"{field} 圖片尺寸不正確。須為 0:{width} x 1:{height} 像素\",\n    \"email\": \"{field} 須為有效的電子信箱\",\n    \"not_one_of\": \"{field} 的選項無效\",\n    \"ext\": \"{field} 須為有效的檔案\",\n    \"image\": \"{field} 須為圖片\",\n    \"one_of\": \"{field} 的選項無效\",\n    \"integer\": \"{field} 須為整數\",\n    \"length\": \"{field} 的長度須為 0:{length}\",\n    \"max\": \"{field} 不能大於 0:{length} 個字元\",\n    \"max_value\": \"{field} 不得大於 0:{max}\",\n    \"mimes\": \"{field} 須為有效的檔案類型\",\n    \"min\": \"{field} 不能小於 0:{length} 個字元\",\n    \"min_value\": \"{field} 不得小於 0:{min}\",\n    \"numeric\": \"{field} 須為數字\",\n    \"regex\": \"{field} 的格式錯誤\",\n    \"required\": \"{field} 為必填\",\n    \"required_if\": \"{field} 為必填\",\n    \"size\": \"{field} 的檔案須小於 0:{size}KB\",\n    \"url\": \"{field} 須為有效的URL\"\n  }\n}\n"
  },
  {
    "path": "packages/i18n/src/utils.ts",
    "content": "import { InterpolateOptions } from '../../shared/types';\n\n/**\n * Replaces placeholder values in a string with their actual values\n */\nexport function interpolate(template: string, values: Record<string, any>, options: InterpolateOptions): string {\n  const { prefix, suffix } = options;\n\n  const regExp = buildRegex(prefix, suffix);\n\n  return template.replace(regExp, function (_, param, placeholder): string {\n    if (!param || !values.params) {\n      return placeholder in values\n        ? values[placeholder]\n        : values.params && placeholder in values.params\n          ? values.params[placeholder]\n          : `${prefix}${placeholder}${suffix}`;\n    }\n\n    // Handles extended object params format\n    if (!Array.isArray(values.params)) {\n      return placeholder in values.params ? values.params[placeholder] : `${prefix}${placeholder}${suffix}`;\n    }\n\n    // Extended Params exit in the format of `paramIndex:{paramName}` where the index is optional\n    const paramIndex = Number(param.replace(':', ''));\n\n    return paramIndex in values.params ? values.params[paramIndex] : `${param}${prefix}${placeholder}${suffix}`;\n  });\n}\n\nfunction escapeRegex(string: string) {\n  return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function buildRegex(prefix: string, suffix: string): RegExp {\n  const safePrefix = escapeRegex(prefix);\n  const safeSuffix = escapeRegex(suffix);\n\n  return new RegExp(`([0-9]:)?${safePrefix}((?:(?!${safeSuffix}).)+)${safeSuffix}`, 'g');\n}\n"
  },
  {
    "path": "packages/i18n/tests/index.spec.ts",
    "content": "import { Ref } from 'vue';\nimport { defineRule, configure, useField } from '@/vee-validate';\nimport { required, between } from '@/rules';\nimport { localize, setFallbackLocale, setLocale } from '@/i18n';\nimport { mountWithHoc, setValue, flushPromises } from '../../vee-validate/tests/helpers';\n\ndefineRule('required', required);\ndefineRule('between', between);\n\nbeforeEach(() => {\n  localize('en', {\n    messages: {\n      required: 'The {field} is required',\n    },\n  });\n});\n\ntest('can define new locales', async () => {\n  configure({\n    generateMessage: localize('ar', {\n      messages: {\n        required: 'هذا الحقل مطلوب',\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n      <div>\n        <Field name=\"field\" validateOnMount rules=\"required\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n\n  // flush the pending validation.\n  await flushPromises();\n\n  expect(error.textContent).toContain('هذا الحقل مطلوب');\n});\n\ntest('can define specific messages for specific fields', async () => {\n  configure({\n    generateMessage: localize('en', {\n      fields: {\n        test: {\n          required: 'WRONG!',\n        },\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"test\" :validateOnMount=\"true\" rules=\"required\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n\n          <Field name=\"name\" :validateOnMount=\"true\" rules=\"required\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  await flushPromises();\n  const errors = wrapper.$el.querySelectorAll('.error');\n  expect(errors).toHaveLength(2);\n\n  expect(errors[0].textContent).toContain('WRONG!');\n  expect(errors[1].textContent).toContain('The name is required');\n});\n\n// #4097\ntest('can define specific messages for specific fields with labels', async () => {\n  configure({\n    generateMessage: localize('en', {\n      fields: {\n        test: {\n          required: '{field} WRONG!',\n        },\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"test\" :validateOnMount=\"true\" rules=\"required\" v-slot=\"{ field, errors }\" label=\"field\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n\n          <Field name=\"name\" :validateOnMount=\"true\" rules=\"required\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  await flushPromises();\n  const errors = wrapper.$el.querySelectorAll('.error');\n  expect(errors).toHaveLength(2);\n\n  expect(errors[0].textContent).toContain('field WRONG!');\n  expect(errors[1].textContent).toContain('The name is required');\n});\n\n// #4097\ntest('can define specific messages for specific fields with labels and form schema', async () => {\n  configure({\n    generateMessage: localize('en', {\n      fields: {\n        test: {\n          required: '{field} WRONG!',\n        },\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <VForm :validation-schema=\"schema\">\n          <Field name=\"test\" :validateOnMount=\"true\" v-slot=\"{ field, errors }\" label=\"field\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n\n          <Field name=\"name\" :validateOnMount=\"true\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </VForm>\n      `,\n    setup() {\n      return {\n        schema: {\n          test: 'required',\n          name: 'required',\n        },\n      };\n    },\n  });\n\n  await flushPromises();\n  const errors = wrapper.$el.querySelectorAll('.error');\n  expect(errors).toHaveLength(2);\n\n  expect(errors[0].textContent).toContain('field WRONG!');\n  expect(errors[1].textContent).toContain('The name is required');\n});\n\ntest('can define labels or names for fields', async () => {\n  configure({\n    generateMessage: localize('en', {\n      messages: { required: '{field} is required' },\n      names: {\n        first: 'First test',\n        second: 'Second test',\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"first\" :validateOnMount=\"true\" rules=\"required\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n\n          <Field name=\"second\" :validateOnMount=\"true\" rules=\"required\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  await flushPromises();\n  const errors = wrapper.$el.querySelectorAll('.error');\n  expect(errors).toHaveLength(2);\n\n  expect(errors[0].textContent).toContain('First test is required');\n  expect(errors[1].textContent).toContain('Second test is required');\n});\n\ntest('can define localized labels for fields', async () => {\n  configure({\n    generateMessage: localize('en', {\n      messages: { required: '{field} is required' },\n      names: {\n        first: 'First test',\n        second: 'Second test',\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"first.value\" label=\"first\" :validateOnMount=\"true\" rules=\"required\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n\n          <Field name=\"second.value\" label=\"second\" :validateOnMount=\"true\" rules=\"required\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span class=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  await flushPromises();\n  const errors = wrapper.$el.querySelectorAll('.error');\n  expect(errors).toHaveLength(2);\n\n  expect(errors[0].textContent).toContain('First test is required');\n  expect(errors[1].textContent).toContain('Second test is required');\n});\n\n// #4164\ntest('can define labels or names for fields with useField', async () => {\n  let errorMessage!: Ref<string | undefined>;\n  configure({\n    generateMessage: localize('en', {\n      messages: { required: '{field} is required' },\n      names: {\n        first: 'First test',\n        second: 'Second test',\n      },\n    }),\n  });\n\n  mountWithHoc({\n    setup() {\n      const field = useField('first', 'required', { validateOnMount: true });\n      errorMessage = field.errorMessage;\n    },\n    template: `\n        <div>\n        </div>\n      `,\n  });\n\n  await flushPromises();\n  expect(errorMessage.value).toBe('First test is required');\n});\n\ntest('can merge locales without setting the current one', async () => {\n  configure({\n    generateMessage: localize({\n      ar: {\n        messages: {\n          required: 'هذا الحقل مطلوب',\n        },\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"field\" :validateOnMount=\"true\" rules=\"required\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The field is required');\n});\n\ntest('falls back to the default message if rule without message exists', async () => {\n  defineRule('i18n', () => false);\n\n  const wrapper = mountWithHoc({\n    template: `\n      <div>\n        <Field name=\"name\" rules=\"required|i18n\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  const input = wrapper.$el.querySelector('input');\n  setValue(input, '12');\n  await flushPromises();\n\n  expect(error.textContent).toContain('name is not valid');\n});\n\ntest('falls back to a language specific default message if rule without message exists', async () => {\n  defineRule('i18n', () => false);\n  configure({\n    generateMessage: localize('nl', {\n      messages: {\n        _default: '{field} is ongeldig',\n      },\n    }),\n  });\n  setLocale('nl');\n\n  const wrapper = mountWithHoc({\n    template: `\n      <div>\n        <Field name=\"field\" rules=\"required|i18n\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  const input = wrapper.$el.querySelector('input');\n  setValue(input, '12');\n  await flushPromises();\n\n  expect(error.textContent).toContain('field is ongeldig');\n});\n\ntest('can switch between locales with setLocale', async () => {\n  configure({\n    generateMessage: localize({\n      en: {\n        messages: {\n          required: 'This field is required',\n        },\n      },\n      ar: {\n        messages: {\n          required: 'هذا الحقل مطلوب',\n        },\n      },\n    }),\n  });\n\n  setLocale('en');\n\n  const wrapper = mountWithHoc({\n    template: `\n      <div>\n        <Field name=\"field\" validateOnMount rules=\"required\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n\n  // flush the pending validation.\n  await flushPromises();\n\n  expect(error.textContent).toContain('This field is required');\n  setLocale('ar');\n  setValue(wrapper.$el.querySelector('input'), '');\n\n  await flushPromises();\n  expect(error.textContent).toContain('هذا الحقل مطلوب');\n});\n\ntest('interpolates object params with short format', async () => {\n  configure({\n    generateMessage: localize('en', {\n      messages: {\n        between: `The {field} field must be between {min} and {max}`,\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: { min: 1, max: 10 } }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\ntest('interpolates object params with extended format', async () => {\n  configure({\n    generateMessage: localize('en', {\n      messages: {\n        between: `The {field} field must be between 0:{min} and 1:{max}`,\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: { min: 1, max: 10 } }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\ntest('interpolates array params', async () => {\n  configure({\n    generateMessage: localize('en', {\n      messages: {\n        between: 'The {field} field must be between 0:{min} and 1:{max}',\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: [1, 10] }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\ntest('interpolates string params', async () => {\n  configure({\n    generateMessage: localize('en', {\n      messages: {\n        between: 'The {field} field must be between 0:{min} and 1:{max}',\n      },\n    }),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" rules=\"between:1,10\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\ndescribe('interpolation preserves placeholders if not found', () => {\n  test('array format', async () => {\n    configure({\n      generateMessage: localize('en', {\n        messages: {\n          between: 'The {field} field must be between 0:{min} and 1:{max}',\n        },\n      }),\n    });\n\n    const wrapper = mountWithHoc({\n      template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: [1] }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    // flush the pending validation.\n    await flushPromises();\n\n    // locale wasn't set.\n    expect(error.textContent).toContain('The name field must be between 1 and 1:{max}');\n  });\n\n  test('object format', async () => {\n    configure({\n      generateMessage: localize('en', {\n        messages: {\n          between: 'The {field} field must be between 0:{min} and 1:{max}',\n        },\n      }),\n    });\n\n    const wrapper = mountWithHoc({\n      template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: { min: 0 } }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    // flush the pending validation.\n    await flushPromises();\n\n    // locale wasn't set.\n    expect(error.textContent).toContain('The name field must be between 0 and {max}');\n  });\n});\n\n// #4726 - custom interpolation options\ntest('custom interpolation options - interpolates object params with short format', async () => {\n  configure({\n    generateMessage: localize(\n      'en',\n      {\n        messages: {\n          between: `The {{field}} field must be between {{min}} and {{max}}`,\n        },\n      },\n      {\n        prefix: '{{',\n        suffix: '}}',\n      },\n    ),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: { min: 1, max: 10 } }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\n// #4809\ntest('custom interpolation options - interpolates with long suffix/prefix', async () => {\n  configure({\n    generateMessage: localize(\n      'en',\n      {\n        messages: {\n          between: `The <start>field<end> field must be between <start>min<end> and <start>max<end>`,\n        },\n      },\n      {\n        prefix: '<start>',\n        suffix: '<end>',\n      },\n    ),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: { min: 1, max: 10 } }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\ntest('custom interpolation options - interpolates object params with short format and handlebars style interpolation', async () => {\n  configure({\n    generateMessage: localize(\n      'en',\n      {\n        messages: {\n          between: `The <%field%> field must be between <%min%> and <%max%>`,\n        },\n      },\n      {\n        prefix: '<%',\n        suffix: '%>',\n      },\n    ),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: { min: 1, max: 10 } }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\ntest('custom interpolation options - interpolates object params with extended format', async () => {\n  configure({\n    generateMessage: localize(\n      'en',\n      {\n        messages: {\n          between: `The {{field}} field must be between 0:{{min}} and 1:{{max}}`,\n        },\n      },\n      {\n        prefix: '{{',\n        suffix: '}}',\n      },\n    ),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: { min: 1, max: 10 } }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\ntest('custom interpolation options - interpolates array params', async () => {\n  configure({\n    generateMessage: localize(\n      'en',\n      {\n        messages: {\n          between: 'The {{field}} field must be between 0:{{min}} and 1:{{max}}',\n        },\n      },\n      {\n        prefix: '{{',\n        suffix: '}}',\n      },\n    ),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: [1, 10] }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\ntest('custom interpolation options - interpolates string params', async () => {\n  configure({\n    generateMessage: localize(\n      'en',\n      {\n        messages: {\n          between: 'The {{field}} field must be between 0:{{min}} and 1:{{max}}',\n        },\n      },\n      {\n        prefix: '{{',\n        suffix: '}}',\n      },\n    ),\n  });\n\n  const wrapper = mountWithHoc({\n    template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" rules=\"between:1,10\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  // flush the pending validation.\n  await flushPromises();\n\n  // locale wasn't set.\n  expect(error.textContent).toContain('The name field must be between 1 and 10');\n});\n\ndescribe('interpolation preserves placeholders if not found', () => {\n  test('custom interpolation options - array format', async () => {\n    configure({\n      generateMessage: localize(\n        'en',\n        {\n          messages: {\n            between: 'The {{field}} field must be between 0:{{min}} and 1:{{max}}',\n          },\n        },\n        {\n          prefix: '{{',\n          suffix: '}}',\n        },\n      ),\n    });\n\n    const wrapper = mountWithHoc({\n      template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: [1] }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    // flush the pending validation.\n    await flushPromises();\n\n    // locale wasn't set.\n    expect(error.textContent).toContain('The name field must be between 1 and 1:{{max}}');\n  });\n\n  test('custom interpolation options - object format', async () => {\n    configure({\n      generateMessage: localize(\n        'en',\n        {\n          messages: {\n            between: 'The {{field}} field must be between 0:{{min}} and 1:{{max}}',\n          },\n        },\n        {\n          prefix: '{{',\n          suffix: '}}',\n        },\n      ),\n    });\n\n    const wrapper = mountWithHoc({\n      template: `\n        <div>\n          <Field name=\"name\" value=\"-1\" :validateOnMount=\"true\" :rules=\"{ between: { min: 0 } }\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    // flush the pending validation.\n    await flushPromises();\n\n    // locale wasn't set.\n    expect(error.textContent).toContain('The name field must be between 0 and {{max}}');\n  });\n});\n\ntest('can define fallback locale', async () => {\n  configure({\n    generateMessage: localize({\n      en: {\n        messages: {\n          test: `Field is required`,\n        },\n      },\n      ar: {\n        messages: {},\n      },\n    }),\n  });\n\n  setLocale('ar');\n  setFallbackLocale('en');\n  defineRule('test', () => false);\n\n  const wrapper = mountWithHoc({\n    template: `\n      <div>\n        <Field name=\"name\" rules=\"test\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n  });\n\n  const error = wrapper.$el.querySelector('#error');\n  const input = wrapper.$el.querySelector('input');\n  setValue(input, '12');\n  await flushPromises();\n\n  expect(error.textContent).toContain('Field is required');\n});\n"
  },
  {
    "path": "packages/nuxt/CHANGELOG.md",
    "content": "# @vee-validate/nuxt\n\n## 5.0.0-beta.1\n\n### Patch Changes\n\n- Updated dependencies [f629397]\n- Updated dependencies [f2807b8]\n- Updated dependencies [e6db423]\n- Updated dependencies [49fcf4c]\n- Updated dependencies [1ce0731]\n- Updated dependencies [fb5e04e]\n- Updated dependencies [095df65]\n  - vee-validate@5.0.0-beta.1\n\n## 5.0.0-beta.0\n\n### Major Changes\n\n- 04ff47c: feat: implement standard schema\n\n### Patch Changes\n\n- Updated dependencies [04ff47c]\n  - vee-validate@5.0.0-beta.0\n\n## 4.15.1\n\n### Patch Changes\n\n- Updated dependencies [721e980]\n- Updated dependencies [546d82e]\n  - vee-validate@4.15.1\n\n## 4.15.0\n\n### Patch Changes\n\n- Updated dependencies [30281f5]\n- Updated dependencies [ec121b1]\n  - vee-validate@4.15.0\n\n## 4.14.7\n\n### Patch Changes\n\n- Updated dependencies [be994b4]\n  - vee-validate@4.14.7\n\n## 4.14.6\n\n### Patch Changes\n\n- 41d82fd: fix: force vee-validate out of optimized deps\n  - vee-validate@4.14.6\n\n## 4.14.5\n\n### Patch Changes\n\n- 141ad3e: chore: upgrade nuxt module dependencies and switch default to module type\n- e9f8c88: fix: force loading the mjs module when using nuxt\n- Updated dependencies [e9f8c88]\n  - vee-validate@4.14.5\n\n## 4.14.4\n\n### Patch Changes\n\n- Updated dependencies [f33974c]\n- Updated dependencies [0991c01]\n- Updated dependencies [ecb540a]\n- Updated dependencies [4f88d85]\n  - vee-validate@4.14.4\n\n## 4.14.3\n\n### Patch Changes\n\n- Updated dependencies [07c27d5]\n  - vee-validate@4.14.3\n\n## 4.14.2\n\n### Patch Changes\n\n- Updated dependencies [f0d4e24]\n  - vee-validate@4.14.2\n\n## 4.14.1\n\n### Patch Changes\n\n- vee-validate@4.14.1\n\n## 4.14.0\n\n### Minor Changes\n\n- 404cf57: chore: bump release\n\n### Patch Changes\n\n- Updated dependencies [f7a4929]\n- Updated dependencies [97cebd8]\n- Updated dependencies [404cf57]\n- Updated dependencies [421ae69]\n  - vee-validate@4.14.0\n\n## 4.13.2\n\n### Patch Changes\n\n- Updated dependencies [afbd0e5]\n  - vee-validate@4.13.2\n\n## 4.13.1\n\n### Patch Changes\n\n- vee-validate@4.13.1\n\n## 4.13.0\n\n### Patch Changes\n\n- Updated dependencies [454bc45]\n- Updated dependencies [ae3772a]\n- Updated dependencies [27fe5c8]\n- Updated dependencies [fd008c1]\n  - vee-validate@4.13.0\n\n## 4.12.8\n\n### Patch Changes\n\n- Updated dependencies [f8bab9c]\n  - vee-validate@4.12.8\n\n## 4.12.7\n\n### Patch Changes\n\n- Updated dependencies [1376794]\n- Updated dependencies [c4415f8]\n  - vee-validate@4.12.7\n\n## 4.12.6\n\n### Patch Changes\n\n- Updated dependencies [07d01fd]\n  - vee-validate@4.12.6\n\n## 4.12.5\n\n### Patch Changes\n\n- Updated dependencies [d779980]\n- Updated dependencies [9eda544]\n  - vee-validate@4.12.5\n\n## 4.12.4\n\n### Patch Changes\n\n- Updated dependencies [2a09a58]\n  - vee-validate@4.12.4\n\n## 4.12.3\n\n### Patch Changes\n\n- Updated dependencies [72e4379]\n- Updated dependencies [a18c19f]\n- Updated dependencies [e2171f8]\n  - vee-validate@4.12.3\n\n## 4.12.2\n\n### Patch Changes\n\n- Updated dependencies [b2203c8e]\n- Updated dependencies [ec8a4d7e]\n  - vee-validate@4.12.2\n\n## 4.12.1\n\n### Patch Changes\n\n- Updated dependencies [36f6b9e6]\n- Updated dependencies [c1c6f399]\n  - vee-validate@4.12.1\n\n## 4.12.0\n\n### Patch Changes\n\n- Updated dependencies [f9a95843]\n- Updated dependencies [bbecc973]\n- Updated dependencies [f688896f]\n- Updated dependencies [2abb8966]\n- Updated dependencies [e370413b]\n- Updated dependencies [95b701f7]\n  - vee-validate@4.12.0\n\n## 4.11.8\n\n### Patch Changes\n\n- Updated dependencies [d1b5b855]\n- Updated dependencies [78c4668e]\n  - vee-validate@4.11.8\n\n## 4.11.7\n\n### Patch Changes\n\n- Updated dependencies [a1414f6a]\n  - vee-validate@4.11.7\n\n## 4.11.6\n\n### Patch Changes\n\n- Updated dependencies [f683e909]\n  - vee-validate@4.11.6\n\n## 4.11.5\n\n### Patch Changes\n\n- Updated dependencies [27c9ef24]\n- Updated dependencies [804ec6fa]\n  - vee-validate@4.11.5\n\n## 4.11.4\n\n### Patch Changes\n\n- Updated dependencies [4d8ed7eb]\n- Updated dependencies [b53400e2]\n- Updated dependencies [8f680bf1]\n- Updated dependencies [5231f439]\n  - vee-validate@4.11.4\n\n## 4.11.3\n\n### Patch Changes\n\n- vee-validate@4.11.3\n\n## 4.11.2\n\n### Patch Changes\n\n- Updated dependencies [2ff045c1]\n- Updated dependencies [73219b40]\n- Updated dependencies [4947e88f]\n- Updated dependencies [ecbb690d]\n  - vee-validate@4.11.2\n\n## 4.11.1\n\n### Patch Changes\n\n- Updated dependencies [5e23dcb9]\n  - vee-validate@4.11.1\n\n## 4.11.0\n\n### Patch Changes\n\n- Updated dependencies [2d8143f9]\n  - vee-validate@4.11.0\n\n## 4.10.9\n\n### Patch Changes\n\n- Updated dependencies [c02337f3]\n  - vee-validate@4.10.9\n\n## 4.10.8\n\n### Patch Changes\n\n- Updated dependencies [a9a473b4]\n  - vee-validate@4.10.8\n\n## 4.10.7\n\n### Patch Changes\n\n- Updated dependencies [9290f5a9]\n- Updated dependencies [93f8001a]\n  - vee-validate@4.10.7\n\n## 4.10.6\n\n### Patch Changes\n\n- Updated dependencies [40ce7a91]\n- Updated dependencies [e9b215a7]\n- Updated dependencies [4e11ff95]\n- Updated dependencies [e354a13a]\n- Updated dependencies [68080d28]\n  - vee-validate@4.10.6\n\n## 4.10.5\n\n### Patch Changes\n\n- Updated dependencies [6a1dc9bd]\n  - vee-validate@4.10.5\n\n## 4.10.4\n\n### Patch Changes\n\n- Updated dependencies [2f9ca91c]\n  - vee-validate@4.10.4\n\n## 4.10.3\n\n### Patch Changes\n\n- Updated dependencies [32537e14]\n- Updated dependencies [c3698f07]\n  - vee-validate@4.10.3\n\n## 4.10.2\n\n### Patch Changes\n\n- Updated dependencies [1660048e]\n  - vee-validate@4.10.2\n\n## 4.10.1\n\n### Patch Changes\n\n- Updated dependencies [fc416918]\n- Updated dependencies [435e7857]\n- Updated dependencies [273cca74]\n  - vee-validate@4.10.1\n\n## 4.10.0\n\n### Patch Changes\n\n- Updated dependencies [77345c42]\n- Updated dependencies [7a548f42]\n- Updated dependencies [7ce9d671]\n- Updated dependencies [bfd6b00a]\n- Updated dependencies [f1dc1359]\n- Updated dependencies [d4fafc95]\n- Updated dependencies [3e4a7c13]\n- Updated dependencies [2cf0eec9]\n- Updated dependencies [05d957ec]\n- Updated dependencies [ed208918]\n- Updated dependencies [6a3f9f15]\n  - vee-validate@4.10.0\n\n## 4.9.6\n\n### Patch Changes\n\n- Updated dependencies [b138282a]\n- Updated dependencies [6e074f77]\n  - vee-validate@4.9.6\n\n## 4.9.5\n\n### Patch Changes\n\n- Updated dependencies [7356c102]\n  - vee-validate@4.9.5\n\n## 4.9.4\n\n### Patch Changes\n\n- Updated dependencies [f4ea2c05]\n  - vee-validate@4.9.4\n\n## 4.9.3\n\n### Patch Changes\n\n- Updated dependencies [09d5596b]\n- Updated dependencies [9bfbfaaf]\n- Updated dependencies [48b45d91]\n  - vee-validate@4.9.3\n\n## 4.9.2\n\n### Patch Changes\n\n- Updated dependencies [31090e0d]\n- Updated dependencies [9046308b]\n- Updated dependencies [fe322a07]\n  - vee-validate@4.9.2\n\n## 4.9.1\n\n### Patch Changes\n\n- Updated dependencies [681bbab4]\n  - vee-validate@4.9.1\n\n## 4.9.0\n\n### Patch Changes\n\n- Updated dependencies [7554d4a6]\n- Updated dependencies [41b5d39b]\n- Updated dependencies [95409080]\n- Updated dependencies [298577b7]\n  - vee-validate@4.9.0\n\n## 4.8.6\n\n### Patch Changes\n\n- 6e0b0557: Introduced official nuxt module package\n- Updated dependencies [6e0b0557]\n  - vee-validate@4.8.6\n"
  },
  {
    "path": "packages/nuxt/README.md",
    "content": "# @vee-validate/nuxt\n\n<p align=\"center\">\n  <a href=\"https://vee-validate.logaretm.com/v5/guide/global-validators\" target=\"_blank\">\n    <img width=\"150\" src=\"https://github.com/logaretm/vee-validate/raw/main/logo.png\">\n  </a>\n\n  <a href=\"https://nuxt.com/\" target=\"_blank\">\n    <img width=\"150\" src=\"https://nuxt.com/assets/design-kit/logo/icon-green.svg\">\n  </a>\n</p>\n\n> Official vee-validate Nuxt module\n\n<p align=\"center\">\n  <a href=\"https://github.com/sponsors/logaretm\">\n    <img src='https://sponsors.logaretm.com/sponsors.svg'>\n  </a>\n</p>\n\nOfficial vee-validate's Nuxt module\n\n## Features\n\n- Auto import of vee-validate components\n- Auto import of vee-validate composables\n- Detecting if you are using `zod` or `yup` and exposing the `toTypedSchema` suitable for either.\n\n## Getting Started\n\nIn your nuxt project install the vee-validate nuxt module:\n\n```sh\n# npm\nnpm i @vee-validate/nuxt\n\n# pnpm\npnpm add @vee-validate/nuxt\n\n# yarn\nyarn add @vee-validate/nuxt\n```\n\nThen add the module to your `modules` config in `nuxt.config.ts`:\n\n```ts\nexport default defineNuxtConfig({\n  // ...\n  modules: [\n    //...\n    '@vee-validate/nuxt',\n  ],\n});\n```\n\n## Types\n\nNo types are exposed by default to avoid having conflicts with other libraries, aside from vee-validate's main API components/composables. You can still import them via `vee-validate`.\n\n## Configuration\n\nYou can configure a few aspects of the `@vee-validate/nuxt` module. Here is the config interface:\n\n```ts\nexport default defineNuxtConfig({\n  // ...\n  modules: [\n    //...\n    [\n      '@vee-validate/nuxt',\n      {\n        // disable or enable auto imports\n        autoImports: true,\n        // Use different names for components\n        componentNames: {\n          Form: 'VeeForm',\n          Field: 'VeeField',\n          FieldArray: 'VeeFieldArray',\n          ErrorMessage: 'VeeErrorMessage',\n        },\n      },\n    ],\n  ],\n});\n```\n\nYou can also use the `veeValidate` config key instead of the array syntax:\n\n```ts\nexport default defineNuxtConfig({\n  // ...\n  modules: [\n    //...\n    '@vee-validate/nuxt',\n  ],\n  veeValidate: {\n    // disable or enable auto imports\n    autoImports: true,\n    // Use different names for components\n    componentNames: {\n      Form: 'VeeForm',\n      Field: 'VeeField',\n      FieldArray: 'VeeFieldArray',\n      ErrorMessage: 'VeeErrorMessage',\n    },\n  },\n});\n```\n"
  },
  {
    "path": "packages/nuxt/package.json",
    "content": "{\n  \"name\": \"@vee-validate/nuxt\",\n  \"version\": \"5.0.0-beta.1\",\n  \"description\": \"Official vee-validate nuxt module\",\n  \"author\": \"Abdelrahman Awad <logaretm1@gmail.com>\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"main\": \"./dist/module.mjs\",\n  \"types\": \"./dist/module.d.ts\",\n  \"homepage\": \"https://vee-validate.logaretm.com/v5/integrations/nuxt\",\n  \"repository\": {\n    \"url\": \"https://github.com/logaretm/vee-validate.git\",\n    \"type\": \"git\",\n    \"directory\": \"packages/nuxt\"\n  },\n  \"scripts\": {\n    \"build\": \"nuxt-module-build build\"\n  },\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/module.d.ts\",\n      \"import\": \"./dist/module.mjs\",\n      \"require\": \"./dist/module.cjs\"\n    }\n  },\n  \"sideEffects\": false,\n  \"keywords\": [\n    \"VueJS\",\n    \"Vue\",\n    \"nuxtjs\",\n    \"nuxt\",\n    \"validation\",\n    \"validator\",\n    \"inputs\",\n    \"form\"\n  ],\n  \"files\": [\n    \"dist/*\"\n  ],\n  \"dependencies\": {\n    \"@nuxt/kit\": \"^3.13.2\",\n    \"local-pkg\": \"^0.5.0\",\n    \"vee-validate\": \"workspace:*\"\n  },\n  \"devDependencies\": {\n    \"@nuxt/eslint-config\": \"^0.6.0\",\n    \"@nuxt/module-builder\": \"^0.8.4\",\n    \"@nuxt/schema\": \"^3.13.2\",\n    \"@nuxt/test-utils\": \"^3.14.4\",\n    \"nuxt\": \"^3.13.2\"\n  }\n}\n"
  },
  {
    "path": "packages/nuxt/src/module.ts",
    "content": "import { defineNuxtModule, addComponent, addImports, resolveModule } from '@nuxt/kit';\nimport type { Nuxt, NuxtModule } from '@nuxt/schema';\n\ntype ComponentName = 'Field' | 'Form' | 'ErrorMessage' | 'FieldArray';\n\nexport interface VeeValidateNuxtOptions {\n  autoImports?: boolean;\n  componentNames?: Partial<Record<ComponentName, string>>;\n}\n\nconst components: ComponentName[] = ['ErrorMessage', 'Field', 'FieldArray', 'Form'];\n\nconst composables = [\n  'useField',\n  'useFieldArray',\n  'useFieldError',\n  'useFieldValue',\n  'useForm',\n  'useFormContext',\n  'useFormErrors',\n  'useFormValues',\n  'useIsFieldDirty',\n  'useIsFieldTouched',\n  'useIsFieldValid',\n  'useIsFormDirty',\n  'useIsFormTouched',\n  'useIsFormValid',\n  'useIsSubmitting',\n  'useIsValidating',\n  'useResetForm',\n  'useSubmitCount',\n  'useSubmitForm',\n  'useValidateField',\n  'useValidateForm',\n];\n\nexport default defineNuxtModule<VeeValidateNuxtOptions>({\n  meta: {\n    name: 'vee-validate',\n    configKey: 'veeValidate',\n  },\n  defaults: {\n    autoImports: true,\n    componentNames: {},\n  },\n  setup(options, nuxt) {\n    addMjsAlias('vee-validate', 'vee-validate', nuxt);\n    prepareVeeValidate(nuxt);\n\n    if (options.autoImports) {\n      composables.forEach(composable => {\n        addImports({\n          name: composable,\n          as: composable,\n          from: 'vee-validate',\n        });\n      });\n\n      components.forEach(component => {\n        addComponent({\n          name: options.componentNames?.[component] ?? component,\n          export: component,\n          filePath: 'vee-validate',\n        });\n      });\n    }\n  },\n}) as NuxtModule<VeeValidateNuxtOptions>;\n\nfunction addMjsAlias(pkgName: string, fileName: string, nuxt: Nuxt) {\n  // FIXME: Deprecated, idk why since it duplicate imports\n  nuxt.options.alias[pkgName] =\n    nuxt.options.alias[pkgName] ||\n    resolveModule(`${pkgName}/dist/${fileName}.mjs`, {\n      paths: [nuxt.options.rootDir, import.meta.url],\n    });\n}\n\ndeclare module '@nuxt/schema' {\n  interface NuxtConfig {\n    'vee-validate'?: VeeValidateNuxtOptions;\n  }\n  interface NuxtOptions {\n    'vee-validate'?: VeeValidateNuxtOptions;\n  }\n}\n\n/**\n * Excludes vee-validate and vee-validate/rules from the optimization process.\n * The optimization process causes issues with the symbols export not matching between the module components and the main vee-validate package.\n * Maybe it is because vite chunks them in different files/sources.\n * Only happens with SSR tho, SPA works.\n */\nfunction prepareVeeValidate(nuxt: Nuxt) {\n  nuxt.options.vite.optimizeDeps = nuxt.options.vite.optimizeDeps || {};\n  nuxt.options.vite.optimizeDeps.exclude = nuxt.options.vite.optimizeDeps.exclude || [];\n  nuxt.options.vite.optimizeDeps.exclude.push('vee-validate', '@vee-validate/rules');\n}\n"
  },
  {
    "path": "packages/rules/CHANGELOG.md",
    "content": "# Change Log\n\n## 5.0.0-beta.1\n\n### Patch Changes\n\n- Updated dependencies [f629397]\n- Updated dependencies [f2807b8]\n- Updated dependencies [e6db423]\n- Updated dependencies [49fcf4c]\n- Updated dependencies [1ce0731]\n- Updated dependencies [fb5e04e]\n- Updated dependencies [095df65]\n  - vee-validate@5.0.0-beta.1\n\n## 5.0.0-beta.0\n\n### Major Changes\n\n- 04ff47c: feat: implement standard schema\n\n### Patch Changes\n\n- Updated dependencies [04ff47c]\n  - vee-validate@5.0.0-beta.0\n\n## 4.15.1\n\n### Patch Changes\n\n- Updated dependencies [721e980]\n- Updated dependencies [546d82e]\n  - vee-validate@4.15.1\n\n## 4.15.0\n\n### Patch Changes\n\n- Updated dependencies [30281f5]\n- Updated dependencies [ec121b1]\n  - vee-validate@4.15.0\n\n## 4.14.7\n\n### Patch Changes\n\n- Updated dependencies [be994b4]\n  - vee-validate@4.14.7\n\n## 4.14.6\n\n### Patch Changes\n\n- vee-validate@4.14.6\n\n## 4.14.5\n\n### Patch Changes\n\n- Updated dependencies [e9f8c88]\n  - vee-validate@4.14.5\n\n## 4.14.4\n\n### Patch Changes\n\n- 4f88d85: fix: specify module type on package.json\n- Updated dependencies [f33974c]\n- Updated dependencies [0991c01]\n- Updated dependencies [ecb540a]\n- Updated dependencies [4f88d85]\n  - vee-validate@4.14.4\n\n## 4.14.3\n\n### Patch Changes\n\n- Updated dependencies [07c27d5]\n  - vee-validate@4.14.3\n\n## 4.14.2\n\n### Patch Changes\n\n- Updated dependencies [f0d4e24]\n  - vee-validate@4.14.2\n\n## 4.14.1\n\n### Patch Changes\n\n- vee-validate@4.14.1\n\n## 4.14.0\n\n### Minor Changes\n\n- 404cf57: chore: bump release\n\n### Patch Changes\n\n- a8524a1: fix: incorrect shared type import in rules\n- 97cebd8: chore: add 'exports' field in package.json for all packages\n- e69e0df: fix: updated email regex closes #4801\n- Updated dependencies [f7a4929]\n- Updated dependencies [97cebd8]\n- Updated dependencies [404cf57]\n- Updated dependencies [421ae69]\n  - vee-validate@4.14.0\n\n## 4.13.2\n\n### Patch Changes\n\n- Updated dependencies [afbd0e5]\n  - vee-validate@4.13.2\n\n## 4.13.1\n\n### Patch Changes\n\n- vee-validate@4.13.1\n\n## 4.13.0\n\n### Patch Changes\n\n- fdb2d47: fix: offer an all export with simplified typings closes #4766\n- Updated dependencies [454bc45]\n- Updated dependencies [ae3772a]\n- Updated dependencies [27fe5c8]\n- Updated dependencies [fd008c1]\n  - vee-validate@4.13.0\n\n## 4.12.8\n\n### Patch Changes\n\n- Updated dependencies [f8bab9c]\n  - vee-validate@4.12.8\n\n## 4.12.7\n\n### Patch Changes\n\n- Updated dependencies [1376794]\n- Updated dependencies [c4415f8]\n  - vee-validate@4.12.7\n\n## 4.12.6\n\n### Patch Changes\n\n- Updated dependencies [07d01fd]\n  - vee-validate@4.12.6\n\n## 4.12.5\n\n### Patch Changes\n\n- Updated dependencies [d779980]\n- Updated dependencies [9eda544]\n  - vee-validate@4.12.5\n\n## 4.12.4\n\n### Patch Changes\n\n- Updated dependencies [2a09a58]\n  - vee-validate@4.12.4\n\n## 4.12.3\n\n### Patch Changes\n\n- 797f663: fix: use a better email re pulled from zod closes #4585\n- Updated dependencies [72e4379]\n- Updated dependencies [a18c19f]\n- Updated dependencies [e2171f8]\n  - vee-validate@4.12.3\n\n## 4.12.2\n\n### Patch Changes\n\n- Updated dependencies [b2203c8e]\n- Updated dependencies [ec8a4d7e]\n  - vee-validate@4.12.2\n\n## 4.12.1\n\n### Patch Changes\n\n- Updated dependencies [36f6b9e6]\n- Updated dependencies [c1c6f399]\n  - vee-validate@4.12.1\n\n## 4.12.0\n\n### Patch Changes\n\n- e35c361c: fix: make length rule consistent with other rules closes #4522\n- Updated dependencies [f9a95843]\n- Updated dependencies [bbecc973]\n- Updated dependencies [f688896f]\n- Updated dependencies [2abb8966]\n- Updated dependencies [e370413b]\n- Updated dependencies [95b701f7]\n  - vee-validate@4.12.0\n\n## 4.11.8\n\n### Patch Changes\n\n- Updated dependencies [d1b5b855]\n- Updated dependencies [78c4668e]\n  - vee-validate@4.11.8\n\n## 4.11.7\n\n### Patch Changes\n\n- c6a1edc4: \"fix: removed default export in rules pkg closes #4470\"\n- Updated dependencies [a1414f6a]\n  - vee-validate@4.11.7\n\n## 4.11.6\n\n### Patch Changes\n\n- Updated dependencies [f683e909]\n  - vee-validate@4.11.6\n\n## 4.11.5\n\n### Patch Changes\n\n- Updated dependencies [27c9ef24]\n- Updated dependencies [804ec6fa]\n  - vee-validate@4.11.5\n\n## 4.11.4\n\n### Patch Changes\n\n- Updated dependencies [4d8ed7eb]\n- Updated dependencies [b53400e2]\n- Updated dependencies [8f680bf1]\n- Updated dependencies [5231f439]\n  - vee-validate@4.11.4\n\n## 4.11.3\n\n### Patch Changes\n\n- vee-validate@4.11.3\n\n## 4.11.2\n\n### Patch Changes\n\n- Updated dependencies [2ff045c1]\n- Updated dependencies [73219b40]\n- Updated dependencies [4947e88f]\n- Updated dependencies [ecbb690d]\n  - vee-validate@4.11.2\n\n## 4.11.1\n\n### Patch Changes\n\n- Updated dependencies [5e23dcb9]\n  - vee-validate@4.11.1\n\n## 4.11.0\n\n### Patch Changes\n\n- Updated dependencies [2d8143f9]\n  - vee-validate@4.11.0\n\n## 4.10.9\n\n### Patch Changes\n\n- Updated dependencies [c02337f3]\n  - vee-validate@4.10.9\n\n## 4.10.8\n\n### Patch Changes\n\n- Updated dependencies [a9a473b4]\n  - vee-validate@4.10.8\n\n## 4.10.7\n\n### Patch Changes\n\n- Updated dependencies [9290f5a9]\n- Updated dependencies [93f8001a]\n  - vee-validate@4.10.7\n\n## 4.10.6\n\n### Patch Changes\n\n- Updated dependencies [40ce7a91]\n- Updated dependencies [e9b215a7]\n- Updated dependencies [4e11ff95]\n- Updated dependencies [e354a13a]\n- Updated dependencies [68080d28]\n  - vee-validate@4.10.6\n\n## 4.10.5\n\n### Patch Changes\n\n- Updated dependencies [6a1dc9bd]\n  - vee-validate@4.10.5\n\n## 4.10.4\n\n### Patch Changes\n\n- Updated dependencies [2f9ca91c]\n  - vee-validate@4.10.4\n\n## 4.10.3\n\n### Patch Changes\n\n- Updated dependencies [32537e14]\n- Updated dependencies [c3698f07]\n  - vee-validate@4.10.3\n\n## 4.10.2\n\n### Patch Changes\n\n- Updated dependencies [1660048e]\n  - vee-validate@4.10.2\n\n## 4.10.1\n\n### Patch Changes\n\n- Updated dependencies [fc416918]\n- Updated dependencies [435e7857]\n- Updated dependencies [273cca74]\n  - vee-validate@4.10.1\n\n## 4.10.0\n\n### Patch Changes\n\n- Updated dependencies [77345c42]\n- Updated dependencies [7a548f42]\n- Updated dependencies [7ce9d671]\n- Updated dependencies [bfd6b00a]\n- Updated dependencies [f1dc1359]\n- Updated dependencies [d4fafc95]\n- Updated dependencies [3e4a7c13]\n- Updated dependencies [2cf0eec9]\n- Updated dependencies [05d957ec]\n- Updated dependencies [ed208918]\n- Updated dependencies [6a3f9f15]\n  - vee-validate@4.10.0\n\n## 4.9.6\n\n### Patch Changes\n\n- Updated dependencies [b138282a]\n- Updated dependencies [6e074f77]\n  - vee-validate@4.9.6\n\n## 4.9.5\n\n### Patch Changes\n\n- Updated dependencies [7356c102]\n  - vee-validate@4.9.5\n\n## 4.9.4\n\n### Patch Changes\n\n- Updated dependencies [f4ea2c05]\n  - vee-validate@4.9.4\n\n## 4.9.3\n\n### Patch Changes\n\n- Updated dependencies [09d5596b]\n- Updated dependencies [9bfbfaaf]\n- Updated dependencies [48b45d91]\n  - vee-validate@4.9.3\n\n## 4.9.2\n\n### Patch Changes\n\n- Updated dependencies [31090e0d]\n- Updated dependencies [9046308b]\n- Updated dependencies [fe322a07]\n  - vee-validate@4.9.2\n\n## 4.9.1\n\n### Patch Changes\n\n- Updated dependencies [681bbab4]\n  - vee-validate@4.9.1\n\n## 4.9.0\n\n### Patch Changes\n\n- f5b34823: handle mimes with plus signs\n- Updated dependencies [7554d4a6]\n- Updated dependencies [41b5d39b]\n- Updated dependencies [95409080]\n- Updated dependencies [298577b7]\n  - vee-validate@4.9.0\n\n## 4.8.6\n\n### Patch Changes\n\n- 6e0b0557: Introduced official nuxt module package\n- Updated dependencies [6e0b0557]\n  - vee-validate@4.8.6\n\n## 4.8.5\n\n### Patch Changes\n\n- 9048a238: fixed zod union issues not showing up as errors closes #4204\n- Updated dependencies [9048a238]\n  - vee-validate@4.8.5\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n## [4.8.4](https://github.com/logaretm/vee-validate/compare/v4.8.3...v4.8.4) (2023-03-24)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.8.3](https://github.com/logaretm/vee-validate/compare/v4.8.2...v4.8.3) (2023-03-15)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.8.2](https://github.com/logaretm/vee-validate/compare/v4.8.1...v4.8.2) (2023-03-14)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.8.1](https://github.com/logaretm/vee-validate/compare/v4.8.0...v4.8.1) (2023-03-12)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.8.0](https://github.com/logaretm/vee-validate/compare/v4.7.4...v4.8.0) (2023-03-12)\n\n### Bug Fixes\n\n- remove dead code closes [#4145](https://github.com/logaretm/vee-validate/issues/4145) closes [#4143](https://github.com/logaretm/vee-validate/issues/4143) ([04338f5](https://github.com/logaretm/vee-validate/commit/04338f53336ddc053c88b00c1ec6b1fe6935374d))\n- remove extra double negation from between rule closes [#4144](https://github.com/logaretm/vee-validate/issues/4144) ([192d23f](https://github.com/logaretm/vee-validate/commit/192d23fb07de2c2d9872961e6f242e105a6bb8ea))\n\n### Features\n\n- Better Yup and Zod typing with output types and input inference ([#4064](https://github.com/logaretm/vee-validate/issues/4064)) ([3820a5b](https://github.com/logaretm/vee-validate/commit/3820a5b8eb3f8c6cd9239057746ccfb4b2e57e76))\n\n## [4.7.4](https://github.com/logaretm/vee-validate/compare/v4.7.3...v4.7.4) (2023-02-07)\n\n### Bug Fixes\n\n- ext rule regex has wildcard when it should be literal period ([#4045](https://github.com/logaretm/vee-validate/issues/4045)) ([5265af5](https://github.com/logaretm/vee-validate/commit/5265af5c75b7809ebd73b22d4c8319a8a146da5a))\n\n## [4.7.3](https://github.com/logaretm/vee-validate/compare/v4.7.2...v4.7.3) (2022-11-13)\n\n### Bug Fixes\n\n- rename old excluded with not_one_of closes [#3993](https://github.com/logaretm/vee-validate/issues/3993) ([7fc5077](https://github.com/logaretm/vee-validate/commit/7fc50773275c9c65cdbb0735d0b14dfe7ffca227))\n\n## [4.7.2](https://github.com/logaretm/vee-validate/compare/v4.7.1...v4.7.2) (2022-11-02)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.7.1](https://github.com/logaretm/vee-validate/compare/v4.7.0...v4.7.1) (2022-10-23)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.7.0](https://github.com/logaretm/vee-validate/compare/v4.6.10...v4.7.0) (2022-10-09)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.10](https://github.com/logaretm/vee-validate/compare/v4.6.9...v4.6.10) (2022-09-30)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.9](https://github.com/logaretm/vee-validate/compare/v4.6.8...v4.6.9) (2022-09-19)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.8](https://github.com/logaretm/vee-validate/compare/v4.6.7...v4.6.8) (2022-09-19)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.7](https://github.com/logaretm/vee-validate/compare/v4.6.6...v4.6.7) (2022-08-27)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.6](https://github.com/logaretm/vee-validate/compare/v4.6.5...v4.6.6) (2022-08-16)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.5](https://github.com/logaretm/vee-validate/compare/v4.6.4...v4.6.5) (2022-08-11)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.4](https://github.com/logaretm/vee-validate/compare/v4.6.3...v4.6.4) (2022-08-07)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.3](https://github.com/logaretm/vee-validate/compare/v4.6.2...v4.6.3) (2022-08-07)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.2](https://github.com/logaretm/vee-validate/compare/v4.6.1...v4.6.2) (2022-07-17)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.6.1](https://github.com/logaretm/vee-validate/compare/v4.6.0...v4.6.1) (2022-07-12)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.6.0](https://github.com/logaretm/vee-validate/compare/v4.5.11...v4.6.0) (2022-07-11)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.11](https://github.com/logaretm/vee-validate/compare/v4.5.10...v4.5.11) (2022-04-10)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.10](https://github.com/logaretm/vee-validate/compare/v4.5.9...v4.5.10) (2022-03-08)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.9](https://github.com/logaretm/vee-validate/compare/v4.5.8...v4.5.9) (2022-02-22)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.8](https://github.com/logaretm/vee-validate/compare/v4.5.7...v4.5.8) (2022-01-23)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.7](https://github.com/logaretm/vee-validate/compare/v4.5.6...v4.5.7) (2021-12-07)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.6](https://github.com/logaretm/vee-validate/compare/v4.5.5...v4.5.6) (2021-11-17)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.5](https://github.com/logaretm/vee-validate/compare/v4.5.4...v4.5.5) (2021-11-01)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.4](https://github.com/logaretm/vee-validate/compare/v4.5.3...v4.5.4) (2021-10-20)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.3](https://github.com/logaretm/vee-validate/compare/v4.5.2...v4.5.3) (2021-10-17)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.2](https://github.com/logaretm/vee-validate/compare/v4.5.1...v4.5.2) (2021-09-30)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.5.1](https://github.com/logaretm/vee-validate/compare/v4.5.0...v4.5.1) (2021-09-29)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.5.0](https://github.com/logaretm/vee-validate/compare/v4.4.11...v4.5.0) (2021-09-26)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.4.11](https://github.com/logaretm/vee-validate/compare/v4.4.10...v4.4.11) (2021-09-11)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.4.10](https://github.com/logaretm/vee-validate/compare/v4.4.9...v4.4.10) (2021-08-31)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.4.9](https://github.com/logaretm/vee-validate/compare/v4.4.8...v4.4.9) (2021-08-05)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.4.8](https://github.com/logaretm/vee-validate/compare/v4.4.7...v4.4.8) (2021-07-31)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.4.7](https://github.com/logaretm/vee-validate/compare/v4.4.6...v4.4.7) (2021-07-20)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.4.6](https://github.com/logaretm/vee-validate/compare/v4.4.5...v4.4.6) (2021-07-08)\n\n## [4.4.5](https://github.com/logaretm/vee-validate/compare/v4.4.4...v4.4.5) (2021-06-13)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.4.4](https://github.com/logaretm/vee-validate/compare/v4.4.3...v4.4.4) (2021-06-05)\n\n## [4.4.3](https://github.com/logaretm/vee-validate/compare/v4.4.2...v4.4.3) (2021-06-02)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.4.2](https://github.com/logaretm/vee-validate/compare/v4.4.1...v4.4.2) (2021-05-28)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.4.1](https://github.com/logaretm/vee-validate/compare/v4.4.0...v4.4.1) (2021-05-24)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.4.0](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.2...v4.4.0) (2021-05-23)\n\n### Bug Fixes\n\n- export the URL rule closes [#3310](https://github.com/logaretm/vee-validate/issues/3310) ([50b6b64](https://github.com/logaretm/vee-validate/commit/50b6b64bf0b2b9a905946ed0ef7b8252501b0ccb))\n\n# [4.4.0-alpha.2](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.1...v4.4.0-alpha.2) (2021-05-14)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.4.0-alpha.1](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.0...v4.4.0-alpha.1) (2021-05-14)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.4.0-alpha.0](https://github.com/logaretm/vee-validate/compare/v4.3.6...v4.4.0-alpha.0) (2021-05-14)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.3.6](https://github.com/logaretm/vee-validate/compare/v4.3.5...v4.3.6) (2021-05-08)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.3.5](https://github.com/logaretm/vee-validate/compare/v4.3.4...v4.3.5) (2021-05-01)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.3.4](https://github.com/logaretm/vee-validate/compare/v4.3.3...v4.3.4) (2021-04-27)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.3.3](https://github.com/logaretm/vee-validate/compare/v4.3.2...v4.3.3) (2021-04-22)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.3.2](https://github.com/logaretm/vee-validate/compare/v4.3.1...v4.3.2) (2021-04-21)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.3.1](https://github.com/logaretm/vee-validate/compare/v4.3.0...v4.3.1) (2021-04-18)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.3.0](https://github.com/logaretm/vee-validate/compare/v4.2.4...v4.3.0) (2021-04-07)\n\n### Features\n\n- **rules:** add url validator ([#3253](https://github.com/logaretm/vee-validate/issues/3253)) ([1fad5bb](https://github.com/logaretm/vee-validate/commit/1fad5bb5e0f3264386bc8e40beeb4cdae2a832cb))\n\n## [4.2.4](https://github.com/logaretm/vee-validate/compare/v4.2.3...v4.2.4) (2021-03-26)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.2.3](https://github.com/logaretm/vee-validate/compare/v4.2.2...v4.2.3) (2021-03-22)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.2.2](https://github.com/logaretm/vee-validate/compare/v4.2.1...v4.2.2) (2021-03-03)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.2.1](https://github.com/logaretm/vee-validate/compare/v4.2.0...v4.2.1) (2021-02-26)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.2.0](https://github.com/logaretm/vee-validate/compare/v4.1.20...v4.2.0) (2021-02-24)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.1.20](https://github.com/logaretm/vee-validate/compare/v4.1.19...v4.1.20) (2021-02-24)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.1.19](https://github.com/logaretm/vee-validate/compare/v4.1.18...v4.1.19) (2021-02-16)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.1.17](https://github.com/logaretm/vee-validate/compare/v3.2.0...v4.1.17) (2021-02-08)\n\n### Bug Fixes\n\n- cast digits param to number when in string format closes [#3067](https://github.com/logaretm/vee-validate/issues/3067) ([e7eb242](https://github.com/logaretm/vee-validate/commit/e7eb242a0ee9effa217133a3321e877b11cec652))\n- digits rule bug ([8662307](https://github.com/logaretm/vee-validate/commit/8662307a5d86af475e304b745cc87ee16cd27d2f))\n- handle empty files in files rules ([8e2f3d4](https://github.com/logaretm/vee-validate/commit/8e2f3d41fb6ff7cf6e9db593c8a5168fe53afada))\n\n### Features\n\n- added yup adapter pkg ([1847605](https://github.com/logaretm/vee-validate/commit/18476056fdeec7425d850313ee38b12de5ffd6c7))\n- remove deprecated isTarget option ([0a7dd9c](https://github.com/logaretm/vee-validate/commit/0a7dd9cdf2cf197d84ce429c470e7b3e6e3468bd))\n\n## [4.0.6](https://github.com/logaretm/vee-validate/compare/@vee-validate/rules@4.0.5...@vee-validate/rules@4.0.6) (2021-02-07)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.0.5](https://github.com/logaretm/vee-validate/compare/@vee-validate/rules@4.0.4...@vee-validate/rules@4.0.5) (2021-01-11)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.0.4](https://github.com/logaretm/vee-validate/compare/@vee-validate/rules@4.0.3...@vee-validate/rules@4.0.4) (2020-12-20)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.0.3](https://github.com/logaretm/vee-validate/compare/@vee-validate/rules@4.0.2...@vee-validate/rules@4.0.3) (2020-12-07)\n\n### Bug Fixes\n\n- cast digits param to number when in string format closes [#3067](https://github.com/logaretm/vee-validate/issues/3067) ([e7eb242](https://github.com/logaretm/vee-validate/commit/e7eb242a0ee9effa217133a3321e877b11cec652))\n\n## [4.0.2](https://github.com/logaretm/vee-validate/compare/@vee-validate/rules@4.0.1...@vee-validate/rules@4.0.2) (2020-12-05)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n## [4.0.1](https://github.com/logaretm/vee-validate/compare/@vee-validate/rules@4.0.0...@vee-validate/rules@4.0.1) (2020-11-25)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.0.0](https://github.com/logaretm/vee-validate/compare/@vee-validate/rules@4.0.0-beta.0...@vee-validate/rules@4.0.0) (2020-11-16)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# [4.0.0-beta.0](https://github.com/logaretm/vee-validate/compare/@vee-validate/rules@4.0.0-alpha.2...@vee-validate/rules@4.0.0-beta.0) (2020-10-01)\n\n### Bug Fixes\n\n- handle empty files in files rules ([8e2f3d4](https://github.com/logaretm/vee-validate/commit/8e2f3d41fb6ff7cf6e9db593c8a5168fe53afada))\n\n# [4.0.0-alpha.2](https://github.com/logaretm/vee-validate/compare/@vee-validate/rules@4.0.0-alpha.1...@vee-validate/rules@4.0.0-alpha.2) (2020-07-27)\n\n**Note:** Version bump only for package @vee-validate/rules\n\n# 4.0.0-alpha.1 (2020-07-18)\n\n### Bug Fixes\n\n- digits rule bug ([8662307](https://github.com/logaretm/vee-validate/commit/8662307a5d86af475e304b745cc87ee16cd27d2f))\n\n### Features\n\n- added yup adapter pkg ([1847605](https://github.com/logaretm/vee-validate/commit/18476056fdeec7425d850313ee38b12de5ffd6c7))\n- remove deprecated isTarget option ([0a7dd9c](https://github.com/logaretm/vee-validate/commit/0a7dd9cdf2cf197d84ce429c470e7b3e6e3468bd))\n"
  },
  {
    "path": "packages/rules/README.md",
    "content": "# @vee-validate/rules\r\n\r\n<p align=\"center\">\r\n  <a href=\"https://vee-validate.logaretm.com/v5/guide/global-validators\" target=\"_blank\">\r\n    <img width=\"150\" src=\"https://github.com/logaretm/vee-validate/blob/main/logo.png\">\r\n  </a>\r\n</p>\r\n\r\n> Common Laravel-Like rules module for vee-validate\r\n\r\n<p align=\"center\">\r\n  <a href=\"https://github.com/sponsors/logaretm\">\r\n    <img src='https://sponsors.logaretm.com/sponsors.svg'>\r\n  </a>\r\n</p>\r\n\r\n## What's this\r\n\r\nVeeValidate v4 breaks up the parts that made it a popular solution for form validation into it isolated parts. The core `vee-validate` package no longer includes the rules that came by default in previous releases, the built-in rules were rebranded as **global validators**,\r\n\r\nThis is where this package comes in, It includes the most common validators you will use in most of your applications, vee-validate allows you to express global rules just like Laravel's validation syntax.\r\n\r\n## Installation\r\n\r\n```sh\r\nyarn add @vee-validate/rules\r\n\r\n# or with npm\r\nnpm install @vee-validate/rules\r\n```\r\n\r\n## Usage\r\n\r\nUse the `defineRule` function from `vee-validate` core library to add rules exported by this library:\r\n\r\n```js\r\nimport { defineRule } from 'vee-validate';\r\nimport { required, email, min } from '@vee-validate/rules';\r\n\r\ndefineRule('required', required);\r\ndefineRule('email', email);\r\ndefineRule('min', min);\r\n```\r\n\r\nOr you can globally define all the available rules in the `@vee-validate/rules` package:\r\n\r\n```js\r\nimport { defineRule } from 'vee-validate';\r\nimport * as rules from '@vee-validate/rules';\r\n\r\nObject.keys(rules).forEach(rule => {\r\n  defineRule(rule, rules[rule]);\r\n});\r\n```\r\n\r\n### Available Rules\r\n\r\n- alpha\r\n- alpha_dash\r\n- alpha_num\r\n- alpha_spaces\r\n- between\r\n- confirmed\r\n- digits\r\n- dimensions\r\n- email\r\n- excluded\r\n- ext\r\n- image\r\n- one_of\r\n- integer\r\n- is\r\n- is_not\r\n- length\r\n- max\r\n- max_value\r\n- mimes\r\n- min\r\n- min_value\r\n- numeric\r\n- regex\r\n- required\r\n- required_if\r\n- size\r\n\r\nFor more information about each rules, check the [documentation for global validators](https://vee-validate.logaretm.com/v5/guide/global-validators)\r\n\r\n## Credits\r\n\r\n- Inspired by Laravel's [validation syntax](https://laravel.com/docs/5.4/validation)\r\n"
  },
  {
    "path": "packages/rules/package.json",
    "content": "{\n  \"name\": \"@vee-validate/rules\",\n  \"version\": \"5.0.0-beta.1\",\n  \"description\": \"Form Validation for Vue.js\",\n  \"author\": \"Abdelrahman Awad <logaretm1@gmail.com>\",\n  \"license\": \"MIT\",\n  \"module\": \"dist/vee-validate-rules.mjs\",\n  \"unpkg\": \"dist/vee-validate-rules.iife.js\",\n  \"main\": \"dist/vee-validate-rules.mjs\",\n  \"types\": \"dist/vee-validate-rules.d.ts\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/vee-validate-rules.d.ts\",\n      \"import\": \"./dist/vee-validate-rules.mjs\",\n      \"require\": \"./dist/vee-validate-rules.cjs\"\n    }\n  },\n  \"homepage\": \"https://vee-validate.logaretm.com/v5/guide/global-validators\",\n  \"repository\": {\n    \"url\": \"https://github.com/logaretm/vee-validate.git\",\n    \"type\": \"git\",\n    \"directory\": \"packages/rules\"\n  },\n  \"sideEffects\": false,\n  \"keywords\": [\n    \"VueJS\",\n    \"Vue\",\n    \"validation\",\n    \"validator\",\n    \"inputs\",\n    \"form\"\n  ],\n  \"files\": [\n    \"dist/*.js\",\n    \"dist/*.d.ts\",\n    \"dist/*.cjs\",\n    \"dist/*.mjs\"\n  ],\n  \"dependencies\": {\n    \"@standard-schema/spec\": \"^1.0.0\",\n    \"vee-validate\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "packages/rules/src/alpha.ts",
    "content": "import { alpha, getLocale } from './alpha_helper';\nimport { isEmpty } from './utils';\n\nconst alphaValidator = (value: unknown, params: [string | undefined] | { locale?: string }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const locale = getLocale(params);\n  if (Array.isArray(value)) {\n    return value.every(val => alphaValidator(val, { locale }));\n  }\n\n  const valueAsString = String(value);\n  // Match at least one locale.\n  if (!locale) {\n    return Object.keys(alpha).some(loc => alpha[loc].test(valueAsString));\n  }\n\n  return (alpha[locale] || alpha.en).test(valueAsString);\n};\n\nexport default alphaValidator;\n"
  },
  {
    "path": "packages/rules/src/alpha_dash.ts",
    "content": "import { alphaDash, getLocale } from './alpha_helper';\nimport { isEmpty } from './utils';\n\nconst alphaDashValidator = (value: unknown, params: [string | undefined] | { locale?: string }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const locale = getLocale(params);\n  if (Array.isArray(value)) {\n    return value.every(val => alphaDashValidator(val, { locale }));\n  }\n\n  const valueAsString = String(value);\n  // Match at least one locale.\n  if (!locale) {\n    return Object.keys(alphaDash).some(loc => alphaDash[loc].test(valueAsString));\n  }\n\n  return (alphaDash[locale] || alphaDash.en).test(valueAsString);\n};\n\nexport default alphaDashValidator;\n"
  },
  {
    "path": "packages/rules/src/alpha_helper.ts",
    "content": "/* eslint-disable no-misleading-character-class */\n/**\n * Some Alpha Regex helpers.\n * https://github.com/chriso/validator.js/blob/master/src/lib/alpha.js\n */\n\nexport const alpha: { [k: string]: RegExp } = {\n  en: /^[A-Z]*$/i,\n  cs: /^[A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]*$/i,\n  da: /^[A-ZÆØÅ]*$/i,\n  de: /^[A-ZÄÖÜß]*$/i,\n  es: /^[A-ZÁÉÍÑÓÚÜ]*$/i,\n  fr: /^[A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]*$/i,\n  it: /^[A-Z\\xC0-\\xFF]*$/i,\n  lt: /^[A-ZĄČĘĖĮŠŲŪŽ]*$/i,\n  nl: /^[A-ZÉËÏÓÖÜ]*$/i,\n  hu: /^[A-ZÁÉÍÓÖŐÚÜŰ]*$/i,\n  pl: /^[A-ZĄĆĘŚŁŃÓŻŹ]*$/i,\n  pt: /^[A-ZÃÁÀÂÇÉÊÍÕÓÔÚÜ]*$/i,\n  ru: /^[А-ЯЁ]*$/i,\n  kz: /^[А-ЯЁ\\u04D8\\u04B0\\u0406\\u04A2\\u0492\\u04AE\\u049A\\u04E8\\u04BA]*$/i,\n  sk: /^[A-ZÁÄČĎÉÍĹĽŇÓŔŠŤÚÝŽ]*$/i,\n  sr: /^[A-ZČĆŽŠĐ]*$/i,\n  sv: /^[A-ZÅÄÖ]*$/i,\n  tr: /^[A-ZÇĞİıÖŞÜ]*$/i,\n  uk: /^[А-ЩЬЮЯЄІЇҐ]*$/i,\n  ar: /^[ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]*$/,\n  az: /^[A-ZÇƏĞİıÖŞÜ]*$/i,\n  ug: /^[A-Zچۋېرتيۇڭوپھسداەىقكلزشغۈبنمژفگخجۆئ]*$/i,\n};\n\nexport const alphaSpaces: { [k: string]: RegExp } = {\n  en: /^[A-Z\\s]*$/i,\n  cs: /^[A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ\\s]*$/i,\n  da: /^[A-ZÆØÅ\\s]*$/i,\n  de: /^[A-ZÄÖÜß\\s]*$/i,\n  es: /^[A-ZÁÉÍÑÓÚÜ\\s]*$/i,\n  fr: /^[A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ\\s]*$/i,\n  it: /^[A-Z\\xC0-\\xFF\\s]*$/i,\n  lt: /^[A-ZĄČĘĖĮŠŲŪŽ\\s]*$/i,\n  nl: /^[A-ZÉËÏÓÖÜ\\s]*$/i,\n  hu: /^[A-ZÁÉÍÓÖŐÚÜŰ\\s]*$/i,\n  pl: /^[A-ZĄĆĘŚŁŃÓŻŹ\\s]*$/i,\n  pt: /^[A-ZÃÁÀÂÇÉÊÍÕÓÔÚÜ\\s]*$/i,\n  ru: /^[А-ЯЁ\\s]*$/i,\n  kz: /^[А-ЯЁ\\u04D8\\u04B0\\u0406\\u04A2\\u0492\\u04AE\\u049A\\u04E8\\u04BA\\s]*$/i,\n  sk: /^[A-ZÁÄČĎÉÍĹĽŇÓŔŠŤÚÝŽ\\s]*$/i,\n  sr: /^[A-ZČĆŽŠĐ\\s]*$/i,\n  sv: /^[A-ZÅÄÖ\\s]*$/i,\n  tr: /^[A-ZÇĞİıÖŞÜ\\s]*$/i,\n  uk: /^[А-ЩЬЮЯЄІЇҐ\\s]*$/i,\n  ar: /^[ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ\\s]*$/,\n  az: /^[A-ZÇƏĞİıÖŞÜ\\s]*$/i,\n  ug: /^[A-Zچۋېرتيۇڭوپھسداەىقكلزشغۈبنمژفگخجۆئ\\s]*$/i,\n};\n\nexport const alphanumeric: { [k: string]: RegExp } = {\n  en: /^[0-9A-Z]*$/i,\n  cs: /^[0-9A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]*$/i,\n  da: /^[0-9A-ZÆØÅ]$/i,\n  de: /^[0-9A-ZÄÖÜß]*$/i,\n  es: /^[0-9A-ZÁÉÍÑÓÚÜ]*$/i,\n  fr: /^[0-9A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]*$/i,\n  it: /^[0-9A-Z\\xC0-\\xFF]*$/i,\n  lt: /^[0-9A-ZĄČĘĖĮŠŲŪŽ]*$/i,\n  hu: /^[0-9A-ZÁÉÍÓÖŐÚÜŰ]*$/i,\n  nl: /^[0-9A-ZÉËÏÓÖÜ]*$/i,\n  pl: /^[0-9A-ZĄĆĘŚŁŃÓŻŹ]*$/i,\n  pt: /^[0-9A-ZÃÁÀÂÇÉÊÍÕÓÔÚÜ]*$/i,\n  ru: /^[0-9А-ЯЁ]*$/i,\n  kz: /^[0-9А-ЯЁ\\u04D8\\u04B0\\u0406\\u04A2\\u0492\\u04AE\\u049A\\u04E8\\u04BA]*$/i,\n  sk: /^[0-9A-ZÁÄČĎÉÍĹĽŇÓŔŠŤÚÝŽ]*$/i,\n  sr: /^[0-9A-ZČĆŽŠĐ]*$/i,\n  sv: /^[0-9A-ZÅÄÖ]*$/i,\n  tr: /^[0-9A-ZÇĞİıÖŞÜ]*$/i,\n  uk: /^[0-9А-ЩЬЮЯЄІЇҐ]*$/i,\n  ar: /^[٠١٢٣٤٥٦٧٨٩0-9ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]*$/,\n  az: /^[0-9A-ZÇƏĞİıÖŞÜ]*$/i,\n  ug: /^[0-9A-Zچۋېرتيۇڭوپھسداەىقكلزشغۈبنمژفگخجۆئ]*$/i,\n};\n\nexport const alphaDash: { [k: string]: RegExp } = {\n  en: /^[0-9A-Z_-]*$/i,\n  cs: /^[0-9A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ_-]*$/i,\n  da: /^[0-9A-ZÆØÅ_-]*$/i,\n  de: /^[0-9A-ZÄÖÜß_-]*$/i,\n  es: /^[0-9A-ZÁÉÍÑÓÚÜ_-]*$/i,\n  fr: /^[0-9A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ_-]*$/i,\n  it: /^[0-9A-Z\\xC0-\\xFF_-]*$/i,\n  lt: /^[0-9A-ZĄČĘĖĮŠŲŪŽ_-]*$/i,\n  nl: /^[0-9A-ZÉËÏÓÖÜ_-]*$/i,\n  hu: /^[0-9A-ZÁÉÍÓÖŐÚÜŰ_-]*$/i,\n  pl: /^[0-9A-ZĄĆĘŚŁŃÓŻŹ_-]*$/i,\n  pt: /^[0-9A-ZÃÁÀÂÇÉÊÍÕÓÔÚÜ_-]*$/i,\n  ru: /^[0-9А-ЯЁ_-]*$/i,\n  kz: /^[0-9А-ЯЁ\\u04D8\\u04B0\\u0406\\u04A2\\u0492\\u04AE\\u049A\\u04E8\\u04BA_-]*$/i,\n  sk: /^[0-9A-ZÁÄČĎÉÍĹĽŇÓŔŠŤÚÝŽ_-]*$/i,\n  sr: /^[0-9A-ZČĆŽŠĐ_-]*$/i,\n  sv: /^[0-9A-ZÅÄÖ_-]*$/i,\n  tr: /^[0-9A-ZÇĞİıÖŞÜ_-]*$/i,\n  uk: /^[0-9А-ЩЬЮЯЄІЇҐ_-]*$/i,\n  ar: /^[٠١٢٣٤٥٦٧٨٩0-9ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ_-]*$/,\n  az: /^[0-9A-ZÇƏĞİıÖŞÜ_-]*$/i,\n  ug: /^[0-9A-Zچۋېرتيۇڭوپھسداەىقكلزشغۈبنمژفگخجۆئ_-]*$/i,\n};\n\nexport const getLocale = (params?: { locale?: string } | [string | undefined]) => {\n  if (!params) {\n    return undefined;\n  }\n\n  return Array.isArray(params) ? params[0] : params.locale;\n};\n"
  },
  {
    "path": "packages/rules/src/alpha_num.ts",
    "content": "import { alphanumeric, getLocale } from './alpha_helper';\nimport { isEmpty } from './utils';\n\nconst alphaNumValidator = (value: unknown, params: [string | undefined] | { locale?: string }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const locale = getLocale(params);\n  if (Array.isArray(value)) {\n    return value.every(val => alphaNumValidator(val, { locale }));\n  }\n\n  const valueAsString = String(value);\n  // Match at least one locale.\n  if (!locale) {\n    return Object.keys(alphanumeric).some(loc => alphanumeric[loc].test(valueAsString));\n  }\n\n  return (alphanumeric[locale] || alphanumeric.en).test(valueAsString);\n};\n\nexport default alphaNumValidator;\n"
  },
  {
    "path": "packages/rules/src/alpha_spaces.ts",
    "content": "import { alphaSpaces, getLocale } from './alpha_helper';\nimport { isEmpty } from './utils';\n\nconst alphaSpacesValidator = (value: unknown, params: [string | undefined] | { locale?: string }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const locale = getLocale(params);\n  if (Array.isArray(value)) {\n    return value.every(val => alphaSpacesValidator(val, { locale }));\n  }\n\n  const valueAsString = String(value);\n\n  // Match at least one locale.\n  if (!locale) {\n    return Object.keys(alphaSpaces).some(loc => alphaSpaces[loc].test(valueAsString));\n  }\n\n  return (alphaSpaces[locale] || alphaSpaces.en).test(valueAsString);\n};\n\nexport default alphaSpacesValidator;\n"
  },
  {
    "path": "packages/rules/src/between.ts",
    "content": "import { SimpleValidationRuleFunction } from '../../shared';\nimport { isEmpty } from './utils';\n\ntype BetweenParams = [string | number, string | number] | { min: number | string; max: number | string };\n\nfunction getParams(params: BetweenParams) {\n  if (Array.isArray(params)) {\n    return { min: params[0], max: params[1] };\n  }\n\n  return params;\n}\n\nconst betweenValidator: SimpleValidationRuleFunction<unknown, BetweenParams> = (value, params): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const { min, max } = getParams(params);\n  if (Array.isArray(value)) {\n    return value.every(val => betweenValidator(val, { min, max }));\n  }\n\n  const valueAsNumber = Number(value);\n  return Number(min) <= valueAsNumber && Number(max) >= valueAsNumber;\n};\n\nexport default betweenValidator;\n"
  },
  {
    "path": "packages/rules/src/confirmed.ts",
    "content": "import { getSingleParam } from './utils';\n\nconst confirmedValidator = (value: unknown, params: [string] | { target: string }) => {\n  const target = getSingleParam(params, 'target');\n\n  return String(value) === String(target);\n};\n\nexport default confirmedValidator;\n"
  },
  {
    "path": "packages/rules/src/digits.ts",
    "content": "import { getSingleParam, isEmpty } from './utils';\n\nconst digitsValidator = (value: unknown, params: [string | number] | { length: string | number }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n  const length = getSingleParam(params, 'length');\n  if (Array.isArray(value)) {\n    return value.every(val => digitsValidator(val, { length }));\n  }\n  const strVal = String(value);\n\n  return /^[0-9]*$/.test(strVal) && strVal.length === Number(length);\n};\n\nexport default digitsValidator;\n"
  },
  {
    "path": "packages/rules/src/dimensions.ts",
    "content": "import { isEmpty } from './utils';\n\nconst validateImage = (file: File, width: number, height: number): Promise<boolean> => {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  const URL = window.URL || (window as any).webkitURL;\n\n  return new Promise(resolve => {\n    const image = new Image();\n    image.onerror = () => resolve(false);\n    image.onload = () => resolve(image.width === width && image.height === height);\n\n    image.src = URL.createObjectURL(file);\n  });\n};\n\ntype Params = [number | string, number | string] | { width: string | number; height: string | number };\n\nfunction getParams(params: Params) {\n  if (!params) {\n    return { width: 0, height: 0 };\n  }\n\n  if (Array.isArray(params)) {\n    return { width: Number(params[0]), height: Number(params[1]) };\n  }\n\n  return {\n    width: Number(params.width),\n    height: Number(params.height),\n  };\n}\n\nconst dimensionsValidator = (files: unknown, params: Params) => {\n  if (isEmpty(files)) {\n    return true;\n  }\n\n  const { width, height } = getParams(params);\n  const list = [];\n  const fileList = Array.isArray(files) ? files : [files];\n  for (let i = 0; i < fileList.length; i++) {\n    // if file is not an image, reject.\n    if (!/\\.(jpg|svg|jpeg|png|bmp|gif)$/i.test(fileList[i].name)) {\n      return Promise.resolve(false);\n    }\n\n    list.push(fileList[i]);\n  }\n\n  return Promise.all(list.map(file => validateImage(file, width, height))).then(values => {\n    return values.every(v => v);\n  });\n};\n\nexport default dimensionsValidator;\n"
  },
  {
    "path": "packages/rules/src/email.ts",
    "content": "/* eslint-disable no-useless-escape */\nimport { isEmpty } from './utils';\n\n// https://github.com/colinhacks/zod/blob/40e72f9eaf576985f876d1afc2dbc22f73abc1ba/src/types.ts#L595\nconst emailRE = /^(?!\\.)(?!.*\\.\\.)([A-Z0-9_'+\\-\\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\\-]*\\.)+[A-Z]{2,}$/i;\n\nconst emailValidator = (value: unknown) => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  if (Array.isArray(value)) {\n    return value.every(val => emailRE.test(String(val)));\n  }\n\n  return emailRE.test(String(value));\n};\n\nexport default emailValidator;\n"
  },
  {
    "path": "packages/rules/src/ext.ts",
    "content": "import { isEmpty } from './utils';\n\nconst extValidator = (files: unknown, extensions: string[]) => {\n  if (isEmpty(files)) {\n    return true;\n  }\n\n  const regex = new RegExp(`\\\\.(${extensions.join('|')})$`, 'i');\n  if (Array.isArray(files)) {\n    return files.every(file => regex.test((file as File).name));\n  }\n\n  return regex.test((files as File).name);\n};\n\nexport default extValidator;\n"
  },
  {
    "path": "packages/rules/src/image.ts",
    "content": "import { isEmpty } from './utils';\n\nconst imageValidator = (files: unknown) => {\n  if (isEmpty(files)) {\n    return true;\n  }\n\n  const regex = /\\.(jpg|svg|jpeg|png|bmp|gif|webp)$/i;\n  if (Array.isArray(files)) {\n    return files.every(file => regex.test((file as File).name));\n  }\n\n  return regex.test((files as File).name);\n};\n\nexport default imageValidator;\n"
  },
  {
    "path": "packages/rules/src/index.ts",
    "content": "import alpha from './alpha';\nimport alpha_dash from './alpha_dash';\nimport alpha_num from './alpha_num';\nimport alpha_spaces from './alpha_spaces';\nimport between from './between';\nimport confirmed from './confirmed';\nimport digits from './digits';\nimport dimensions from './dimensions';\nimport email from './email';\nimport ext from './ext';\nimport image from './image';\nimport integer from './integer';\nimport is from './is';\nimport is_not from './is_not';\nimport length from './length';\nimport max from './max';\nimport max_value from './max_value';\nimport mimes from './mimes';\nimport min from './min';\nimport min_value from './min_value';\nimport not_one_of from './not_one_of';\nimport numeric from './numeric';\nimport one_of from './one_of';\nimport regex from './regex';\nimport required from './required';\nimport size from './size';\nimport url from './url';\nimport { toTypedSchema } from './toTypedSchema';\nimport { SimpleValidationRuleFunction } from '../../shared/types';\n\nexport const all: Record<string, SimpleValidationRuleFunction<any, any>> = {\n  alpha_dash,\n  alpha_num,\n  alpha_spaces,\n  alpha,\n  between,\n  confirmed,\n  digits,\n  dimensions,\n  email,\n  ext,\n  image,\n  integer,\n  is_not,\n  is,\n  length,\n  max_value,\n  max,\n  mimes,\n  min_value,\n  min,\n  not_one_of,\n  numeric,\n  one_of,\n  regex,\n  required,\n  size,\n  url,\n};\n\nexport {\n  alpha_dash,\n  alpha_num,\n  alpha_spaces,\n  alpha,\n  between,\n  confirmed,\n  digits,\n  dimensions,\n  email,\n  ext,\n  image,\n  integer,\n  is_not,\n  is,\n  length,\n  max_value,\n  max,\n  mimes,\n  min_value,\n  min,\n  not_one_of,\n  numeric,\n  one_of,\n  regex,\n  required,\n  size,\n  url,\n  toTypedSchema,\n};\n"
  },
  {
    "path": "packages/rules/src/integer.ts",
    "content": "import { isEmpty } from './utils';\n\nconst integerValidator = (value: unknown) => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  if (Array.isArray(value)) {\n    return value.every(val => /^-?[0-9]+$/.test(String(val)));\n  }\n\n  return /^-?[0-9]+$/.test(String(value));\n};\n\nexport default integerValidator;\n"
  },
  {
    "path": "packages/rules/src/is.ts",
    "content": "import { getSingleParam } from './utils';\n\nconst isValidator = (value: unknown, params: [unknown] | { other: unknown }) => {\n  const other = getSingleParam(params, 'other');\n\n  return value === other;\n};\n\nexport default isValidator;\n"
  },
  {
    "path": "packages/rules/src/is_not.ts",
    "content": "import { getSingleParam } from './utils';\n\nconst isNotValidator = (value: unknown, params: [unknown] | { other: unknown }) => {\n  const other = getSingleParam(params, 'other');\n\n  return value !== other;\n};\n\nexport default isNotValidator;\n"
  },
  {
    "path": "packages/rules/src/length.ts",
    "content": "import { getSingleParam, isEmpty } from './utils';\n\nconst lengthValidator = (value: unknown, params: [number | string] | { length: string | number }) => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  // Normalize the length value\n  const length = getSingleParam(params, 'length');\n\n  if (typeof value === 'number') {\n    value = String(value);\n  }\n\n  if (!(value as ArrayLike<unknown>).length) {\n    value = Array.from(value as ArrayLike<unknown>);\n  }\n\n  return (value as ArrayLike<unknown>).length === Number(length);\n};\n\nexport default lengthValidator;\n"
  },
  {
    "path": "packages/rules/src/max.ts",
    "content": "import { getSingleParam, isEmpty } from './utils';\n\nconst maxLengthValidator = (value: unknown, params: [string | number] | { length: string | number }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const length = getSingleParam(params, 'length');\n  if (Array.isArray(value)) {\n    return value.every(val => maxLengthValidator(val, { length }));\n  }\n\n  return [...String(value)].length <= Number(length);\n};\n\nexport default maxLengthValidator;\n"
  },
  {
    "path": "packages/rules/src/max_value.ts",
    "content": "import { getSingleParam, isEmpty } from './utils';\n\nconst maxValueValidator = (value: unknown, params: [string | number] | { max: string | number }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const max = getSingleParam(params, 'max');\n  if (Array.isArray(value)) {\n    return value.length > 0 && value.every(val => maxValueValidator(val, { max }));\n  }\n\n  return Number(value) <= Number(max);\n};\n\nexport default maxValueValidator;\n"
  },
  {
    "path": "packages/rules/src/mimes.ts",
    "content": "import { isEmpty } from './utils';\n\nconst ADDED_MIME_RE = /\\+(.+)?/;\n\nfunction buildRegExp(mime: string) {\n  let strPattern = mime;\n  if (ADDED_MIME_RE.test(mime)) {\n    strPattern = mime.replace(ADDED_MIME_RE, '(\\\\+$1)?');\n  }\n\n  return new RegExp(strPattern.replace('*', '.+'), 'i');\n}\n\nconst mimesValidator = (files: unknown, mimes: string[]) => {\n  if (isEmpty(files)) {\n    return true;\n  }\n\n  if (!mimes) {\n    mimes = [];\n  }\n\n  const patterns = mimes.map(buildRegExp);\n  if (Array.isArray(files)) {\n    return files.every(file => patterns.some(p => p.test((file as File).type)));\n  }\n\n  return patterns.some(p => p.test((files as File).type));\n};\n\nexport default mimesValidator;\n"
  },
  {
    "path": "packages/rules/src/min.ts",
    "content": "import { getSingleParam, isEmpty } from './utils';\n\nconst minValidator = (value: unknown, params: [string | number] | { length: string | number }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const length = getSingleParam(params, 'length');\n  if (Array.isArray(value)) {\n    return value.every(val => minValidator(val, { length }));\n  }\n\n  return [...String(value)].length >= Number(length);\n};\n\nexport default minValidator;\n"
  },
  {
    "path": "packages/rules/src/min_value.ts",
    "content": "import { getSingleParam, isEmpty } from './utils';\n\nconst minValueValidator = (value: unknown, params: [string | number] | { min: string | number }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const min = getSingleParam(params, 'min');\n  if (Array.isArray(value)) {\n    return value.length > 0 && value.every(val => minValueValidator(val, { min }));\n  }\n\n  return Number(value) >= Number(min);\n};\n\nexport default minValueValidator;\n"
  },
  {
    "path": "packages/rules/src/not_one_of.ts",
    "content": "import oneOf from './one_of';\nimport { isEmpty } from './utils';\n\nconst notOneOfValidator = (value: unknown, list: unknown[]) => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  return !oneOf(value, list);\n};\n\nexport default notOneOfValidator;\n"
  },
  {
    "path": "packages/rules/src/numeric.ts",
    "content": "import { isEmpty } from './utils';\n\nconst ar = /^[٠١٢٣٤٥٦٧٨٩]+$/;\nconst en = /^[0-9]+$/;\n\nconst numericValidator = (value: unknown) => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  const testValue = (val: unknown) => {\n    const strValue = String(val);\n\n    return en.test(strValue) || ar.test(strValue);\n  };\n\n  if (Array.isArray(value)) {\n    return value.every(testValue);\n  }\n\n  return testValue(value);\n};\n\nexport default numericValidator;\n"
  },
  {
    "path": "packages/rules/src/one_of.ts",
    "content": "import { isEmpty } from './utils';\n\nconst oneOfValidator = (value: unknown, list: unknown[]): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  if (Array.isArray(value)) {\n    return value.every(val => oneOfValidator(val, list));\n  }\n\n  return Array.from(list).some(item => {\n    return item == value;\n  });\n};\n\nexport default oneOfValidator;\n"
  },
  {
    "path": "packages/rules/src/regex.ts",
    "content": "import { getSingleParam, isEmpty } from './utils';\n\nconst regexValidator = (value: unknown, params: [string | RegExp] | { regex: RegExp | string }): boolean => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  let regex = getSingleParam(params, 'regex');\n  if (typeof regex === 'string') {\n    regex = new RegExp(regex);\n  }\n\n  if (Array.isArray(value)) {\n    return value.every(val => regexValidator(val, { regex }));\n  }\n\n  return regex.test(String(value));\n};\n\nexport default regexValidator;\n"
  },
  {
    "path": "packages/rules/src/required.ts",
    "content": "import { isEmptyArray, isNullOrUndefined } from '../../shared';\n\nconst requiredValidator = (value: unknown) => {\n  if (isNullOrUndefined(value) || isEmptyArray(value) || value === false) {\n    return false;\n  }\n\n  return !!String(value).trim().length;\n};\n\nexport default requiredValidator;\n"
  },
  {
    "path": "packages/rules/src/size.ts",
    "content": "import { getSingleParam, isEmpty } from './utils';\n\nconst sizeValidator = (files: unknown, params: [number | string] | { size: string | number }) => {\n  if (isEmpty(files)) {\n    return true;\n  }\n\n  let size = getSingleParam(params, 'size');\n  size = Number(size);\n  if (isNaN(size)) {\n    return false;\n  }\n\n  const nSize = size * 1024;\n  if (!Array.isArray(files)) {\n    return (files as File).size <= nSize;\n  }\n\n  for (let i = 0; i < files.length; i++) {\n    if ((files[i] as File).size > nSize) {\n      return false;\n    }\n  }\n\n  return true;\n};\n\nexport default sizeValidator;\n"
  },
  {
    "path": "packages/rules/src/toTypedSchema.ts",
    "content": "import { RawFormSchema, validateObject, validate, GenericObject } from 'vee-validate';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport function toTypedSchema<TInput, TOutput = TInput>(\n  rawSchema: RawFormSchema<TInput> | string,\n): StandardSchemaV1<TInput, TOutput> {\n  const schema: StandardSchemaV1<TInput, TOutput> = {\n    '~standard': {\n      vendor: 'vee-validate',\n      version: 1,\n      async validate(values: unknown) {\n        // single field\n        if (typeof rawSchema === 'string') {\n          const result = await validate(values, rawSchema);\n\n          return {\n            issues: result.errors.map(error => ({\n              path: [],\n              message: error,\n            })),\n          };\n        }\n\n        const result = await validateObject(rawSchema, values as GenericObject | undefined);\n        const issues: StandardSchemaV1.Issue[] = [];\n        if (result.valid) {\n          return {\n            value: result.values as TOutput,\n          };\n        }\n\n        for (const [path, error] of Object.entries(result.errors)) {\n          if (error) {\n            issues.push({\n              path: [path],\n              message: error,\n            });\n          }\n        }\n\n        return {\n          issues,\n        };\n      },\n    },\n  };\n\n  return schema;\n}\n"
  },
  {
    "path": "packages/rules/src/url.ts",
    "content": "import { getSingleParam, isEmpty } from './utils';\n\nconst urlValidator = (value: unknown, params: [string | RegExp | undefined] | { pattern?: string | RegExp }) => {\n  if (isEmpty(value)) {\n    return true;\n  }\n\n  let pattern = getSingleParam(params, 'pattern');\n  if (typeof pattern === 'string') {\n    pattern = new RegExp(pattern);\n  }\n\n  try {\n    new URL(value as string);\n  } catch {\n    return false;\n  }\n\n  return pattern?.test(value as string) ?? true;\n};\n\nexport default urlValidator;\n"
  },
  {
    "path": "packages/rules/src/utils.ts",
    "content": "export function getSingleParam<TParam = unknown>(params: [TParam] | Record<string, TParam>, paramName: string) {\n  return Array.isArray(params) ? params[0] : params[paramName];\n}\n\nexport function isEmpty(value: unknown): boolean {\n  if (value === null || value === undefined || value === '') {\n    return true;\n  }\n\n  if (Array.isArray(value) && value.length === 0) {\n    return true;\n  }\n\n  return false;\n}\n"
  },
  {
    "path": "packages/rules/tests/.eslintrc.json",
    "content": "{\n  \"rules\": {\n    \"@typescript-eslint/no-explicit-any\": \"off\"\n  }\n}\n"
  },
  {
    "path": "packages/rules/tests/alpha.spec.ts",
    "content": "import validate from '../src/alpha';\n\ntest('validates that the string may only contains alphabetic characters', () => {\n  expect(validate('abcdefgHijklMnOpqRsTUVwxYZ', [undefined])).toBe(true);\n  expect(validate('', [undefined])).toBe(true);\n  expect(validate(null, [undefined])).toBe(true);\n  expect(validate(undefined, [undefined])).toBe(true);\n  expect(validate('null', [undefined])).toBe(true);\n  expect(validate('undefined', [undefined])).toBe(true);\n  expect(validate(true, [undefined])).toBe(true);\n  expect(validate(false, [undefined])).toBe(true);\n  expect(validate(['abcdefg', 'hijk', 'lmnopq'], [undefined])).toBe(true);\n\n  // invalid\n  expect(validate('this is sparta', [undefined])).toBe(false);\n  expect(validate('1234567a89', [undefined])).toBe(false);\n  expect(validate({}, [undefined])).toBe(false);\n  expect(validate(' ', [undefined])).toBe(false);\n  expect(validate(['abcdefg', 'hijk', 'lmnopq123'], [undefined])).toBe(false);\n});\n\ntest('validates the string contains alphabetic chars from other locales', () => {\n  // any locale.\n  expect(validate('سلام', [undefined])).toBe(true);\n  expect(validate('Привет', [undefined])).toBe(true);\n\n  // specific locale\n  expect(validate('peace', { locale: 'ar' })).toBe(false);\n  expect(validate('peace', { locale: 'ru' })).toBe(false);\n\n  // non-existent locale defaults to english validation.\n  expect(validate('peace', { locale: 'blah' })).toBe(true);\n  expect(validate('اين اشيائي', { locale: 'blah' })).toBe(false); // non english characters.\n});\n"
  },
  {
    "path": "packages/rules/tests/alpha_dash.spec.ts",
    "content": "import validate from '../src/alpha_dash';\n\ntest('validates that the string may only contain alpha-numeric characters as well as dashes and spaces', () => {\n  expect(validate('a', [undefined])).toBe(true);\n  expect(validate('abcdefgHijklMnOpqRsTUVwxYZ', [undefined])).toBe(true);\n  expect(validate('1234567890', [undefined])).toBe(true);\n  expect(validate('abc123', [undefined])).toBe(true);\n  expect(validate(123, [undefined])).toBe(true);\n  expect(validate('', [undefined])).toBe(true);\n  expect(validate(null, [undefined])).toBe(true);\n  expect(validate(undefined, [undefined])).toBe(true);\n  expect(validate('null', [undefined])).toBe(true);\n  expect(validate('undefined', [undefined])).toBe(true);\n  expect(validate('123-abc', [undefined])).toBe(true);\n  expect(validate('123_abc', [undefined])).toBe(true);\n  expect(validate(true, [undefined])).toBe(true);\n  expect(validate(false, [undefined])).toBe(true);\n  expect(validate(['a', 'b', 'cdef-_'], [undefined])).toBe(true);\n\n  expect(validate('this is sparta', [undefined])).toBe(false);\n  expect(validate({}, [undefined])).toBe(false);\n  expect(validate(' ', [undefined])).toBe(false);\n  expect(validate([' ', 'ada as'], [undefined])).toBe(false);\n});\n\ntest('validates the string contains alphabetic chars from other locales', () => {\n  // any locale.\n  expect(validate('سلا-م_', [undefined])).toBe(true);\n  expect(validate('Привет_-', [undefined])).toBe(true);\n\n  // specific locale\n  expect(validate('peace', { locale: 'ar' })).toBe(false);\n  expect(validate('peace', { locale: 'ru' })).toBe(false);\n\n  // non-existent locale defaults to english validation.\n  expect(validate('peace', { locale: 'blah' })).toBe(true);\n  expect(validate('اين اشيائي', { locale: 'blah' })).toBe(false); // non english characters.\n});\n"
  },
  {
    "path": "packages/rules/tests/alpha_num.spec.ts",
    "content": "import validate from '../src/alpha_num';\n\ntest('validates that the string may only contain alphabetic and numeric characters', () => {\n  expect(validate('a', [undefined])).toBe(true);\n  expect(validate('abcdefgHijklMnOpqRsTUVwxYZ', [undefined])).toBe(true);\n  expect(validate('1234567890', [undefined])).toBe(true);\n  expect(validate('abc123', [undefined])).toBe(true);\n  expect(validate(123, [undefined])).toBe(true);\n  expect(validate('', [undefined])).toBe(true);\n  expect(validate(null, [undefined])).toBe(true);\n  expect(validate(undefined, [undefined])).toBe(true);\n  expect(validate('null', [undefined])).toBe(true);\n  expect(validate('undefined', [undefined])).toBe(true);\n  expect(validate(true, [undefined])).toBe(true);\n  expect(validate(false, [undefined])).toBe(true);\n  expect(validate(['asdad', 123, 'asd2123'], [undefined])).toBe(true);\n\n  expect(validate('this is sparta', [undefined])).toBe(false);\n  expect(validate('123-abc', [undefined])).toBe(false);\n  expect(validate({}, [undefined])).toBe(false);\n  expect(validate(' ', [undefined])).toBe(false);\n  expect(validate(['asdasda  ', '123 ad'], [undefined])).toBe(false);\n});\n\ntest('validates the string contains alphabetic chars from other locales', () => {\n  // any locale.\n  expect(validate('سلام12', [undefined])).toBe(true);\n  expect(validate('Привет12', [undefined])).toBe(true);\n\n  // specific locale\n  expect(validate('peace', { locale: 'ar' })).toBe(false);\n  expect(validate('peace', { locale: 'ru' })).toBe(false);\n\n  // non-existent locale defaults to english validation.\n  expect(validate('peace', { locale: 'blah' })).toBe(true);\n  expect(validate('اين اشيائي', { locale: 'blah' })).toBe(false); // non english characters.\n});\n"
  },
  {
    "path": "packages/rules/tests/alpha_spaces.spec.ts",
    "content": "import validate from '../src/alpha_spaces';\n\ntest('validates that the string may only contain alphabetic characters and spaces', () => {\n  expect(validate('a', [undefined])).toBe(true);\n  expect(validate('abcdefgHijklMnOpqRsTUVwxYZ', [undefined])).toBe(true);\n  expect(validate('', [undefined])).toBe(true);\n  expect(validate(null, [undefined])).toBe(true);\n  expect(validate(undefined, [undefined])).toBe(true);\n  expect(validate('null', [undefined])).toBe(true);\n  expect(validate('undefined', [undefined])).toBe(true);\n  expect(validate(true, [undefined])).toBe(true);\n  expect(validate(false, [undefined])).toBe(true);\n  expect(validate('this is sparta', [undefined])).toBe(true);\n  expect(validate(' ', [undefined])).toBe(true);\n  expect(validate(['adasd dasdasda', 'yy'], [undefined])).toBe(true);\n\n  // invalid\n  expect(validate('123-abc', [undefined])).toBe(false);\n  expect(validate({}, [undefined])).toBe(false);\n  expect(validate('1234567890', [undefined])).toBe(false);\n  expect(validate('abc123', [undefined])).toBe(false);\n  expect(validate(123, [undefined])).toBe(false);\n  expect(validate(['adasd dasdasda', '123'], [undefined])).toBe(false);\n});\n\ntest('validates the string contains alphabetic chars from other locales', () => {\n  // any locale.\n  expect(validate('سلام عليكم', [undefined])).toBe(true);\n  expect(validate('Привет т', [undefined])).toBe(true);\n\n  // specific locale\n  expect(validate('peace', { locale: 'ar' })).toBe(false);\n  expect(validate('peace', { locale: 'ru' })).toBe(false);\n\n  // non-existent locale defaults to english validation.\n  expect(validate('peace', { locale: 'blah' })).toBe(true);\n  expect(validate('اين اشيائي', { locale: 'blah' })).toBe(false); // non english characters.\n});\n"
  },
  {
    "path": "packages/rules/tests/between.spec.ts",
    "content": "import validate from '../src/between';\n\ntest('validates numbers range', () => {\n  const params = { min: 1, max: 3 };\n  expect(validate('1', params)).toBe(true);\n  expect(validate(2, params)).toBe(true);\n  expect(validate(3, params)).toBe(true);\n  expect(validate([1, 2, 3], params)).toBe(true);\n  expect(validate(undefined, params)).toBe(true);\n  expect(validate(null, params)).toBe(true);\n  expect(validate('', params)).toBe(true);\n  expect(validate([], params)).toBe(true);\n\n  // invalid\n  expect(validate({}, params)).toBe(false);\n  expect(validate('1234', params)).toBe(false);\n  expect(validate('12', params)).toBe(false);\n  expect(validate('abc', params)).toBe(false);\n  expect(validate('12a', params)).toBe(false);\n  expect(validate(0, params)).toBe(false);\n  expect(validate(4, params)).toBe(false);\n  expect(validate(-1, params)).toBe(false);\n  expect(validate([4, 5, 6], params)).toBe(false);\n});\n\ntest('validates numbers range including negative numbers', () => {\n  const range = { min: -10, max: 1 };\n  expect(validate(0, range)).toBe(true);\n  expect(validate('-9', range)).toBe(true);\n});\n"
  },
  {
    "path": "packages/rules/tests/confirmed.spec.ts",
    "content": "import validate from '../src/confirmed';\n\ntest('validates a field confirmation', () => {\n  expect(validate('p@$$word', { target: 'p@$$word' })).toBe(true);\n\n  // fields do not match.\n  expect(validate('password', { target: 'p@$$word' })).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/digits.spec.ts",
    "content": "import validate from '../src/digits';\n\ntest('validates digits', () => {\n  const params = { length: 3 }; // 3 digits only.\n  expect(validate('123', params)).toBe(true);\n  expect(validate('456', params)).toBe(true);\n  expect(validate('789', params)).toBe(true);\n  expect(validate('012', params)).toBe(true);\n  expect(validate('000', params)).toBe(true);\n  expect(validate(['012', '789'], params)).toBe(true);\n  expect(validate(undefined, params)).toBe(true);\n  expect(validate(null, params)).toBe(true);\n  expect(validate('', params)).toBe(true);\n  expect(validate([], params)).toBe(true);\n\n  // invalid\n  expect(validate(0, params)).toBe(false);\n  expect(validate({}, params)).toBe(false);\n  expect(validate('1234', params)).toBe(false);\n  expect(validate('12', params)).toBe(false);\n  expect(validate('abc', params)).toBe(false);\n  expect(validate('12a', params)).toBe(false);\n  expect(validate(['123', '12a'], params)).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/dimensions.spec.ts",
    "content": "import validate from '../src/dimensions';\nimport helpers from './helpers';\n\nlet fails = false;\n\nbeforeEach(() => {\n  window.URL.createObjectURL = () => {\n    return 'data:image/png;base64,AAAAAAA';\n  };\n\n  (window as any).webkitURL = {\n    createObjectURL() {\n      return 'data:image/png;base64,AAAAAAA';\n    },\n  };\n\n  (window as any).Image = class Image {\n    get src() {\n      return 'test';\n    }\n\n    set src(_: any) {\n      (this as any).width = 150;\n      (this as any).height = 100;\n\n      (this as any)[fails ? 'onerror' : 'onload']();\n    }\n  };\n});\n\ntest('validates image dimensions', async () => {\n  let result = await validate(helpers.file('file.jpg', 'image/jpeg', 10), { width: 150, height: 100 });\n  expect(result).toBe(true);\n\n  // mock a failing Image, even with the right dimensions.\n  fails = true;\n  result = await validate([helpers.file('file.jpg', 'image/jpeg', 10)], { width: 150, height: 100 });\n  expect(result).toBe(false);\n\n  fails = false;\n  // not an image.\n  result = await validate([helpers.file('file.pdf', 'application/pdf', 10)], { width: 150, height: 100 });\n  expect(result).toBe(false);\n\n  // wrong dimensions.\n  result = await validate([helpers.file('file.jpg', 'image/jpeg', 10)], { width: 15, height: 10 });\n  expect(result).toBe(false);\n\n  (window as any).URL = undefined; // test webkit fallback.\n  result = await validate([helpers.file('file.jpg', 'image/jpeg', 10)], { width: 150, height: 100 });\n  expect(result).toBe(true);\n});\n"
  },
  {
    "path": "packages/rules/tests/email.spec.ts",
    "content": "import validate from '../src/email';\n\ntest('validates that the string is a valid email address', () => {\n  expect(validate('someone@example.com')).toBe(true);\n  expect(validate('someone@example.co')).toBe(true);\n  expect(validate('someone123@example.co.uk')).toBe(true);\n  expect(validate('very.common@example.com')).toBe(true);\n  expect(validate('other.email-with-dash@example.com')).toBe(true);\n  expect(validate('disposable.style.email.with+symbol@example.com')).toBe(true);\n  expect(validate(['someone@example.com', 'someone12@example.com'])).toBe(true);\n  expect(validate(undefined)).toBe(true);\n  expect(validate(null)).toBe(true);\n  expect(validate('')).toBe(true);\n  expect(validate([])).toBe(true);\n\n  // invalid\n  expect(validate('Pelé@example.com')).toBe(false);\n  expect(validate('@example.com')).toBe(false);\n  expect(validate('@example')).toBe(false);\n  expect(validate('undefined')).toBe(false);\n  expect(validate('null')).toBe(false);\n  expect(validate('someone@example.c')).toBe(false);\n  expect(validate(['someone@example.com', 'someone@example.c'])).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/ext.spec.ts",
    "content": "import validate from '../src/ext';\nimport helpers from './helpers';\ntest('validates files extensions', () => {\n  const params = ['txt', 'jpg', 'svg'];\n  const validFiles = [\n    helpers.file('file.txt', 'text/plain'),\n    helpers.file('file.jpg', 'image/jpeg'),\n    helpers.file('file.svg', 'image/svg'),\n  ];\n\n  expect(validate(validFiles, params)).toBe(true);\n  expect(validate(helpers.file('file.pdf', 'application/pdf'), params)).toBe(false);\n  expect(validate(helpers.file('filetxt', 'text/plain'), params)).toBe(false);\n  expect(validate(helpers.file('file.jpgg', 'image/jpeg'), params)).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/helpers/index.ts",
    "content": "export default {\n  file: (name: string, type: string, size = 1) =>\n    ({\n      name,\n      type,\n      size: size * 1024,\n    }) as File,\n};\n"
  },
  {
    "path": "packages/rules/tests/image.spec.ts",
    "content": "import validate from '../src/image';\nimport helpers from './helpers';\ntest('validates image files', () => {\n  const validFiles = [\n    helpers.file('file.gif', 'image/gif'),\n    helpers.file('file.jpg', 'image/jpeg'),\n    helpers.file('file.jpeg', 'image/jpeg'),\n    helpers.file('file.svg', 'image/svg'),\n    helpers.file('file.bmp', 'image/bmp'),\n    helpers.file('file.png', 'image/png'),\n    helpers.file('file.png', 'image/webp'),\n  ];\n\n  expect(validate(validFiles)).toBe(true);\n  expect(validate(helpers.file('file.pdf', 'application/pdf'))).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/integer.spec.ts",
    "content": "import validate from '../src/integer';\n\ntest('validates integer numbers', () => {\n  expect(validate('1234567890')).toBe(true);\n  expect(validate(123)).toBe(true);\n  expect(validate(-123)).toBe(true);\n  expect(validate('-1234')).toBe(true);\n  expect(validate(undefined)).toBe(true);\n  expect(validate(null)).toBe(true);\n  expect(validate('')).toBe(true);\n  expect(validate([])).toBe(true);\n  expect(validate(0)).toBe(true);\n\n  // invalid\n  expect(validate('a')).toBe(false);\n  expect(validate('1234567a89')).toBe(false);\n  expect(validate(true)).toBe(false);\n  expect(validate(false)).toBe(false);\n  expect(validate({})).toBe(false);\n  expect(validate('+123')).toBe(false);\n  expect(validate(12.2)).toBe(false);\n  expect(validate('13.3')).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/is.spec.ts",
    "content": "import validate from '../src/is';\n\ntest('checks if the value matches another', () => {\n  expect(validate(1, { other: '1' })).toBe(false);\n  expect(validate(1, { other: 1 })).toBe(true);\n  expect(validate(1, { other: 2 })).toBe(false);\n  expect(validate({}, { other: {} })).toBe(false);\n  const obj = {};\n  expect(validate(obj, { other: obj })).toBe(true);\n});\n"
  },
  {
    "path": "packages/rules/tests/is_not.spec.ts",
    "content": "import validate from '../src/is_not';\n\ntest('checks if the value does not match another', () => {\n  expect(validate(1, { other: '1' })).toBe(true);\n  expect(validate(1, { other: 1 })).toBe(false);\n  expect(validate(1, { other: 2 })).toBe(true);\n  expect(validate({}, { other: {} })).toBe(true);\n  const obj = {};\n  expect(validate(obj, { other: obj })).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/length.spec.ts",
    "content": "import validate from '../src/length';\n\ntest('validates number of characters in a string', () => {\n  // exact length\n  expect(validate('hey', { length: 3 })).toBe(true);\n  expect(validate('hello', { length: 3 })).toBe(false);\n});\n\ntest('validates number of elements in an enumerable', () => {\n  const firstSet = new Set(['h', 'e', 'y']);\n  const secondSet = new Set(['h', 'e', 'l', 'l']);\n  expect(validate(firstSet as any, { length: 3 })).toBe(true);\n  expect(validate(secondSet as any, { length: 4 })).toBe(false);\n});\n\ntest('validates number of elements in an array', () => {\n  // exact length\n  expect(validate(['h', 'e', 'y'], { length: 3 })).toBe(true);\n  expect(validate(['h', 'e', 'l', 'l', 'o'], { length: 3 })).toBe(false);\n});\n\ntest('validates strings consisting of numbers', () => {\n  expect(validate(123 as any, { length: 3 })).toBe(true);\n});\n\ntest('skips empty values', () => {\n  expect(validate('', { length: 3 })).toBe(true);\n  expect(validate(null as any, { length: 3 })).toBe(true);\n  expect(validate(undefined as any, { length: 3 })).toBe(true);\n});\n"
  },
  {
    "path": "packages/rules/tests/max.spec.ts",
    "content": "import validate from '../src/max';\n\ntest('validates maximum number of characters in a string', () => {\n  const params = { length: 3 };\n  // valid\n  expect(validate(123, params)).toBe(true);\n  expect(validate('abc', params)).toBe(true);\n  expect(validate(1, params)).toBe(true);\n  expect(validate(12, params)).toBe(true);\n  expect(validate(undefined, params)).toBe(true);\n  expect(validate(null, params)).toBe(true);\n  expect(validate('', params)).toBe(true);\n  expect(validate([1, 2], params)).toBe(true);\n  expect(validate('𩸽寿司', params)).toBe(true);\n\n  // invalid\n  expect(validate('abcde', params)).toBe(false);\n  expect(validate('null', params)).toBe(false);\n  expect(validate('undefined', params)).toBe(false);\n  expect(validate(['1234'], params)).toBe(false);\n  expect(validate('𩸽寿司の', params)).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/max_value.spec.ts",
    "content": "import validate from '../src/max_value';\n\ntest('validates number maximum value', () => {\n  const params = { max: 10 };\n\n  // valid.\n  expect(validate(0, params)).toBe(true);\n  expect(validate('1', params)).toBe(true);\n  expect(validate(10, params)).toBe(true);\n  expect(validate([10], params)).toBe(true);\n  expect(validate(undefined, params)).toBe(true);\n  expect(validate(null, params)).toBe(true);\n  expect(validate('', params)).toBe(true);\n  expect(validate([], params)).toBe(true);\n\n  // invalid\n  expect(validate(10.01, params)).toBe(false);\n  expect(validate(11, params)).toBe(false);\n  expect(validate({}, params)).toBe(false);\n  expect(validate('abc', params)).toBe(false);\n  expect(validate([10.01], params)).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/mimes.spec.ts",
    "content": "import validate from '../src/mimes';\nimport helpers from './helpers';\n\ntest('validates mime types', () => {\n  const params = ['image/*', 'text/plain'];\n\n  expect(\n    validate(\n      [\n        helpers.file('file.txt', 'text/plain'),\n        helpers.file('file.jpg', 'image/jpeg'),\n        helpers.file('file.svg', 'image/svg'),\n      ],\n      params,\n    ),\n  ).toBe(true);\n\n  expect(validate(helpers.file('file.pdf', 'application/pdf'), params)).toBe(false);\n});\n\ntest('mimes with regex characters', () => {\n  expect(validate(helpers.file('file.svg', 'image/svg'), ['image/svg+xml'])).toBe(true);\n  expect(validate(helpers.file('file.svg', 'image/xml'), ['image/svg+xml'])).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/min.spec.ts",
    "content": "import validate from '../src/min';\n\ntest('validates minimum number of characters in a string', () => {\n  const params = { length: 3 };\n  // valid.\n  expect(validate('asjdj', params)).toBe(true);\n  expect(validate('null', params)).toBe(true);\n  expect(validate('undefined', params)).toBe(true);\n  expect(validate(123, params)).toBe(true);\n  expect(validate('abc', params)).toBe(true);\n  expect(validate([123, '123', 'abc'], params)).toBe(true);\n  expect(validate(undefined, params)).toBe(true);\n  expect(validate(null, params)).toBe(true);\n  expect(validate('', params)).toBe(true);\n  expect(validate([], params)).toBe(true);\n  expect(validate('𩸽寿司', params)).toBe(true);\n\n  // invalid\n  expect(validate(1, params)).toBe(false);\n  expect(validate(12, params)).toBe(false);\n  expect(validate([1], params)).toBe(false);\n  expect(validate('𩸽', params)).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/min_value.spec.ts",
    "content": "import validate from '../src/min_value';\n\ntest('validates number minimum value', () => {\n  const params = { min: -1 };\n  expect(validate(-1, params)).toBe(true);\n  expect(validate(0, params)).toBe(true);\n  expect(validate('5', params)).toBe(true);\n  expect(validate([-1, 5], params)).toBe(true);\n  expect(validate(undefined, params)).toBe(true);\n  expect(validate(null, params)).toBe(true);\n  expect(validate('', params)).toBe(true);\n  expect(validate([], params)).toBe(true);\n\n  // invalid\n  expect(validate({}, params)).toBe(false);\n  expect(validate('abc', params)).toBe(false);\n  expect(validate(-2, params)).toBe(false);\n  expect(validate('-3', params)).toBe(false);\n  expect(validate(['-3'], params)).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/not_one_of.spec.ts",
    "content": "import validate from '../src/not_one_of';\n\ntest('validates that the value does not exist within a list', () => {\n  const list = [1, 2, 3, 4, 5];\n\n  // valid.\n  expect(validate(0, list)).toBe(true);\n  expect(validate(6, list)).toBe(true);\n  expect(validate([6], list)).toBe(true);\n\n  // invalid\n  expect(validate(1, list)).toBe(false);\n  expect(validate(2, list)).toBe(false);\n  expect(validate(3, list)).toBe(false);\n  expect(validate(4, list)).toBe(false);\n  expect(validate(5, list)).toBe(false);\n  expect(validate([1, 2], list)).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/numeric.spec.ts",
    "content": "import validate from '../src/numeric';\n\ntest('validates that the string only contains numeric characters', () => {\n  // valid.\n  expect(validate('1234567890')).toBe(true);\n  expect(validate(123)).toBe(true);\n  expect(validate('٠١٢٣٤')).toBe(true);\n  expect(validate('٠١٢٣٤٥٦٧٨٩')).toBe(true);\n  expect(validate(undefined)).toBe(true);\n  expect(validate(null)).toBe(true);\n  expect(validate('')).toBe(true);\n  expect(validate([])).toBe(true);\n  expect(validate(0)).toBe(true);\n\n  // invalid\n  expect(validate('a')).toBe(false);\n  expect(validate('1234567a89')).toBe(false);\n  expect(validate(true)).toBe(false);\n  expect(validate(false)).toBe(false);\n  expect(validate({})).toBe(false);\n  expect(validate('+123')).toBe(false);\n  expect(validate('-123')).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/one_of.spec.ts",
    "content": "import validate from '../src/one_of';\n\ntest('validates that the value exists within a list', () => {\n  const list = [1, 2, 3, 4, 5];\n\n  // valid.\n  expect(validate(1, list)).toBe(true);\n  expect(validate(2, list)).toBe(true);\n  expect(validate(3, list)).toBe(true);\n  expect(validate(4, list)).toBe(true);\n  expect(validate(5, list)).toBe(true);\n\n  // invalid\n  expect(validate(0, list)).toBe(false);\n  expect(validate(6, list)).toBe(false);\n  expect(validate([1, 6], list)).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/regex.spec.ts",
    "content": "import validate from '../src/regex';\n\ntest('validates regular expressions', () => {\n  const params = { regex: /^[0-9]+$/ };\n  expect(validate('1234567890', params)).toBe(true);\n  expect(validate('abc', params)).toBe(false);\n  expect(validate('abc-123', params)).toBe(false);\n  expect(validate('1234abc5', params)).toBe(false);\n  expect(validate(['1234567890', '321'], params)).toBe(true);\n  expect(validate(['1234567890', 'abc'], params)).toBe(false);\n\n  // empty values should pass\n  expect(validate('', params)).toBe(true); // empty values pass\n  expect(validate(undefined, params)).toBe(true); // empty values pass\n  expect(validate(null, params)).toBe(true); // empty values pass\n  expect(validate([], params)).toBe(true); // empty values pass\n});\n"
  },
  {
    "path": "packages/rules/tests/required.spec.ts",
    "content": "import validate from '../src/required';\n\ntest('validates required', () => {\n  // valid\n  expect(validate('asjdj')).toBe(true);\n  expect(validate(0)).toBe(true);\n  expect(validate('undefined')).toBe(true);\n  expect(validate('null')).toBe(true);\n  expect(validate('s ')).toBe(true);\n  expect(validate(true)).toBe(true);\n\n  // invalid\n  expect(validate('')).toBe(false);\n  expect(validate(' ')).toBe(false);\n  expect(validate([])).toBe(false);\n  expect(validate(undefined)).toBe(false);\n  expect(validate(null)).toBe(false);\n  expect(validate(false)).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/size.spec.ts",
    "content": "import validate from '../src/size';\nimport helpers from './helpers';\n\ntest('validates file size', () => {\n  const params = { size: 15 };\n  expect(validate([helpers.file('file.txt', 'text/plain', 10)], params)).toBe(true);\n  expect(validate(helpers.file('file.txt', 'text/plain', 15), params)).toBe(true);\n  expect(validate([helpers.file('file.txt', 'text/plain', 16)], params)).toBe(false);\n  expect(validate([helpers.file('file.txt', 'text/plain', 16)], { size: 'not a number' })).toBe(false);\n});\n"
  },
  {
    "path": "packages/rules/tests/toTypedSchema.spec.ts",
    "content": "import { defineRule, useField, useForm } from 'vee-validate';\nimport { toTypedSchema } from '../src/toTypedSchema';\nimport { mountWithHoc, flushPromises, setValue } from '../../vee-validate/tests/helpers';\nimport required from '../src/required';\nimport email from '../src/email';\nimport min from '../src/min';\n\nconst REQUIRED_MSG = 'field is required';\nconst MIN_MSG = 'field is too short';\nconst EMAIL_MSG = 'field must be a valid email';\n\ndefineRule('required', (val: any) => (required(val) ? true : REQUIRED_MSG));\ndefineRule('email', (val: any) => (email(val) ? true : EMAIL_MSG));\ndefineRule('min', (val: any, params: any) => (min(val, params) ? true : MIN_MSG));\n\ntest('validates typed schema form with global rules', async () => {\n  const wrapper = mountWithHoc({\n    setup() {\n      const schema = toTypedSchema<{ email: string; password: string }>({\n        email: 'required|email',\n        password: 'required|min:8',\n      });\n\n      const { defineField, errors } = useForm({\n        validationSchema: schema,\n        validateOnMount: true,\n      });\n\n      const [email] = defineField('email', { validateOnModelUpdate: true });\n      const [password] = defineField('password', { validateOnModelUpdate: true });\n\n      return {\n        schema,\n        email,\n        password,\n        errors,\n      };\n    },\n    template: `\n      <div>\n        <input id=\"email\" name=\"email\" v-model=\"email\" />\n        <span id=\"emailErr\">{{ errors.email }}</span>\n\n        <input id=\"password\" name=\"password\" type=\"password\" v-model=\"password\" />\n        <span id=\"passwordErr\">{{ errors.password }}</span>\n      </div>\n    `,\n  });\n\n  const email = wrapper.$el.querySelector('#email');\n  const password = wrapper.$el.querySelector('#password');\n  const emailError = wrapper.$el.querySelector('#emailErr');\n  const passwordError = wrapper.$el.querySelector('#passwordErr');\n\n  await flushPromises();\n\n  setValue(email, 'hello@');\n  setValue(password, '1234');\n  await flushPromises();\n\n  expect(emailError.textContent).toBe(EMAIL_MSG);\n  expect(passwordError.textContent).toBe(MIN_MSG);\n\n  setValue(email, 'hello@email.com');\n  setValue(password, '12346789');\n  await flushPromises();\n\n  expect(emailError.textContent).toBe('');\n  expect(passwordError.textContent).toBe('');\n});\n\ntest('validates typed field with global rules', async () => {\n  const wrapper = mountWithHoc({\n    setup() {\n      const rules = toTypedSchema<string>('required|min:8');\n      const { value, errorMessage } = useField('test', rules);\n\n      return {\n        value,\n        errorMessage,\n      };\n    },\n    template: `\n      <div>\n          <input v-model=\"value\" type=\"text\">\n          <p>{{ errorMessage }}</p>\n      </div>\n    `,\n  });\n\n  const input = wrapper.$el.querySelector('input');\n  const error = wrapper.$el.querySelector('p');\n\n  setValue(input, '');\n  await flushPromises();\n  expect(error.textContent).toBe(REQUIRED_MSG);\n  setValue(input, '12');\n  await flushPromises();\n  expect(error.textContent).toBe(MIN_MSG);\n  setValue(input, '12345678');\n  await flushPromises();\n  expect(error.textContent).toBe('');\n});\n"
  },
  {
    "path": "packages/rules/tests/url.spec.ts",
    "content": "import validate from '../src/url';\n\ntest('validates url', () => {\n  const validUrl = 'https://test.com:8080/en/whatever/?q=test#wow';\n\n  // no pattern\n  expect(validate(validUrl, {})).toBe(true);\n  expect(validate('/only/path', {})).toBe(false);\n  expect(validate('invalid', {})).toBe(false);\n\n  // with pattern\n  expect(validate(validUrl, { pattern: 'https://.*' })).toBe(true);\n  expect(validate(validUrl, { pattern: /http:\\/\\/.*/ })).toBe(false);\n  expect(validate(validUrl, ['/en/whatever/'])).toBe(true);\n  expect(validate(validUrl, ['/fr/whatever/'])).toBe(false);\n});\n"
  },
  {
    "path": "packages/shared/README.md",
    "content": "# @vee-validate/shared\n\nCommon functions and utils used in other packages, this is never published and should be inlined with other packages output.\n"
  },
  {
    "path": "packages/shared/index.ts",
    "content": "export * from './utils';\nexport * from './types';\n"
  },
  {
    "path": "packages/shared/types.ts",
    "content": "export interface FieldValidationMetaInfo {\n  field: string;\n  name: string;\n  label?: string;\n  value: unknown;\n  form: Record<string, unknown>;\n  rule?: {\n    name: string;\n    params?: Record<string, unknown> | unknown[];\n  };\n}\n\nexport type ValidationRuleFunction<TValue = unknown, TParams = unknown[] | Record<string, unknown>> = (\n  value: TValue,\n  params: TParams,\n  ctx: FieldValidationMetaInfo,\n) => boolean | string | Promise<boolean | string>;\n\nexport type SimpleValidationRuleFunction<TValue = unknown, TParams = unknown[] | Record<string, unknown>> = (\n  value: TValue,\n  params: TParams,\n) => boolean | string | Promise<boolean | string>;\n\nexport type ValidationMessageGenerator = (ctx: FieldValidationMetaInfo) => string;\n\nexport type Optional<T> = T extends Record<string, any> ? Partial<T> : T | undefined;\n\nexport type InterpolateOptions = {\n  prefix: string;\n  suffix: string;\n};\n"
  },
  {
    "path": "packages/shared/utils.spec.ts",
    "content": "import { getTag, isPlainObject } from './utils';\n\ndescribe('getTag()', () => {\n  test('should return [object Undefined] for undefined type', () => {\n    const tag = getTag(undefined);\n\n    expect(tag).toBe('[object Undefined]');\n  });\n\n  test('should return [object Null] for null type', () => {\n    const tag = getTag(null);\n\n    expect(tag).toBe('[object Null]');\n  });\n});\n\ndescribe('isPlainObject()', () => {\n  test('should return true if object has no prototype', () => {\n    const result = isPlainObject(Object.create(null));\n\n    expect(result).toBe(true);\n  });\n});\n"
  },
  {
    "path": "packages/shared/utils.ts",
    "content": "export function isCallable(fn: unknown): fn is (...args: any[]) => any {\n  return typeof fn === 'function';\n}\n\nexport function isNullOrUndefined(value: unknown): value is undefined | null {\n  return value === null || value === undefined;\n}\n\nexport function isEmptyArray(arr: unknown): boolean {\n  return Array.isArray(arr) && arr.length === 0;\n}\n\nexport const isObject = (obj: unknown): obj is Record<string, unknown> =>\n  obj !== null && !!obj && typeof obj === 'object' && !Array.isArray(obj);\n\nexport function isIndex(value: unknown): value is number {\n  return Number(value) >= 0;\n}\n\nexport function toNumber(value: string): number | string {\n  const n = parseFloat(value);\n\n  return isNaN(n) ? value : n;\n}\n\nexport function isObjectLike(value: any) {\n  return typeof value === 'object' && value !== null;\n}\n\nexport function getTag(value: any) {\n  if (value == null) {\n    return value === undefined ? '[object Undefined]' : '[object Null]';\n  }\n  return Object.prototype.toString.call(value);\n}\n\n// Reference: https://github.com/lodash/lodash/blob/master/isPlainObject.js\nexport function isPlainObject(value: any) {\n  if (!isObjectLike(value) || getTag(value) !== '[object Object]') {\n    return false;\n  }\n  if (Object.getPrototypeOf(value) === null) {\n    return true;\n  }\n  let proto = value;\n  while (Object.getPrototypeOf(proto) !== null) {\n    proto = Object.getPrototypeOf(proto);\n  }\n  return Object.getPrototypeOf(value) === proto;\n}\n\nexport function merge(target: any, source: any) {\n  Object.keys(source).forEach(key => {\n    if (isPlainObject(source[key]) && isPlainObject(target[key])) {\n      if (!target[key]) {\n        target[key] = {};\n      }\n\n      merge(target[key], source[key]);\n      return;\n    }\n\n    target[key] = source[key];\n  });\n\n  return target;\n}\n\n/**\n * Constructs a path with dot paths for arrays to use brackets to be compatible with vee-validate path syntax\n */\nexport function normalizeFormPath(path: string): string {\n  const pathArr = path.split('.');\n  if (!pathArr.length) {\n    return '';\n  }\n\n  let fullPath = String(pathArr[0]);\n  for (let i = 1; i < pathArr.length; i++) {\n    if (isIndex(pathArr[i])) {\n      fullPath += `[${pathArr[i]}]`;\n      continue;\n    }\n\n    fullPath += `.${pathArr[i]}`;\n  }\n\n  return fullPath;\n}\n"
  },
  {
    "path": "packages/vee-validate/CHANGELOG.md",
    "content": "# Change Log\n\n## 5.0.0-beta.1\n\n### Minor Changes\n\n- f629397: feat: remove deprecated useField props\n- fb5e04e: feat: remove deprecated useForm define methods\n\n### Patch Changes\n\n- f2807b8: fix(devtools): prevent SSR memory leak in DevTools integration\n- e6db423: feat: expose `getConfig` as a public API\n- 49fcf4c: Fix dev tools not showing all field states\n- 1ce0731: fix: revert number input type back to string from number, closes #4699 and #4482\n- 095df65: Fix dev tools do not display nested fields with name 'id'\n\n## 5.0.0-beta.0\n\n### Major Changes\n\n- 04ff47c: feat: implement standard schema\n\n## 4.15.1\n\n### Patch Changes\n\n- 721e980: Align FormErrors type with its actual structure at runtime.\n- 546d82e: fix: normalize objects before equality checks closes #5006\n\n## 4.15.0\n\n### Patch Changes\n\n- 30281f5: fix: lazy load the devtools dep to force it out of production bundle\n- ec121b1: fix: skip loading devtools if in SSR\n\n## 4.14.7\n\n### Patch Changes\n\n- be994b4: fix: show uncontrolled field info in devtools closes #4914\n\n## 4.14.6\n\n## 4.14.5\n\n### Patch Changes\n\n- e9f8c88: fix: force loading the mjs module when using nuxt\n\n## 4.14.4\n\n### Patch Changes\n\n- f33974c: fix(types): expose field and form slot prop types closes #4900\n- 0991c01: fix: devtools crashing when a field name is defined as getter\n- ecb540a: fix: handle getter field names properly closes #4877\n- 4f88d85: fix: specify module type on package.json\n\n## 4.14.3\n\n### Patch Changes\n\n- 07c27d5: fix: remove rogue console.log\n\n## 4.14.2\n\n### Patch Changes\n\n- f0d4e24: fix: upgrade vue devtools dependency version closes #4863\n\n## 4.14.1\n\n## 4.14.0\n\n### Minor Changes\n\n- 404cf57: chore: bump release\n\n### Patch Changes\n\n- f7a4929: feat: expose useFormContext closes #4490\n- 97cebd8: chore: add 'exports' field in package.json for all packages\n- 421ae69: \"fix(types): export component internal types\"\n\n## 4.13.2\n\n### Patch Changes\n\n- afbd0e5: feat: support valibot 0.33.0\n\n## 4.13.1\n\n## 4.13.0\n\n### Minor Changes\n\n- 454bc45: fix: force resetForm should not merge values closes #4680 closes #4729\n- 27fe5c8: feat: provide form values as context for yup closes #4753\n\n### Patch Changes\n\n- ae3772a: feat: expose setValue on Field instance and slot props closes #4755\n- fd008c1: feat: added ResetFormOpts arg to useResetForm closes #4707\n\n## 4.12.8\n\n### Patch Changes\n\n- f8bab9c: \"fix: field-level validation not working with typed scheams closes #4744\"\n\n## 4.12.7\n\n### Patch Changes\n\n- 1376794: fix: handle meta.required for single field schemas closes #4738\n- 1376794: fix: add try-catch for schema description logic across all major schema providers\n- c4415f8: fix: ensure meta.required is reactive whenever the schema changes closes #4738\n\n## 4.12.6\n\n### Patch Changes\n\n- 07d01fd: fix: re-apply errors to avoid race conditions\n\n## 4.12.5\n\n### Patch Changes\n\n- d779980: fix: make sure removePathState removes the correct path state\n- 9eda544: \"fix: remove event arg from define field handlers for component compat closes #4637\"\n\n## 4.12.4\n\n### Patch Changes\n\n- 2a09a58: \"fix: check if both source and target objects are POJOs\"\n\n## 4.12.3\n\n### Patch Changes\n\n- 72e4379: fix: remove deep data mutation warning closes #4597\n- a18c19f: feat: allow path meta querying for nested fields closes #4575\n- e2171f8: feat: expose some state on form instance\n\n## 4.12.2\n\n### Patch Changes\n\n- b2203c8e: fix: apply schema casts when submitting closes #4565\n- ec8a4d7e: fix: defineField should respect global validateOnModelUpdate closes #4567\n\n## 4.12.1\n\n### Patch Changes\n\n- 36f6b9e6: fix: reset form and field behaviors for unspecified values closes #4564\n- c1c6f399: fix: unref initial values when initializing the form closes #4563\n\n## 4.12.0\n\n### Minor Changes\n\n- bbecc973: feat: deprecate reactive initial values closes #4402\n\n### Patch Changes\n\n- f9a95843: feat: add label support to defineField closes #4530\n- f688896f: fix: avoid overriding paths and destroy path on remove closes #4476 closes #4557\n- 2abb8966: fix: clone values before reset closes #4536\n- e370413b: fix: handle hoisted paths overriding one another\n- 95b701f7: feat: allow getters for field arrays\n\n## 4.11.8\n\n### Patch Changes\n\n- d1b5b855: fix: avoid triggering extra model value events closes #4461\n- 78c4668e: feat: allow null as a valid Form prop type closes #4483\n\n## 4.11.7\n\n### Patch Changes\n\n- a1414f6a: fix: export ModelessBinds type closes #4478\n\n## 4.11.6\n\n### Patch Changes\n\n- f683e909: fix(types): infer the model value prop name correctly\n\n## 4.11.5\n\n### Patch Changes\n\n- 27c9ef24: feat(types): stronger define component bind types closes #4421\n- 804ec6fa: fix: use flags to avoid validating during reset #4404 #4467\n\n## 4.11.4\n\n### Patch Changes\n\n- 4d8ed7eb: feat: added reset opts to force values closes #4440\n- b53400e2: fix: silent validation should not mark a field as validated\n- 8f680bf1: fix: clone the schema object before validating closes #4459\n- 5231f439: fix: respect validate on model update configuration closes #4451, closes #4467\n\n## 4.11.3\n\n## 4.11.2\n\n### Patch Changes\n\n- 2ff045c1: fix: do not warn if a form or a field was resolved closes #4399\n- 73219b40: feat: expose all internal types\n- 4947e88f: feat: expose BaseInputBinds and BaseComponentBinds interfaces #4409\n- ecbb690d: feat: query fields meta state\n\n## 4.11.1\n\n### Patch Changes\n\n- 5e23dcb9: fix: add support for parsing range inputs\n\n## 4.11.0\n\n### Minor Changes\n\n- 2d8143f9: feat: added composition setter functions\n\n## 4.10.9\n\n### Patch Changes\n\n- c02337f3: fix: correct the setErrors type to allow for string[]\n\n## 4.10.8\n\n### Patch Changes\n\n- a9a473b4: feat(perf): improve performance setFieldError and setFieldValue closes #4382\n\n## 4.10.7\n\n### Patch Changes\n\n- 9290f5a9: fix: clone values inserted into field arrays closes #4372\n- 93f8001a: fix: do not warn if the validation is for removed paths closes #4368\n\n## 4.10.6\n\n### Patch Changes\n\n- 40ce7a91: feat: expose normalizeRules closes #4348\n- e9b215a7: fix: resetForm should cast typed schema values closes #4347\n- 4e11ff95: fix: validate form values on setValues by default closes #4359\n- e354a13a: fix: Normalize error paths to use brackets for indices closes #4211\n- 68080d28: feat: use silent validation when field is initialized closes #4312\n\n## 4.10.5\n\n### Patch Changes\n\n- 6a1dc9bd: fix: component blur event and respect model update config closes #4346\n\n## 4.10.4\n\n### Patch Changes\n\n- 2f9ca91c: fix(types): remove deep readonly type for now\n\n## 4.10.3\n\n### Patch Changes\n\n- 32537e14: fix: less strict object checks for undefined and missing keys closes #4341\n- c3698f07: fix: respect model modifiers when emitting the value closes #4333\n\n## 4.10.2\n\n### Patch Changes\n\n- 1660048e: fix: define binds not respecting config events\n\n## 4.10.1\n\n### Patch Changes\n\n- fc416918: fix: handle NaN when parsing number inputs closes #4328\n- 435e7857: fix: reset present values after all path mutation\n- 273cca74: fix: reset field should not validate closes #4323\n\n## 4.10.0\n\n### Minor Changes\n\n- 7a548f42: chore: require vue 3.3 and refactor types\n- 7ce9d671: feat(breaking): disable v-model support by default closes #4283\n- bfd6b00a: \"feat: allow custom models for defineComponentBinds\"\n- d4fafc95: \"feat: allow handleBlur to run validations\"\n- 05d957ec: feat: mark form values as readonly closes #4282\n\n### Patch Changes\n\n- 77345c42: fix: reset form should merge values closes #4320\n- f1dc1359: fix: use event value if no checked value for checkbox/radio closes #4308\n- 3e4a7c13: feat(dx): make `syncVModel` accept the model propName\n- 2cf0eec9: feat: allow multiple messages in a validator fn closes #4322 #4318\n- ed208918: fix: trigger validation with setFieldValue by default closes #4314\n- 6a3f9f15: fix: parse native number fields closes #4313\n\n## 4.9.6\n\n### Patch Changes\n\n- b138282a: fix(types): export SetFieldValueOptions interface closes #4290\n- 6e074f77: fix: handleBlur should respect blur validate config closes #4285\n\n## 4.9.5\n\n### Patch Changes\n\n- 7356c102: fix: setFieldError should set meta.valid closes #4274\n\n## 4.9.4\n\n### Patch Changes\n\n- f4ea2c05: fix: exclude undefined and null from initial values closes #4139\n\n## 4.9.3\n\n### Patch Changes\n\n- 09d5596b: fix: run validation on value change closes #4251\n- 9bfbfaaf: feat: added isValidating to useForm\n- 48b45d91: fix: hoist nested errors path to the deepest direct parent closes #4063\n\n## 4.9.2\n\n### Patch Changes\n\n- 31090e0d: avoid double unset path with field array remove\n- 9046308b: fixed validations running for unmounted fields\n- fe322a07: batch unsets and sort paths unset order for safer unsets closes #4115\n\n## 4.9.1\n\n### Patch Changes\n\n- 681bbab4: Added type-fest to core package dependencies\n\n## 4.9.0\n\n### Minor Changes\n\n- 41b5d39b: Implemented path types into various form API functions\n- 95409080: Added component and input binds helpers\n\n### Patch Changes\n\n- 7554d4a6: fix field array triggering validation when an item is removed\n- 298577b7: setValues does not delete unspecified fields values\n\n## 4.8.6\n\n### Patch Changes\n\n- 6e0b0557: Introduced official nuxt module package\n\n## 4.8.5\n\n### Patch Changes\n\n- 9048a238: fixed zod union issues not showing up as errors closes #4204\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n## [4.8.4](https://github.com/logaretm/vee-validate/compare/v4.8.3...v4.8.4) (2023-03-24)\n\n### Bug Fixes\n\n- make initial values partial closes [#4195](https://github.com/logaretm/vee-validate/issues/4195) ([eeccd0c](https://github.com/logaretm/vee-validate/commit/eeccd0c55814408670eced3717d0347590da3488))\n- properly unref the schema before checking for default values closes [#4196](https://github.com/logaretm/vee-validate/issues/4196) ([8e3663d](https://github.com/logaretm/vee-validate/commit/8e3663d18357574ea4d394197f2c66889eeef6fa))\n\n### Features\n\n- allow name ref to be a lazy function ([8fb543a](https://github.com/logaretm/vee-validate/commit/8fb543a6e91c17d8541389e29c7014dc1f804c91))\n\n## [4.8.3](https://github.com/logaretm/vee-validate/compare/v4.8.2...v4.8.3) (2023-03-15)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.8.2](https://github.com/logaretm/vee-validate/compare/v4.8.1...v4.8.2) (2023-03-14)\n\n### Bug Fixes\n\n- do not use name as a default label for useField closes [#4164](https://github.com/logaretm/vee-validate/issues/4164) ([d5acff7](https://github.com/logaretm/vee-validate/commit/d5acff719797c77ba4ff3be5f78c4a45374f9809))\n\n## [4.8.1](https://github.com/logaretm/vee-validate/compare/v4.8.0...v4.8.1) (2023-03-12)\n\n### Bug Fixes\n\n- make sure to have a fallback for undefined casts closes [#4186](https://github.com/logaretm/vee-validate/issues/4186) ([9f1c63b](https://github.com/logaretm/vee-validate/commit/9f1c63b4dbc59f30c17bfe427020586db36cbdec))\n\n### Features\n\n- expose errorBag to <Form /> slot props ([371744e](https://github.com/logaretm/vee-validate/commit/371744eea3d3cb0a244dcd9788f4f3f2a7714132))\n\n# [4.8.0](https://github.com/logaretm/vee-validate/compare/v4.7.4...v4.8.0) (2023-03-12)\n\n### Bug Fixes\n\n- finally handicap yup schema resolution ([303b1fb](https://github.com/logaretm/vee-validate/commit/303b1fb771ee78816ef0916e4f0e26318ad641b0))\n- initial sync with v-model if enabled closes [#4163](https://github.com/logaretm/vee-validate/issues/4163) ([1040643](https://github.com/logaretm/vee-validate/commit/1040643f40ba622010ab935095dffb8d926cd76d))\n- properly aggregrate nested errors for yup ([7f90bbc](https://github.com/logaretm/vee-validate/commit/7f90bbceeaeb7806a9626adb72981933a69db96f))\n- remove console.log from devtools integration ([3c2d51c](https://github.com/logaretm/vee-validate/commit/3c2d51c56f80918ef6644b034594df1a3e81eb03))\n- remove yup schema type and rely on assertions ([5cbb913](https://github.com/logaretm/vee-validate/commit/5cbb913071e315264d62fda7d1219bdc28d3faf0))\n- render zod multiple errors in nested objects closes [#4078](https://github.com/logaretm/vee-validate/issues/4078) ([f74fb69](https://github.com/logaretm/vee-validate/commit/f74fb69977d17ef8fab4c22734ffd76ca1c02a48))\n- run silent validation after array mutations closes [#4096](https://github.com/logaretm/vee-validate/issues/4096) ([044b4b4](https://github.com/logaretm/vee-validate/commit/044b4b44601908330c65541ce2bee6a110b1604f))\n- type inference fix ([ac0383f](https://github.com/logaretm/vee-validate/commit/ac0383f1fb335bf92c9249f65bf319ca182545b7))\n- watch and re-init array fields if form data changed closes [#4153](https://github.com/logaretm/vee-validate/issues/4153) ([6e784cc](https://github.com/logaretm/vee-validate/commit/6e784ccacbe89b5cd9daa9e3827808f7056aac04))\n\n### Features\n\n- Better Yup and Zod typing with output types and input inference ([#4064](https://github.com/logaretm/vee-validate/issues/4064)) ([3820a5b](https://github.com/logaretm/vee-validate/commit/3820a5b8eb3f8c6cd9239057746ccfb4b2e57e76))\n- export type `FieldState` ([#4159](https://github.com/logaretm/vee-validate/issues/4159)) ([69c0d12](https://github.com/logaretm/vee-validate/commit/69c0d12434d50b52f4691c2f95d739049a3d1fcb))\n\n## [4.7.4](https://github.com/logaretm/vee-validate/compare/v4.7.3...v4.7.4) (2023-02-07)\n\n### Bug Fixes\n\n- pass the field label as a seperate value closes [#4097](https://github.com/logaretm/vee-validate/issues/4097) ([89f8689](https://github.com/logaretm/vee-validate/commit/89f8689b673be27f0fc221d6c096efa11dacd3e6))\n\n### Features\n\n- **#4117:** add resetField on Form/useForm ([#4120](https://github.com/logaretm/vee-validate/issues/4120)) ([87c4278](https://github.com/logaretm/vee-validate/commit/87c42787c0b4de5a09abe0d29deb92b28b59023e)), closes [#4117](https://github.com/logaretm/vee-validate/issues/4117)\n- expose state getters on the form instance via template refs ([#4121](https://github.com/logaretm/vee-validate/issues/4121)) ([7f1c39c](https://github.com/logaretm/vee-validate/commit/7f1c39c0d9a0d1f7b7768b68c6705b5bfda91599))\n\n## [4.7.3](https://github.com/logaretm/vee-validate/compare/v4.7.2...v4.7.3) (2022-11-13)\n\n### Bug Fixes\n\n- use cloned value when setting field value closes [#3991](https://github.com/logaretm/vee-validate/issues/3991) ([90b61fc](https://github.com/logaretm/vee-validate/commit/90b61fc8810a1fdc677507251735b4210f175f4b))\n\n## [4.7.2](https://github.com/logaretm/vee-validate/compare/v4.7.1...v4.7.2) (2022-11-02)\n\n### Bug Fixes\n\n- don't mutate validated meta when silent validation closes [#3981](https://github.com/logaretm/vee-validate/issues/3981) closes [#3982](https://github.com/logaretm/vee-validate/issues/3982) ([6652a22](https://github.com/logaretm/vee-validate/commit/6652a22f99cde5b018c633365025d74e15dde835))\n\n## [4.7.1](https://github.com/logaretm/vee-validate/compare/v4.7.0...v4.7.1) (2022-10-23)\n\n### Bug Fixes\n\n- clean up single group value after unmount closes [#3963](https://github.com/logaretm/vee-validate/issues/3963) ([#3972](https://github.com/logaretm/vee-validate/issues/3972)) ([8ccfd2b](https://github.com/logaretm/vee-validate/commit/8ccfd2b2b542963d3d35cfe5f82490c94ec1635f))\n- correctly mutate deep field array item and trigger validation ([#3974](https://github.com/logaretm/vee-validate/issues/3974)) ([267736f](https://github.com/logaretm/vee-validate/commit/267736f43ca207a8fe35af30020fc61fdc009265))\n- mark slot prop field value as any closes [#3969](https://github.com/logaretm/vee-validate/issues/3969) ([#3973](https://github.com/logaretm/vee-validate/issues/3973)) ([70ddc5b](https://github.com/logaretm/vee-validate/commit/70ddc5b60232f0dc761b7803a3220010d2f8ba69))\n\n# [4.7.0](https://github.com/logaretm/vee-validate/compare/v4.6.10...v4.7.0) (2022-10-09)\n\n### Features\n\n- allow passing form control to useField closes [#3204](https://github.com/logaretm/vee-validate/issues/3204) ([#3923](https://github.com/logaretm/vee-validate/issues/3923)) ([4c59d63](https://github.com/logaretm/vee-validate/commit/4c59d634f25d7fff024b50f3ffd667f7fdf0076c))\n- expose controlled values on useForm ([#3924](https://github.com/logaretm/vee-validate/issues/3924)) ([2517319](https://github.com/logaretm/vee-validate/commit/25173196f3b689d919015cf8e7df8254b9e3090e))\n\n## [4.6.10](https://github.com/logaretm/vee-validate/compare/v4.6.9...v4.6.10) (2022-09-30)\n\n### Bug Fixes\n\n- use ssr safe file check ([56663aa](https://github.com/logaretm/vee-validate/commit/56663aa2e50d7aa285ca1cb22887c8e8b3f7fd3c))\n\n## [4.6.9](https://github.com/logaretm/vee-validate/compare/v4.6.8...v4.6.9) (2022-09-19)\n\n### Bug Fixes\n\n- perform field reset before all values reset closes [#3934](https://github.com/logaretm/vee-validate/issues/3934) ([1c016d9](https://github.com/logaretm/vee-validate/commit/1c016d93b367229644dca643931ef63bc6e433dc))\n\n## [4.6.8](https://github.com/logaretm/vee-validate/compare/v4.6.7...v4.6.8) (2022-09-19)\n\n### Bug Fixes\n\n- ensure validation if we skip checkbox value setting [#3927](https://github.com/logaretm/vee-validate/issues/3927) ([#3930](https://github.com/logaretm/vee-validate/issues/3930)) ([82d05db](https://github.com/logaretm/vee-validate/commit/82d05dbd2a5c7d5ea2fe7b73222dd339e92ee373))\n- extend is equal with file comparison logic [#3911](https://github.com/logaretm/vee-validate/issues/3911) ([#3932](https://github.com/logaretm/vee-validate/issues/3932)) ([c7c806c](https://github.com/logaretm/vee-validate/commit/c7c806c0c5393f3188c16384f5fc1b46ebc78cbd))\n- handle nested value change validation [#3926](https://github.com/logaretm/vee-validate/issues/3926) ([#3929](https://github.com/logaretm/vee-validate/issues/3929)) ([771e7f2](https://github.com/logaretm/vee-validate/commit/771e7f21cf332052b74c5506a8c2f38f666cae55))\n\n### Features\n\n- expose RuleExpression type closes [#3913](https://github.com/logaretm/vee-validate/issues/3913) ([cdaf22d](https://github.com/logaretm/vee-validate/commit/cdaf22df04b42a68f55133ad3854aae9a7ad6953))\n\n## [4.6.7](https://github.com/logaretm/vee-validate/compare/v4.6.6...v4.6.7) (2022-08-27)\n\n### Bug Fixes\n\n- allow generics for generic function type ([91e97aa](https://github.com/logaretm/vee-validate/commit/91e97aa41bca278970780973fcbf90e17fb29920))\n- handle validation races for async validations ([#3908](https://github.com/logaretm/vee-validate/issues/3908)) ([8c82079](https://github.com/logaretm/vee-validate/commit/8c82079dac8535678e45428ad8e5afe7dcd3da63))\n\n## [4.6.6](https://github.com/logaretm/vee-validate/compare/v4.6.5...v4.6.6) (2022-08-16)\n\n### Bug Fixes\n\n- return value if no model modifiers are defined closes [#3895](https://github.com/logaretm/vee-validate/issues/3895) ([#3896](https://github.com/logaretm/vee-validate/issues/3896)) ([6ab40df](https://github.com/logaretm/vee-validate/commit/6ab40df4452c5bee8a487a37164e2273c2aaf0ba))\n\n## [4.6.5](https://github.com/logaretm/vee-validate/compare/v4.6.4...v4.6.5) (2022-08-11)\n\n### Bug Fixes\n\n- reset the original value when resetField is called [#3891](https://github.com/logaretm/vee-validate/issues/3891) ([#3892](https://github.com/logaretm/vee-validate/issues/3892)) ([7113dcc](https://github.com/logaretm/vee-validate/commit/7113dccdeb962d8efa064ff0ebd171b2aa2f4c4d))\n\n## [4.6.4](https://github.com/logaretm/vee-validate/compare/v4.6.3...v4.6.4) (2022-08-07)\n\n### Bug Fixes\n\n- make sure to deep watch created models by useFieldModel ([fbe273c](https://github.com/logaretm/vee-validate/commit/fbe273c6f2c5d30a1996777561eda2268d8a02e0))\n\n## [4.6.3](https://github.com/logaretm/vee-validate/compare/v4.6.2...v4.6.3) (2022-08-07)\n\n### Features\n\n- Expose InvalidSubmissionHandler and GenericValidateFunction types ([#3853](https://github.com/logaretm/vee-validate/issues/3853)) ([3ccf27d](https://github.com/logaretm/vee-validate/commit/3ccf27d5b9c1fe9cf655b89533eb1802cb5717d4))\n\n## [4.6.2](https://github.com/logaretm/vee-validate/compare/v4.6.1...v4.6.2) (2022-07-17)\n\n### Bug Fixes\n\n- avoid toggling field array checkboxes values closes [#3844](https://github.com/logaretm/vee-validate/issues/3844) ([fffad4b](https://github.com/logaretm/vee-validate/commit/fffad4bea68cc949d0bce440b5daf43901aaca7f))\n\n### Features\n\n- expose field and form options closes [#3843](https://github.com/logaretm/vee-validate/issues/3843) ([7437612](https://github.com/logaretm/vee-validate/commit/7437612ab554f8f65b445f7b065725b570a9a14a))\n\n## [4.6.1](https://github.com/logaretm/vee-validate/compare/v4.6.0...v4.6.1) (2022-07-12)\n\n### Bug Fixes\n\n- pass onInvalidSubmit prop to submitForm closes [#3841](https://github.com/logaretm/vee-validate/issues/3841) ([b6cf543](https://github.com/logaretm/vee-validate/commit/b6cf543b600246942fc7f6802a0cc6ea1038603a))\n\n# [4.6.0](https://github.com/logaretm/vee-validate/compare/v4.5.11...v4.6.0) (2022-07-11)\n\n### Bug Fixes\n\n- added existing undefined path fallback closes [#3801](https://github.com/logaretm/vee-validate/issues/3801) ([fd0500c](https://github.com/logaretm/vee-validate/commit/fd0500c9cb4448b232eddb4cd5d8d081e5d48d08))\n- avoid inserting value binding for file type inputs closes [#3760](https://github.com/logaretm/vee-validate/issues/3760) ([3c76bb2](https://github.com/logaretm/vee-validate/commit/3c76bb2ebcbafaf46047b8e41bcc053e41cf27bf))\n- avoid validating when field instance exists ([3759df2](https://github.com/logaretm/vee-validate/commit/3759df20f5ba48a43d5dea4bb6d94e875f15c331))\n- compare form meta.dirty based on original values than staged initials closes [#3782](https://github.com/logaretm/vee-validate/issues/3782) ([f3ffd3c](https://github.com/logaretm/vee-validate/commit/f3ffd3c00ac1f2b73b6a3039cb997d08cf8e452b))\n- expose ValidationOptions type closes [#3825](https://github.com/logaretm/vee-validate/issues/3825) ([9854865](https://github.com/logaretm/vee-validate/commit/9854865ae60431256e6fb9c921d1eabc9093b5e4))\n- exposed component APIs to their TS defs with refs closes [#3292](https://github.com/logaretm/vee-validate/issues/3292) ([ae59d0f](https://github.com/logaretm/vee-validate/commit/ae59d0f6f3728a2a95732517d11fdf970127fe9c))\n- fast equal before deciding value was changed closes [#3808](https://github.com/logaretm/vee-validate/issues/3808) ([3d582ec](https://github.com/logaretm/vee-validate/commit/3d582ec6c884467199cc7fb86ffe0e571d85c4fb))\n- use multiple batch queues for both validation modes closes [#3783](https://github.com/logaretm/vee-validate/issues/3783) ([6156603](https://github.com/logaretm/vee-validate/commit/6156603f537fb46030017fb3a4d003b6bec0d4e8))\n\n### Features\n\n- **4.6:** Allow mutating field array iterable's value property ([#3618](https://github.com/logaretm/vee-validate/issues/3618)) ([#3759](https://github.com/logaretm/vee-validate/issues/3759)) ([c3c40e5](https://github.com/logaretm/vee-validate/commit/c3c40e50b68cbf8aee3356416561fdf5d23ac6d2))\n- add move to FieldArray ([a52f133](https://github.com/logaretm/vee-validate/commit/a52f13356c44616d699e02f9a243dd08c7bcc38e))\n- added unsetValueOnUnmount config ([#3815](https://github.com/logaretm/vee-validate/issues/3815)) ([e6e1c1d](https://github.com/logaretm/vee-validate/commit/e6e1c1d66bfd4c453ac21c00b3faa2d6470040a8))\n- added useFieldModel to useForm API ([26c828e](https://github.com/logaretm/vee-validate/commit/26c828e21495c485d489ea1319575d9b5c271801))\n- allow keep values config to be reactive ([5009bd8](https://github.com/logaretm/vee-validate/commit/5009bd88c09f7a8c753fc52dd5bf8d4d5234567b))\n- better normalization for native input file events ([2751552](https://github.com/logaretm/vee-validate/commit/2751552a42b4eaa57d22ea24c38cd31cfd5b9955))\n- Remove yup type dependency ([#3704](https://github.com/logaretm/vee-validate/issues/3704)) ([e772f9a](https://github.com/logaretm/vee-validate/commit/e772f9a7b9f0e45680a65dfae249ee2092ca850e))\n- Sync useField with component v-model ([#3806](https://github.com/logaretm/vee-validate/issues/3806)) ([0ef7582](https://github.com/logaretm/vee-validate/commit/0ef75823d1b90e1213f8a31014c2cf347d386ec1))\n\n## [4.5.11](https://github.com/logaretm/vee-validate/compare/v4.5.10...v4.5.11) (2022-04-10)\n\n### Bug Fixes\n\n- ignore validation of removed array elements closes [#3748](https://github.com/logaretm/vee-validate/issues/3748) ([3d49faa](https://github.com/logaretm/vee-validate/commit/3d49faa4101902c2e77aee0a2d43cd29b69f7b4e))\n\n### Features\n\n- chain of GenericValidateFunction in useField ([#3725](https://github.com/logaretm/vee-validate/issues/3725)) ([#3726](https://github.com/logaretm/vee-validate/issues/3726)) ([8db4077](https://github.com/logaretm/vee-validate/commit/8db407785c5611c10c221eabd747c3f31770145b))\n\n## [4.5.10](https://github.com/logaretm/vee-validate/compare/v4.5.9...v4.5.10) (2022-03-08)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.5.9](https://github.com/logaretm/vee-validate/compare/v4.5.8...v4.5.9) (2022-02-22)\n\n### Bug Fixes\n\n- mark fields validated via form validate as validated ([ad9fa9d](https://github.com/logaretm/vee-validate/commit/ad9fa9d853a8cabb26cdde04c20c07d4f2673aa4))\n\n## [4.5.8](https://github.com/logaretm/vee-validate/compare/v4.5.7...v4.5.8) (2022-01-23)\n\n### Bug Fixes\n\n- clear old error path error when changing field name closes [#3664](https://github.com/logaretm/vee-validate/issues/3664) ([f736e62](https://github.com/logaretm/vee-validate/commit/f736e62b1bb82f940d14d74a6d505c913c1c3dde))\n- field array swap not working when falsy values are present at paths ([40afbd9](https://github.com/logaretm/vee-validate/commit/40afbd9cc3fb3de71de3f6ebb0a1b2774d9018ff))\n\n## [4.5.7](https://github.com/logaretm/vee-validate/compare/v4.5.6...v4.5.7) (2021-12-07)\n\n### Bug Fixes\n\n- always attach model update event closes [#3583](https://github.com/logaretm/vee-validate/issues/3583) ([6a53e80](https://github.com/logaretm/vee-validate/commit/6a53e80525a9c38ce8851407b832bc8409c3f334))\n\n## [4.5.6](https://github.com/logaretm/vee-validate/compare/v4.5.5...v4.5.6) (2021-11-17)\n\n### Bug Fixes\n\n- corrected the typing for the resetField function closes [#3568](https://github.com/logaretm/vee-validate/issues/3568) ([4e9460e](https://github.com/logaretm/vee-validate/commit/4e9460e3a4f51f4a78ddcdf17f7c3073f899404f))\n- new devtools typings ([f288ca5](https://github.com/logaretm/vee-validate/commit/f288ca5a59d36f23ba7f6bdd210493588f744940))\n- use watchEffect to compute form meta closes [#3580](https://github.com/logaretm/vee-validate/issues/3580) ([e8729dc](https://github.com/logaretm/vee-validate/commit/e8729dc72d2a027a666515360c9537a62a8d46ad))\n\n## [4.5.5](https://github.com/logaretm/vee-validate/compare/v4.5.4...v4.5.5) (2021-11-01)\n\n### Bug Fixes\n\n- prevent toggle checkboxes when form resets closes [#3551](https://github.com/logaretm/vee-validate/issues/3551) ([cad12ba](https://github.com/logaretm/vee-validate/commit/cad12ba7502af7268029930a9176d8e160efeef6))\n\n## [4.5.4](https://github.com/logaretm/vee-validate/compare/v4.5.3...v4.5.4) (2021-10-20)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.5.3](https://github.com/logaretm/vee-validate/compare/v4.5.2...v4.5.3) (2021-10-17)\n\n### Features\n\n- added slot typings for components closes [#3534](https://github.com/logaretm/vee-validate/issues/3534) ([#3537](https://github.com/logaretm/vee-validate/issues/3537)) ([52a2a38](https://github.com/logaretm/vee-validate/commit/52a2a385ec6e65c7eaaed0a67615c45aba07de64))\n\n## [4.5.2](https://github.com/logaretm/vee-validate/compare/v4.5.1...v4.5.2) (2021-09-30)\n\n### Bug Fixes\n\n- use klona/full mode to handle luxon values closes [#3508](https://github.com/logaretm/vee-validate/issues/3508) ([048c9c0](https://github.com/logaretm/vee-validate/commit/048c9c03d38ffd871ee4b3504daf1c83d42e9516))\n\n## [4.5.1](https://github.com/logaretm/vee-validate/compare/v4.5.0...v4.5.1) (2021-09-29)\n\n**Note:** Version bump only for package vee-validate\n\n# [4.5.0](https://github.com/logaretm/vee-validate/compare/v4.4.11...v4.5.0) (2021-09-26)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.4.11](https://github.com/logaretm/vee-validate/compare/v4.4.10...v4.4.11) (2021-09-11)\n\n### Bug Fixes\n\n- dynamic rule forcing validation closes [#3485](https://github.com/logaretm/vee-validate/issues/3485) ([d3f0fc0](https://github.com/logaretm/vee-validate/commit/d3f0fc094c89375bd67bdd3f533e5ab545a83611))\n\n## [4.4.10](https://github.com/logaretm/vee-validate/compare/v4.4.9...v4.4.10) (2021-08-31)\n\n### Bug Fixes\n\n- added silent validation run after reset closes [#3463](https://github.com/logaretm/vee-validate/issues/3463) ([a61f7ab](https://github.com/logaretm/vee-validate/commit/a61f7ab532d6d2fd9f237145f91bbcc9043431f6))\n- handle absent model value closes [#3468](https://github.com/logaretm/vee-validate/issues/3468) ([2c4a7ff](https://github.com/logaretm/vee-validate/commit/2c4a7ffb84811ae86a1698e6e15f41dc32f8fb8d))\n- **types:** remove arguments of PrivateFieldContext.handleReset ([2e45d1f](https://github.com/logaretm/vee-validate/commit/2e45d1f8a8444c0aabfd307364cadfab74802d02))\n- ensure option bound value type is preserved closes [#3440](https://github.com/logaretm/vee-validate/issues/3440) ([b144615](https://github.com/logaretm/vee-validate/commit/b1446152d6f6cd4843ab206d667a7d744c2a14fc))\n\n## [4.4.9](https://github.com/logaretm/vee-validate/compare/v4.4.8...v4.4.9) (2021-08-05)\n\n### Bug Fixes\n\n- ensure to clone user passed values in setters closes [#3428](https://github.com/logaretm/vee-validate/issues/3428) ([a720c24](https://github.com/logaretm/vee-validate/commit/a720c2444b64d28743ba0500aa970419029352cb))\n- prioritize the current value if another field of same name is mounted closes [#3429](https://github.com/logaretm/vee-validate/issues/3429) ([cf036ec](https://github.com/logaretm/vee-validate/commit/cf036ecf9a5dad401c752c132ef5333d0f442441))\n\n## [4.4.8](https://github.com/logaretm/vee-validate/compare/v4.4.7...v4.4.8) (2021-07-31)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.4.7](https://github.com/logaretm/vee-validate/compare/v4.4.6...v4.4.7) (2021-07-20)\n\n### Bug Fixes\n\n- avoid watching values at the end of reset calls closes [#3407](https://github.com/logaretm/vee-validate/issues/3407) ([86f594f](https://github.com/logaretm/vee-validate/commit/86f594f4a7cee5ed5f581419bdbd985fc53f8358))\n\n### Features\n\n- add standalone prop for fields ([#3379](https://github.com/logaretm/vee-validate/issues/3379)) ([3689437](https://github.com/logaretm/vee-validate/commit/36894378aa3636eeb4fb54aa747319e21c6eb5cd))\n- expose FieldContext type closes [#3398](https://github.com/logaretm/vee-validate/issues/3398) ([a6e4c0a](https://github.com/logaretm/vee-validate/commit/a6e4c0ac580d4145c72118ac535bfa082c771068))\n- expose form and field injection keys ([6034e66](https://github.com/logaretm/vee-validate/commit/6034e66836e0566e17f36744da19088aca33fbad))\n\n## [4.4.6](https://github.com/logaretm/vee-validate/compare/v4.4.5...v4.4.6) (2021-07-08)\n\n### Bug Fixes\n\n- clean error message for singular fields after unmount ([#3385](https://github.com/logaretm/vee-validate/issues/3385)) ([4e81cce](https://github.com/logaretm/vee-validate/commit/4e81cce292380974728b952a2fa1724c1ea4f086))\n- quit unsetting path if its already unset ([cfe45ba](https://github.com/logaretm/vee-validate/commit/cfe45ba38690ec27b5ee4e48a80336834a932a78))\n- expose setters in composition API ([d79747d](https://github.com/logaretm/vee-validate/commit/d79747de4a25d1ced151d9bd5b767e815d7e32bf))\n\n## [4.4.5](https://github.com/logaretm/vee-validate/compare/v4.4.4...v4.4.5) (2021-06-13)\n\n## [4.4.4](https://github.com/logaretm/vee-validate/compare/v4.4.3...v4.4.4) (2021-06-05)\n\n### Bug Fixes\n\n- field with pre-register schema errors should be validated on register closes [#3342](https://github.com/logaretm/vee-validate/issues/3342) ([61c7359](https://github.com/logaretm/vee-validate/commit/61c73597b2e69c094e75c02476d825c5236710b5))\n- make sure to create the container path if it exists while null or undefined ([79d3779](https://github.com/logaretm/vee-validate/commit/79d37798ccf2fef56714bdad4db553086df0ad48))\n- make sure to create the container path if it exists while null or undefined ([79d3779](https://github.com/logaretm/vee-validate/commit/79d37798ccf2fef56714bdad4db553086df0ad48))\n\n### Features\n\n- expose setters in composition API ([61f942f](https://github.com/logaretm/vee-validate/commit/61f942f511e6fcceb10a74272ac845017ce88997))\n\n## [4.4.3](https://github.com/logaretm/vee-validate/compare/v4.4.2...v4.4.3) (2021-06-02)\n\n### Bug Fixes\n\n- respect the Field bails option closes [#3332](https://github.com/logaretm/vee-validate/issues/3332) ([6679387](https://github.com/logaretm/vee-validate/commit/66793878e317f32f4759b3d01e27e3b9072eff67))\n\n## [4.4.2](https://github.com/logaretm/vee-validate/compare/v4.4.1...v4.4.2) (2021-05-28)\n\n### Bug Fixes\n\n- clean up the old values path when fields exchange names fixes [#3325](https://github.com/logaretm/vee-validate/issues/3325) ([fe51c12](https://github.com/logaretm/vee-validate/commit/fe51c126ae6258ac0888ee47d9d01a27b889a5c1))\n\n## [4.4.1](https://github.com/logaretm/vee-validate/compare/v4.4.0...v4.4.1) (2021-05-24)\n\n### Bug Fixes\n\n- forgot adding errors in useValidationForm ([d032d3b](https://github.com/logaretm/vee-validate/commit/d032d3b55438169fa87c18d89e073fffe3988d56))\n- re-introduce the errors prop back on the form validation result closes [#3317](https://github.com/logaretm/vee-validate/issues/3317) ([b439a73](https://github.com/logaretm/vee-validate/commit/b439a73bf3c37298c251b74223984d54b8949a95))\n\n# [4.4.0](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.2...v4.4.0) (2021-05-23)\n\n### Bug Fixes\n\n- seperate model detection from event emitting closes [#3312](https://github.com/logaretm/vee-validate/issues/3312) ([5e72852](https://github.com/logaretm/vee-validate/commit/5e72852e80b971121d10422cf84085b07bb2d8fb))\n\n# [4.4.0-alpha.2](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.1...v4.4.0-alpha.2) (2021-05-14)\n\n### Bug Fixes\n\n- avoid clearing all errors before validating schema ([51c2e78](https://github.com/logaretm/vee-validate/commit/51c2e7890b87d971850dfc609c09d19b79a96fb6))\n\n# [4.4.0-alpha.1](https://github.com/logaretm/vee-validate/compare/v4.4.0-alpha.0...v4.4.0-alpha.1) (2021-05-14)\n\n### Bug Fixes\n\n- minifier issue when handling await ([f206cac](https://github.com/logaretm/vee-validate/commit/f206cacd7e0d03a36fce5b236c23906997e0287b))\n\n# [4.4.0-alpha.0](https://github.com/logaretm/vee-validate/compare/v4.3.6...v4.4.0-alpha.0) (2021-05-14)\n\n### Bug Fixes\n\n- deprecate handleInput and use handleChange for both events ([#3303](https://github.com/logaretm/vee-validate/issues/3303)) ([4cb10de](https://github.com/logaretm/vee-validate/commit/4cb10de0a5f589f72c82cdd4a8859b7f044ae84c))\n\n### Features\n\n- custom values and errors ([#3305](https://github.com/logaretm/vee-validate/issues/3305)) ([427802b](https://github.com/logaretm/vee-validate/commit/427802b94ea309d12df26ba51ac1b3a24e4e8d46))\n\n## [4.3.6](https://github.com/logaretm/vee-validate/compare/v4.3.5...v4.3.6) (2021-05-08)\n\n### Bug Fixes\n\n- added a symbol to detect non passed props with Vue 3.1.x ([#3295](https://github.com/logaretm/vee-validate/issues/3295)) ([0663539](https://github.com/logaretm/vee-validate/commit/06635397424526c3a3c4a53f63322bbfd55000ee))\n\n## [4.3.5](https://github.com/logaretm/vee-validate/compare/v4.3.4...v4.3.5) (2021-05-01)\n\n### Bug Fixes\n\n- priotrize self injections over parent injections closes [#3270](https://github.com/logaretm/vee-validate/issues/3270) ([07c1234](https://github.com/logaretm/vee-validate/commit/07c12341d7f2e25e41a56ea0d5e38e9a374ae84b))\n\n## [4.3.4](https://github.com/logaretm/vee-validate/compare/v4.3.3...v4.3.4) (2021-04-27)\n\n### Bug Fixes\n\n- update the valid flag regardless of mode closes [#3284](https://github.com/logaretm/vee-validate/issues/3284) ([6594ad1](https://github.com/logaretm/vee-validate/commit/6594ad15e4423c6a7861da188560b06f98365d9d))\n\n## [4.3.3](https://github.com/logaretm/vee-validate/compare/v4.3.2...v4.3.3) (2021-04-22)\n\n### Features\n\n- touch all fields on submit ([#3278](https://github.com/logaretm/vee-validate/issues/3278)) ([fc4e400](https://github.com/logaretm/vee-validate/commit/fc4e400f7d9349c1e82bba8412d13e0cf69be0e1))\n\n## [4.3.2](https://github.com/logaretm/vee-validate/compare/v4.3.1...v4.3.2) (2021-04-21)\n\n### Bug Fixes\n\n- unwrap initial value with useField.resetField fixes [#3272](https://github.com/logaretm/vee-validate/issues/3272) ([#3274](https://github.com/logaretm/vee-validate/issues/3274)) ([f6e9574](https://github.com/logaretm/vee-validate/commit/f6e95741f31fc085f718e07d3b1f1adfe0229df6))\n\n## [4.3.1](https://github.com/logaretm/vee-validate/compare/v4.3.0...v4.3.1) (2021-04-18)\n\n### Bug Fixes\n\n- give error message component a name ([b7dcebf](https://github.com/logaretm/vee-validate/commit/b7dcebfcd202538cf082314817f97c3b8e07fefb))\n- minor perf enhancement by lazy evaulation of slot props ([a306b1b](https://github.com/logaretm/vee-validate/commit/a306b1b0047ec82eaf727a6e380856de077c4fbe))\n\n# [4.3.0](https://github.com/logaretm/vee-validate/compare/v4.2.4...v4.3.0) (2021-04-07)\n\n### Features\n\n- added support for reactive schemas ([#3238](https://github.com/logaretm/vee-validate/issues/3238)) ([295d656](https://github.com/logaretm/vee-validate/commit/295d6567035bc3c452ad0f13fce13ff362b08005))\n- added support for setting multiple field errors closes [#3117](https://github.com/logaretm/vee-validate/issues/3117) ([db0a6a0](https://github.com/logaretm/vee-validate/commit/db0a6a02cdc0fdab02a18e4756005c46dc06b1f8))\n- support v-model.number ([#3252](https://github.com/logaretm/vee-validate/issues/3252)) ([8f491da](https://github.com/logaretm/vee-validate/commit/8f491da0b0998d0f7383a6a444d6aa498e3d96f4))\n\n## [4.2.4](https://github.com/logaretm/vee-validate/compare/v4.2.3...v4.2.4) (2021-03-26)\n\n### Bug Fixes\n\n- validation triggered on value change ([10549b7](https://github.com/logaretm/vee-validate/commit/10549b77dc350cee4f198cb14e3fd12f61e12b80))\n\n## [4.2.3](https://github.com/logaretm/vee-validate/compare/v4.2.2...v4.2.3) (2021-03-22)\n\n### Bug Fixes\n\n- prevent yup schema from setting non-interacted fields errors closes [#3228](https://github.com/logaretm/vee-validate/issues/3228) ([534f8b2](https://github.com/logaretm/vee-validate/commit/534f8b28850c9f28245a748f956d1358bb7cb2e1))\n\n## [4.2.2](https://github.com/logaretm/vee-validate/compare/v4.2.1...v4.2.2) (2021-03-03)\n\n### Bug Fixes\n\n- ensure having a truthy fallback for fields missing in schema ([7cd6941](https://github.com/logaretm/vee-validate/commit/7cd694114403f7c252b6ba6b83c159110cdc58cf))\n- handle pending validation runs during field unmounting ([ef5a7cc](https://github.com/logaretm/vee-validate/commit/ef5a7ccb269db8bbdee446e76dd60ebe8704b57e))\n\n## [4.2.1](https://github.com/logaretm/vee-validate/compare/v4.2.0...v4.2.1) (2021-02-26)\n\n### Bug Fixes\n\n- added initial check against the field errors ([4288fb6](https://github.com/logaretm/vee-validate/commit/4288fb6291a3ed17d46569fd2b0baa690beb9cb1))\n\n# [4.2.0](https://github.com/logaretm/vee-validate/compare/v4.1.20...v4.2.0) (2021-02-24)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.1.20](https://github.com/logaretm/vee-validate/compare/v4.1.19...v4.1.20) (2021-02-24)\n\n### Bug Fixes\n\n- avoid setting checkbox values before registeration closes [#3183](https://github.com/logaretm/vee-validate/issues/3183) ([ab5f821](https://github.com/logaretm/vee-validate/commit/ab5f82103f8cfe5f5934a51057ce989ad30d0d44))\n- change errors source to form closes [#3177](https://github.com/logaretm/vee-validate/issues/3177) ([7c13c92](https://github.com/logaretm/vee-validate/commit/7c13c92f477bc3d63067509fd9fec72964263f5d))\n- use the issues array for zod error aggregation closes [#3184](https://github.com/logaretm/vee-validate/issues/3184) ([01b89e4](https://github.com/logaretm/vee-validate/commit/01b89e4940e997ef65dc950be3a13e0ffc18e881))\n\n## [4.1.19](https://github.com/logaretm/vee-validate/compare/v4.1.18...v4.1.19) (2021-02-16)\n\n### Bug Fixes\n\n- use relative imports for shared type ([6790545](https://github.com/logaretm/vee-validate/commit/6790545dc9c35550d231fb14a310f3655dbc7256))\n\n### Features\n\n- improve typing for field yup schema ([c59f1f0](https://github.com/logaretm/vee-validate/commit/c59f1f01526b160a1081f276d732523ad9ab5ba2))\n\n## [4.1.18](https://github.com/logaretm/vee-validate/compare/v4.1.17...v4.1.18) (2021-02-10)\n\n### Bug Fixes\n\n- avoid unsetting field value if switched with another closes [#3166](https://github.com/logaretm/vee-validate/issues/3166) ([f5a79fe](https://github.com/logaretm/vee-validate/commit/f5a79fe3b15f7437acf183c162e69178fd4fa7ec))\n\n## [4.1.17](https://github.com/logaretm/vee-validate/compare/v3.2.0...v4.1.17) (2021-02-08)\n\n### Bug Fixes\n\n- add a handler for regex object params closes [#3073](https://github.com/logaretm/vee-validate/issues/3073) ([7a5e2eb](https://github.com/logaretm/vee-validate/commit/7a5e2ebf8303395372ae08ebcca55427a58faecb))\n- added emits and onSubmit custom prop ([#3115](https://github.com/logaretm/vee-validate/issues/3115)) ([8f2c110](https://github.com/logaretm/vee-validate/commit/8f2c110f14add0fbd82a28a91601e89938144624))\n- array radio fields not switching value correctly closes [#3141](https://github.com/logaretm/vee-validate/issues/3141) ([3d4efef](https://github.com/logaretm/vee-validate/commit/3d4efef68c63a3b57e2bf14fed913dbf841a7f5e))\n- avoid returning undefined for form errors when form does not exist ([8cce17a](https://github.com/logaretm/vee-validate/commit/8cce17ae2846be912d51926c79e557ed8bb39582))\n- avoid validating dependencies via watcheffect closes [#3156](https://github.com/logaretm/vee-validate/issues/3156) ([a7b91f6](https://github.com/logaretm/vee-validate/commit/a7b91f6e6c38f0b5262e2d4c1814154efa3b78c8))\n- cast radio buttons value correctly closes [#3064](https://github.com/logaretm/vee-validate/issues/3064) ([3e0f9a4](https://github.com/logaretm/vee-validate/commit/3e0f9a47369edac32d0c8a068f8b61d8f761458f))\n- clear out initial values for unregistered fields closes [#3060](https://github.com/logaretm/vee-validate/issues/3060) ([56206de](https://github.com/logaretm/vee-validate/commit/56206de995fe8f2eaca3e303ab6980784a3c95b1))\n- correctly set the initial value from the v-model closes [#3107](https://github.com/logaretm/vee-validate/issues/3107) ([4bed9a8](https://github.com/logaretm/vee-validate/commit/4bed9a806323139d2f274e51b6bfe3de2190e54d))\n- export submission types [#3112](https://github.com/logaretm/vee-validate/issues/3112) ([3f35167](https://github.com/logaretm/vee-validate/commit/3f351670da02364b0fb8e61198145dfa02dc59b9))\n- fill the target rule params for message generators closes [#3077](https://github.com/logaretm/vee-validate/issues/3077) ([f5e1bd3](https://github.com/logaretm/vee-validate/commit/f5e1bd3cbc278a8588fa0c96af66823d82eefb8c))\n- handle formless checkboxes value toggling closes [#3105](https://github.com/logaretm/vee-validate/issues/3105) ([504f30b](https://github.com/logaretm/vee-validate/commit/504f30bfcbcb1db710397ef05545b5008b0103fb))\n- handle reactive field names and value swaps ([cf8051d](https://github.com/logaretm/vee-validate/commit/cf8051d3b92eb43103f4e7c682e615343239d717))\n- missing export for useErrors helpers ([28537cc](https://github.com/logaretm/vee-validate/commit/28537cc547cf945b10adc485620ad226f71d60fc))\n- pass down listeners to the input node closes [#3048](https://github.com/logaretm/vee-validate/issues/3048) ([2526a63](https://github.com/logaretm/vee-validate/commit/2526a63c2361e412b528cf370c03b39cb84b606d))\n- prevent default reset behavior with handleReset ([a66df13](https://github.com/logaretm/vee-validate/commit/a66df13c3f39d84984581dc3c0ce368b052b6e8e))\n- prevent resetForm from toggling checkbox value [#3084](https://github.com/logaretm/vee-validate/issues/3084) ([38778f9](https://github.com/logaretm/vee-validate/commit/38778f96471b6aa16fb020cfb1bde56b77a19cfb))\n- react to validation events changes ([078e61b](https://github.com/logaretm/vee-validate/commit/078e61b17bd299a28752b733b494a0ddb368a812))\n- reset meta correctly with resetField ([012658c](https://github.com/logaretm/vee-validate/commit/012658c082a00b1beeb53ce8cf3fcd91bc5b21ec))\n- resolve component before rendering closes [#3014](https://github.com/logaretm/vee-validate/issues/3014) ([f8f481d](https://github.com/logaretm/vee-validate/commit/f8f481daad754a4b18a91e2b07b9549433d023f9))\n- resolve path values with global rules closes [#3157](https://github.com/logaretm/vee-validate/issues/3157) ([beaf316](https://github.com/logaretm/vee-validate/commit/beaf3168490aee585542a19c9a910d9493e78208))\n- set field initial value on the fid lookup closes [#3128](https://github.com/logaretm/vee-validate/issues/3128) ([650d5cf](https://github.com/logaretm/vee-validate/commit/650d5cf9f75f9b9247fc813acf2aff4089f05415))\n- support dynamic labels closes [#3053](https://github.com/logaretm/vee-validate/issues/3053) ([31b2238](https://github.com/logaretm/vee-validate/commit/31b223878bda75c3150217ea80bb878d8dc1e320))\n- typing issue from [#3134](https://github.com/logaretm/vee-validate/issues/3134) ([29e5cff](https://github.com/logaretm/vee-validate/commit/29e5cffc654a2502f29fe616eda088de958e02d3))\n- use the custom injection fn for initial field values ([38cd32b](https://github.com/logaretm/vee-validate/commit/38cd32bd3ae9f263510d0ab4a1713c6a9a2011af))\n\n### Features\n\n- add submit count state ([#3070](https://github.com/logaretm/vee-validate/issues/3070)) ([a7fe71e](https://github.com/logaretm/vee-validate/commit/a7fe71e01072dacfeb7baa80eebf0b8d7d9d3ffd))\n- added context awareness to composition helpers for fields ([b59fe88](https://github.com/logaretm/vee-validate/commit/b59fe88197ce3cd587edfc33666bcb676030fa61))\n- added context information to validation functions ([7e6675d](https://github.com/logaretm/vee-validate/commit/7e6675db6a103eae33cbb6d959621b4549af66b2))\n- added test cases and fallbacks for unresolved cases ([71bda03](https://github.com/logaretm/vee-validate/commit/71bda03a72a9e8f27bc0b7620ce78ba48a194309))\n- added the useResetForm helper ([4c57715](https://github.com/logaretm/vee-validate/commit/4c57715ab621526a5c987cff9a53cb5b7af2155a))\n- added unchecked-value prop to the field component ([af910c3](https://github.com/logaretm/vee-validate/commit/af910c3f3c6343538658ab90f356dd8957bb6a1a))\n- added useErrors and useField error helpers ([4cda2fe](https://github.com/logaretm/vee-validate/commit/4cda2fea6428a7f10b53b633daa46252bf779289))\n- added useIsDirty helpers ([6b7e4ab](https://github.com/logaretm/vee-validate/commit/6b7e4abfcdb2f0eebe0dd8c62785178fbee8d25f))\n- added useIsSubmitting helper ([7a58fd8](https://github.com/logaretm/vee-validate/commit/7a58fd840425a5e09f625054389aebbb096c2e1a))\n- added useIsTouched helpers ([fdb2d5a](https://github.com/logaretm/vee-validate/commit/fdb2d5a3c7c82d55aefef2deb95823e1ba6ba93d))\n- added useIsValid helpers ([26fbb29](https://github.com/logaretm/vee-validate/commit/26fbb29467bab66c159e98793e4269768845b938))\n- added useSubmitCount helper ([c4a6dea](https://github.com/logaretm/vee-validate/commit/c4a6deae68b588494ff0e2477d7ec2b9302c6f09))\n- added useSubmitForm hook ([#3101](https://github.com/logaretm/vee-validate/issues/3101)) ([d042882](https://github.com/logaretm/vee-validate/commit/d04288295a090328f7022641799dbaee1c404b91))\n- added useValidateField and useValidateForm helpers ([62355a8](https://github.com/logaretm/vee-validate/commit/62355a8db6477562f0689208669d0a1be63de03c))\n- added validate field function to form and useForm ([#3133](https://github.com/logaretm/vee-validate/issues/3133)) ([926bed1](https://github.com/logaretm/vee-validate/commit/926bed1bded6990f17a51ca68e9aa47c339a80f2))\n- added validate method on the form ref instance closes [#3030](https://github.com/logaretm/vee-validate/issues/3030) ([ed0faff](https://github.com/logaretm/vee-validate/commit/ed0faffd79615830a9f7c247abf1eae2254ee3f9))\n- added validation trigger config per component closes [#3066](https://github.com/logaretm/vee-validate/issues/3066) ([f0e30a2](https://github.com/logaretm/vee-validate/commit/f0e30a2cc79843040028b7070bc88846f2447c85))\n- added value change support for native multi select ([#3146](https://github.com/logaretm/vee-validate/issues/3146)) ([0601586](https://github.com/logaretm/vee-validate/commit/0601586eabbf76fac9d4fa79e6ae1d86fd3a0e37))\n- added values helpers ([e0f16d6](https://github.com/logaretm/vee-validate/commit/e0f16d6f5c01c7b1e4e8832b3490b8cc7e7b8aa7))\n- added warnings for non existent fields and allow reactive paths ([4182d2f](https://github.com/logaretm/vee-validate/commit/4182d2f1716d712962dff3b6be27916e311e5870))\n- avoid watching rules when passed as functions ([539f753](https://github.com/logaretm/vee-validate/commit/539f7535bf935e62030b83f8c7b19e95256bcc52))\n- dont render any tags when no message exists closes [#3118](https://github.com/logaretm/vee-validate/issues/3118) ([92eba41](https://github.com/logaretm/vee-validate/commit/92eba41a2cdef643bc2af4c2a0366382cdffc625))\n- enhance ts typing for form functions ([8f7d8e8](https://github.com/logaretm/vee-validate/commit/8f7d8e89864b5df5255cbe5e88713022537ec236))\n- enhance useField types ([dcb8049](https://github.com/logaretm/vee-validate/commit/dcb80495ffdefb2e789887e1d40b2c4a57ade257))\n- enrich form validation results ([0c84c80](https://github.com/logaretm/vee-validate/commit/0c84c809fa729cd2b8620329305b4da0a45e9eaf))\n- export some internal types closes [#3065](https://github.com/logaretm/vee-validate/issues/3065) ([b88dffd](https://github.com/logaretm/vee-validate/commit/b88dffdb4c638bd439d093f653bfa1915f4ad9be))\n- field.reset() should reset the field to its initial value ([a11f1b7](https://github.com/logaretm/vee-validate/commit/a11f1b7dda3deafe683e13a00b28a7fab09b82cb))\n- implement similar reset API for fields ([38c3923](https://github.com/logaretm/vee-validate/commit/38c392320b4154061ccc5d70dde11517357467e8))\n- new reset API ([6983738](https://github.com/logaretm/vee-validate/commit/69837383e42636c24d6ee7d15cb5fe8e98f2ac55))\n- rename reset methods to be more consistent ([3a0dc4d](https://github.com/logaretm/vee-validate/commit/3a0dc4db2f1a00a8a4f3940ddd452d9b1369cace))\n- update docs ([0f5ac98](https://github.com/logaretm/vee-validate/commit/0f5ac98153f74bdbbd1d9f5090e4dc4b438c998f))\n- use internal yup types ([#3123](https://github.com/logaretm/vee-validate/issues/3123)) ([7554bfc](https://github.com/logaretm/vee-validate/commit/7554bfc49b0103f218f901148bc06e6a455f09b0))\n- use resolveDynamicComponent instead ([f1b5f89](https://github.com/logaretm/vee-validate/commit/f1b5f896840ed159df06cf59badd83282496b777))\n\n### Performance Improvements\n\n- cache field props in a computed property ([d266878](https://github.com/logaretm/vee-validate/commit/d2668787d0ffcab5ba2e8be048ee7334d2b0f9e7))\n- cache form slot props in a computed property ([49fa2c1](https://github.com/logaretm/vee-validate/commit/49fa2c1b4a337149c533c13725d2e71bb2664706))\n\n## [4.1.16](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.15...vee-validate@4.1.16) (2021-02-07)\n\n**Note:** Version bump only for package vee-validate\n\n## [4.1.15](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.14...vee-validate@4.1.15) (2021-02-07)\n\n### Bug Fixes\n\n- resolve path values with global rules closes [#3157](https://github.com/logaretm/vee-validate/issues/3157) ([beaf316](https://github.com/logaretm/vee-validate/commit/beaf3168490aee585542a19c9a910d9493e78208))\n\n## [4.1.14](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.13...vee-validate@4.1.14) (2021-02-06)\n\n### Bug Fixes\n\n- avoid validating dependencies via watcheffect closes [#3156](https://github.com/logaretm/vee-validate/issues/3156) ([a7b91f6](https://github.com/logaretm/vee-validate/commit/a7b91f6e6c38f0b5262e2d4c1814154efa3b78c8))\n\n## [4.1.13](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.12...vee-validate@4.1.13) (2021-02-01)\n\n### Features\n\n- added value change support for native multi select ([#3146](https://github.com/logaretm/vee-validate/issues/3146)) ([0601586](https://github.com/logaretm/vee-validate/commit/0601586eabbf76fac9d4fa79e6ae1d86fd3a0e37))\n\n## [4.1.12](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.11...vee-validate@4.1.12) (2021-01-26)\n\n### Bug Fixes\n\n- array radio fields not switching value correctly closes [#3141](https://github.com/logaretm/vee-validate/issues/3141) ([3d4efef](https://github.com/logaretm/vee-validate/commit/3d4efef68c63a3b57e2bf14fed913dbf841a7f5e))\n- clear out initial values for unregistered fields closes [#3060](https://github.com/logaretm/vee-validate/issues/3060) ([56206de](https://github.com/logaretm/vee-validate/commit/56206de995fe8f2eaca3e303ab6980784a3c95b1))\n- typing issue from [#3134](https://github.com/logaretm/vee-validate/issues/3134) ([29e5cff](https://github.com/logaretm/vee-validate/commit/29e5cffc654a2502f29fe616eda088de958e02d3))\n\n## [4.1.11](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.10...vee-validate@4.1.11) (2021-01-19)\n\n### Features\n\n- added validate field function to form and useForm ([#3133](https://github.com/logaretm/vee-validate/issues/3133)) ([926bed1](https://github.com/logaretm/vee-validate/commit/926bed1bded6990f17a51ca68e9aa47c339a80f2))\n\n## [4.1.10](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.9...vee-validate@4.1.10) (2021-01-17)\n\n### Bug Fixes\n\n- set field initial value on the fid lookup closes [#3128](https://github.com/logaretm/vee-validate/issues/3128) ([650d5cf](https://github.com/logaretm/vee-validate/commit/650d5cf9f75f9b9247fc813acf2aff4089f05415))\n\n## [4.1.9](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.8...vee-validate@4.1.9) (2021-01-13)\n\n### Features\n\n- use internal yup types ([#3123](https://github.com/logaretm/vee-validate/issues/3123)) ([7554bfc](https://github.com/logaretm/vee-validate/commit/7554bfc49b0103f218f901148bc06e6a455f09b0))\n\n## [4.1.8](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.7...vee-validate@4.1.8) (2021-01-12)\n\n### Features\n\n- dont render any tags when no message exists closes [#3118](https://github.com/logaretm/vee-validate/issues/3118) ([92eba41](https://github.com/logaretm/vee-validate/commit/92eba41a2cdef643bc2af4c2a0366382cdffc625))\n\n## [4.1.7](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.6...vee-validate@4.1.7) (2021-01-12)\n\n### Bug Fixes\n\n- export submission types [#3112](https://github.com/logaretm/vee-validate/issues/3112) ([3f35167](https://github.com/logaretm/vee-validate/commit/3f351670da02364b0fb8e61198145dfa02dc59b9))\n\n## [4.1.6](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.5...vee-validate@4.1.6) (2021-01-11)\n\n### Bug Fixes\n\n- added emits and onSubmit custom prop ([#3115](https://github.com/logaretm/vee-validate/issues/3115)) ([8f2c110](https://github.com/logaretm/vee-validate/commit/8f2c110f14add0fbd82a28a91601e89938144624))\n\n## [4.1.5](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.4...vee-validate@4.1.5) (2021-01-05)\n\n### Bug Fixes\n\n- correctly set the initial value from the v-model closes [#3107](https://github.com/logaretm/vee-validate/issues/3107) ([4bed9a8](https://github.com/logaretm/vee-validate/commit/4bed9a806323139d2f274e51b6bfe3de2190e54d))\n\n## [4.1.4](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.3...vee-validate@4.1.4) (2021-01-04)\n\n### Bug Fixes\n\n- handle formless checkboxes value toggling closes [#3105](https://github.com/logaretm/vee-validate/issues/3105) ([504f30b](https://github.com/logaretm/vee-validate/commit/504f30bfcbcb1db710397ef05545b5008b0103fb))\n\n## [4.1.3](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.2...vee-validate@4.1.3) (2021-01-02)\n\n### Features\n\n- enhance useField types ([dcb8049](https://github.com/logaretm/vee-validate/commit/dcb80495ffdefb2e789887e1d40b2c4a57ade257))\n\n## [4.1.2](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.1...vee-validate@4.1.2) (2020-12-26)\n\n### Features\n\n- added useSubmitForm hook ([#3101](https://github.com/logaretm/vee-validate/issues/3101)) ([d042882](https://github.com/logaretm/vee-validate/commit/d04288295a090328f7022641799dbaee1c404b91))\n\n## [4.1.1](https://github.com/logaretm/vee-validate/compare/vee-validate@4.1.0...vee-validate@4.1.1) (2020-12-18)\n\n### Bug Fixes\n\n- missing export for useErrors helpers ([28537cc](https://github.com/logaretm/vee-validate/commit/28537cc547cf945b10adc485620ad226f71d60fc))\n\n# [4.1.0](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.7...vee-validate@4.1.0) (2020-12-18)\n\n### Bug Fixes\n\n- avoid returning undefined for form errors when form does not exist ([8cce17a](https://github.com/logaretm/vee-validate/commit/8cce17ae2846be912d51926c79e557ed8bb39582))\n\n### Features\n\n- added context awareness to composition helpers for fields ([b59fe88](https://github.com/logaretm/vee-validate/commit/b59fe88197ce3cd587edfc33666bcb676030fa61))\n- added test cases and fallbacks for unresolved cases ([71bda03](https://github.com/logaretm/vee-validate/commit/71bda03a72a9e8f27bc0b7620ce78ba48a194309))\n- added the useResetForm helper ([4c57715](https://github.com/logaretm/vee-validate/commit/4c57715ab621526a5c987cff9a53cb5b7af2155a))\n- added useErrors and useField error helpers ([4cda2fe](https://github.com/logaretm/vee-validate/commit/4cda2fea6428a7f10b53b633daa46252bf779289))\n- added useIsDirty helpers ([6b7e4ab](https://github.com/logaretm/vee-validate/commit/6b7e4abfcdb2f0eebe0dd8c62785178fbee8d25f))\n- added useIsSubmitting helper ([7a58fd8](https://github.com/logaretm/vee-validate/commit/7a58fd840425a5e09f625054389aebbb096c2e1a))\n- added useIsTouched helpers ([fdb2d5a](https://github.com/logaretm/vee-validate/commit/fdb2d5a3c7c82d55aefef2deb95823e1ba6ba93d))\n- added useIsValid helpers ([26fbb29](https://github.com/logaretm/vee-validate/commit/26fbb29467bab66c159e98793e4269768845b938))\n- added useSubmitCount helper ([c4a6dea](https://github.com/logaretm/vee-validate/commit/c4a6deae68b588494ff0e2477d7ec2b9302c6f09))\n- added useValidateField and useValidateForm helpers ([62355a8](https://github.com/logaretm/vee-validate/commit/62355a8db6477562f0689208669d0a1be63de03c))\n- added values helpers ([e0f16d6](https://github.com/logaretm/vee-validate/commit/e0f16d6f5c01c7b1e4e8832b3490b8cc7e7b8aa7))\n- added warnings for non existent fields and allow reactive paths ([4182d2f](https://github.com/logaretm/vee-validate/commit/4182d2f1716d712962dff3b6be27916e311e5870))\n- enhance ts typing for form functions ([8f7d8e8](https://github.com/logaretm/vee-validate/commit/8f7d8e89864b5df5255cbe5e88713022537ec236))\n- enrich form validation results ([0c84c80](https://github.com/logaretm/vee-validate/commit/0c84c809fa729cd2b8620329305b4da0a45e9eaf))\n- export some internal types closes [#3065](https://github.com/logaretm/vee-validate/issues/3065) ([b88dffd](https://github.com/logaretm/vee-validate/commit/b88dffdb4c638bd439d093f653bfa1915f4ad9be))\n\n## [4.0.7](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.6...vee-validate@4.0.7) (2020-12-18)\n\n### Bug Fixes\n\n- react to validation events changes ([078e61b](https://github.com/logaretm/vee-validate/commit/078e61b17bd299a28752b733b494a0ddb368a812))\n\n## [4.0.6](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.5...vee-validate@4.0.6) (2020-12-15)\n\n### Bug Fixes\n\n- prevent default reset behavior with handleReset ([a66df13](https://github.com/logaretm/vee-validate/commit/a66df13c3f39d84984581dc3c0ce368b052b6e8e))\n- prevent resetForm from toggling checkbox value [#3084](https://github.com/logaretm/vee-validate/issues/3084) ([38778f9](https://github.com/logaretm/vee-validate/commit/38778f96471b6aa16fb020cfb1bde56b77a19cfb))\n\n### Features\n\n- added unchecked-value prop to the field component ([af910c3](https://github.com/logaretm/vee-validate/commit/af910c3f3c6343538658ab90f356dd8957bb6a1a))\n\n### Performance Improvements\n\n- cache field props in a computed property ([d266878](https://github.com/logaretm/vee-validate/commit/d2668787d0ffcab5ba2e8be048ee7334d2b0f9e7))\n- cache form slot props in a computed property ([49fa2c1](https://github.com/logaretm/vee-validate/commit/49fa2c1b4a337149c533c13725d2e71bb2664706))\n\n## [4.0.5](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.4...vee-validate@4.0.5) (2020-12-12)\n\n### Features\n\n- added validation trigger config per component closes [#3066](https://github.com/logaretm/vee-validate/issues/3066) ([f0e30a2](https://github.com/logaretm/vee-validate/commit/f0e30a2cc79843040028b7070bc88846f2447c85))\n\n## [4.0.4](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.3...vee-validate@4.0.4) (2020-12-09)\n\n### Bug Fixes\n\n- add a handler for regex object params closes [#3073](https://github.com/logaretm/vee-validate/issues/3073) ([7a5e2eb](https://github.com/logaretm/vee-validate/commit/7a5e2ebf8303395372ae08ebcca55427a58faecb))\n- fill the target rule params for message generators closes [#3077](https://github.com/logaretm/vee-validate/issues/3077) ([f5e1bd3](https://github.com/logaretm/vee-validate/commit/f5e1bd3cbc278a8588fa0c96af66823d82eefb8c))\n\n### Features\n\n- add submit count state ([#3070](https://github.com/logaretm/vee-validate/issues/3070)) ([a7fe71e](https://github.com/logaretm/vee-validate/commit/a7fe71e01072dacfeb7baa80eebf0b8d7d9d3ffd))\n\n## [4.0.3](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.2...vee-validate@4.0.3) (2020-12-05)\n\n### Bug Fixes\n\n- cast radio buttons value correctly closes [#3064](https://github.com/logaretm/vee-validate/issues/3064) ([3e0f9a4](https://github.com/logaretm/vee-validate/commit/3e0f9a47369edac32d0c8a068f8b61d8f761458f))\n- reset meta correctly with resetField ([012658c](https://github.com/logaretm/vee-validate/commit/012658c082a00b1beeb53ce8cf3fcd91bc5b21ec))\n- use the custom injection fn for initial field values ([38cd32b](https://github.com/logaretm/vee-validate/commit/38cd32bd3ae9f263510d0ab4a1713c6a9a2011af))\n\n## [4.0.2](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.1...vee-validate@4.0.2) (2020-11-27)\n\n### Bug Fixes\n\n- support dynamic labels closes [#3053](https://github.com/logaretm/vee-validate/issues/3053) ([31b2238](https://github.com/logaretm/vee-validate/commit/31b223878bda75c3150217ea80bb878d8dc1e320))\n\n## [4.0.1](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0...vee-validate@4.0.1) (2020-11-25)\n\n### Bug Fixes\n\n- pass down listeners to the input node closes [#3048](https://github.com/logaretm/vee-validate/issues/3048) ([2526a63](https://github.com/logaretm/vee-validate/commit/2526a63c2361e412b528cf370c03b39cb84b606d))\n\n# [4.0.0](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.19...vee-validate@4.0.0) (2020-11-16)\n\n### Features\n\n- added validate method on the form ref instance closes [#3030](https://github.com/logaretm/vee-validate/issues/3030) ([ed0faff](https://github.com/logaretm/vee-validate/commit/ed0faffd79615830a9f7c247abf1eae2254ee3f9))\n- update docs ([0f5ac98](https://github.com/logaretm/vee-validate/commit/0f5ac98153f74bdbbd1d9f5090e4dc4b438c998f))\n\n# [4.0.0-beta.19](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.18...vee-validate@4.0.0-beta.19) (2020-11-07)\n\n### Bug Fixes\n\n- resolve component before rendering closes [#3014](https://github.com/logaretm/vee-validate/issues/3014) ([f8f481d](https://github.com/logaretm/vee-validate/commit/f8f481daad754a4b18a91e2b07b9549433d023f9))\n\n### Features\n\n- field.reset() should reset the field to its initial value ([a11f1b7](https://github.com/logaretm/vee-validate/commit/a11f1b7dda3deafe683e13a00b28a7fab09b82cb))\n- implement similar reset API for fields ([38c3923](https://github.com/logaretm/vee-validate/commit/38c392320b4154061ccc5d70dde11517357467e8))\n- new reset API ([6983738](https://github.com/logaretm/vee-validate/commit/69837383e42636c24d6ee7d15cb5fe8e98f2ac55))\n- rename reset methods to be more consistent ([3a0dc4d](https://github.com/logaretm/vee-validate/commit/3a0dc4db2f1a00a8a4f3940ddd452d9b1369cace))\n- use resolveDynamicComponent instead ([f1b5f89](https://github.com/logaretm/vee-validate/commit/f1b5f896840ed159df06cf59badd83282496b777))\n\n# [4.0.0-beta.18](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.17...vee-validate@4.0.0-beta.18) (2020-11-05)\n\n### Bug Fixes\n\n- handle reactive field names and value swaps ([cf8051d](https://github.com/logaretm/vee-validate/commit/cf8051d3b92eb43103f4e7c682e615343239d717))\n\n### Features\n\n- avoid watching rules when passed as functions ([539f753](https://github.com/logaretm/vee-validate/commit/539f7535bf935e62030b83f8c7b19e95256bcc52))\n\n# [4.0.0-beta.17](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.16...vee-validate@4.0.0-beta.17) (2020-11-04)\n\n### Features\n\n- added context information to validation functions ([7e6675d](https://github.com/logaretm/vee-validate/commit/7e6675db6a103eae33cbb6d959621b4549af66b2))\n\n# [4.0.0-beta.16](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.15...vee-validate@4.0.0-beta.16) (2020-10-29)\n\n### Features\n\n- initial form meta ([#3003](https://github.com/logaretm/vee-validate/issues/3003)) ([f7fd407](https://github.com/logaretm/vee-validate/commit/f7fd407cf0e6dad9c92585a4a82594af962de8f4))\n\n# [4.0.0-beta.15](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.14...vee-validate@4.0.0-beta.15) (2020-10-28)\n\n### Features\n\n- add `initialErrors` prop ([#3002](https://github.com/logaretm/vee-validate/issues/3002)) ([9850b3f](https://github.com/logaretm/vee-validate/commit/9850b3f2f1c1739f31ff05f32890196097ef426e))\n\n# [4.0.0-beta.14](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.13...vee-validate@4.0.0-beta.14) (2020-10-26)\n\n### Features\n\n- deprecate the disabled prop ([29f4dca](https://github.com/logaretm/vee-validate/commit/29f4dca6bd4d02281bf71f8ed4c836f30e0e46d0))\n- use injection keys to type inject API ([79207b2](https://github.com/logaretm/vee-validate/commit/79207b25a23782acc527394af23703b138c881db))\n\n# [4.0.0-beta.13](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.12...vee-validate@4.0.0-beta.13) (2020-10-23)\n\n### Features\n\n- `useForm` Field types ([#2996](https://github.com/logaretm/vee-validate/issues/2996)) ([727f229](https://github.com/logaretm/vee-validate/commit/727f2295d421ef92620995a356bcaee53770299b))\n\n# [4.0.0-beta.12](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.11...vee-validate@4.0.0-beta.12) (2020-10-21)\n\n### Bug Fixes\n\n- upgrade to Vue 3.0.2 and fix broken cases ([ede7214](https://github.com/logaretm/vee-validate/commit/ede72147bd998b888825457541ff964df5e7a2fd))\n\n# [4.0.0-beta.11](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.10...vee-validate@4.0.0-beta.11) (2020-10-18)\n\n### Bug Fixes\n\n- provide yup object schema type to the useForm closes [#2988](https://github.com/logaretm/vee-validate/issues/2988) ([29157f7](https://github.com/logaretm/vee-validate/commit/29157f7a36dd14dc9a6c411ffddbbeb9d3749f6e))\n\n# [4.0.0-beta.10](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.9...vee-validate@4.0.0-beta.10) (2020-10-15)\n\n### Bug Fixes\n\n- properly initialize initial values closes [#2978](https://github.com/logaretm/vee-validate/issues/2978) ([c0ba699](https://github.com/logaretm/vee-validate/commit/c0ba699757cbd2c3ab409d5ee8d2fa3a205907d8))\n- typos in test descriptions ([#2970](https://github.com/logaretm/vee-validate/issues/2970)) ([a0132df](https://github.com/logaretm/vee-validate/commit/a0132dfcc2aab4ba48f175b846228544c80fe4a8))\n\n# [4.0.0-beta.9](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.8...vee-validate@4.0.0-beta.9) (2020-10-14)\n\n### Bug Fixes\n\n- improve useForm meta types ([#2963](https://github.com/logaretm/vee-validate/issues/2963)) ([6b46047](https://github.com/logaretm/vee-validate/commit/6b46047278633a095243fcce4ba94ddd94e08c11))\n\n### Features\n\n- meta setters ([#2967](https://github.com/logaretm/vee-validate/issues/2967)) ([5036e13](https://github.com/logaretm/vee-validate/commit/5036e13e0f5974589387746398446fa5f318dc0d))\n\n# [4.0.0-beta.8](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.7...vee-validate@4.0.0-beta.8) (2020-10-12)\n\n### Features\n\n- added handleInput and handleBlur to field scoped slot props ([69d5833](https://github.com/logaretm/vee-validate/commit/69d5833e85d1f455fa43de83251c634b8efa89fa))\n- expose reset() on the form controller object ([3229ee7](https://github.com/logaretm/vee-validate/commit/3229ee722e8df5f2e79155e1a4e5ec4729dff726))\n- new meta tags API ([#2958](https://github.com/logaretm/vee-validate/issues/2958)) ([7494bfc](https://github.com/logaretm/vee-validate/commit/7494bfc6533fa29bd0668294d694aca96721d52d))\n- remove aria attributes and leave it to userland ([365d825](https://github.com/logaretm/vee-validate/commit/365d825b9bc3e2955b31b941f12d5856c9be8bfe))\n- remove valid fields from errors mapping ([1eee524](https://github.com/logaretm/vee-validate/commit/1eee52407f4d7156a541811053b529f7540c931c))\n\n# [4.0.0-beta.7](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.6...vee-validate@4.0.0-beta.7) (2020-10-10)\n\n### Bug Fixes\n\n- avoid accessing properties in form directly to avoid warninings ([c5627af](https://github.com/logaretm/vee-validate/commit/c5627af64b252c8f7ec18e7f0a4296f315c7bf99))\n- update the handleSubmit signature ([#2954](https://github.com/logaretm/vee-validate/issues/2954)) ([d17517d](https://github.com/logaretm/vee-validate/commit/d17517daf692c48ac4fa1cfce5ac0bb051e73d2e))\n\n# [4.0.0-beta.6](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.5...vee-validate@4.0.0-beta.6) (2020-10-10)\n\n### Features\n\n- form and fields values setters ([#2949](https://github.com/logaretm/vee-validate/issues/2949)) ([cc2cb41](https://github.com/logaretm/vee-validate/commit/cc2cb413dfa23aefeb8be6e4bf7fa17927e0e1ce))\n- reactive initial form values ([#2946](https://github.com/logaretm/vee-validate/issues/2946)) ([ac2c68f](https://github.com/logaretm/vee-validate/commit/ac2c68fdbfb7062674f8294a1f0f6d33fc8792b3))\n\n# [4.0.0-beta.5](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.4...vee-validate@4.0.0-beta.5) (2020-10-08)\n\n### Bug Fixes\n\n- sync model value on input closes [#2944](https://github.com/logaretm/vee-validate/issues/2944) ([5f77fa9](https://github.com/logaretm/vee-validate/commit/5f77fa931bdb01cc6415c4edd1dcaa7eb7e1a0d2))\n\n# [4.0.0-beta.4](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.3...vee-validate@4.0.0-beta.4) (2020-10-08)\n\n### Bug Fixes\n\n- prevent recursive re-render model update ([#2943](https://github.com/logaretm/vee-validate/issues/2943)) ([9fa319f](https://github.com/logaretm/vee-validate/commit/9fa319f0e42f8225565e2f54d1bebd07898574a4))\n- set falsy initial values ([4b29e72](https://github.com/logaretm/vee-validate/commit/4b29e721f06fe30a5f7207935ae3d6291ea464fe))\n- use validateField instead of onChange handler for blur events ([636077a](https://github.com/logaretm/vee-validate/commit/636077a35183b33372825cd4075a143383ed0c68))\n\n# [4.0.0-beta.3](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.2...vee-validate@4.0.0-beta.3) (2020-10-06)\n\n### Bug Fixes\n\n- avoid toggling checkbox `checked` attr in `handleChange` ([#2937](https://github.com/logaretm/vee-validate/issues/2937)) ([b8dafbd](https://github.com/logaretm/vee-validate/commit/b8dafbdb75e305f00c6effc21391f364db9236d0))\n\n### Features\n\n- added `validateOnMount` prop to `Field` and `Form` components ([#2938](https://github.com/logaretm/vee-validate/issues/2938)) ([3a0d878](https://github.com/logaretm/vee-validate/commit/3a0d878e453163f305acc87c5d4c93812f77f340))\n\n# [4.0.0-beta.2](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.1...vee-validate@4.0.0-beta.2) (2020-10-05)\n\n### Features\n\n- field labels ([#2933](https://github.com/logaretm/vee-validate/issues/2933)) ([513137f](https://github.com/logaretm/vee-validate/commit/513137f28c6266d3e752448b00eb1c3d410ae474))\n\n# [4.0.0-beta.1](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-beta.0...vee-validate@4.0.0-beta.1) (2020-10-02)\n\n### Bug Fixes\n\n- avoid binding the value to file inputs ([02a2745](https://github.com/logaretm/vee-validate/commit/02a27456ba961540a882ec4f94a24a271b0ea3a3))\n\n# [4.0.0-beta.0](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.14...vee-validate@4.0.0-beta.0) (2020-10-01)\n\n### Bug Fixes\n\n- make sure to unwrap initial value ([0298a92](https://github.com/logaretm/vee-validate/commit/0298a926de5536154a69088b55cb688133638a39))\n\n### Features\n\n- validation triggers ([#2927](https://github.com/logaretm/vee-validate/issues/2927)) ([e725f43](https://github.com/logaretm/vee-validate/commit/e725f43a47dd1993699c0450fd8777aa921c7a49))\n\n# [4.0.0-alpha.14](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.13...vee-validate@4.0.0-alpha.14) (2020-09-20)\n\n### Bug Fixes\n\n- **core:** in case of radio or checkbox explicitly set initialValue ([#2907](https://github.com/logaretm/vee-validate/issues/2907)) ([e45ec82](https://github.com/logaretm/vee-validate/commit/e45ec82ee8fa6fabd4d3012a03ba8f9b72854631))\n\n### Features\n\n- use symbols to avoid provide/inject conflicts ([cc80032](https://github.com/logaretm/vee-validate/commit/cc8003213c34a8a33d84802f2c93598e1ac3c6f0))\n- workspaces ([#2904](https://github.com/logaretm/vee-validate/issues/2904)) ([0c05f94](https://github.com/logaretm/vee-validate/commit/0c05f9486a73744273de6816f00f689916aba91c))\n\n# [4.0.0-alpha.13](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.12...vee-validate@4.0.0-alpha.13) (2020-09-16)\n\n### Features\n\n- nested objects/arrays ([#2897](https://github.com/logaretm/vee-validate/issues/2897)) ([8d161a1](https://github.com/logaretm/vee-validate/commit/8d161a137a65c90ec8f7189743be24802231cf29))\n\n# [4.0.0-alpha.12](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.11...vee-validate@4.0.0-alpha.12) (2020-09-15)\n\n### Features\n\n- cast single checkboxes values to booleans closes [#2889](https://github.com/logaretm/vee-validate/issues/2889) ([7a08184](https://github.com/logaretm/vee-validate/commit/7a081845ac6a4bc09c51e52c5996b65814a48baf))\n- invoke generateMessage handler for local functions closes [#2893](https://github.com/logaretm/vee-validate/issues/2893) ([e9fe773](https://github.com/logaretm/vee-validate/commit/e9fe77365877edda51548c9539ec085fff91586b))\n\n# [4.0.0-alpha.11](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.10...vee-validate@4.0.0-alpha.11) (2020-09-02)\n\n**Note:** Version bump only for package vee-validate\n\n# [4.0.0-alpha.10](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.9...vee-validate@4.0.0-alpha.10) (2020-08-29)\n\n### Bug Fixes\n\n- added temporary fix for [#2873](https://github.com/logaretm/vee-validate/issues/2873) with form meta ([6e1bf17](https://github.com/logaretm/vee-validate/commit/6e1bf176e7ba5c890afab6c11731dac54924d39b))\n\n# [4.0.0-alpha.9](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.8...vee-validate@4.0.0-alpha.9) (2020-08-28)\n\n### Bug Fixes\n\n- adapt to the breaking changes in #vue-1682 closes [#2873](https://github.com/logaretm/vee-validate/issues/2873) ([05f7df3](https://github.com/logaretm/vee-validate/commit/05f7df313f9f47ca79bdf99be35cb2ccfea0c346))\n\n# [4.0.0-alpha.8](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.7...vee-validate@4.0.0-alpha.8) (2020-08-13)\n\n### Bug Fixes\n\n- detect initial values from v-model ([e566302](https://github.com/logaretm/vee-validate/commit/e566302bb485353f03baccdf98f35a255605e15d))\n- handle unmount issue when removed value is falsy for checkboxes ([b6393f4](https://github.com/logaretm/vee-validate/commit/b6393f4adce9346cadaf1f423dca29645bf3c2f1))\n- initial array values for checkboxes not populated correctly in form ([fb99edc](https://github.com/logaretm/vee-validate/commit/fb99edc309c26f9be2baa71f90ec1ac59ddcdc9d))\n- umounting group of checkbox issues ([8c77af5](https://github.com/logaretm/vee-validate/commit/8c77af52955b235a6bd2357a35036097e109e37f))\n\n### Features\n\n- added basic v-model support ([c93d125](https://github.com/logaretm/vee-validate/commit/c93d125b4d6c0af8365920ee577c883493e60648))\n- merge ctx.attrs to any rendered root node ([5c9979c](https://github.com/logaretm/vee-validate/commit/5c9979ce45d4ab10cd019ad0c25159e013198301))\n- sync the model value with inner value ([57d7923](https://github.com/logaretm/vee-validate/commit/57d79232f490be3525c2576ef83376a2f5643386))\n\n# [4.0.0-alpha.7](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.6...vee-validate@4.0.0-alpha.7) (2020-08-04)\n\n### Bug Fixes\n\n- avoid removing array value for a non-group field closes [#2847](https://github.com/logaretm/vee-validate/issues/2847) ([69f2092](https://github.com/logaretm/vee-validate/commit/69f2092db7d53665986dd384cae561d1b13bd8f5))\n- bails affects yup non-object validators ([a50645b](https://github.com/logaretm/vee-validate/commit/a50645b1c0206d0e7d85ec6681ff6dc224536fa2))\n- initial values on HTML inputs ([c4f4eb9](https://github.com/logaretm/vee-validate/commit/c4f4eb9fe97b13fedb93ac760614eb53c177ffb3))\n\n### Features\n\n- deprecate the skipOptional config ([e62f5ea](https://github.com/logaretm/vee-validate/commit/e62f5ea6d31e82ac9f257627e8544431b933c4f9))\n\n# [4.0.0-alpha.6](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.5...vee-validate@4.0.0-alpha.6) (2020-07-27)\n\n### Bug Fixes\n\n- render input tags by default for the field component ([858c47b](https://github.com/logaretm/vee-validate/commit/858c47b4a7fa740611abaf026e6e5db6cdb41050))\n\n# [4.0.0-alpha.5](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.4...vee-validate@4.0.0-alpha.5) (2020-07-24)\n\n### Bug Fixes\n\n- unregister fields once they are unmounted ([0d601cb](https://github.com/logaretm/vee-validate/commit/0d601cb60b3ba907e6c0d73dd129c0c7b086316e))\n\n### Features\n\n- **v4:** add checkbox and radio HTML input support ([#2835](https://github.com/logaretm/vee-validate/issues/2835)) ([ab3d499](https://github.com/logaretm/vee-validate/commit/ab3d4998caf5950656dc0476f13215d598b28832))\n- render input by default for the field component ([81d055d](https://github.com/logaretm/vee-validate/commit/81d055d704deaa12b392fd9197218733b3a0bb8d))\n\n# [4.0.0-alpha.4](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.3...vee-validate@4.0.0-alpha.4) (2020-07-23)\n\n**Note:** Version bump only for package vee-validate\n\n# [4.0.0-alpha.3](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.2...vee-validate@4.0.0-alpha.3) (2020-07-21)\n\n### Features\n\n- automatic injection of the form controller ([c039831](https://github.com/logaretm/vee-validate/commit/c0398318ec70c925b6bcb2afa859ec89488e1f78))\n- remove debounce feature and make it userland ([b7263ce](https://github.com/logaretm/vee-validate/commit/b7263ce0f887388709846975b59965e440636089))\n\n# [4.0.0-alpha.2](https://github.com/logaretm/vee-validate/compare/vee-validate@4.0.0-alpha.1...vee-validate@4.0.0-alpha.2) (2020-07-19)\n\n### Features\n\n- always render a from by default ([402603a](https://github.com/logaretm/vee-validate/commit/402603a8f755a377a056debf24815611a01c3037))\n\n# 4.0.0-alpha.1 (2020-07-18)\n\n### Bug Fixes\n\n- added check for cross-fields extraction on unsupported schema ([0ff1bad](https://github.com/logaretm/vee-validate/commit/0ff1bad84a90189f11897cada01fd091e5593bb7))\n- added errorMessage prop to the field type ([f1553d0](https://github.com/logaretm/vee-validate/commit/f1553d01b94a74580700fd8712b67688f9c89c15))\n- added single error message prop to the provider slot props ([bc97d0c](https://github.com/logaretm/vee-validate/commit/bc97d0c6463cd7e466bb7b3555671e7891d4c60b))\n- added unwrap util function ([121bffc](https://github.com/logaretm/vee-validate/commit/121bffc05a9c6e2e204b843d5eb8d7678e5d0fff))\n- adjust the useField options to be less strict ([7ea8263](https://github.com/logaretm/vee-validate/commit/7ea826373a78b4fa6343f1da9db0e43879fa0e4e))\n- check if a form is present before accessing its schema ([3656181](https://github.com/logaretm/vee-validate/commit/3656181b17a6e44c8f470570ee5126cf2a83ae41))\n- debouncing not working correctly and move it to hoc only ([86280a1](https://github.com/logaretm/vee-validate/commit/86280a15e9fb1f94ef8c042a9d04d437f38936b0))\n- ensure we unwrap the field id if it was reactive ([7f91e93](https://github.com/logaretm/vee-validate/commit/7f91e930ec8cce4f2e17b49ee9d642d7e9343d6f))\n- initial validation not respecting the config opts ([2443d44](https://github.com/logaretm/vee-validate/commit/2443d44b1b00eda39ff884f33f85414aa2b1d34e))\n- localization default fallback not being interpolated correctly ([165e89c](https://github.com/logaretm/vee-validate/commit/165e89c6136126d6b946640623261f32b299a2a3))\n- no clue why this isn't building ([0d3e7fd](https://github.com/logaretm/vee-validate/commit/0d3e7fdea6f28e29d25f488cae527e925608da7e))\n- only add novalidate attr if the rendered element is form ([3638cea](https://github.com/logaretm/vee-validate/commit/3638cead19c9501783e23b43248ce49d7bdf51d7))\n- param mapping causing target names to resolve incorrectly ([fb77dc6](https://github.com/logaretm/vee-validate/commit/fb77dc673cb1eff72a1508cff7b4aaed60d8450e))\n- set pending back to false earlier in the cycle ([a4237a2](https://github.com/logaretm/vee-validate/commit/a4237a2f8dfde5efcc1d39b5a400e988b8740df9))\n- temporary fix for the unamed import issue with vue-beta 4 ([62d27e9](https://github.com/logaretm/vee-validate/commit/62d27e9c9293026d26d62709c2e691d3eb15753e))\n- unwrap flags before sending them to the observer slot ([19f7886](https://github.com/logaretm/vee-validate/commit/19f7886adae59b4442139f6e1a3f3905ab54f86a))\n- use the proper model event name ([5704db8](https://github.com/logaretm/vee-validate/commit/5704db879019b89b001f496f5f113df24ad09bc6))\n- watch target fields once they change ([a4184b0](https://github.com/logaretm/vee-validate/commit/a4184b0065c26df77b680cfbda7450a81b6764ef))\n\n### Features\n\n- adapt the changes from the v3 master branch ([2301c5a](https://github.com/logaretm/vee-validate/commit/2301c5ae75eb8590cb2cc919215ffe4ae934b885))\n- add name resolution from v3 ([ba77fdd](https://github.com/logaretm/vee-validate/commit/ba77fdde4f7e5400c6755331af4705715ecc885b))\n- add native submit alternative to handleSubmit ([bc00888](https://github.com/logaretm/vee-validate/commit/bc008880607f0393c4e6bd9eb2d44ebb40aa3604))\n- added 'as' prop to the validation provider ([5c8ae9c](https://github.com/logaretm/vee-validate/commit/5c8ae9cac2dd418c5bf78b8a0c68e7d256dc96ce))\n- added alert role to the error message ([714abfe](https://github.com/logaretm/vee-validate/commit/714abfede6cb2cd2ab1dd72319d27630af6fe9b6))\n- added aria and a11y improvements ([ca74f16](https://github.com/logaretm/vee-validate/commit/ca74f165988be3c0c5a6f828508b6aed3fd6e3a0))\n- added built-in support for yup validation schema ([e436b75](https://github.com/logaretm/vee-validate/commit/e436b75c4b8b7a085adf701d07b54b798da9a774))\n- added ErrorMessage component ([9570412](https://github.com/logaretm/vee-validate/commit/957041270b947e1b70301c3935b6d1ac0bb05a5d))\n- added support for custom components ([c661c7e](https://github.com/logaretm/vee-validate/commit/c661c7e1f352e2806c2e2da7bc2c860cfa62f3ff))\n- added useField and useForm hooks ([c1e9007](https://github.com/logaretm/vee-validate/commit/c1e900736ed9585d8997d2080f001aad28060281))\n- allow the as prop to be a component definition ([29790d4](https://github.com/logaretm/vee-validate/commit/29790d47f17fe49c897bf5b2fda0508f57990479))\n- allow the observer to render forms and handle submit events ([9e0d59b](https://github.com/logaretm/vee-validate/commit/9e0d59b11d239c7f1e6d4bc287d9e49aa0376f0d))\n- allow validation schema to accept other expressions ([ddeeaea](https://github.com/logaretm/vee-validate/commit/ddeeaea8041c3fad894aff0c827dd9f71b65224d))\n- change default field value to undefiend ([00c8754](https://github.com/logaretm/vee-validate/commit/00c87549244447423e0833f8294c5c607bdcf105))\n- deprecate names option on validate API ([fe90820](https://github.com/logaretm/vee-validate/commit/fe90820b4b0d4d10df81c2bbd019c3b63d371edf))\n- deprecate the 'required' flag ([283caa0](https://github.com/logaretm/vee-validate/commit/283caa0fdd353d990680d42e64be8d8362b6aad5))\n- enable interaction modes and localization APIs ([8486aaf](https://github.com/logaretm/vee-validate/commit/8486aaf0fadba03f38b5dd8a5ab857c10e7aa49c))\n- expose errorMessage prop on useField and Provider ([04eecaa](https://github.com/logaretm/vee-validate/commit/04eecaa13cc8ab0cc18336021bb912f924e37968))\n- expose the form values and pass them to the handleSubmit ([de51155](https://github.com/logaretm/vee-validate/commit/de511555c371bef73037d514e19d44eb4d292eae))\n- hook up the provider with new observer implementation ([4d18a65](https://github.com/logaretm/vee-validate/commit/4d18a6572af6af4630bdc2508e027e67d3c0d579))\n- implement bails for useField and ValidationProvider ([486babd](https://github.com/logaretm/vee-validate/commit/486babd031efd5a71a819ff535a0e0c661bc45fe))\n- implement initial values ([8239130](https://github.com/logaretm/vee-validate/commit/82391301152751eb03097dad4521dc1c275c47e7))\n- implement validation debounce ([e294409](https://github.com/logaretm/vee-validate/commit/e2944099ef2074d59f908f7949df3a1059ab3b4e))\n- implemented disabled prop ([88bf28e](https://github.com/logaretm/vee-validate/commit/88bf28e89d9e635ebbc79e593a326d4dd2025cdb))\n- make rules watchable ([90530cd](https://github.com/logaretm/vee-validate/commit/90530cdebede5bf33a62221371380ad8554326ba))\n- make the as prop take priority to determine what to render ([d5a033f](https://github.com/logaretm/vee-validate/commit/d5a033fc57b7ddea8aff4a0f4fe802d7c2489a9c))\n- new field binding object ([a58a84b](https://github.com/logaretm/vee-validate/commit/a58a84b009fef5dbfffa2a93a54643b3830cb4bc))\n- new handleSubmit signature ([63cbeaf](https://github.com/logaretm/vee-validate/commit/63cbeafd1cfb5e1e14ec42e34c0691a26b258897))\n- only export the provider for now ([0bf3efe](https://github.com/logaretm/vee-validate/commit/0bf3efe230be2d80b9e4693779e095c04997a52b))\n- remove vid from fields ([1b9bded](https://github.com/logaretm/vee-validate/commit/1b9bdedeb68006535c7087aef267906e2f7bed1d))\n- support immediate validation ([42cd6ed](https://github.com/logaretm/vee-validate/commit/42cd6edcfc0c11ea05106e66486ed4772c749548))\n- support inline rules as functions ([3c74681](https://github.com/logaretm/vee-validate/commit/3c7468186ac5a6e7fa6bb44b30de4102ef5c31cd))\n- support yup validation schemas on field-level ([0802512](https://github.com/logaretm/vee-validate/commit/0802512e181a8a33feaa227770f9e203fcf0cea5))\n- updated vnode utils to handle Vue 3 VNode API ([29a4fe8](https://github.com/logaretm/vee-validate/commit/29a4fe859823d5a74814c2dabb3b664185e56366))\n- use defineComponent to type Provider and Observer definitions ([80980cf](https://github.com/logaretm/vee-validate/commit/80980cfec81447638aa82b42c208f9ec6f9826f8))\n- validate yup form schemas using object validation ([bf216dd](https://github.com/logaretm/vee-validate/commit/bf216dde30a6d90c976bac844129ccbd08a00392))\n- validation schema support ([523824a](https://github.com/logaretm/vee-validate/commit/523824a0977d599f6ff2a271ee2edebd5aef36ef))\n- working draft for the vprovider with composition api ([b830054](https://github.com/logaretm/vee-validate/commit/b8300547cbafa9904f2b769b8309925ad6da180f))\n"
  },
  {
    "path": "packages/vee-validate/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) Abdelrahman Awad <logaretm1@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "packages/vee-validate/README.md",
    "content": "<p align=\"center\">\r\n  <a href=\"https://vee-validate.logaretm.com\" target=\"_blank\">\r\n    <img src=\"https://raw.githubusercontent.com/logaretm/vee-validate/main/logo.png\" width=\"200\" title=\"Go to website\">\r\n  </a>\r\n</p>\r\n\r\n<p align=\"center\">\r\nPainless Vue forms\r\n</p>\r\n\r\n<p align=\"center\">\r\n\r\n<a target=\"_blank\" href=\"https://www.npmjs.com/package/vee-validate\">\r\n  <img src=\"https://img.shields.io/npm/v/vee-validate.svg?label=&color=05bda8\">\r\n</a>\r\n\r\n<a target=\"_blank\" href=\"https://npm-stat.com/charts.html?package=vee-validate\">\r\n  <img src=\"https://img.shields.io/npm/dm/vee-validate.svg?color=05bd6d&label=\">\r\n</a>\r\n\r\n<a href=\"https://vee-validate.logaretm.com/v5/\" target=\"_blank\">\r\n  <img src=\"https://img.shields.io/badge/-docs%20and%20demos-009f53\">\r\n</a>\r\n\r\n<a href=\"https://github.com/sponsors/logaretm\">\r\n  <img src=\"https://img.shields.io/badge/-%E2%99%A5%20Sponsors-ec5cc6\">\r\n\r\n</a>\r\n\r\n</p>\r\n\r\n<br>\r\n\r\n<p align=\"center\">\r\n  <a href=\"https://github.com/sponsors/logaretm\">\r\n    <img src='https://sponsors.logaretm.com/sponsors.svg'>\r\n  </a>\r\n</p>\r\n\r\n<br>\r\n\r\n## Features\r\n\r\n- **🍞 Easy:** Declarative validation that is familiar and easy to setup\r\n- **🧘‍♀️ Flexible:** Synchronous, Asynchronous, field-level or form-level validation\r\n- **⚡️ Fast:** Build faster forms faster with intuitive API and small footprint\r\n- **🏏 Minimal:** Only handles the complicated form concerns, gives you full control over everything else\r\n- **😎 UI Agnostic:** Works with native HTML elements or your favorite UI library components\r\n- **🦾 Progressive:** Works whether you use Vue.js as a progressive enhancement or in a complex setup\r\n- **✅ Built-in Rules:** Companion lib with 25+ Rules that covers most needs in most web applications\r\n- **🌐 i18n:** 45+ locales for built-in rules contributed by developers from all over the world\r\n\r\n## Getting Started\r\n\r\n### Installation\r\n\r\n```sh\r\n# Install with yarn\r\nyarn add vee-validate\r\n\r\n# Install with npm\r\nnpm install vee-validate --save\r\n```\r\n\r\n### Vue version support\r\n\r\nThe main v4 version supports Vue 3.x only, for previous versions of Vue, check the following the table\r\n\r\n| vue Version | vee-validate version | Documentation Link                                                                       |\r\n| ----------- | -------------------- | ---------------------------------------------------------------------------------------- |\r\n| `2.x`       | `2.x` or `3.x`       | [v2](https://vee-validate.logaretm.com/v2) or [v3](https://vee-validate.logaretm.com/v3) |\r\n| `3.x`       | `4.x` or `5.x`       | [v4](https://vee-validate.logaretm.com/v4) or [v5](https://vee-validate.logaretm.com/v5) |\r\n\r\n### Usage\r\n\r\nvee-validate offers two styles to integrate form validation into your Vue.js apps.\r\n\r\n#### Composition API\r\n\r\nThe fastest way to create a form and manage its validation, behavior, and values is with the composition API.\r\n\r\nCreate your form with `useForm` and then use `defineField` to create your field model and props/attributes and `handleSubmit` to use the values and send them to an API.\r\n\r\n```vue\r\n<script setup>\r\nimport { useForm } from 'vee-validate';\r\n\r\n// Validation, or use `yup` or `zod`\r\nfunction required(value) {\r\n  return value ? true : 'This field is required';\r\n}\r\n\r\n// Create the form\r\nconst { defineField, handleSubmit, errors } = useForm({\r\n  validationSchema: {\r\n    field: required,\r\n  },\r\n});\r\n\r\n// Define fields\r\nconst [field, fieldProps] = defineField('field');\r\n\r\n// Submit handler\r\nconst onSubmit = handleSubmit(values => {\r\n  // Submit to API\r\n  console.log(values);\r\n});\r\n</script>\r\n\r\n<template>\r\n  <form @submit=\"onSubmit\">\r\n    <input v-model=\"field\" v-bind=\"fieldProps\" />\r\n    <span>{{ errors.field }}</span>\r\n\r\n    <button>Submit</button>\r\n  </form>\r\n</template>\r\n```\r\n\r\nYou can do so much more than this, for more info [check the composition API documentation](https://vee-validate.logaretm.com/v5/guide/composition-api/getting-started/).\r\n\r\n#### Declarative Components\r\n\r\nHigher-order components can also be used to build forms. Register the `Field` and `Form` components and create a simple `required` validator:\r\n\r\n```vue\r\n<script setup>\r\nimport { Field, Form } from 'vee-validate';\r\n\r\n// Validation, or use `yup` or `zod`\r\nfunction required(value) {\r\n  return value ? true : 'This field is required';\r\n}\r\n\r\n// Submit handler\r\nfunction onSubmit(values) {\r\n  // Submit to API\r\n  console.log(values);\r\n}\r\n</script>\r\n\r\n<template>\r\n  <Form v-slot=\"{ errors }\" @submit=\"onSubmit\">\r\n    <Field name=\"field\" :rules=\"required\" />\r\n\r\n    <span>{{ errors.field }}</span>\r\n\r\n    <button>Submit</button>\r\n  </Form>\r\n</template>\r\n```\r\n\r\nThe `Field` component renders an `input` of type `text` by default but you can [control that](https://vee-validate.logaretm.com/v5/api/field#rendering-fields)\r\n\r\n## 📚 Documentation\r\n\r\nRead the [documentation and demos](https://vee-validate.logaretm.com/v4).\r\n\r\n## Contributing\r\n\r\nYou are welcome to contribute to this project, but before you do, please make sure you read the [contribution guide](/CONTRIBUTING.md).\r\n\r\n## Credits\r\n\r\n- Inspired by Laravel's [validation syntax](https://laravel.com/docs/5.4/validation)\r\n- v4 API Inspired by [Formik's](https://github.com/formium/formik)\r\n- Nested path types by [react-hook-form](https://github.com/react-hook-form/react-hook-form)\r\n- Logo by [Baianat](https://github.com/baianat)\r\n\r\n## Emeriti\r\n\r\nHere we honor past contributors and sponsors who have been a major part on this project.\r\n\r\n- [Baianat](https://github.com/baianat).\r\n\r\n## ⚖️ License\r\n\r\nReleased under [MIT](/LICENSE) by [@logaretm](https://github.com/logaretm).\r\n"
  },
  {
    "path": "packages/vee-validate/package.json",
    "content": "{\n  \"name\": \"vee-validate\",\n  \"version\": \"5.0.0-beta.1\",\n  \"description\": \"Painless forms for Vue.js\",\n  \"author\": \"Abdelrahman Awad <logaretm1@gmail.com>\",\n  \"license\": \"MIT\",\n  \"module\": \"dist/vee-validate.mjs\",\n  \"unpkg\": \"dist/vee-validate.iife.js\",\n  \"main\": \"dist/vee-validate.mjs\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/vee-validate.d.ts\",\n      \"import\": \"./dist/vee-validate.mjs\",\n      \"require\": \"./dist/vee-validate.cjs\"\n    },\n    \"./dist/*\": \"./dist/*\"\n  },\n  \"types\": \"dist/vee-validate.d.ts\",\n  \"homepage\": \"https://vee-validate.logaretm.com/\",\n  \"repository\": {\n    \"url\": \"https://github.com/logaretm/vee-validate.git\",\n    \"type\": \"git\",\n    \"directory\": \"packages/vee-validate\"\n  },\n  \"sideEffects\": false,\n  \"keywords\": [\n    \"VueJS\",\n    \"Vue\",\n    \"validation\",\n    \"validator\",\n    \"inputs\",\n    \"form\"\n  ],\n  \"files\": [\n    \"dist/*.js\",\n    \"dist/*.d.ts\",\n    \"dist/*.cjs\",\n    \"dist/*.mjs\"\n  ],\n  \"peerDependencies\": {\n    \"vue\": \"^3.4.26\"\n  },\n  \"dependencies\": {\n    \"@standard-schema/spec\": \"^1.0.0\",\n    \"@standard-schema/utils\": \"^0.3.0\",\n    \"@vue/devtools-api\": \"^7.5.2\",\n    \"type-fest\": \"^4.8.3\"\n  }\n}\n"
  },
  {
    "path": "packages/vee-validate/src/ErrorMessage.ts",
    "content": "import { inject, h, defineComponent, computed, resolveDynamicComponent, VNode } from 'vue';\nimport { FormContextKey } from './symbols';\nimport { normalizeChildren } from './utils';\n\nexport interface ErrorMessageSlotProps {\n  message: string | undefined;\n}\n\nconst ErrorMessageImpl = /** #__PURE__ */ defineComponent({\n  name: 'ErrorMessage',\n  props: {\n    as: {\n      type: String,\n      default: undefined,\n    },\n    name: {\n      type: String,\n      required: true,\n    },\n  },\n  setup(props, ctx) {\n    const form = inject(FormContextKey, undefined);\n    const message = computed<string | undefined>(() => {\n      return form?.errors.value[props.name];\n    });\n\n    function slotProps(): ErrorMessageSlotProps {\n      return {\n        message: message.value,\n      };\n    }\n\n    return () => {\n      // Renders nothing if there are no messages\n      if (!message.value) {\n        return undefined;\n      }\n\n      const tag = (props.as ? resolveDynamicComponent(props.as) : props.as) as string;\n      const children = normalizeChildren(tag, ctx, slotProps as any);\n\n      const attrs = {\n        role: 'alert',\n        ...ctx.attrs,\n      };\n\n      // If no tag was specified and there are children\n      // render the slot as is without wrapping it\n      if (!tag && (Array.isArray(children) || !children) && children?.length) {\n        return children;\n      }\n\n      // If no children in slot\n      // render whatever specified and fallback to a <span> with the message in it's contents\n      if ((Array.isArray(children) || !children) && !children?.length) {\n        return h(tag || 'span', attrs, message.value);\n      }\n\n      return h(tag, attrs, children);\n    };\n  },\n});\n\nexport const ErrorMessage = ErrorMessageImpl as typeof ErrorMessageImpl & {\n  new (): {\n    $slots: {\n      default: (arg: ErrorMessageSlotProps) => VNode[];\n    };\n  };\n};\n"
  },
  {
    "path": "packages/vee-validate/src/Field.ts",
    "content": "import {\n  h,\n  defineComponent,\n  toRef,\n  SetupContext,\n  resolveDynamicComponent,\n  computed,\n  PropType,\n  VNode,\n  UnwrapRef,\n} from 'vue';\nimport { getConfig } from './config';\nimport { RuleExpression, useField } from './useField';\nimport { normalizeChildren, hasCheckedAttr, shouldHaveValueBinding, isPropPresent } from './utils';\nimport { IS_ABSENT } from './symbols';\nimport { FieldMeta, InputType } from './types';\nimport { FieldContext } from '.';\nimport { isCallable } from '../../shared';\n\ninterface ValidationTriggersProps {\n  validateOnMount: boolean;\n  validateOnBlur: boolean;\n  validateOnChange: boolean;\n  validateOnInput: boolean;\n  validateOnModelUpdate: boolean;\n}\n\ninterface SharedBindingObject<TValue = any> {\n  name: string;\n  onBlur: (e: Event) => void;\n  onInput: (e: Event | unknown) => void;\n  onChange: (e: Event | unknown) => void;\n  'onUpdate:modelValue'?: ((e: TValue) => unknown) | undefined;\n}\n\nexport interface FieldBindingObject<TValue = any> extends SharedBindingObject<TValue> {\n  value?: TValue;\n  checked?: boolean;\n}\n\nexport interface ComponentFieldBindingObject<TValue = any> extends SharedBindingObject<TValue> {\n  modelValue?: TValue;\n}\n\nexport interface FieldSlotProps<TValue = unknown>\n  extends Pick<\n    FieldContext,\n    'validate' | 'resetField' | 'handleChange' | 'handleReset' | 'handleBlur' | 'setTouched' | 'setErrors' | 'setValue'\n  > {\n  field: FieldBindingObject<TValue>;\n  componentField: ComponentFieldBindingObject<TValue>;\n  value: TValue;\n  meta: FieldMeta<TValue>;\n  errors: string[];\n  errorMessage: string | undefined;\n  handleInput: FieldContext['handleChange'];\n}\n\nconst FieldImpl = /** #__PURE__ */ defineComponent({\n  name: 'Field',\n  inheritAttrs: false,\n  props: {\n    as: {\n      type: [String, Object],\n      default: undefined,\n    },\n    name: {\n      type: String,\n      required: true,\n    },\n    rules: {\n      type: [Object, String, Function] as PropType<RuleExpression<unknown>>,\n      default: undefined,\n    },\n    validateOnMount: {\n      type: Boolean,\n      default: false,\n    },\n    validateOnBlur: {\n      type: Boolean,\n      default: undefined,\n    },\n    validateOnChange: {\n      type: Boolean,\n      default: undefined,\n    },\n    validateOnInput: {\n      type: Boolean,\n      default: undefined,\n    },\n    validateOnModelUpdate: {\n      type: Boolean,\n      default: undefined,\n    },\n    bails: {\n      type: Boolean,\n      default: () => getConfig().bails,\n    },\n    label: {\n      type: String,\n      default: undefined,\n    },\n    uncheckedValue: {\n      type: null,\n      default: undefined,\n    },\n    modelValue: {\n      type: null,\n      default: IS_ABSENT,\n    },\n    modelModifiers: {\n      type: null,\n      default: () => ({}),\n    },\n    'onUpdate:modelValue': {\n      type: null as unknown as PropType<((e: any) => unknown) | undefined>,\n      default: undefined,\n    },\n    controlled: {\n      type: Boolean,\n      default: true,\n    },\n    keepValue: {\n      type: Boolean,\n      default: undefined,\n    },\n  },\n  setup(props, ctx) {\n    const rules = toRef(props, 'rules');\n    const name = toRef(props, 'name');\n    const label = toRef(props, 'label');\n    const uncheckedValue = toRef(props, 'uncheckedValue');\n    const keepValue = toRef(props, 'keepValue');\n\n    const {\n      errors,\n      value,\n      errorMessage,\n      validate: validateField,\n      handleChange,\n      handleBlur,\n      setTouched,\n      resetField,\n      handleReset,\n      meta,\n      checked,\n      setErrors,\n      setValue,\n    } = useField(name, rules, {\n      validateOnMount: props.validateOnMount,\n      bails: props.bails,\n      controlled: props.controlled,\n      type: ctx.attrs.type as InputType,\n      initialValue: resolveInitialValue(props, ctx),\n      // Only for checkboxes and radio buttons\n      checkedValue: ctx.attrs.value,\n      uncheckedValue,\n      label,\n      validateOnValueUpdate: props.validateOnModelUpdate,\n      keepValueOnUnmount: keepValue,\n      syncVModel: true,\n    });\n\n    // If there is a v-model applied on the component we need to emit the `update:modelValue` whenever the value binding changes\n    const onChangeHandler = function handleChangeWithModel(e: Event | unknown, shouldValidate = true) {\n      handleChange(e, shouldValidate);\n    };\n\n    const sharedProps = computed(() => {\n      const { validateOnInput, validateOnChange, validateOnBlur, validateOnModelUpdate } =\n        resolveValidationTriggers(props);\n\n      function baseOnBlur(e: Event) {\n        handleBlur(e, validateOnBlur);\n        if (isCallable(ctx.attrs.onBlur)) {\n          ctx.attrs.onBlur(e);\n        }\n      }\n\n      function baseOnInput(e: Event | unknown) {\n        onChangeHandler(e, validateOnInput);\n        if (isCallable(ctx.attrs.onInput)) {\n          ctx.attrs.onInput(e);\n        }\n      }\n\n      function baseOnChange(e: Event | unknown) {\n        onChangeHandler(e, validateOnChange);\n        if (isCallable(ctx.attrs.onChange)) {\n          ctx.attrs.onChange(e);\n        }\n      }\n\n      const attrs: FieldBindingObject<unknown> = {\n        name: props.name,\n        onBlur: baseOnBlur,\n        onInput: baseOnInput,\n        onChange: baseOnChange,\n      };\n\n      attrs['onUpdate:modelValue'] = e => onChangeHandler(e, validateOnModelUpdate);\n\n      return attrs;\n    });\n\n    const fieldProps = computed(() => {\n      const attrs = {\n        ...sharedProps.value,\n      };\n\n      if (hasCheckedAttr(ctx.attrs.type) && checked) {\n        attrs.checked = checked.value;\n      }\n\n      const tag = resolveTag(props, ctx);\n      if (shouldHaveValueBinding(tag, ctx.attrs)) {\n        attrs.value = value.value;\n      }\n\n      return attrs;\n    });\n\n    const componentProps = computed(() => {\n      return {\n        ...sharedProps.value,\n        modelValue: value.value,\n      };\n    });\n\n    function slotProps(): FieldSlotProps {\n      return {\n        field: fieldProps.value,\n        componentField: componentProps.value,\n        value: value.value,\n        meta,\n        errors: errors.value,\n        errorMessage: errorMessage.value,\n        validate: validateField,\n        resetField,\n        handleChange: onChangeHandler,\n        handleInput: e => onChangeHandler(e, false),\n        handleReset,\n        handleBlur: sharedProps.value.onBlur,\n        setTouched,\n        setErrors,\n        setValue,\n      };\n    }\n\n    ctx.expose({\n      value,\n      meta,\n      errors,\n      errorMessage,\n      setErrors,\n      setTouched,\n      setValue,\n      reset: resetField,\n      validate: validateField,\n      handleChange,\n    });\n\n    return () => {\n      const tag = resolveDynamicComponent(resolveTag(props, ctx)) as string;\n      const children = normalizeChildren(tag, ctx, slotProps as any);\n\n      if (tag) {\n        return h(\n          tag,\n          {\n            ...ctx.attrs,\n            ...fieldProps.value,\n          },\n          children,\n        );\n      }\n\n      return children;\n    };\n  },\n});\n\nfunction resolveTag(props: Record<string, any>, ctx: SetupContext<any>) {\n  let tag: string = props.as || '';\n\n  if (!props.as && !ctx.slots.default) {\n    tag = 'input';\n  }\n\n  return tag;\n}\n\nfunction resolveValidationTriggers(props: Partial<ValidationTriggersProps>) {\n  const { validateOnInput, validateOnChange, validateOnBlur, validateOnModelUpdate } = getConfig();\n\n  return {\n    validateOnInput: props.validateOnInput ?? validateOnInput,\n    validateOnChange: props.validateOnChange ?? validateOnChange,\n    validateOnBlur: props.validateOnBlur ?? validateOnBlur,\n    validateOnModelUpdate: props.validateOnModelUpdate ?? validateOnModelUpdate,\n  };\n}\n\nfunction resolveInitialValue(props: Record<string, unknown>, ctx: SetupContext<any>) {\n  // Gets the initial value either from `value` prop/attr or `v-model` binding (modelValue)\n  // For checkboxes and radio buttons it will always be the model value not the `value` attribute\n  if (!hasCheckedAttr(ctx.attrs.type)) {\n    return isPropPresent(props, 'modelValue') ? props.modelValue : ctx.attrs.value;\n  }\n\n  return isPropPresent(props, 'modelValue') ? props.modelValue : undefined;\n}\n\nexport const Field = FieldImpl as typeof FieldImpl & {\n  new (): {\n    value: UnwrapRef<FieldContext['value']>;\n    meta: UnwrapRef<FieldContext['meta']>;\n    errors: UnwrapRef<FieldContext['errors']>;\n    errorMessage: UnwrapRef<FieldContext['errorMessage']>;\n    setErrors: FieldContext['setErrors'];\n    setTouched: FieldContext['setTouched'];\n    reset: FieldContext['resetField'];\n    validate: FieldContext['validate'];\n    setValue: FieldContext['setValue'];\n    handleChange: FieldContext['handleChange'];\n    $slots: {\n      default: (arg: FieldSlotProps<any>) => VNode[];\n    };\n  };\n};\n"
  },
  {
    "path": "packages/vee-validate/src/FieldArray.ts",
    "content": "import { defineComponent, UnwrapRef, VNode } from 'vue';\nimport { FieldArrayContext } from './types';\nimport { useFieldArray } from './useFieldArray';\nimport { normalizeChildren } from './utils';\n\nconst FieldArrayImpl = /** #__PURE__ */ defineComponent({\n  name: 'FieldArray',\n  inheritAttrs: false,\n  props: {\n    name: {\n      type: String,\n      required: true,\n    },\n  },\n  setup(props, ctx) {\n    const { push, remove, swap, insert, replace, update, prepend, move, fields } = useFieldArray(() => props.name);\n\n    function slotProps() {\n      return {\n        fields: fields.value,\n        push,\n        remove,\n        swap,\n        insert,\n        update,\n        replace,\n        prepend,\n        move,\n      };\n    }\n\n    ctx.expose({\n      push,\n      remove,\n      swap,\n      insert,\n      update,\n      replace,\n      prepend,\n      move,\n    });\n\n    return () => {\n      const children = normalizeChildren(undefined, ctx, slotProps);\n\n      return children;\n    };\n  },\n});\n\nexport const FieldArray = FieldArrayImpl as typeof FieldArrayImpl & {\n  new (): {\n    push: FieldArrayContext['push'];\n    remove: FieldArrayContext['remove'];\n    swap: FieldArrayContext['swap'];\n    insert: FieldArrayContext['insert'];\n    update: FieldArrayContext['update'];\n    replace: FieldArrayContext['replace'];\n    prepend: FieldArrayContext['prepend'];\n    move: FieldArrayContext['move'];\n    $slots: {\n      default: (arg: UnwrapRef<FieldArrayContext>) => VNode[];\n    };\n  };\n};\n"
  },
  {
    "path": "packages/vee-validate/src/Form.ts",
    "content": "import { klona as deepCopy } from 'klona/full';\nimport { defineComponent, h, PropType, resolveDynamicComponent, toRef, UnwrapRef, VNode } from 'vue';\nimport { FormContext, FormErrors, FormMeta, GenericObject, InvalidSubmissionHandler, SubmissionHandler } from './types';\nimport { useForm } from './useForm';\nimport { isEvent, isFormSubmitEvent, normalizeChildren } from './utils';\n\nexport type FormSlotProps = UnwrapRef<\n  Pick<\n    FormContext,\n    | 'meta'\n    | 'errors'\n    | 'errorBag'\n    | 'values'\n    | 'isSubmitting'\n    | 'isValidating'\n    | 'submitCount'\n    | 'validate'\n    | 'validateField'\n    | 'handleReset'\n    | 'setErrors'\n    | 'setFieldError'\n    | 'setFieldValue'\n    | 'setValues'\n    | 'setFieldTouched'\n    | 'setTouched'\n    | 'resetForm'\n    | 'resetField'\n    | 'controlledValues'\n  >\n> & {\n  handleSubmit: (evt: Event | SubmissionHandler, onSubmit?: SubmissionHandler) => Promise<unknown>;\n  submitForm(evt?: Event): void;\n  getValues<TValues extends GenericObject = GenericObject>(): TValues;\n  getMeta<TValues extends GenericObject = GenericObject>(): FormMeta<TValues>;\n  getErrors<TValues extends GenericObject = GenericObject>(): FormErrors<TValues>;\n};\n\nconst FormImpl = /** #__PURE__ */ defineComponent({\n  name: 'Form',\n  inheritAttrs: false,\n  props: {\n    as: {\n      type: null as unknown as PropType<string | null>,\n      default: 'form',\n    },\n    validationSchema: {\n      type: Object,\n      default: undefined,\n    },\n    initialValues: {\n      type: Object,\n      default: undefined,\n    },\n    initialErrors: {\n      type: Object,\n      default: undefined,\n    },\n    initialTouched: {\n      type: Object,\n      default: undefined,\n    },\n    validateOnMount: {\n      type: Boolean,\n      default: false,\n    },\n    onSubmit: {\n      type: Function as PropType<SubmissionHandler<GenericObject>>,\n      default: undefined,\n    },\n    onInvalidSubmit: {\n      type: Function as PropType<InvalidSubmissionHandler>,\n      default: undefined,\n    },\n    keepValues: {\n      type: Boolean,\n      default: false,\n    },\n    name: {\n      type: String,\n      default: 'Form',\n    },\n  },\n  setup(props, ctx) {\n    const validationSchema = toRef(props, 'validationSchema');\n    const keepValues = toRef(props, 'keepValues');\n\n    const {\n      errors,\n      errorBag,\n      values,\n      meta,\n      isSubmitting,\n      isValidating,\n      submitCount,\n      controlledValues,\n      validate,\n      validateField,\n      handleReset,\n      resetForm,\n      handleSubmit,\n      setErrors,\n      setFieldError,\n      setFieldValue,\n      setValues,\n      setFieldTouched,\n      setTouched,\n      resetField,\n    } = useForm({\n      validationSchema: validationSchema.value ? validationSchema : undefined,\n      initialValues: props.initialValues,\n      initialErrors: props.initialErrors,\n      initialTouched: props.initialTouched,\n      validateOnMount: props.validateOnMount,\n      keepValuesOnUnmount: keepValues,\n      name: props.name,\n    });\n\n    const submitForm = handleSubmit((_, { evt }) => {\n      if (isFormSubmitEvent(evt)) {\n        evt.target.submit();\n      }\n    }, props.onInvalidSubmit);\n\n    const onSubmit = props.onSubmit ? handleSubmit(props.onSubmit, props.onInvalidSubmit) : submitForm;\n    function handleFormReset(e?: Event) {\n      if (isEvent(e)) {\n        // Prevent default form reset behavior\n        e.preventDefault();\n      }\n\n      handleReset();\n      if (typeof ctx.attrs.onReset === 'function') {\n        ctx.attrs.onReset();\n      }\n    }\n\n    function handleScopedSlotSubmit(evt: Event | SubmissionHandler, onSubmit?: SubmissionHandler) {\n      const onSuccess = typeof evt === 'function' && !onSubmit ? evt : onSubmit;\n\n      return handleSubmit(onSuccess as SubmissionHandler<Record<string, unknown>>, props.onInvalidSubmit)(evt as Event);\n    }\n\n    function getValues<TValues extends GenericObject = GenericObject>() {\n      return deepCopy(values) as TValues;\n    }\n\n    function getMeta<TValues extends GenericObject = GenericObject>() {\n      return deepCopy(meta.value) as FormMeta<TValues>;\n    }\n\n    function getErrors<TValues extends GenericObject = GenericObject>() {\n      return deepCopy(errors.value) as FormErrors<TValues>;\n    }\n\n    function slotProps(): FormSlotProps {\n      return {\n        meta: meta.value,\n        errors: errors.value,\n        errorBag: errorBag.value,\n        values,\n        isSubmitting: isSubmitting.value,\n        isValidating: isValidating.value,\n        submitCount: submitCount.value,\n        controlledValues: controlledValues.value,\n        validate,\n        validateField,\n        handleSubmit: handleScopedSlotSubmit,\n        handleReset,\n        submitForm,\n        setErrors,\n        setFieldError,\n        setFieldValue,\n        setValues,\n        setFieldTouched,\n        setTouched,\n        resetForm,\n        resetField,\n        getValues,\n        getMeta,\n        getErrors,\n      };\n    }\n\n    // expose these functions and methods as part of public API\n    ctx.expose({\n      setFieldError,\n      setErrors,\n      setFieldValue,\n      setValues,\n      setFieldTouched,\n      setTouched,\n      resetForm,\n      validate,\n      validateField,\n      resetField,\n      getValues,\n      getMeta,\n      getErrors,\n      values,\n      meta,\n      errors,\n    });\n\n    return function renderForm() {\n      // avoid resolving the form component as itself\n      const tag = props.as === 'form' ? props.as : !props.as ? null : (resolveDynamicComponent(props.as) as string);\n      const children = normalizeChildren(tag, ctx, slotProps as any);\n\n      if (!tag) {\n        return children;\n      }\n\n      // Attributes to add on a native `form` tag\n      const formAttrs =\n        tag === 'form'\n          ? {\n              // Disables native validation as vee-validate will handle it.\n              novalidate: true,\n            }\n          : {};\n\n      return h(\n        tag,\n        {\n          ...formAttrs,\n          ...ctx.attrs,\n          onSubmit,\n          onReset: handleFormReset,\n        },\n        children,\n      );\n    };\n  },\n});\n\nexport const Form = FormImpl as typeof FormImpl & {\n  new (): {\n    setFieldError: FormContext['setFieldError'];\n    setErrors: FormContext['setErrors'];\n    setFieldValue: FormContext['setFieldValue'];\n    setValues: FormContext['setValues'];\n    setFieldTouched: FormContext['setFieldTouched'];\n    setTouched: FormContext['setTouched'];\n    resetForm: FormContext['resetForm'];\n    resetField: FormContext['resetField'];\n    validate: FormContext['validate'];\n    validateField: FormContext['validateField'];\n    getValues: FormSlotProps['getValues'];\n    getMeta: FormSlotProps['getMeta'];\n    getErrors: FormSlotProps['getErrors'];\n    meta: FormSlotProps['meta'];\n    values: FormSlotProps['values'];\n    errors: FormSlotProps['errors'];\n    $slots: {\n      default: (arg: FormSlotProps) => VNode[];\n    };\n  };\n};\n"
  },
  {
    "path": "packages/vee-validate/src/config.ts",
    "content": "import { ValidationMessageGenerator } from '../../shared';\n\nexport interface VeeValidateConfig {\n  bails: boolean;\n  generateMessage: ValidationMessageGenerator;\n  validateOnInput: boolean;\n  validateOnChange: boolean;\n  validateOnBlur: boolean;\n  validateOnModelUpdate: boolean;\n}\n\nconst DEFAULT_CONFIG: VeeValidateConfig = {\n  generateMessage: ({ field }) => `${field} is not valid.`,\n  bails: true,\n  validateOnBlur: true,\n  validateOnChange: true,\n  validateOnInput: false,\n  validateOnModelUpdate: true,\n};\n\nexport let currentConfig: VeeValidateConfig = { ...DEFAULT_CONFIG };\n\nexport const getConfig = () => currentConfig;\n\nconst setConfig = (newConf: Partial<VeeValidateConfig>) => {\n  currentConfig = { ...currentConfig, ...newConf };\n};\n\nexport const configure = setConfig;\n"
  },
  {
    "path": "packages/vee-validate/src/defineRule.ts",
    "content": "import { ValidationRuleFunction, SimpleValidationRuleFunction, isCallable } from '../../shared';\n\nconst RULES: Record<string, ValidationRuleFunction | SimpleValidationRuleFunction> = {};\n\n/**\n * Adds a custom validator to the list of validation rules.\n */\nexport function defineRule<TValue = unknown, TParams = any[] | Record<string, any>>(\n  id: string,\n  validator: ValidationRuleFunction<TValue, TParams> | SimpleValidationRuleFunction<TValue, TParams>,\n) {\n  // makes sure new rules are properly formatted.\n  guardExtend(id, validator);\n\n  RULES[id] = validator as SimpleValidationRuleFunction;\n}\n\n/**\n * Gets an already defined rule\n */\nexport function resolveRule(id: string) {\n  return RULES[id];\n}\n\n/**\n * Guards from extension violations.\n */\nfunction guardExtend<TValue, TParams>(\n  id: string,\n  validator: ValidationRuleFunction<TValue, TParams> | SimpleValidationRuleFunction<TValue, TParams>,\n) {\n  if (isCallable(validator)) {\n    return;\n  }\n\n  throw new Error(`Extension Error: The validator '${id}' must be a function.`);\n}\n"
  },
  {
    "path": "packages/vee-validate/src/devtools.ts",
    "content": "import { App, ComponentInternalInstance, getCurrentInstance, nextTick, onUnmounted, toValue, unref } from 'vue';\nimport type { InspectorNodeTag, CustomInspectorState, CustomInspectorNode } from '@vue/devtools-kit';\nimport { PathState, PrivateFieldContext, PrivateFormContext } from './types';\nimport { isClient, keysOf, setInPath, throttle } from './utils';\nimport { isObject } from '../../shared';\n\nconst DEVTOOLS_FORMS: Record<string, PrivateFormContext & { _vm?: ComponentInternalInstance | null }> = {};\nconst DEVTOOLS_FIELDS: Record<string, PrivateFieldContext & { _vm?: ComponentInternalInstance | null }> = {};\n\nconst INSPECTOR_ID = 'vee-validate-inspector';\n\nconst COLORS = {\n  error: 0xbd4b4b,\n  success: 0x06d77b,\n  unknown: 0x54436b,\n  white: 0xffffff,\n  black: 0x000000,\n  blue: 0x035397,\n  purple: 0xb980f0,\n  orange: 0xf5a962,\n  gray: 0xbbbfca,\n};\n\nlet SELECTED_NODE:\n  | { type: 'pathState'; form: PrivateFormContext; state: PathState }\n  | { type: 'form'; form: PrivateFormContext & { _vm?: ComponentInternalInstance | null } }\n  | { type: 'field'; field: PrivateFieldContext & { _vm?: ComponentInternalInstance | null } }\n  | null = null;\n\n/**\n * Plugin API\n */\nlet API: any;\n\nasync function installDevtoolsPlugin(app: App) {\n  if (__DEV__) {\n    if (!isClient) {\n      return;\n    }\n\n    const devtools = await import('@vue/devtools-api');\n    devtools.setupDevtoolsPlugin(\n      {\n        id: 'vee-validate-devtools-plugin',\n        label: 'VeeValidate Plugin',\n        packageName: 'vee-validate',\n        homepage: 'https://vee-validate.logaretm.com/v4',\n        app,\n        logo: 'https://vee-validate.logaretm.com/v5/logo.png',\n      },\n      api => {\n        API = api;\n\n        api.addInspector({\n          id: INSPECTOR_ID,\n          icon: 'rule',\n          label: 'vee-validate',\n          noSelectionText: 'Select a vee-validate node to inspect',\n          actions: [\n            {\n              icon: 'done_outline',\n              tooltip: 'Validate selected item',\n              action: async () => {\n                if (!SELECTED_NODE) {\n                  // eslint-disable-next-line no-console\n                  console.error('There is not a valid selected vee-validate node or component');\n                  return;\n                }\n\n                if (SELECTED_NODE.type === 'field') {\n                  await SELECTED_NODE.field.validate();\n                  return;\n                }\n\n                if (SELECTED_NODE.type === 'form') {\n                  await SELECTED_NODE.form.validate();\n                  return;\n                }\n\n                if (SELECTED_NODE.type === 'pathState') {\n                  await SELECTED_NODE.form.validateField(SELECTED_NODE.state.path);\n                }\n              },\n            },\n            {\n              icon: 'delete_sweep',\n              tooltip: 'Clear validation state of the selected item',\n              action: () => {\n                if (!SELECTED_NODE) {\n                  // eslint-disable-next-line no-console\n                  console.error('There is not a valid selected vee-validate node or component');\n                  return;\n                }\n\n                if (SELECTED_NODE.type === 'field') {\n                  SELECTED_NODE.field.resetField();\n                  return;\n                }\n\n                if (SELECTED_NODE.type === 'form') {\n                  SELECTED_NODE.form.resetForm();\n                }\n\n                if (SELECTED_NODE.type === 'pathState') {\n                  SELECTED_NODE.form.resetField(SELECTED_NODE.state.path);\n                }\n              },\n            },\n          ],\n        });\n\n        api.on.getInspectorTree(payload => {\n          if (payload.inspectorId !== INSPECTOR_ID) {\n            return;\n          }\n\n          const forms = Object.values(DEVTOOLS_FORMS);\n          const fields = Object.values(DEVTOOLS_FIELDS);\n\n          payload.rootNodes = [\n            ...forms.map(mapFormForDevtoolsInspector),\n            ...fields.map(field => mapFieldForDevtoolsInspector(field)),\n          ];\n        });\n\n        api.on.getInspectorState(payload => {\n          if (payload.inspectorId !== INSPECTOR_ID) {\n            return;\n          }\n\n          const { form, field, state, type } = decodeNodeId(payload.nodeId);\n\n          api.unhighlightElement();\n\n          if (form && type === 'form') {\n            payload.state = buildFormState(form);\n            SELECTED_NODE = { type: 'form', form };\n            api.highlightElement(form._vm);\n            return;\n          }\n\n          if (state && type === 'pathState' && form) {\n            payload.state = buildFieldState(state);\n            SELECTED_NODE = { type: 'pathState', state, form };\n            return;\n          }\n\n          if (field && type === 'field') {\n            payload.state = buildFieldState({\n              errors: field.errors.value,\n              dirty: field.meta.dirty,\n              valid: field.meta.valid,\n              touched: field.meta.touched,\n              value: field.value.value,\n              initialValue: field.meta.initialValue,\n            });\n            SELECTED_NODE = { field, type: 'field' };\n            api.highlightElement(field._vm);\n            return;\n          }\n\n          SELECTED_NODE = null;\n          api.unhighlightElement();\n        });\n      },\n    );\n  }\n}\n\nexport const refreshInspector = throttle(() => {\n  setTimeout(async () => {\n    await nextTick();\n    API?.sendInspectorState(INSPECTOR_ID);\n    API?.sendInspectorTree(INSPECTOR_ID);\n  }, 100);\n}, 100);\n\nexport function registerFormWithDevTools(form: PrivateFormContext) {\n  if (!__DEV__ || !isClient) {\n    return;\n  }\n\n  const vm = getCurrentInstance();\n  if (!API) {\n    const app = vm?.appContext.app;\n    if (!app) {\n      return;\n    }\n\n    installDevtoolsPlugin(app as unknown as App);\n  }\n\n  DEVTOOLS_FORMS[form.formId] = { ...form };\n  DEVTOOLS_FORMS[form.formId]._vm = vm;\n  onUnmounted(() => {\n    delete DEVTOOLS_FORMS[form.formId];\n    refreshInspector();\n  });\n\n  refreshInspector();\n}\n\nexport function registerSingleFieldWithDevtools(field: PrivateFieldContext) {\n  if (!__DEV__ || !isClient) {\n    return;\n  }\n\n  const vm = getCurrentInstance();\n  if (!API) {\n    const app = vm?.appContext.app;\n    if (!app) {\n      return;\n    }\n\n    installDevtoolsPlugin(app as unknown as App);\n  }\n\n  DEVTOOLS_FIELDS[field.id] = { ...field };\n  DEVTOOLS_FIELDS[field.id]._vm = vm;\n\n  onUnmounted(() => {\n    delete DEVTOOLS_FIELDS[field.id];\n    refreshInspector();\n  });\n\n  refreshInspector();\n}\n\nfunction mapFormForDevtoolsInspector(form: PrivateFormContext): CustomInspectorNode {\n  const { textColor, bgColor } = getValidityColors(form.meta.value.valid);\n\n  const formTreeNodes = {};\n  Object.values(form.getAllPathStates()).forEach(state => {\n    setInPath(formTreeNodes, toValue(state.path), mapPathForDevtoolsInspector(state, form));\n  });\n\n  function buildFormTree(tree: any[] | Record<string, any>, path: string[] = []): CustomInspectorNode {\n    const key = [...path].pop();\n    if ('id' in tree && typeof tree.id === 'string') {\n      return {\n        ...tree,\n        label: key || tree.label,\n      } as CustomInspectorNode;\n    }\n\n    if (isObject(tree)) {\n      return {\n        id: `${path.join('.')}`,\n        label: key || '',\n        children: Object.keys(tree).map(key => buildFormTree(tree[key] as any, [...path, key])),\n      };\n    }\n\n    if (Array.isArray(tree)) {\n      return {\n        id: `${path.join('.')}`,\n        label: `${key}[]`,\n        children: tree.map((c, idx) => buildFormTree(c, [...path, String(idx)])),\n      };\n    }\n\n    return { id: '', label: '', children: [] };\n  }\n\n  const { children } = buildFormTree(formTreeNodes);\n\n  return {\n    id: encodeNodeId(form),\n    label: form.name,\n    children,\n    tags: [\n      {\n        label: 'Form',\n        textColor,\n        backgroundColor: bgColor,\n      },\n      {\n        label: `${form.getAllPathStates().length} fields`,\n        textColor: COLORS.white,\n        backgroundColor: COLORS.unknown,\n      },\n    ],\n  };\n}\n\nfunction mapPathForDevtoolsInspector(state: PathState, form?: PrivateFormContext): CustomInspectorNode {\n  return {\n    id: encodeNodeId(form, state),\n    label: toValue(state.path),\n    tags: getFieldNodeTags(state.multiple, state.fieldsCount, state.type, state.valid, form),\n  };\n}\n\nfunction mapFieldForDevtoolsInspector(field: PrivateFieldContext, form?: PrivateFormContext): CustomInspectorNode {\n  return {\n    id: encodeNodeId(form, field),\n    label: unref(field.name),\n    tags: getFieldNodeTags(false, 1, field.type, field.meta.valid, form),\n  };\n}\n\nfunction getFieldNodeTags(\n  multiple: boolean,\n  fieldsCount: number,\n  type: string | undefined,\n  valid: boolean,\n  form: PrivateFormContext | undefined,\n) {\n  const { textColor, bgColor } = getValidityColors(valid);\n\n  return [\n    multiple\n      ? undefined\n      : {\n          label: 'Field',\n          textColor,\n          backgroundColor: bgColor,\n        },\n    !form\n      ? {\n          label: 'Standalone',\n          textColor: COLORS.black,\n          backgroundColor: COLORS.gray,\n        }\n      : undefined,\n    type === 'checkbox'\n      ? {\n          label: 'Checkbox',\n          textColor: COLORS.white,\n          backgroundColor: COLORS.blue,\n        }\n      : undefined,\n    type === 'radio'\n      ? {\n          label: 'Radio',\n          textColor: COLORS.white,\n          backgroundColor: COLORS.purple,\n        }\n      : undefined,\n    multiple\n      ? {\n          label: 'Multiple',\n          textColor: COLORS.black,\n          backgroundColor: COLORS.orange,\n        }\n      : undefined,\n  ].filter(Boolean) as InspectorNodeTag[];\n}\n\nfunction encodeNodeId(form?: PrivateFormContext, stateOrField?: PathState | PrivateFieldContext): string {\n  const type = stateOrField ? ('path' in stateOrField ? 'pathState' : 'field') : 'form';\n  const fieldPath = stateOrField ? ('path' in stateOrField ? stateOrField?.path : toValue(stateOrField?.name)) : '';\n  const ff = type === 'field' ? stateOrField?.id : fieldPath;\n  const idObject = { f: form?.formId, ff, type };\n\n  return btoa(encodeURIComponent(JSON.stringify(idObject)));\n}\n\nfunction decodeNodeId(nodeId: string): {\n  field?: PrivateFieldContext & { _vm?: ComponentInternalInstance | null };\n  form?: PrivateFormContext & { _vm?: ComponentInternalInstance | null };\n  state?: PathState;\n  type?: 'form' | 'field' | 'pathState';\n} {\n  try {\n    const idObject = JSON.parse(decodeURIComponent(atob(nodeId)));\n    const form = DEVTOOLS_FORMS[idObject.f];\n\n    if (!form && idObject.ff) {\n      const field = DEVTOOLS_FIELDS[idObject.ff];\n      if (!field) {\n        return {};\n      }\n\n      return {\n        type: idObject.type,\n        field,\n      };\n    }\n\n    if (!form) {\n      return {};\n    }\n\n    const state = form.getPathState(idObject.ff);\n\n    return {\n      type: idObject.type,\n      form,\n      state,\n    };\n  } catch (err) {\n    // console.error(`Devtools: [vee-validate] Failed to parse node id ${nodeId}`);\n  }\n\n  return {};\n}\n\nfunction buildFieldState(\n  state: Pick<PathState, 'errors' | 'initialValue' | 'touched' | 'dirty' | 'value' | 'valid'>,\n): CustomInspectorState {\n  return {\n    'Field state': [\n      { key: 'errors', value: state.errors },\n      {\n        key: 'initialValue',\n        value: state.initialValue,\n      },\n      {\n        key: 'currentValue',\n        value: state.value,\n      },\n      {\n        key: 'touched',\n        value: state.touched,\n      },\n      {\n        key: 'dirty',\n        value: state.dirty,\n      },\n      {\n        key: 'valid',\n        value: state.valid,\n      },\n    ],\n  };\n}\n\nfunction buildFormState(form: PrivateFormContext): CustomInspectorState {\n  const { errorBag, meta, values, isSubmitting, isValidating, submitCount } = form;\n\n  return {\n    'Form state': [\n      {\n        key: 'submitCount',\n        value: submitCount.value,\n      },\n      {\n        key: 'isSubmitting',\n        value: isSubmitting.value,\n      },\n      {\n        key: 'isValidating',\n        value: isValidating.value,\n      },\n      {\n        key: 'touched',\n        value: meta.value.touched,\n      },\n      {\n        key: 'dirty',\n        value: meta.value.dirty,\n      },\n      {\n        key: 'valid',\n        value: meta.value.valid,\n      },\n      {\n        key: 'initialValues',\n        value: meta.value.initialValues,\n      },\n      {\n        key: 'currentValues',\n        value: values,\n      },\n      {\n        key: 'errors',\n        value: keysOf(errorBag.value).reduce(\n          (acc, key) => {\n            const message = errorBag.value[key]?.[0];\n            if (message) {\n              acc[key] = message;\n            }\n\n            return acc;\n          },\n          {} as Record<string, string | undefined>,\n        ),\n      },\n    ],\n  };\n}\n\n/**\n * Resolves the tag color based on the form state\n */\nfunction getValidityColors(valid: boolean) {\n  return {\n    bgColor: valid ? COLORS.success : COLORS.error,\n    textColor: valid ? COLORS.black : COLORS.white,\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/src/globals.d.ts",
    "content": "/* eslint-disable no-var */\n\ndeclare var __VUE_PROD_DEVTOOLS__: boolean;\ndeclare var __DEV__: boolean;\n"
  },
  {
    "path": "packages/vee-validate/src/index.ts",
    "content": "export { validate, validateObjectSchema as validateObject } from './validate';\nexport { defineRule } from './defineRule';\nexport { configure, getConfig } from './config';\nexport { normalizeRules, isNotNestedPath, cleanupNonNestedPath } from './utils';\nexport { Field, FieldBindingObject, ComponentFieldBindingObject, FieldSlotProps } from './Field';\nexport { Form, FormSlotProps } from './Form';\nexport { FieldArray } from './FieldArray';\nexport { ErrorMessage } from './ErrorMessage';\nexport { useField, FieldOptions, RuleExpression } from './useField';\nexport { useForm, useFormContext, FormOptions } from './useForm';\nexport { useFieldArray } from './useFieldArray';\nexport * from './types';\nexport { useResetForm } from './useResetForm';\nexport { useIsFieldDirty } from './useIsFieldDirty';\nexport { useIsFieldTouched } from './useIsFieldTouched';\nexport { useIsFieldValid } from './useIsFieldValid';\nexport { useIsSubmitting } from './useIsSubmitting';\nexport { useIsValidating } from './useIsValidating';\nexport { useValidateField } from './useValidateField';\nexport { useIsFormDirty } from './useIsFormDirty';\nexport { useIsFormTouched } from './useIsFormTouched';\nexport { useIsFormValid } from './useIsFormValid';\nexport { useValidateForm } from './useValidateForm';\nexport { useSubmitCount } from './useSubmitCount';\nexport { useFieldValue } from './useFieldValue';\nexport { useFormValues } from './useFormValues';\nexport { useFormErrors } from './useFormErrors';\nexport { useFieldError } from './useFieldError';\nexport { useSubmitForm } from './useSubmitForm';\nexport { useSetFieldError } from './useSetFieldError';\nexport { useSetFieldTouched } from './useSetFieldTouched';\nexport { useSetFieldValue } from './useSetFieldValue';\nexport { useSetFormErrors } from './useSetFormErrors';\nexport { useSetFormTouched } from './useSetFormTouched';\nexport { useSetFormValues } from './useSetFormValues';\nexport * from './symbols';\n"
  },
  {
    "path": "packages/vee-validate/src/symbols.ts",
    "content": "import { InjectionKey } from 'vue';\nimport { PrivateFormContext, PrivateFieldContext, FormContext } from './types';\n\nexport const FormContextKey: InjectionKey<PrivateFormContext> = Symbol('vee-validate-form');\n\nexport const PublicFormContextKey: InjectionKey<FormContext> = Symbol('vee-validate-form-context');\n\nexport const FieldContextKey: InjectionKey<PrivateFieldContext<unknown>> = Symbol('vee-validate-field-instance');\n\nexport const IS_ABSENT = Symbol('Default empty value');\n"
  },
  {
    "path": "packages/vee-validate/src/types/common.ts",
    "content": "import { MaybeRef, Ref } from 'vue';\nimport { Path, PathValue } from './paths';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type GenericObject = Record<string, any>;\n\nexport type MaybeArray<T> = T | T[];\n\nexport type MaybePromise<T> = T | Promise<T>;\n\nexport type FlattenAndSetPathsType<TRecord, TType> = { [K in Path<TRecord>]: TType };\n\nexport type MapValuesPathsToRefs<\n  TValues extends GenericObject,\n  TPaths extends readonly [...MaybeRef<Path<TValues>>[]],\n> = {\n  readonly [K in keyof TPaths]: TPaths[K] extends MaybeRef<infer TKey>\n    ? TKey extends Path<TValues>\n      ? Ref<PathValue<TValues, TKey>>\n      : Ref<unknown>\n    : Ref<unknown>;\n};\n"
  },
  {
    "path": "packages/vee-validate/src/types/devtools.ts",
    "content": "import { FieldMeta, FormErrors, FormMeta } from './forms';\n\nexport interface DevtoolsPluginFieldState {\n  name: string;\n  value: any;\n  initialValue: any;\n  errors: string[];\n  meta: FieldMeta<any>;\n}\n\nexport interface DevtoolsPluginFormState {\n  meta: FormMeta<Record<string, any>>;\n  errors: FormErrors<Record<string, any>>;\n  values: Record<string, any>;\n  isSubmitting: boolean;\n  isValidating: boolean;\n  submitCount: number;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/types/forms.ts",
    "content": "import { ComputedRef, Ref, MaybeRef, MaybeRefOrGetter } from 'vue';\nimport { GenericObject, MaybeArray, MaybePromise, FlattenAndSetPathsType } from './common';\nimport { FieldValidationMetaInfo } from '../../../shared';\nimport { Path, PathValue } from './paths';\nimport { PartialDeep } from 'type-fest';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport interface ValidationResult<TValue = unknown> {\n  errors: string[];\n  valid: boolean;\n  value?: TValue;\n}\n\nexport type FlattenAndMapPathsValidationResult<TInput extends GenericObject, TOutput extends GenericObject> = {\n  [K in Path<TInput>]: ValidationResult<TOutput[K]>;\n};\n\nexport type Locator = { __locatorRef: string } & ((values: GenericObject) => unknown);\n\nexport interface FieldMeta<TValue> {\n  touched: boolean;\n  dirty: boolean;\n  valid: boolean;\n  validated: boolean;\n  pending: boolean;\n  initialValue?: TValue;\n}\n\nexport interface FormMeta<TValues extends GenericObject> {\n  touched: boolean;\n  dirty: boolean;\n  valid: boolean;\n  pending: boolean;\n  initialValues?: Partial<TValues>;\n}\n\nexport interface FieldState<TValue = unknown> {\n  value: TValue;\n  touched: boolean;\n  errors: string[];\n}\n\nexport type InputType = 'checkbox' | 'radio' | 'default';\n\n/**\n * validated-only: only mutate the previously validated fields\n * silent: do not mutate any field\n * force: validate all fields and mutate their state\n */\nexport type SchemaValidationMode = 'validated-only' | 'silent' | 'force';\n\nexport interface ValidationOptions {\n  mode: SchemaValidationMode;\n  warn: boolean;\n}\n\nexport type FieldValidator<TOutput> = (opts?: Partial<ValidationOptions>) => Promise<ValidationResult<TOutput>>;\n\nexport interface PathStateConfig<TOutput> {\n  bails: boolean;\n  label: MaybeRefOrGetter<string | undefined>;\n  type: InputType;\n  validate: FieldValidator<TOutput>;\n  schema?: MaybeRefOrGetter<StandardSchemaV1 | undefined>;\n}\n\nexport type IssueCollection<TPath = string> = {\n  path: TPath;\n  messages: string[];\n};\n\nexport interface PathState<TInput = unknown, TOutput = TInput> {\n  id: number | number[];\n  path: string;\n  touched: boolean;\n  dirty: boolean;\n  valid: boolean;\n  validated: boolean;\n  pending: boolean;\n  initialValue: TInput | undefined;\n  value: TInput | undefined;\n  errors: string[];\n  bails: boolean;\n  label: string | undefined;\n  type: InputType;\n  multiple: boolean;\n  fieldsCount: number;\n  __flags: {\n    pendingUnmount: Record<string, boolean>;\n    pendingReset: boolean;\n  };\n  validate?: FieldValidator<TOutput>;\n}\n\nexport interface FieldEntry<TValue = unknown> {\n  value: TValue;\n  key: string | number;\n  isFirst: boolean;\n  isLast: boolean;\n}\n\nexport interface FieldArrayContext<TValue = unknown> {\n  fields: Ref<FieldEntry<TValue>[]>;\n  remove(idx: number): void;\n  replace(newArray: TValue[]): void;\n  update(idx: number, value: TValue): void;\n  push(value: TValue): void;\n  swap(indexA: number, indexB: number): void;\n  insert(idx: number, value: TValue): void;\n  prepend(value: TValue): void;\n  move(oldIdx: number, newIdx: number): void;\n}\n\nexport interface PrivateFieldArrayContext<TValue = unknown> extends FieldArrayContext<TValue> {\n  reset(): void;\n  path: MaybeRefOrGetter<string>;\n}\n\nexport interface PrivateFieldContext<TInput = unknown, TOutput = TInput> {\n  id: number;\n  name: MaybeRef<string>;\n  value: Ref<TInput>;\n  meta: FieldMeta<TInput>;\n  errors: Ref<string[]>;\n  errorMessage: Ref<string | undefined>;\n  label?: MaybeRefOrGetter<string | undefined>;\n  type?: string;\n  bails?: boolean;\n  keepValueOnUnmount?: MaybeRefOrGetter<boolean | undefined>;\n  checkedValue?: MaybeRefOrGetter<TInput>;\n  uncheckedValue?: MaybeRefOrGetter<TInput>;\n  checked?: Ref<boolean>;\n  resetField(state?: Partial<FieldState<TInput>>): void;\n  handleReset(): void;\n  validate: FieldValidator<TOutput>;\n  handleChange(e: Event | unknown, shouldValidate?: boolean): void;\n  handleBlur(e?: Event, shouldValidate?: boolean): void;\n  setState(state: Partial<FieldState<TInput>>): void;\n  setTouched(isTouched: boolean): void;\n  setErrors(message: string | string[]): void;\n  setValue(value: TInput, shouldValidate?: boolean): void;\n}\n\nexport type FieldContext<TValue = unknown> = Omit<PrivateFieldContext<TValue>, 'id' | 'instances'>;\n\nexport type GenericValidateFunction<TValue = unknown> = (\n  value: TValue,\n  ctx: FieldValidationMetaInfo,\n) => MaybePromise<boolean | MaybeArray<string>>;\n\nexport interface FormState<TValues> {\n  values: PartialDeep<TValues>;\n  errors: Partial<Record<Path<TValues>, string | undefined>>;\n  touched: Partial<Record<Path<TValues>, boolean>>;\n  submitCount: number;\n}\n\nexport type FormErrors<TValues extends GenericObject> = Partial<Record<Path<TValues> | '', string | undefined>>;\nexport type FormErrorBag<TValues extends GenericObject> = Partial<Record<Path<TValues> | '', string[]>>;\n\nexport interface ResetFormOpts {\n  force: boolean;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport interface FormActions<TValues extends GenericObject, TOutput = TValues> {\n  setFieldValue<T extends Path<TValues>>(field: T, value: PathValue<TValues, T>, shouldValidate?: boolean): void;\n  setFieldError(field: Path<TValues>, message: string | string[] | undefined): void;\n  setErrors(fields: Partial<FlattenAndSetPathsType<TValues, string | string[] | undefined>>): void;\n  setValues(fields: PartialDeep<TValues>, shouldValidate?: boolean): void;\n  setFieldTouched(field: Path<TValues>, isTouched: boolean): void;\n  setTouched(fields: Partial<Record<Path<TValues>, boolean>> | boolean): void;\n  resetForm(state?: Partial<FormState<TValues>>, opts?: Partial<ResetFormOpts>): void;\n  resetField(field: Path<TValues>, state?: Partial<FieldState>): void;\n}\n\nexport interface FormValidationResult<TInput extends GenericObject, TOutput extends GenericObject = TInput> {\n  valid: boolean;\n  results: Partial<FlattenAndMapPathsValidationResult<TInput, TOutput>>;\n  errors: Partial<Record<Path<TInput>, string>>;\n  values?: Partial<TOutput>;\n  source: 'schema' | 'fields' | 'none';\n}\n\nexport interface SubmissionContext<TInput extends GenericObject = GenericObject> extends FormActions<TInput> {\n  evt?: Event;\n  controlledValues: Partial<TInput>;\n}\n\nexport type SubmissionHandler<TInput extends GenericObject = GenericObject, TOutput = TInput, TReturn = unknown> = (\n  values: TOutput,\n  ctx: SubmissionContext<TInput>,\n) => TReturn;\n\nexport interface InvalidSubmissionContext<\n  TInput extends GenericObject = GenericObject,\n  TOutput extends GenericObject = TInput,\n> {\n  values: TInput;\n  evt?: Event;\n  errors: Partial<Record<Path<TInput>, string>>;\n  results: FormValidationResult<TInput, TOutput>['results'];\n}\n\nexport type InvalidSubmissionHandler<\n  TInput extends GenericObject = GenericObject,\n  TOutput extends GenericObject = TInput,\n> = (ctx: InvalidSubmissionContext<TInput, TOutput>) => void;\n\nexport type RawFormSchema<TValues> = Record<Path<TValues>, string | GenericValidateFunction | GenericObject>;\n\nexport type FieldPathLookup<TValues extends GenericObject = GenericObject> = Partial<\n  Record<Path<TValues>, PrivateFieldContext | PrivateFieldContext[]>\n>;\n\ntype HandleSubmitFactory<TValues extends GenericObject, TOutput extends GenericObject = TValues> = <TReturn = unknown>(\n  cb: SubmissionHandler<TValues, TOutput, TReturn>,\n  onSubmitValidationErrorCb?: InvalidSubmissionHandler<TValues, TOutput>,\n) => (e?: Event) => Promise<TReturn | undefined>;\n\nexport type PublicPathState<TValue = unknown> = Omit<\n  PathState<TValue>,\n  'bails' | 'label' | 'multiple' | 'fieldsCount' | 'validate' | 'id' | 'type' | '__flags'\n>;\n\nexport interface BaseFieldProps {\n  onBlur: () => void;\n  onChange: () => void;\n  onInput: () => void;\n}\n\nexport interface InputBindsConfig<TValue = unknown, TExtraProps extends GenericObject = GenericObject> {\n  props: (state: PublicPathState<TValue>) => TExtraProps;\n  validateOnBlur: boolean;\n  label: MaybeRefOrGetter<string>;\n  validateOnChange: boolean;\n  validateOnInput: boolean;\n  validateOnModelUpdate: boolean;\n}\n\nexport type LazyInputBindsConfig<TValue = unknown, TExtraProps extends GenericObject = GenericObject> = (\n  state: PublicPathState<TValue>,\n) => Partial<{\n  props: TExtraProps;\n  validateOnBlur: boolean;\n  validateOnChange: boolean;\n  validateOnInput: boolean;\n  validateOnModelUpdate: boolean;\n}>;\n\nexport interface ComponentBindsConfig<\n  TValue = unknown,\n  TExtraProps extends GenericObject = GenericObject,\n  TModel extends string = 'modelValue',\n> {\n  mapProps: (state: PublicPathState<TValue>) => TExtraProps;\n  validateOnBlur: boolean;\n  validateOnModelUpdate: boolean;\n  model: TModel;\n}\n\nexport type LazyComponentBindsConfig<\n  TValue = unknown,\n  TExtraProps extends GenericObject = GenericObject,\n  TModel extends string = 'modelValue',\n> = (state: PublicPathState<TValue>) => Partial<{\n  props: TExtraProps;\n  validateOnBlur: boolean;\n  validateOnModelUpdate: boolean;\n  model: TModel;\n}>;\n\nexport interface ComponentModellessBinds {\n  onBlur: () => void;\n}\n\nexport type ComponentModelBinds<TValue = any, TModel extends string = 'modelValue'> = ComponentModellessBinds & {\n  [TKey in `onUpdate:${TModel}`]: (value: TValue) => void;\n};\n\nexport type BaseComponentBinds<TValue = any, TModel extends string = 'modelValue'> = ComponentModelBinds<\n  TValue,\n  TModel\n> & {\n  [k in TModel]: TValue;\n};\n\nexport interface BaseInputBinds<TValue = unknown> {\n  value: TValue | undefined;\n  onBlur: (e: Event) => void;\n  onChange: (e: Event) => void;\n  onInput: (e: Event) => void;\n}\n\nexport interface PrivateFormContext<\n  TValues extends GenericObject = GenericObject,\n  TOutput extends GenericObject = TValues,\n> extends FormActions<TValues> {\n  name: string;\n  formId: number;\n  values: TValues;\n  initialValues: Ref<Partial<TValues>>;\n  controlledValues: Ref<TValues>;\n  fieldArrays: PrivateFieldArrayContext[];\n  submitCount: Ref<number>;\n  schema?: MaybeRef<RawFormSchema<TValues> | StandardSchemaV1<TValues, TOutput> | undefined>;\n  errorBag: Ref<FormErrorBag<TValues>>;\n  errors: ComputedRef<FormErrors<TValues>>;\n  meta: ComputedRef<FormMeta<TValues>>;\n  isSubmitting: Ref<boolean>;\n  isValidating: Ref<boolean>;\n  keepValuesOnUnmount: MaybeRef<boolean>;\n  validateSchema?: (mode: SchemaValidationMode) => Promise<FormValidationResult<TValues, TOutput>>;\n  validate(opts?: Partial<ValidationOptions>): Promise<FormValidationResult<TValues, TOutput>>;\n  validateField<TPath extends Path<TValues>>(\n    field: TPath,\n    opts?: Partial<ValidationOptions>,\n  ): Promise<ValidationResult<TOutput[TPath]>>;\n  stageInitialValue(path: string, value: unknown, updateOriginal?: boolean): void;\n  unsetInitialValue(path: string): void;\n  handleSubmit: HandleSubmitFactory<TValues, TOutput> & { withControlled: HandleSubmitFactory<TValues, TOutput> };\n  setFieldInitialValue(path: string, value: unknown, updateOriginal?: boolean): void;\n  createPathState<TPath extends Path<TValues>>(\n    path: MaybeRef<TPath>,\n    config?: Partial<PathStateConfig<TOutput[TPath]>>,\n  ): PathState<PathValue<TValues, TPath>>;\n  getPathState<TPath extends Path<TValues>>(path: TPath): PathState<PathValue<TValues, TPath>> | undefined;\n  getAllPathStates(): PathState[];\n  removePathState<TPath extends Path<TValues>>(path: TPath, id: number): void;\n  unsetPathValue<TPath extends Path<TValues>>(path: TPath): void;\n  destroyPath(path: string): void;\n  isFieldTouched<TPath extends Path<TValues>>(path: TPath): boolean;\n  isFieldDirty<TPath extends Path<TValues>>(path: TPath): boolean;\n  isFieldValid<TPath extends Path<TValues>>(path: TPath): boolean;\n  defineField<\n    TPath extends Path<TValues>,\n    TValue = PathValue<TValues, TPath>,\n    TExtras extends GenericObject = GenericObject,\n  >(\n    path: MaybeRefOrGetter<TPath>,\n    config?: Partial<InputBindsConfig<TValue, TExtras>> | LazyInputBindsConfig<TValue, TExtras>,\n  ): [Ref<TValue>, Ref<BaseFieldProps & TExtras>];\n}\n\nexport interface FormContext<TValues extends GenericObject = GenericObject, TOutput extends GenericObject = TValues>\n  extends Omit<\n    PrivateFormContext<TValues, TOutput>,\n    | 'formId'\n    | 'schema'\n    | 'initialValues'\n    | 'getPathState'\n    | 'getAllPathStates'\n    | 'removePathState'\n    | 'unsetPathValue'\n    | 'validateSchema'\n    | 'stageInitialValue'\n    | 'setFieldInitialValue'\n    | 'unsetInitialValue'\n    | 'fieldArrays'\n    | 'markForUnmount'\n    | 'keepValuesOnUnmount'\n    | 'values'\n  > {\n  values: TValues;\n  handleReset: () => void;\n  submitForm: (e?: unknown) => Promise<void>;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/types/index.ts",
    "content": "export * from './common';\nexport * from './paths';\nexport * from './forms';\nexport * from './devtools';\n"
  },
  {
    "path": "packages/vee-validate/src/types/paths.ts",
    "content": "// Originally implemented in react-hook-form\n// https://github.com/react-hook-form/react-hook-form/tree/master/src/types/path\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\ntype BrowserNativeObject = Date | FileList | File;\n\ntype Primitive = null | undefined | string | number | boolean | symbol | bigint;\n\n/**\n * Checks whether the type is any\n * See {@link https://stackoverflow.com/a/49928360/3406963}\n * @typeParam T - type which may be any\n * ```\n * IsAny<any> = true\n * IsAny<string> = false\n * ```\n */\nexport type IsAny<T> = 0 extends 1 & T ? true : false;\n\n/**\n * Checks whether T1 can be exactly (mutually) assigned to T2\n * @typeParam T1 - type to check\n * @typeParam T2 - type to check against\n * ```\n * IsEqual<string, string> = true\n * IsEqual<'foo', 'foo'> = true\n * IsEqual<string, number> = false\n * IsEqual<string, number> = false\n * IsEqual<string, 'foo'> = false\n * IsEqual<'foo', string> = false\n * IsEqual<'foo' | 'bar', 'foo'> = boolean // 'foo' is assignable, but 'bar' is not (true | false) -> boolean\n * ```\n */\nexport type IsEqual<T1, T2> = T1 extends T2\n  ? (<G>() => G extends T1 ? 1 : 2) extends <G>() => G extends T2 ? 1 : 2\n    ? true\n    : false\n  : false;\n\n/**\n * Type to query whether an array type T is a tuple type.\n * @typeParam T - type which may be an array or tuple\n * @example\n * ```\n * IsTuple<[number]> = true\n * IsTuple<number[]> = false\n * ```\n */\ntype IsTuple<T extends ReadonlyArray<any>> = number extends T['length'] ? false : true;\n\n/**\n * Type which can be used to index an array or tuple type.\n */\ntype ArrayKey = number;\n\n/**\n * Helper function to break apart T1 and check if any are equal to T2\n *\n * See {@link IsEqual}\n */\ntype AnyIsEqual<T1, T2> = T1 extends T2 ? (IsEqual<T1, T2> extends true ? true : never) : never;\n\n/**\n * Type which given a tuple type returns its own keys, i.e. only its indices.\n * @typeParam T - tuple type\n * @example\n * ```\n * TupleKeys<[number, string]> = '0' | '1'\n * ```\n */\ntype TupleKeys<T extends ReadonlyArray<any>> = Exclude<keyof T, keyof any[]>;\n\n/**\n * Helper type to construct tuple key paths and recurse into its elements.\n *\n * See {@link Path}\n */\ntype PathInternalTuple<TValue extends ReadonlyArray<any>, TraversedTypes> = {\n  [Key in TupleKeys<TValue> & string]: `[${Key}]` | `[${Key}]${PathInternal<TValue[Key], TraversedTypes, false>}`;\n}[TupleKeys<TValue> & string];\n\n/**\n * Helper type to construct array key paths and recurse into its elements.\n *\n * See {@link Path}\n */\ntype PathInternalArray<TValue extends ReadonlyArray<any>, TraversedTypes> =\n  | `[${ArrayKey}]`\n  | `[${ArrayKey}]${PathInternal<TValue[ArrayKey], TraversedTypes, false>}`;\n\n/**\n * Helper type to construct object key paths and recurse into its nested values.\n *\n * See {@link Path}\n */\ntype PathInternalObject<TValue, TraversedTypes, First extends boolean> = {\n  [Key in keyof TValue & string]: First extends true\n    ? `${Key}` | `${Key}${PathInternal<TValue[Key], TraversedTypes, false>}`\n    : `.${Key}` | `.${Key}${PathInternal<TValue[Key], TraversedTypes, false>}`;\n}[keyof TValue & string];\n\n/**\n * Helper type to construct nested any object key paths.\n *\n * See {@link Path}\n */\ntype PathInternalAny = `.${string}` | `[${string}]` | `[${string}].${string}`;\n\n/**\n * Helper type for recursively constructing paths through a type.\n *\n * This obscures internal type params TraversedTypes and First from ed contract.\n *\n * See {@link Path}\n */\ntype PathInternal<TValue, TraversedTypes, First extends boolean> = TValue extends Primitive | BrowserNativeObject\n  ? IsAny<TValue> extends true\n    ? PathInternalAny\n    : never\n  : TValue extends ReadonlyArray<any>\n    ? // Check so that we don't recurse into the same type by ensuring that the\n      // types are mutually assignable mutually required to avoid false\n      // positives of subtypes\n      true extends AnyIsEqual<TraversedTypes, TValue>\n      ? never\n      : IsTuple<TValue> extends true\n        ? PathInternalTuple<TValue, TraversedTypes | TValue>\n        : PathInternalArray<TValue, TraversedTypes | TValue>\n    : TValue extends Record<string, any>\n      ? PathInternalObject<TValue, TraversedTypes | TValue, First>\n      : '';\n\n/**\n * Helper type for recursively constructing paths through a type.\n * This actually constructs the strings and recurses into nested\n * object types.\n *\n * See {@link ArrayPath}\n */\ntype ArrayPathImpl<K extends string | number, V, TraversedTypes> = V extends Primitive | BrowserNativeObject\n  ? IsAny<V> extends true\n    ? string\n    : never\n  : V extends ReadonlyArray<infer U>\n    ? U extends Primitive | BrowserNativeObject\n      ? IsAny<V> extends true\n        ? string\n        : never\n      : // Check so that we don't recurse into the same type\n        // by ensuring that the types are mutually assignable\n        // mutually required to avoid false positives of subtypes\n        true extends AnyIsEqual<TraversedTypes, V>\n        ? never\n        : `${K}` | `${K}.${ArrayPathInternal<V, TraversedTypes | V>}`\n    : true extends AnyIsEqual<TraversedTypes, V>\n      ? never\n      : `${K}.${ArrayPathInternal<V, TraversedTypes | V>}`;\n\n/**\n * Helper type for recursively constructing paths through a type.\n * This obscures the internal type param TraversedTypes from ed contract.\n *\n * See {@link ArrayPath}\n */\ntype ArrayPathInternal<T, TraversedTypes = T> =\n  T extends ReadonlyArray<infer V>\n    ? IsTuple<T> extends true\n      ? {\n          [K in TupleKeys<T>]-?: ArrayPathImpl<K & string, T[K], TraversedTypes>;\n        }[TupleKeys<T>]\n      : ArrayPathImpl<ArrayKey, V, TraversedTypes>\n    : {\n        [K in keyof T]-?: ArrayPathImpl<K & string, T[K], TraversedTypes>;\n      }[keyof T];\n\n/**\n * Type which eagerly collects all paths through a type which point to an array\n * type.\n * @typeParam T - type which should be introspected.\n * @example\n * ```\n * Path<{foo: {bar: string[], baz: number[]}}> = 'foo.bar' | 'foo.baz'\n * ```\n */\n// We want to explode the union type and process each individually\n// so assignable types don't leak onto the stack from the base.\ntype ArrayPath<T> = T extends any ? ArrayPathInternal<T> : never;\n\n/**\n * Type to evaluate the type which the given path points to.\n * @typeParam T - deeply nested type which is indexed by the path\n * @typeParam P - path into the deeply nested type\n * @example\n * ```\n * PathValue<{foo: {bar: string}}, 'foo.bar'> = string\n * PathValue<[number, string], '1'> = string\n * ```\n */\nexport type PathValue<T, P extends Path<T> | ArrayPath<T>> = T extends any\n  ? P extends `${infer K}.${infer R}`\n    ? K extends keyof T\n      ? R extends Path<T[K]>\n        ? PathValue<T[K], R>\n        : never\n      : K extends `${ArrayKey}`\n        ? T extends ReadonlyArray<infer V>\n          ? PathValue<V, R & Path<V>>\n          : never\n        : never\n    : P extends keyof T\n      ? T[P]\n      : P extends `${ArrayKey}`\n        ? T extends ReadonlyArray<infer V>\n          ? V\n          : never\n        : never\n  : never;\n\n/**\n * Type which eagerly collects all paths through a type\n * @typeParam T - type which should be introspected\n * @example\n * ```\n * Path<{foo: {bar: string}}> = 'foo' | 'foo.bar'\n * ```\n */\n// We want to explode the union type and process each individually\n// so assignable types don't leak onto the stack from the base.\nexport type Path<T> = T extends any ? PathInternal<T, T, true> & string : never;\n"
  },
  {
    "path": "packages/vee-validate/src/useField.ts",
    "content": "import {\n  watch,\n  isRef,\n  computed,\n  onMounted,\n  provide,\n  getCurrentInstance,\n  Ref,\n  ComponentInternalInstance,\n  onBeforeUnmount,\n  toValue,\n  MaybeRef,\n  MaybeRefOrGetter,\n  unref,\n} from 'vue';\nimport { klona as deepCopy } from 'klona/full';\nimport { validate as validateValue } from './validate';\nimport {\n  GenericValidateFunction,\n  FieldContext,\n  FieldState,\n  PrivateFieldContext,\n  SchemaValidationMode,\n  ValidationOptions,\n  FormContext,\n  PrivateFormContext,\n  InputType,\n} from './types';\nimport {\n  normalizeRules,\n  extractLocators,\n  normalizeEventValue,\n  hasCheckedAttr,\n  getFromPath,\n  injectWithSelf,\n  resolveNextCheckboxValue,\n  applyModelModifiers,\n  withLatest,\n  isEqual,\n  isStandardSchema,\n} from './utils';\nimport { isCallable, normalizeFormPath } from '../../shared';\nimport { FieldContextKey, FormContextKey, IS_ABSENT } from './symbols';\nimport { useFieldState } from './useFieldState';\nimport { refreshInspector, registerSingleFieldWithDevtools } from './devtools';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport interface FieldOptions<TValue = unknown> {\n  initialValue?: MaybeRef<TValue>;\n  validateOnValueUpdate: boolean;\n  validateOnMount?: boolean;\n  bails?: boolean;\n  type?: InputType;\n  checkedValue?: MaybeRefOrGetter<TValue>;\n  uncheckedValue?: MaybeRefOrGetter<TValue>;\n  label?: MaybeRefOrGetter<string | undefined>;\n  controlled?: boolean;\n  keepValueOnUnmount?: MaybeRefOrGetter<boolean | undefined>;\n  syncVModel?: boolean | string;\n  form?: FormContext;\n}\n\nexport type RuleExpression<TValue> =\n  | string\n  | Record<string, unknown>\n  | GenericValidateFunction<TValue>\n  | GenericValidateFunction<TValue>[]\n  | StandardSchemaV1<TValue>\n  | undefined;\n\n/**\n * Creates a field composite.\n */\nexport function useField<TValue = unknown>(\n  path: MaybeRefOrGetter<string>,\n  rules?: MaybeRef<RuleExpression<TValue>>,\n  opts?: Partial<FieldOptions<TValue>>,\n): FieldContext<TValue> {\n  if (hasCheckedAttr(opts?.type)) {\n    return useFieldWithChecked(path, rules, opts);\n  }\n\n  return _useField(path, rules, opts);\n}\n\nfunction _useField<TValue = unknown>(\n  path: MaybeRefOrGetter<string>,\n  rules?: MaybeRef<RuleExpression<TValue>>,\n  opts?: Partial<FieldOptions<TValue>>,\n): FieldContext<TValue> {\n  const {\n    initialValue: modelValue,\n    validateOnMount,\n    bails,\n    type,\n    checkedValue,\n    label,\n    validateOnValueUpdate,\n    uncheckedValue,\n    controlled,\n    keepValueOnUnmount,\n    syncVModel,\n    form: controlForm,\n  } = normalizeOptions(opts);\n\n  const injectedForm = controlled ? injectWithSelf(FormContextKey) : undefined;\n  const form = (controlForm as PrivateFormContext | undefined) || injectedForm;\n  const name = computed(() => normalizeFormPath(toValue(path)));\n\n  const validator = computed(() => {\n    const schema = toValue(form?.schema);\n    if (schema) {\n      return undefined;\n    }\n\n    const rulesValue = unref(rules);\n\n    if (isStandardSchema(rulesValue) || isCallable(rulesValue) || Array.isArray(rulesValue)) {\n      return rulesValue;\n    }\n\n    return normalizeRules(rulesValue);\n  });\n\n  const { id, value, initialValue, meta, setState, errors, flags } = useFieldState<TValue>(name, {\n    modelValue,\n    form,\n    bails,\n    label,\n    type,\n    validate: validator.value ? validate : undefined,\n  });\n\n  const errorMessage = computed(() => errors.value[0]);\n\n  if (syncVModel) {\n    useVModel({\n      value,\n      prop: syncVModel,\n      handleChange,\n      shouldValidate: () => validateOnValueUpdate && !flags.pendingReset,\n    });\n  }\n\n  /**\n   * Handles common onBlur meta update\n   */\n  const handleBlur = (evt?: unknown, shouldValidate = false) => {\n    meta.touched = true;\n    if (shouldValidate) {\n      validateWithStateMutation();\n    }\n  };\n\n  async function validateCurrentValue(mode: SchemaValidationMode) {\n    if (form?.validateSchema) {\n      const { results } = await form.validateSchema(mode);\n\n      return results[toValue(name)] ?? { valid: true, errors: [] };\n    }\n\n    if (validator.value) {\n      return validateValue(value.value, validator.value, {\n        name: toValue(name),\n        label: toValue(label),\n        values: form?.values ?? {},\n        bails,\n      });\n    }\n\n    return { valid: true, errors: [] };\n  }\n\n  const validateWithStateMutation = withLatest(\n    async () => {\n      meta.pending = true;\n      meta.validated = true;\n\n      return validateCurrentValue('validated-only');\n    },\n    result => {\n      if (flags.pendingUnmount[field.id]) {\n        return result;\n      }\n\n      setState({ errors: result.errors });\n      meta.pending = false;\n      meta.valid = result.valid;\n\n      return result;\n    },\n  );\n\n  const validateValidStateOnly = withLatest(\n    async () => {\n      return validateCurrentValue('silent');\n    },\n    result => {\n      meta.valid = result.valid;\n\n      return result;\n    },\n  );\n\n  function validate(opts?: Partial<ValidationOptions>) {\n    if (opts?.mode === 'silent') {\n      return validateValidStateOnly();\n    }\n\n    return validateWithStateMutation();\n  }\n\n  // Common input/change event handler\n  function handleChange(e: unknown, shouldValidate = true) {\n    const newValue = normalizeEventValue(e) as TValue;\n    setValue(newValue, shouldValidate);\n  }\n\n  // Runs the initial validation\n  onMounted(() => {\n    if (validateOnMount) {\n      return validateWithStateMutation();\n    }\n\n    // validate self initially if no form was handling this\n    // forms should have their own initial silent validation run to make things more efficient\n    if (!form || !form.validateSchema) {\n      validateValidStateOnly();\n    }\n  });\n\n  function setTouched(isTouched: boolean) {\n    meta.touched = isTouched;\n  }\n\n  function resetField(state?: Partial<FieldState<TValue>>) {\n    const newValue = state && 'value' in state ? (state.value as TValue) : initialValue.value;\n\n    setState({\n      value: deepCopy(newValue),\n      initialValue: deepCopy(newValue),\n      touched: state?.touched ?? false,\n      errors: state?.errors || [],\n    });\n\n    meta.pending = false;\n    meta.validated = false;\n    validateValidStateOnly();\n  }\n\n  const vm = getCurrentInstance();\n\n  function setValue(newValue: TValue, shouldValidate = true) {\n    value.value = vm && syncVModel ? applyModelModifiers<TValue>(newValue, vm.props.modelModifiers) : newValue;\n    const validateFn = shouldValidate ? validateWithStateMutation : validateValidStateOnly;\n    validateFn();\n  }\n\n  function setErrors(errors: string[] | string) {\n    setState({ errors: Array.isArray(errors) ? errors : [errors] });\n  }\n\n  const valueProxy = computed({\n    get() {\n      return value.value;\n    },\n    set(newValue: TValue) {\n      setValue(newValue, validateOnValueUpdate);\n    },\n  });\n\n  const field: PrivateFieldContext<TValue> = {\n    id,\n    name,\n    label,\n    value: valueProxy,\n    meta,\n    errors,\n    errorMessage,\n    type,\n    checkedValue,\n    uncheckedValue,\n    bails,\n    keepValueOnUnmount,\n    resetField,\n    handleReset: () => resetField(),\n    validate,\n    handleChange,\n    handleBlur,\n    setState,\n    setTouched,\n    setErrors,\n    setValue,\n  };\n\n  provide(FieldContextKey, field);\n\n  if (isRef(rules) && typeof unref(rules) !== 'function') {\n    watch(\n      rules,\n      (value, oldValue) => {\n        if (isEqual(value, oldValue)) {\n          return;\n        }\n\n        meta.validated ? validateWithStateMutation() : validateValidStateOnly();\n      },\n      {\n        deep: true,\n      },\n    );\n  }\n\n  if (__DEV__) {\n    (field as any)._vm = getCurrentInstance();\n    watch(() => ({ errors: errors.value, ...meta, value: value.value }), refreshInspector, {\n      deep: true,\n    });\n\n    if (!form) {\n      registerSingleFieldWithDevtools(field);\n    }\n  }\n\n  // if no associated form return the field API immediately\n  if (!form) {\n    return field;\n  }\n\n  // associate the field with the given form\n\n  // extract cross-field dependencies in a computed prop\n  const dependencies = computed(() => {\n    const rulesVal = validator.value;\n    // is falsy, a function schema or a standard schema\n    if (!rulesVal || isCallable(rulesVal) || isStandardSchema(rulesVal) || Array.isArray(rulesVal)) {\n      return {};\n    }\n\n    return Object.keys(rulesVal).reduce(\n      (acc, rule: string) => {\n        const deps = extractLocators(rulesVal[rule])\n          .map((dep: any) => dep.__locatorRef)\n          .reduce(\n            (depAcc, depName) => {\n              const depValue = getFromPath(form.values, depName) || form.values[depName];\n\n              if (depValue !== undefined) {\n                depAcc[depName] = depValue;\n              }\n\n              return depAcc;\n            },\n            {} as Record<string, unknown>,\n          );\n\n        Object.assign(acc, deps);\n\n        return acc;\n      },\n      {} as Record<string, unknown>,\n    );\n  });\n\n  // Adds a watcher that runs the validation whenever field dependencies change\n  watch(dependencies, (deps, oldDeps) => {\n    // Skip if no dependencies or if the field wasn't manipulated\n    if (!Object.keys(deps).length) {\n      return;\n    }\n\n    const shouldValidate = !isEqual(deps, oldDeps);\n    if (shouldValidate) {\n      meta.validated ? validateWithStateMutation() : validateValidStateOnly();\n    }\n  });\n\n  onBeforeUnmount(() => {\n    const shouldKeepValue = toValue(field.keepValueOnUnmount) ?? toValue(form.keepValuesOnUnmount);\n    const path = toValue(name);\n    if (shouldKeepValue || !form || flags.pendingUnmount[field.id]) {\n      form?.removePathState(path, id);\n\n      return;\n    }\n\n    flags.pendingUnmount[field.id] = true;\n    const pathState = form.getPathState(path);\n    const matchesId =\n      Array.isArray(pathState?.id) && pathState?.multiple\n        ? pathState?.id.includes(field.id)\n        : pathState?.id === field.id;\n    if (!matchesId) {\n      return;\n    }\n\n    if (pathState?.multiple && Array.isArray(pathState.value)) {\n      const valueIdx = pathState.value.findIndex(i => isEqual(i, toValue(field.checkedValue)));\n      if (valueIdx > -1) {\n        const newVal = [...pathState.value];\n        newVal.splice(valueIdx, 1);\n        form.setFieldValue(path, newVal);\n      }\n\n      if (Array.isArray(pathState.id)) {\n        pathState.id.splice(pathState.id.indexOf(field.id), 1);\n      }\n    } else {\n      form.unsetPathValue(toValue(name));\n    }\n\n    form.removePathState(path, id);\n  });\n\n  return field;\n}\n\n/**\n * Normalizes partial field options to include the full options\n */\nfunction normalizeOptions<TValue>(opts: Partial<FieldOptions<TValue>> | undefined): FieldOptions<TValue> {\n  const defaults = (): Partial<FieldOptions<TValue>> => ({\n    initialValue: undefined,\n    validateOnMount: false,\n    bails: true,\n    label: undefined,\n    validateOnValueUpdate: true,\n    keepValueOnUnmount: undefined,\n    syncVModel: false,\n    controlled: true,\n  });\n\n  const isVModelSynced = !!opts?.syncVModel;\n  const modelPropName = typeof opts?.syncVModel === 'string' ? opts.syncVModel : 'modelValue';\n  const initialValue =\n    isVModelSynced && !('initialValue' in (opts || {}))\n      ? getCurrentModelValue(getCurrentInstance(), modelPropName)\n      : opts?.initialValue;\n\n  if (!opts) {\n    return { ...defaults(), initialValue } as FieldOptions<TValue>;\n  }\n\n  const controlled = opts.controlled ?? true;\n  const syncVModel = opts?.syncVModel || false;\n\n  return {\n    ...defaults(),\n    ...(opts || {}),\n    initialValue,\n    controlled: controlled ?? true,\n    checkedValue: opts?.checkedValue,\n    syncVModel,\n  } as FieldOptions<TValue>;\n}\n\nfunction useFieldWithChecked<TValue = unknown>(\n  name: MaybeRefOrGetter<string>,\n  rules?: MaybeRef<RuleExpression<TValue>>,\n  opts?: Partial<FieldOptions<TValue>>,\n): FieldContext<TValue> {\n  const form = opts?.controlled ? injectWithSelf(FormContextKey) : undefined;\n  const checkedValue = opts?.checkedValue;\n  const uncheckedValue = opts?.uncheckedValue;\n\n  function patchCheckedApi(\n    field: FieldContext<TValue> & { originalHandleChange?: FieldContext['handleChange'] },\n  ): FieldContext<TValue> {\n    const handleChange = field.handleChange;\n\n    const checked = computed(() => {\n      const currentValue = toValue(field.value);\n      const checkedVal = toValue(checkedValue);\n\n      return Array.isArray(currentValue)\n        ? currentValue.findIndex(v => isEqual(v, checkedVal)) >= 0\n        : isEqual(checkedVal, currentValue);\n    });\n\n    function handleCheckboxChange(e: unknown, shouldValidate = true) {\n      if (checked.value === ((e as Event)?.target as HTMLInputElement)?.checked) {\n        if (shouldValidate) {\n          field.validate();\n        }\n        return;\n      }\n\n      const path = toValue(name);\n      const pathState = form?.getPathState(path);\n      const value = normalizeEventValue(e);\n      let newValue = toValue(checkedValue) ?? value;\n      if (form && pathState?.multiple && pathState.type === 'checkbox') {\n        newValue = resolveNextCheckboxValue(getFromPath(form.values, path) || [], newValue, undefined) as TValue;\n      } else if (opts?.type === 'checkbox') {\n        newValue = resolveNextCheckboxValue(toValue(field.value), newValue, toValue(uncheckedValue)) as TValue;\n      }\n\n      handleChange(newValue, shouldValidate);\n    }\n\n    return {\n      ...field,\n      checked,\n      checkedValue,\n      uncheckedValue,\n      handleChange: handleCheckboxChange,\n    };\n  }\n\n  return patchCheckedApi(_useField<TValue>(name, rules, opts));\n}\n\ninterface ModelOpts<TValue> {\n  prop: string | boolean;\n  value: Ref<TValue>;\n  handleChange: FieldContext['handleChange'];\n  shouldValidate: () => boolean;\n}\n\nfunction useVModel<TValue = unknown>({ prop, value, handleChange, shouldValidate }: ModelOpts<TValue>) {\n  const vm = getCurrentInstance();\n  /* istanbul ignore next */\n  if (!vm || !prop) {\n    if (__DEV__) {\n      // eslint-disable-next-line no-console\n      console.warn('Failed to setup model events because `useField` was not called in setup.');\n    }\n    return;\n  }\n\n  const propName = typeof prop === 'string' ? prop : 'modelValue';\n  const emitName = `update:${propName}`;\n\n  // Component doesn't have a model prop setup (must be defined on the props)\n  if (!(propName in vm.props)) {\n    return;\n  }\n\n  watch(value, newValue => {\n    if (isEqual(newValue, getCurrentModelValue(vm, propName))) {\n      return;\n    }\n\n    vm.emit(emitName, newValue);\n  });\n\n  watch(\n    () => getCurrentModelValue<TValue>(vm, propName),\n    propValue => {\n      if ((propValue as any) === IS_ABSENT && value.value === undefined) {\n        return;\n      }\n\n      const newValue = (propValue as any) === IS_ABSENT ? undefined : propValue;\n      if (isEqual(newValue, value.value)) {\n        return;\n      }\n\n      handleChange(newValue, shouldValidate());\n    },\n  );\n}\n\nfunction getCurrentModelValue<TValue = unknown>(vm: ComponentInternalInstance | null, propName: string) {\n  if (!vm) {\n    return undefined;\n  }\n\n  return vm.props[propName] as TValue;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useFieldArray.ts",
    "content": "import { Ref, unref, ref, onBeforeUnmount, watch, MaybeRefOrGetter, toValue } from 'vue';\nimport { klona as deepCopy } from 'klona/full';\nimport { isNullOrUndefined } from '../../shared';\nimport { FormContextKey } from './symbols';\nimport { FieldArrayContext, FieldEntry, PrivateFieldArrayContext, PrivateFormContext } from './types';\nimport { computedDeep, getFromPath, injectWithSelf, warn, isEqual, setInPath } from './utils';\n\nexport function useFieldArray<TValue = unknown>(arrayPath: MaybeRefOrGetter<string>): FieldArrayContext<TValue> {\n  const form = injectWithSelf(FormContextKey, undefined) as PrivateFormContext;\n  const fields: Ref<FieldEntry<TValue>[]> = ref([]);\n\n  const noOp = () => {};\n  const noOpApi: FieldArrayContext<TValue> = {\n    fields,\n    remove: noOp,\n    push: noOp,\n    swap: noOp,\n    insert: noOp,\n    update: noOp,\n    replace: noOp,\n    prepend: noOp,\n    move: noOp,\n  };\n\n  if (!form) {\n    if (__DEV__) {\n      warn(\n        'FieldArray requires being a child of `<Form/>` or `useForm` being called before it. Array fields may not work correctly',\n      );\n    }\n\n    return noOpApi;\n  }\n\n  if (!unref(arrayPath)) {\n    if (__DEV__) {\n      warn('FieldArray requires a field path to be provided, did you forget to pass the `name` prop?');\n    }\n    return noOpApi;\n  }\n\n  const alreadyExists = form.fieldArrays.find(a => unref(a.path) === unref(arrayPath));\n  if (alreadyExists) {\n    return alreadyExists as PrivateFieldArrayContext<TValue>;\n  }\n\n  let entryCounter = 0;\n\n  function getCurrentValues() {\n    return getFromPath<TValue[]>(form?.values, toValue(arrayPath), []) || [];\n  }\n\n  function initFields() {\n    const currentValues = getCurrentValues();\n    if (!Array.isArray(currentValues)) {\n      return;\n    }\n\n    fields.value = currentValues.map((v, idx) => createEntry(v, idx, fields.value));\n    updateEntryFlags();\n  }\n\n  initFields();\n\n  function updateEntryFlags() {\n    const fieldsLength = fields.value.length;\n    for (let i = 0; i < fieldsLength; i++) {\n      const entry = fields.value[i];\n      entry.isFirst = i === 0;\n      entry.isLast = i === fieldsLength - 1;\n    }\n  }\n\n  function createEntry(value: TValue, idx?: number, currentFields?: FieldEntry<TValue>[]): FieldEntry<TValue> {\n    // Skips the work by returning the current entry if it already exists\n    // This should make the `key` prop stable and doesn't cause more re-renders than needed\n    // The value is computed and should update anyways\n    if (currentFields && !isNullOrUndefined(idx) && currentFields[idx]) {\n      return currentFields[idx];\n    }\n\n    const key = entryCounter++;\n    const entry: FieldEntry<TValue> = {\n      key,\n      value: computedDeep<TValue>({\n        get() {\n          const currentValues = getFromPath<TValue[]>(form?.values, toValue(arrayPath), []) || [];\n          const idx = fields.value.findIndex(e => e.key === key);\n\n          return idx === -1 ? value : currentValues[idx];\n        },\n        set(value: TValue) {\n          const idx = fields.value.findIndex(e => e.key === key);\n          if (idx === -1) {\n            if (__DEV__) {\n              warn(`Attempting to update a non-existent array item`);\n            }\n            return;\n          }\n\n          update(idx, value);\n        },\n      }) as TValue, // will be auto unwrapped\n      isFirst: false,\n      isLast: false,\n    };\n\n    return entry;\n  }\n\n  function afterMutation() {\n    updateEntryFlags();\n    // Should trigger a silent validation since a field may not do that #4096\n    form?.validate({ mode: 'silent' });\n  }\n\n  function remove(idx: number) {\n    const pathName = toValue(arrayPath);\n    const pathValue = getFromPath<TValue[]>(form?.values, pathName);\n    if (!pathValue || !Array.isArray(pathValue)) {\n      return;\n    }\n\n    const newValue = [...pathValue];\n    newValue.splice(idx, 1);\n    const fieldPath = pathName + `[${idx}]`;\n    form.destroyPath(fieldPath);\n    form.unsetInitialValue(fieldPath);\n    setInPath(form.values, pathName, newValue);\n    fields.value.splice(idx, 1);\n    afterMutation();\n  }\n\n  function push(initialValue: TValue) {\n    const value = deepCopy(initialValue);\n    const pathName = toValue(arrayPath);\n    const pathValue = getFromPath<TValue[]>(form?.values, pathName);\n    const normalizedPathValue = isNullOrUndefined(pathValue) ? [] : pathValue;\n    if (!Array.isArray(normalizedPathValue)) {\n      return;\n    }\n\n    const newValue = [...normalizedPathValue];\n    newValue.push(value);\n    form.stageInitialValue(pathName + `[${newValue.length - 1}]`, value);\n    setInPath(form.values, pathName, newValue);\n    fields.value.push(createEntry(value));\n    afterMutation();\n  }\n\n  function swap(indexA: number, indexB: number) {\n    const pathName = toValue(arrayPath);\n    const pathValue = getFromPath<TValue[]>(form?.values, pathName);\n    if (!Array.isArray(pathValue) || !(indexA in pathValue) || !(indexB in pathValue)) {\n      return;\n    }\n\n    const newValue = [...pathValue];\n    const newFields = [...fields.value];\n\n    // the old switcheroo\n    const temp = newValue[indexA];\n    newValue[indexA] = newValue[indexB];\n    newValue[indexB] = temp;\n\n    const tempEntry = newFields[indexA];\n    newFields[indexA] = newFields[indexB];\n    newFields[indexB] = tempEntry;\n    setInPath(form.values, pathName, newValue);\n    fields.value = newFields;\n    updateEntryFlags();\n  }\n\n  function insert(idx: number, initialValue: TValue) {\n    const value = deepCopy(initialValue);\n    const pathName = toValue(arrayPath);\n    const pathValue = getFromPath<TValue[]>(form?.values, pathName);\n    if (!Array.isArray(pathValue) || pathValue.length < idx) {\n      return;\n    }\n\n    const newValue = [...pathValue];\n    const newFields = [...fields.value];\n\n    newValue.splice(idx, 0, value);\n    newFields.splice(idx, 0, createEntry(value));\n    setInPath(form.values, pathName, newValue);\n    fields.value = newFields;\n    afterMutation();\n  }\n\n  function replace(arr: TValue[]) {\n    const pathName = toValue(arrayPath);\n    form.stageInitialValue(pathName, arr);\n    setInPath(form.values, pathName, arr);\n    initFields();\n    afterMutation();\n  }\n\n  function update(idx: number, value: TValue) {\n    const pathName = toValue(arrayPath);\n    const pathValue = getFromPath<TValue[]>(form?.values, pathName);\n    if (!Array.isArray(pathValue) || pathValue.length - 1 < idx) {\n      return;\n    }\n\n    setInPath(form.values, `${pathName}[${idx}]`, value);\n    form?.validate({ mode: 'validated-only' });\n  }\n\n  function prepend(initialValue: TValue) {\n    const value = deepCopy(initialValue);\n    const pathName = toValue(arrayPath);\n    const pathValue = getFromPath<TValue[]>(form?.values, pathName);\n    const normalizedPathValue = isNullOrUndefined(pathValue) ? [] : pathValue;\n    if (!Array.isArray(normalizedPathValue)) {\n      return;\n    }\n\n    const newValue = [value, ...normalizedPathValue];\n    setInPath(form.values, pathName, newValue);\n    form.stageInitialValue(pathName + `[0]`, value);\n    fields.value.unshift(createEntry(value));\n    afterMutation();\n  }\n\n  function move(oldIdx: number, newIdx: number) {\n    const pathName = toValue(arrayPath);\n    const pathValue = getFromPath<TValue[]>(form?.values, pathName);\n    const newValue = isNullOrUndefined(pathValue) ? [] : [...pathValue];\n\n    if (!Array.isArray(pathValue) || !(oldIdx in pathValue) || !(newIdx in pathValue)) {\n      return;\n    }\n\n    const newFields = [...fields.value];\n\n    const movedItem = newFields[oldIdx];\n    newFields.splice(oldIdx, 1);\n    newFields.splice(newIdx, 0, movedItem);\n\n    const movedValue = newValue[oldIdx];\n    newValue.splice(oldIdx, 1);\n    newValue.splice(newIdx, 0, movedValue);\n    setInPath(form.values, pathName, newValue);\n    fields.value = newFields;\n    afterMutation();\n  }\n\n  const fieldArrayCtx: FieldArrayContext<TValue> = {\n    fields,\n    remove,\n    push,\n    swap,\n    insert,\n    update,\n    replace,\n    prepend,\n    move,\n  };\n\n  form.fieldArrays.push({\n    path: arrayPath,\n    reset: initFields,\n    ...fieldArrayCtx,\n  });\n\n  onBeforeUnmount(() => {\n    const idx = form.fieldArrays.findIndex(i => toValue(i.path) === toValue(arrayPath));\n    if (idx >= 0) {\n      form.fieldArrays.splice(idx, 1);\n    }\n  });\n\n  // Makes sure to sync the form values with the array value if they go out of sync\n  // #4153\n  watch(getCurrentValues, formValues => {\n    const fieldsValues = fields.value.map(f => f.value);\n    // If form values are not the same as the current values then something overrode them.\n    if (!isEqual(formValues, fieldsValues)) {\n      initFields();\n    }\n  });\n\n  return fieldArrayCtx;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useFieldError.ts",
    "content": "import { computed, inject, MaybeRefOrGetter, toValue } from 'vue';\nimport { FieldContextKey, FormContextKey } from './symbols';\nimport { injectWithSelf } from './utils';\n\n/**\n * Gives access to a single field error\n */\nexport function useFieldError(path?: MaybeRefOrGetter<string>) {\n  const form = injectWithSelf(FormContextKey);\n  // We don't want to use self injected context as it doesn't make sense\n  const field = path ? undefined : inject(FieldContextKey);\n\n  return computed<string | undefined>(() => {\n    if (path) {\n      return form?.errors.value[toValue(path)];\n    }\n\n    return field?.errorMessage.value;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useFieldState.ts",
    "content": "import { computed, isRef, reactive, ref, Ref, unref, watch, MaybeRef, MaybeRefOrGetter } from 'vue';\nimport { FieldMeta, FieldState, FieldValidator, InputType, PrivateFormContext, PathState } from './types';\nimport { getFromPath, isEqual, normalizeErrorItem } from './utils';\n\nexport interface StateSetterInit<TValue = unknown> extends FieldState<TValue> {\n  initialValue: TValue;\n}\n\nexport interface FieldStateComposable<TValue = unknown> {\n  id: number;\n  path: MaybeRef<string>;\n  meta: FieldMeta<TValue>;\n  value: Ref<TValue>;\n  flags: PathState['__flags'];\n  initialValue: Ref<TValue>;\n  errors: Ref<string[]>;\n  setState(state: Partial<StateSetterInit<TValue>>): void;\n}\n\nexport interface StateInit<TInput = unknown, TOutput = TInput> {\n  modelValue: MaybeRef<TInput>;\n  form?: PrivateFormContext;\n  bails: boolean;\n  label?: MaybeRefOrGetter<string | undefined>;\n  type?: InputType;\n  validate?: FieldValidator<TOutput>;\n}\n\nlet ID_COUNTER = 0;\n\nexport function useFieldState<TValue = unknown>(\n  path: MaybeRef<string>,\n  init: Partial<StateInit<TValue>>,\n): FieldStateComposable<TValue> {\n  const { value, initialValue, setInitialValue } = _useFieldValue<TValue>(path, init.modelValue, init.form);\n\n  if (!init.form) {\n    const { errors, setErrors } = createFieldErrors();\n    const id = ID_COUNTER >= Number.MAX_SAFE_INTEGER ? 0 : ++ID_COUNTER;\n    const meta = createFieldMeta(value, initialValue, errors);\n\n    function setState(state: Partial<StateSetterInit<TValue>>) {\n      if ('value' in state) {\n        value.value = state.value as TValue;\n      }\n\n      if ('errors' in state) {\n        setErrors(state.errors);\n      }\n\n      if ('touched' in state) {\n        meta.touched = state.touched ?? meta.touched;\n      }\n\n      if ('initialValue' in state) {\n        setInitialValue(state.initialValue as TValue);\n      }\n    }\n\n    return {\n      id,\n      path,\n      value,\n      initialValue,\n      meta,\n      flags: { pendingUnmount: { [id]: false }, pendingReset: false },\n      errors,\n      setState,\n    };\n  }\n\n  const state = init.form.createPathState(path, {\n    bails: init.bails,\n    label: init.label,\n    type: init.type,\n    validate: init.validate,\n  });\n\n  const errors = computed(() => state.errors);\n\n  function setState(state: Partial<StateSetterInit<TValue>>) {\n    if ('value' in state) {\n      value.value = state.value as TValue;\n    }\n\n    if ('errors' in state) {\n      init.form?.setFieldError(unref(path), state.errors);\n    }\n\n    if ('touched' in state) {\n      init.form?.setFieldTouched(unref(path), state.touched ?? false);\n    }\n\n    if ('initialValue' in state) {\n      setInitialValue(state.initialValue as TValue);\n    }\n  }\n\n  return {\n    id: Array.isArray(state.id) ? state.id[state.id.length - 1] : state.id,\n    path,\n    value,\n    errors,\n    meta: state,\n    initialValue,\n    flags: state.__flags,\n    setState,\n  };\n}\n\ninterface FieldValueComposable<TValue = unknown> {\n  value: Ref<TValue>;\n  initialValue: Ref<TValue>;\n  setInitialValue(value: TValue): void;\n}\n\n/**\n * Creates the field value and resolves the initial value\n */\nexport function _useFieldValue<TValue = unknown>(\n  path: MaybeRef<string>,\n  modelValue?: MaybeRef<TValue>,\n  form?: PrivateFormContext,\n): FieldValueComposable<TValue> {\n  const modelRef = ref(unref(modelValue)) as Ref<TValue>;\n\n  function resolveInitialValue() {\n    if (!form) {\n      return unref(modelRef) as TValue;\n    }\n\n    return getFromPath<TValue>(form.initialValues.value, unref(path), unref(modelRef)) as TValue;\n  }\n\n  function setInitialValue(value: TValue) {\n    if (!form) {\n      modelRef.value = value;\n      return;\n    }\n\n    form.setFieldInitialValue(unref(path), value, true);\n  }\n\n  const initialValue = computed(resolveInitialValue);\n\n  // if no form is associated, use a regular ref.\n  if (!form) {\n    const value = ref(resolveInitialValue()) as Ref<TValue>;\n\n    return {\n      value,\n      initialValue,\n      setInitialValue,\n    };\n  }\n\n  // to set the initial value, first check if there is a current value, if there is then use it.\n  // otherwise use the configured initial value if it exists.\n  // prioritize model value over form values\n  // #3429\n  const currentValue = resolveModelValue(modelValue, form, initialValue, path);\n  form.stageInitialValue(unref(path), currentValue, true);\n  // otherwise use a computed setter that triggers the `setFieldValue`\n  const value = computed<TValue>({\n    get() {\n      return getFromPath<TValue>(form.values, unref(path)) as TValue;\n    },\n    set(newVal) {\n      form.setFieldValue(unref(path), newVal, false);\n    },\n  }) as Ref<TValue>;\n\n  return {\n    value,\n    initialValue,\n    setInitialValue,\n  };\n}\n\n/*\n  to set the initial value, first check if there is a current value, if there is then use it.\n  otherwise use the configured initial value if it exists.\n  prioritize model value over form values\n  #3429\n*/\nfunction resolveModelValue<TValue>(\n  modelValue: MaybeRef<TValue> | undefined,\n  form: PrivateFormContext,\n  initialValue: MaybeRef<TValue> | undefined,\n  path: MaybeRef<string>,\n): TValue {\n  if (isRef(modelValue)) {\n    return unref(modelValue);\n  }\n\n  if (modelValue !== undefined) {\n    return modelValue;\n  }\n\n  return getFromPath(form.values, unref(path), unref(initialValue)) as TValue;\n}\n\n/**\n * Creates meta flags state and some associated effects with them\n */\nfunction createFieldMeta<TValue>(\n  currentValue: Ref<TValue>,\n  initialValue: MaybeRef<TValue> | undefined,\n  errors: Ref<string[]>,\n) {\n  const meta = reactive({\n    touched: false,\n    pending: false,\n    valid: true,\n    validated: !!unref(errors).length,\n    initialValue: computed(() => unref(initialValue) as TValue | undefined),\n    dirty: computed(() => {\n      return !isEqual(unref(currentValue), unref(initialValue));\n    }),\n  }) as FieldMeta<TValue>;\n\n  watch(\n    errors,\n    value => {\n      meta.valid = !value.length;\n    },\n    {\n      immediate: true,\n      flush: 'sync',\n    },\n  );\n\n  return meta;\n}\n\n/**\n * Creates the error message state for the field state\n */\nexport function createFieldErrors() {\n  const errors = ref<string[]>([]);\n\n  return {\n    errors,\n    setErrors: (messages: string | string[] | null | undefined) => {\n      errors.value = normalizeErrorItem(messages);\n    },\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useFieldValue.ts",
    "content": "import { computed, inject, MaybeRefOrGetter, toValue } from 'vue';\nimport { FieldContextKey, FormContextKey } from './symbols';\nimport { getFromPath, injectWithSelf } from './utils';\n\n/**\n * Gives access to a field's current value\n */\nexport function useFieldValue<TValue = unknown>(path?: MaybeRefOrGetter<string>) {\n  const form = injectWithSelf(FormContextKey);\n  // We don't want to use self injected context as it doesn't make sense\n  const field = path ? undefined : inject(FieldContextKey);\n\n  return computed(() => {\n    if (path) {\n      return getFromPath(form?.values, toValue(path)) as TValue;\n    }\n\n    return toValue(field?.value) as TValue;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useForm.ts",
    "content": "import {\n  computed,\n  ref,\n  Ref,\n  provide,\n  reactive,\n  onMounted,\n  isRef,\n  watch,\n  unref,\n  nextTick,\n  warn,\n  watchEffect,\n  shallowRef,\n  readonly,\n  toValue,\n  MaybeRef,\n  MaybeRefOrGetter,\n  inject,\n} from 'vue';\nimport { PartialDeep } from 'type-fest';\nimport { klona as deepCopy } from 'klona/full';\nimport {\n  FieldMeta,\n  SubmissionHandler,\n  GenericValidateFunction,\n  ValidationResult,\n  FormState,\n  FormValidationResult,\n  FlattenAndMapPathsValidationResult,\n  PrivateFormContext,\n  FormContext,\n  FormErrors,\n  FormErrorBag,\n  SchemaValidationMode,\n  RawFormSchema,\n  ValidationOptions,\n  PrivateFieldArrayContext,\n  InvalidSubmissionHandler,\n  FieldState,\n  GenericObject,\n  Path,\n  FlattenAndSetPathsType,\n  PathValue,\n  PathState,\n  PathStateConfig,\n  BaseFieldProps,\n  InputBindsConfig,\n  LazyInputBindsConfig,\n  ResetFormOpts,\n} from './types';\nimport {\n  getFromPath,\n  keysOf,\n  setInPath,\n  unsetPath,\n  isFormSubmitEvent,\n  debounceAsync,\n  withLatest,\n  isEqual,\n  normalizeErrorItem,\n  omit,\n  debounceNextTick,\n  isStandardSchema,\n} from './utils';\nimport { FormContextKey, PublicFormContextKey } from './symbols';\nimport { validateStandardSchema, validateObjectSchema } from './validate';\nimport { refreshInspector, registerFormWithDevTools } from './devtools';\nimport { isCallable, merge, normalizeFormPath } from '../../shared';\nimport { getConfig } from './config';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\n\ntype FormSchema<TValues extends Record<string, unknown>> =\n  | FlattenAndSetPathsType<TValues, GenericValidateFunction | string | GenericObject>\n  | undefined;\n\nexport interface FormOptions<\n  TValues extends GenericObject,\n  TOutput = TValues,\n  TSchema extends StandardSchemaV1<TValues, TOutput> | FormSchema<TValues> = FormSchema<TValues>,\n> {\n  validationSchema?: MaybeRef<TSchema extends StandardSchemaV1 ? StandardSchemaV1<TValues, TOutput> : any>;\n  initialValues?: PartialDeep<TValues> | undefined | null;\n  initialErrors?: FlattenAndSetPathsType<TValues, string | undefined>;\n  initialTouched?: FlattenAndSetPathsType<TValues, boolean>;\n  validateOnMount?: boolean;\n  keepValuesOnUnmount?: MaybeRef<boolean>;\n  name?: string;\n}\n\nlet FORM_COUNTER = 0;\n\nconst PRIVATE_PATH_STATE_KEYS: (keyof PathState)[] = ['bails', 'fieldsCount', 'id', 'multiple', 'type', 'validate'];\n\nfunction resolveInitialValues<TValues extends GenericObject = GenericObject>(opts?: FormOptions<TValues>): TValues {\n  const givenInitial = opts?.initialValues || {};\n  const providedValues = { ...toValue(givenInitial) };\n\n  return deepCopy(providedValues) as TValues;\n}\n\nexport function useForm<\n  TValues extends GenericObject = GenericObject,\n  TOutput extends GenericObject = TValues,\n  TSchema extends FormSchema<TValues> | StandardSchemaV1<TValues, TOutput> = FormSchema<TValues>,\n>(opts?: FormOptions<TValues, TOutput, TSchema>): FormContext<TValues, TOutput> {\n  const formId = FORM_COUNTER++;\n  const name = opts?.name || 'Form';\n\n  // Prevents fields from double resetting their values, which causes checkboxes to toggle their initial value\n  let FIELD_ID_COUNTER = 0;\n\n  // If the form is currently submitting\n  const isSubmitting = ref(false);\n\n  // If the form is currently validating\n  const isValidating = ref(false);\n\n  // The number of times the user tried to submit the form\n  const submitCount = ref(0);\n\n  // field arrays managed by this form\n  const fieldArrays: PrivateFieldArrayContext[] = [];\n\n  // a private ref for all form values\n  const formValues = reactive(resolveInitialValues(opts)) as TValues;\n\n  const pathStates = ref<PathState<unknown>[]>([]);\n\n  const extraErrorsBag: Ref<FormErrorBag<TValues>> = ref({});\n\n  const pathStateLookup = ref<Record<string, PathState>>({});\n\n  const rebuildPathLookup = debounceNextTick(() => {\n    pathStateLookup.value = pathStates.value.reduce(\n      (names, state) => {\n        names[normalizeFormPath(toValue(state.path))] = state;\n\n        return names;\n      },\n      {} as Record<string, PathState>,\n    );\n  });\n\n  /**\n   * Manually sets an error message on a specific field\n   */\n  function setFieldError(field: Path<TValues> | PathState, message: string | undefined | string[]) {\n    const state = findPathState(field);\n    if (!state) {\n      if (typeof field === 'string') {\n        extraErrorsBag.value[normalizeFormPath(field) as Path<TValues>] = normalizeErrorItem(message);\n      }\n      return;\n    }\n\n    // Move the error from the extras path if exists\n    if (typeof field === 'string') {\n      const normalizedPath = normalizeFormPath(field) as Path<TValues>;\n      if (extraErrorsBag.value[normalizedPath]) {\n        delete extraErrorsBag.value[normalizedPath];\n      }\n    }\n\n    state.errors = normalizeErrorItem(message);\n    state.valid = !state.errors.length;\n  }\n\n  /**\n   * Sets errors for the fields specified in the object\n   */\n  function setErrors(paths: Partial<FlattenAndSetPathsType<TValues, string | string[] | undefined>>) {\n    keysOf(paths).forEach(path => {\n      setFieldError(path, paths[path]);\n    });\n  }\n\n  if (opts?.initialErrors) {\n    setErrors(opts.initialErrors);\n  }\n\n  const errorBag = computed<FormErrorBag<TValues>>(() => {\n    const pathErrors = pathStates.value.reduce((acc, state) => {\n      if (state.errors.length) {\n        acc[toValue(state.path) as Path<TValues>] = state.errors;\n      }\n\n      return acc;\n    }, {} as FormErrorBag<TValues>);\n\n    return { ...extraErrorsBag.value, ...pathErrors };\n  });\n\n  // Gets the first error of each field\n  const errors = computed<FormErrors<TValues>>(() => {\n    return keysOf(errorBag.value).reduce((acc, key) => {\n      const errors = errorBag.value[key];\n      if (errors?.length) {\n        acc[key] = errors[0];\n      }\n\n      return acc;\n    }, {} as FormErrors<TValues>);\n  });\n\n  /**\n   * Holds a computed reference to all fields names and labels\n   */\n  const fieldNames = computed(() => {\n    return pathStates.value.reduce(\n      (names, state) => {\n        names[toValue(state.path)] = { name: toValue(state.path) || '', label: state.label || '' };\n\n        return names;\n      },\n      {} as Record<string, { name: string; label: string }>,\n    );\n  });\n\n  const fieldBailsMap = computed(() => {\n    return pathStates.value.reduce(\n      (map, state) => {\n        map[toValue(state.path)] = state.bails ?? true;\n\n        return map;\n      },\n      {} as Record<string, boolean>,\n    );\n  });\n\n  // mutable non-reactive reference to initial errors\n  // we need this to process initial errors then unset them\n  const initialErrors = {\n    ...(opts?.initialErrors || ({} as FlattenAndSetPathsType<TValues, string | undefined>)),\n  };\n\n  const keepValuesOnUnmount = opts?.keepValuesOnUnmount ?? false;\n\n  // initial form values\n  const { initialValues, originalInitialValues, setInitialValues } = useFormInitialValues<TValues>(\n    pathStates,\n    formValues,\n    opts,\n  );\n\n  // form meta aggregations\n  const meta = useFormMeta(pathStates, formValues, originalInitialValues, errors);\n\n  const controlledValues = computed(() => {\n    return pathStates.value.reduce((acc, state) => {\n      const value = getFromPath(formValues, toValue(state.path));\n      setInPath(acc, toValue(state.path), value);\n\n      return acc;\n    }, {} as TValues);\n  });\n\n  const schema = opts?.validationSchema;\n\n  function createPathState<TPath extends Path<TValues>>(\n    path: MaybeRefOrGetter<TPath>,\n    config?: Partial<PathStateConfig<TOutput[TPath]>>,\n  ): PathState<TValues[TPath], TOutput[TPath]> {\n    const initialValue = computed(() => getFromPath(initialValues.value, toValue(path)));\n    const pathStateExists = pathStateLookup.value[toValue(path)];\n    const isCheckboxOrRadio = config?.type === 'checkbox' || config?.type === 'radio';\n    if (pathStateExists && isCheckboxOrRadio) {\n      pathStateExists.multiple = true;\n      const id = FIELD_ID_COUNTER++;\n      if (Array.isArray(pathStateExists.id)) {\n        pathStateExists.id.push(id);\n      } else {\n        pathStateExists.id = [pathStateExists.id, id];\n      }\n\n      pathStateExists.fieldsCount++;\n      pathStateExists.__flags.pendingUnmount[id] = false;\n\n      return pathStateExists as PathState<TValues[TPath], TOutput[TPath]>;\n    }\n\n    const currentValue = computed(() => getFromPath(formValues, toValue(path)));\n    const pathValue = toValue(path);\n\n    const unsetBatchIndex = UNSET_BATCH.findIndex(_path => _path === pathValue);\n    if (unsetBatchIndex !== -1) {\n      UNSET_BATCH.splice(unsetBatchIndex, 1);\n    }\n\n    const id = FIELD_ID_COUNTER++;\n    const state = reactive({\n      id,\n      path,\n      touched: false,\n      pending: false,\n      valid: true,\n      validated: !!initialErrors[pathValue]?.length,\n      initialValue,\n      errors: shallowRef([]),\n      bails: config?.bails ?? false,\n      label: config?.label,\n      type: config?.type || 'default',\n      value: currentValue,\n      multiple: false,\n      __flags: {\n        pendingUnmount: { [id]: false },\n        pendingReset: false,\n      },\n      fieldsCount: 1,\n      validate: config?.validate,\n      dirty: computed(() => {\n        return !isEqual(unref(currentValue), unref(initialValue));\n      }),\n    }) as PathState<TValues[TPath], TOutput[TPath]>;\n\n    pathStates.value.push(state);\n    pathStateLookup.value[pathValue] = state;\n    rebuildPathLookup();\n\n    if (errors.value[pathValue] && !initialErrors[pathValue]) {\n      nextTick(() => {\n        validateField(pathValue, { mode: 'silent' });\n      });\n    }\n\n    // Handles when a path changes\n    if (isRef(path)) {\n      watch(path, newPath => {\n        rebuildPathLookup();\n        const nextValue = deepCopy(currentValue.value);\n        pathStateLookup.value[newPath] = state;\n\n        nextTick(() => {\n          setInPath(formValues, newPath, nextValue);\n        });\n      });\n    }\n\n    return state;\n  }\n\n  /**\n   * Batches validation runs in 5ms batches\n   * Must have two distinct batch queues to make sure they don't override each other settings #3783\n   */\n  const debouncedSilentValidation = debounceAsync(_validateSchema, 5);\n  const debouncedValidation = debounceAsync(_validateSchema, 5);\n\n  const validateSchema = withLatest(\n    async (mode: SchemaValidationMode) => {\n      return (await (mode === 'silent'\n        ? debouncedSilentValidation()\n        : debouncedValidation())) as FormValidationResult<TValues>;\n    },\n    (formResult, [mode]) => {\n      // fields by id lookup\n      // errors fields names, we need it to also check if custom errors are updated\n      const currentErrorsPaths = keysOf(formCtx.errorBag.value);\n      // collect all the keys from the schema and all fields\n      // this ensures we have a complete key map of all the fields\n      const paths = [\n        ...new Set([...keysOf(formResult.results), ...pathStates.value.map(p => p.path), ...currentErrorsPaths]),\n      ].sort() as string[];\n\n      // aggregates the paths into a single result object while applying the results on the fields\n      const results = paths.reduce(\n        (validation, _path) => {\n          const expectedPath = _path as Path<TValues>;\n          const pathState = findPathState(expectedPath) || findHoistedPath(expectedPath);\n          const messages = formResult.results[expectedPath]?.errors || [];\n          // This is the real path of the field, because it might've been a hoisted field\n          const path = (toValue(pathState?.path) || expectedPath) as Path<TValues>;\n          // It is possible that multiple paths are collected across loops\n          // We want to merge them to avoid overriding any iteration's results\n          const fieldResult = mergeValidationResults(\n            { errors: messages, valid: !messages.length },\n            validation.results[path],\n          );\n          validation.results[path] = fieldResult;\n          if (!fieldResult.valid) {\n            validation.errors[path] = fieldResult.errors[0];\n          }\n\n          // clean up extra errors if path state exists\n          if (pathState && extraErrorsBag.value[path]) {\n            delete extraErrorsBag.value[path];\n          }\n\n          // field not rendered\n          if (!pathState) {\n            setFieldError(path, messages);\n\n            return validation;\n          }\n\n          // always update the valid flag regardless of the mode\n          pathState.valid = fieldResult.valid;\n          if (mode === 'silent') {\n            return validation;\n          }\n\n          if (mode === 'validated-only' && !pathState.validated) {\n            return validation;\n          }\n\n          setFieldError(pathState, fieldResult.errors);\n\n          return validation;\n        },\n        {\n          valid: formResult.valid,\n          results: {},\n          errors: {},\n          source: formResult.source,\n        } as FormValidationResult<TValues>,\n      );\n\n      if (formResult.values) {\n        results.values = formResult.values;\n        results.source = formResult.source;\n      }\n\n      keysOf(results.results).forEach(path => {\n        const pathState = findPathState(path);\n        if (!pathState) {\n          return;\n        }\n\n        if (mode === 'silent') {\n          return;\n        }\n\n        if (mode === 'validated-only' && !pathState.validated) {\n          return;\n        }\n\n        setFieldError(pathState, results.results[path]?.errors);\n      });\n\n      return results;\n    },\n  );\n\n  function mutateAllPathState(mutation: (state: PathState) => void) {\n    pathStates.value.forEach(mutation);\n  }\n\n  function findPathState<TPath extends Path<TValues>>(path: TPath | PathState) {\n    const normalizedPath = typeof path === 'string' ? normalizeFormPath(path) : path;\n    const pathState = typeof normalizedPath === 'string' ? pathStateLookup.value[normalizedPath] : normalizedPath;\n\n    return pathState as PathState<PathValue<TValues, TPath>> | undefined;\n  }\n\n  function findHoistedPath(path: Path<TValues>) {\n    const candidates = pathStates.value.filter(state => path.startsWith(toValue(state.path)));\n\n    return candidates.reduce(\n      (bestCandidate, candidate) => {\n        if (!bestCandidate) {\n          return candidate as PathState<PathValue<TValues, Path<TValues>>>;\n        }\n\n        return (candidate.path.length > bestCandidate.path.length ? candidate : bestCandidate) as PathState<\n          PathValue<TValues, Path<TValues>>\n        >;\n      },\n      undefined as PathState<PathValue<TValues, Path<TValues>>> | undefined,\n    );\n  }\n\n  let UNSET_BATCH: Path<TValues>[] = [];\n  let PENDING_UNSET: Promise<void> | null;\n  function unsetPathValue<TPath extends Path<TValues>>(path: TPath) {\n    UNSET_BATCH.push(path);\n    if (!PENDING_UNSET) {\n      PENDING_UNSET = nextTick(() => {\n        const sortedPaths = [...UNSET_BATCH].sort().reverse();\n        sortedPaths.forEach(p => {\n          unsetPath(formValues, p);\n        });\n\n        UNSET_BATCH = [];\n        PENDING_UNSET = null;\n      });\n    }\n\n    return PENDING_UNSET;\n  }\n\n  function makeSubmissionFactory(onlyControlled: boolean) {\n    return function submitHandlerFactory<TReturn = unknown>(\n      fn?: SubmissionHandler<TValues, TOutput, TReturn>,\n      onValidationError?: InvalidSubmissionHandler<TValues, TOutput>,\n    ) {\n      return function submissionHandler(e: unknown) {\n        if (e instanceof Event) {\n          e.preventDefault();\n          e.stopPropagation();\n        }\n\n        // Touch all fields\n        mutateAllPathState(s => (s.touched = true));\n\n        isSubmitting.value = true;\n        submitCount.value++;\n        return validate()\n          .then(result => {\n            const values = deepCopy(formValues);\n\n            if (result.valid && typeof fn === 'function') {\n              const controlled = deepCopy(controlledValues.value);\n              let submittedValues = (onlyControlled ? controlled : values) as unknown as TOutput;\n\n              if (result.values) {\n                submittedValues =\n                  result.source === 'schema'\n                    ? (result.values as TOutput)\n                    : Object.assign({}, submittedValues, result.values);\n              }\n\n              return fn(submittedValues, {\n                evt: e as Event,\n                controlledValues: controlled,\n                setErrors,\n                setFieldError,\n                setTouched,\n                setFieldTouched,\n                setValues,\n                setFieldValue,\n                resetForm,\n                resetField,\n              });\n            }\n\n            if (!result.valid && typeof onValidationError === 'function') {\n              onValidationError({\n                values,\n                evt: e as Event,\n                errors: result.errors,\n                results: result.results,\n              });\n            }\n          })\n          .then(\n            returnVal => {\n              isSubmitting.value = false;\n\n              return returnVal;\n            },\n            err => {\n              isSubmitting.value = false;\n\n              // re-throw the err so it doesn't go silent\n              throw err;\n            },\n          );\n      };\n    };\n  }\n\n  const handleSubmitImpl = makeSubmissionFactory(false);\n  const handleSubmit: typeof handleSubmitImpl & { withControlled: typeof handleSubmitImpl } = handleSubmitImpl as any;\n  handleSubmit.withControlled = makeSubmissionFactory(true);\n\n  function removePathState<TPath extends Path<TValues>>(path: TPath, id: number) {\n    const idx = pathStates.value.findIndex(s => {\n      return s.path === path && (Array.isArray(s.id) ? s.id.includes(id) : s.id === id);\n    });\n    const pathState = pathStates.value[idx];\n    if (idx === -1 || !pathState) {\n      return;\n    }\n\n    nextTick(() => {\n      validateField(path, { mode: 'silent', warn: false });\n    });\n\n    if (pathState.multiple && pathState.fieldsCount) {\n      pathState.fieldsCount--;\n    }\n\n    if (Array.isArray(pathState.id)) {\n      const idIndex = pathState.id.indexOf(id);\n      if (idIndex >= 0) {\n        pathState.id.splice(idIndex, 1);\n      }\n\n      delete pathState.__flags.pendingUnmount[id];\n    }\n\n    if (!pathState.multiple || pathState.fieldsCount <= 0) {\n      pathStates.value.splice(idx, 1);\n      unsetInitialValue(path);\n      rebuildPathLookup();\n      delete pathStateLookup.value[path];\n    }\n  }\n\n  function destroyPath(path: string) {\n    keysOf(pathStateLookup.value).forEach(key => {\n      if (key.startsWith(path)) {\n        delete pathStateLookup.value[key];\n      }\n    });\n\n    pathStates.value = pathStates.value.filter(s => !s.path.startsWith(path));\n    nextTick(() => {\n      rebuildPathLookup();\n    });\n  }\n\n  const formCtx: PrivateFormContext<TValues, TOutput> = {\n    name,\n    formId,\n    values: formValues,\n    controlledValues,\n    errorBag,\n    errors,\n    schema,\n    submitCount,\n    meta,\n    isSubmitting,\n    isValidating,\n    fieldArrays,\n    keepValuesOnUnmount,\n    validateSchema: unref(schema) ? validateSchema : undefined,\n    validate,\n    setFieldError,\n    validateField,\n    setFieldValue,\n    setValues,\n    setErrors,\n    setFieldTouched,\n    setTouched,\n    resetForm,\n    resetField,\n    handleSubmit,\n    defineField,\n    stageInitialValue,\n    unsetInitialValue,\n    setFieldInitialValue,\n    createPathState,\n    getPathState: findPathState,\n    unsetPathValue,\n    removePathState,\n    initialValues: initialValues as Ref<TValues>,\n    getAllPathStates: () => pathStates.value,\n    destroyPath,\n    isFieldTouched,\n    isFieldDirty,\n    isFieldValid,\n  };\n\n  /**\n   * Sets a single field value\n   */\n  function setFieldValue<T extends Path<TValues>>(\n    field: T | PathState,\n    value: PathValue<TValues, T> | undefined,\n    shouldValidate = true,\n  ) {\n    const clonedValue = deepCopy(value);\n    const path = typeof field === 'string' ? field : (field.path as Path<TValues>);\n    const pathState = findPathState(path);\n    if (!pathState) {\n      createPathState(path);\n    }\n\n    setInPath(formValues, path, clonedValue);\n    if (shouldValidate) {\n      validateField(path);\n    }\n  }\n\n  function forceSetValues(fields: PartialDeep<TValues>, shouldValidate = true) {\n    // clean up old values\n    keysOf(formValues).forEach(key => {\n      delete formValues[key];\n    });\n\n    // set up new values\n    keysOf(fields).forEach(path => {\n      setFieldValue(path as Path<TValues>, fields[path], false);\n    });\n\n    if (shouldValidate) {\n      validate();\n    }\n  }\n\n  /**\n   * Sets multiple fields values\n   */\n  function setValues(fields: PartialDeep<TValues>, shouldValidate = true) {\n    merge(formValues, fields);\n    // regenerate the arrays when the form values change\n    fieldArrays.forEach(f => f && f.reset());\n\n    if (shouldValidate) {\n      validate();\n    }\n  }\n\n  function createModel<TPath extends Path<TValues>>(\n    path: MaybeRefOrGetter<TPath>,\n    shouldValidate?: MaybeRefOrGetter<boolean>,\n  ) {\n    const pathState = findPathState(toValue(path)) || createPathState(path);\n\n    return computed({\n      get() {\n        return pathState.value;\n      },\n      set(value) {\n        const pathValue = toValue(path);\n        setFieldValue(pathValue, value, toValue(shouldValidate) ?? false);\n      },\n    }) as Ref<PathValue<TValues, TPath>>;\n  }\n\n  /**\n   * Sets the touched meta state on a field\n   */\n  function setFieldTouched(field: Path<TValues> | PathState, isTouched: boolean) {\n    const pathState = findPathState(field);\n    if (pathState) {\n      pathState.touched = isTouched;\n    }\n  }\n\n  function isFieldTouched(field: Path<TValues>) {\n    const pathState = findPathState(field);\n    if (pathState) {\n      return pathState.touched;\n    }\n\n    // Find all nested paths and consider their touched state\n    return pathStates.value.filter(s => s.path.startsWith(field)).some(s => s.touched);\n  }\n\n  function isFieldDirty(field: Path<TValues>) {\n    const pathState = findPathState(field);\n    if (pathState) {\n      return pathState.dirty;\n    }\n\n    return pathStates.value.filter(s => s.path.startsWith(field)).some(s => s.dirty);\n  }\n\n  function isFieldValid(field: Path<TValues>) {\n    const pathState = findPathState(field);\n    if (pathState) {\n      return pathState.valid;\n    }\n\n    return pathStates.value.filter(s => s.path.startsWith(field)).every(s => s.valid);\n  }\n\n  /**\n   * Sets the touched meta state on multiple fields\n   */\n  function setTouched(fields: Partial<FlattenAndSetPathsType<TValues, boolean>> | boolean) {\n    if (typeof fields === 'boolean') {\n      mutateAllPathState(state => {\n        state.touched = fields;\n      });\n\n      return;\n    }\n\n    keysOf(fields).forEach(field => {\n      setFieldTouched(field, !!fields[field]);\n    });\n  }\n\n  function resetField(field: Path<TValues>, state?: Partial<FieldState>) {\n    const newValue = state && 'value' in state ? state.value : getFromPath(initialValues.value, field);\n    const pathState = findPathState(field);\n    if (pathState) {\n      pathState.__flags.pendingReset = true;\n    }\n\n    setFieldInitialValue(field, deepCopy(newValue), true);\n    setFieldValue(field, newValue as PathValue<TValues, typeof field>, false);\n    setFieldTouched(field, state?.touched ?? false);\n    setFieldError(field, state?.errors || []);\n\n    nextTick(() => {\n      if (pathState) {\n        pathState.__flags.pendingReset = false;\n      }\n    });\n  }\n\n  /**\n   * Resets all fields\n   */\n  function resetForm(resetState?: Partial<FormState<TValues>>, opts?: ResetFormOpts) {\n    let newValues = deepCopy(resetState?.values ? resetState.values : originalInitialValues.value);\n    newValues = opts?.force ? newValues : merge(originalInitialValues.value, newValues);\n\n    setInitialValues(newValues, { force: opts?.force });\n    mutateAllPathState(state => {\n      state.__flags.pendingReset = true;\n      state.validated = false;\n      state.touched = resetState?.touched?.[toValue(state.path) as Path<TValues>] || false;\n\n      setFieldValue(toValue(state.path) as Path<TValues>, getFromPath(newValues, toValue(state.path)), false);\n      setFieldError(toValue(state.path) as Path<TValues>, undefined);\n    });\n\n    opts?.force ? forceSetValues(newValues, false) : setValues(newValues, false);\n    setErrors(resetState?.errors || {});\n    submitCount.value = resetState?.submitCount || 0;\n    nextTick(() => {\n      validate({ mode: 'silent' });\n\n      mutateAllPathState(state => {\n        state.__flags.pendingReset = false;\n      });\n    });\n  }\n\n  async function validate(opts?: Partial<ValidationOptions>): Promise<FormValidationResult<TValues, TOutput>> {\n    const mode = opts?.mode || 'force';\n    if (mode === 'force') {\n      mutateAllPathState(f => (f.validated = true));\n    }\n\n    if (formCtx.validateSchema) {\n      return formCtx.validateSchema(mode);\n    }\n\n    isValidating.value = true;\n\n    // No schema, each field is responsible to validate itself\n    const validations = await Promise.all(\n      pathStates.value.map(state => {\n        if (!state.validate) {\n          return Promise.resolve({\n            key: toValue(state.path),\n            valid: true,\n            errors: [],\n            value: undefined,\n          });\n        }\n\n        return state.validate(opts).then(result => {\n          return {\n            key: toValue(state.path),\n            valid: result.valid,\n            errors: result.errors,\n            value: result.value,\n          };\n        });\n      }),\n    );\n\n    isValidating.value = false;\n\n    const results: Partial<FlattenAndMapPathsValidationResult<TValues, TOutput>> = {};\n    const errors: Partial<FlattenAndSetPathsType<TValues, string>> = {};\n    const values: Partial<TOutput> = {};\n\n    for (const validation of validations) {\n      results[validation.key as Path<TValues>] = {\n        valid: validation.valid,\n        errors: validation.errors,\n      };\n\n      if (validation.value) {\n        setInPath(values, validation.key, validation.value);\n      }\n\n      if (validation.errors.length) {\n        errors[validation.key as Path<TValues>] = validation.errors[0];\n      }\n    }\n\n    return {\n      valid: validations.every(r => r.valid),\n      results,\n      errors,\n      values,\n      source: 'fields',\n    };\n  }\n\n  async function validateField<TPath extends Path<TValues>>(\n    path: TPath,\n    opts?: Partial<ValidationOptions>,\n  ): Promise<ValidationResult<TOutput[TPath]>> {\n    const state = findPathState(path);\n    if (state && opts?.mode !== 'silent') {\n      state.validated = true;\n    }\n\n    if (schema) {\n      const { results }: FormValidationResult<TValues, TOutput> = await validateSchema(opts?.mode || 'validated-only');\n\n      return results[path] || { errors: [], valid: true };\n    }\n\n    if (state?.validate) {\n      return state.validate(opts);\n    }\n\n    const shouldWarn = !state && (opts?.warn ?? true);\n    if (shouldWarn) {\n      if (__DEV__) {\n        warn(`field with path ${path} was not found`);\n      }\n    }\n\n    return Promise.resolve({ errors: [], valid: true });\n  }\n\n  function unsetInitialValue(path: string) {\n    unsetPath(initialValues.value, path);\n  }\n\n  /**\n   * Sneaky function to set initial field values\n   */\n  function stageInitialValue(path: string, value: unknown, updateOriginal = false) {\n    setFieldInitialValue(path, value);\n    setInPath(formValues, path, value);\n    if (updateOriginal && !opts?.initialValues) {\n      setInPath(originalInitialValues.value, path, deepCopy(value));\n    }\n  }\n\n  function setFieldInitialValue(path: string, value: unknown, updateOriginal = false) {\n    setInPath(initialValues.value, path, deepCopy(value));\n    if (updateOriginal) {\n      setInPath(originalInitialValues.value, path, deepCopy(value));\n    }\n  }\n\n  async function _validateSchema(): Promise<FormValidationResult<TValues, TOutput>> {\n    const schemaValue = unref(schema);\n    if (!schemaValue) {\n      return { valid: true, results: {}, errors: {}, source: 'none' };\n    }\n\n    isValidating.value = true;\n\n    const formResult = isStandardSchema(schemaValue)\n      ? await validateStandardSchema<TValues, TOutput>(schemaValue, formValues)\n      : await validateObjectSchema<TValues, TOutput>(schemaValue as RawFormSchema<TValues>, formValues, {\n          names: fieldNames.value,\n          bailsMap: fieldBailsMap.value,\n        });\n\n    isValidating.value = false;\n\n    return formResult;\n  }\n\n  const submitForm = handleSubmit((_, { evt }) => {\n    if (isFormSubmitEvent(evt)) {\n      evt.target.submit();\n    }\n  });\n\n  // Trigger initial validation\n  onMounted(() => {\n    if (opts?.initialErrors) {\n      setErrors(opts.initialErrors);\n    }\n\n    if (opts?.initialTouched) {\n      setTouched(opts.initialTouched);\n    }\n\n    // if validate on mount was enabled\n    if (opts?.validateOnMount) {\n      validate();\n      return;\n    }\n\n    // otherwise run initial silent validation through schema if available\n    // the useField should skip their own silent validation if a yup schema is present\n    if (formCtx.validateSchema) {\n      formCtx.validateSchema('silent');\n    }\n  });\n\n  if (isRef(schema)) {\n    watch(schema, () => {\n      formCtx.validateSchema?.('validated-only');\n    });\n  }\n\n  // Provide injections\n  provide(FormContextKey, formCtx as PrivateFormContext);\n\n  if (__DEV__) {\n    registerFormWithDevTools(formCtx as PrivateFormContext);\n    watch(\n      () => ({\n        errors: errorBag.value,\n        ...meta.value,\n        values: formValues,\n        isSubmitting: isSubmitting.value,\n        isValidating: isValidating.value,\n        submitCount: submitCount.value,\n      }),\n      refreshInspector,\n      {\n        deep: true,\n      },\n    );\n  }\n\n  function defineField<\n    TPath extends Path<TValues>,\n    TValue = PathValue<TValues, TPath>,\n    TExtras extends GenericObject = GenericObject,\n  >(\n    path: MaybeRefOrGetter<TPath>,\n    config?: Partial<InputBindsConfig<TValue, TExtras>> | LazyInputBindsConfig<TValue, TExtras>,\n  ) {\n    const label = isCallable(config) ? undefined : config?.label;\n    const pathState = (findPathState(toValue(path)) || createPathState(path, { label })) as PathState<TValue>;\n    const evalConfig = () => (isCallable(config) ? config(omit(pathState, PRIVATE_PATH_STATE_KEYS)) : config || {});\n\n    function onBlur() {\n      pathState.touched = true;\n      const validateOnBlur = evalConfig().validateOnBlur ?? getConfig().validateOnBlur;\n      if (validateOnBlur) {\n        validateField(toValue(pathState.path) as Path<TValues>);\n      }\n    }\n\n    function onInput() {\n      const validateOnInput = evalConfig().validateOnInput ?? getConfig().validateOnInput;\n      if (validateOnInput) {\n        nextTick(() => {\n          validateField(toValue(pathState.path) as Path<TValues>);\n        });\n      }\n    }\n\n    function onChange() {\n      const validateOnChange = evalConfig().validateOnChange ?? getConfig().validateOnChange;\n      if (validateOnChange) {\n        nextTick(() => {\n          validateField(toValue(pathState.path) as Path<TValues>);\n        });\n      }\n    }\n\n    const props = computed(() => {\n      const base: BaseFieldProps = {\n        onChange,\n        onInput,\n        onBlur,\n      };\n\n      if (isCallable(config)) {\n        return {\n          ...base,\n          ...(config(omit(pathState, PRIVATE_PATH_STATE_KEYS)).props || {}),\n        } as BaseFieldProps & TExtras;\n      }\n\n      if (config?.props) {\n        return {\n          ...base,\n          ...config.props(omit(pathState, PRIVATE_PATH_STATE_KEYS)),\n        } as BaseFieldProps & TExtras;\n      }\n\n      return base as BaseFieldProps & TExtras;\n    });\n\n    const model = createModel(\n      path,\n      () => evalConfig().validateOnModelUpdate ?? getConfig()?.validateOnModelUpdate ?? true,\n    );\n\n    return [model, props] as [Ref<TValue>, Ref<BaseFieldProps & TExtras>];\n  }\n\n  const ctx: FormContext<TValues, TOutput> = {\n    ...formCtx,\n    values: readonly(formValues) as TValues,\n    handleReset: () => resetForm(),\n    submitForm,\n  };\n\n  provide(PublicFormContextKey, ctx);\n\n  return ctx;\n}\n\n/**\n * Manages form meta aggregation\n */\nfunction useFormMeta<TValues extends Record<string, unknown>>(\n  pathsState: Ref<PathState<unknown>[]>,\n  currentValues: TValues,\n  initialValues: MaybeRef<PartialDeep<TValues>>,\n  errors: Ref<FormErrors<TValues>>,\n) {\n  const MERGE_STRATEGIES: Record<keyof Pick<FieldMeta<unknown>, 'touched' | 'pending' | 'valid'>, 'every' | 'some'> = {\n    touched: 'some',\n    pending: 'some',\n    valid: 'every',\n  };\n\n  const isDirty = computed(() => {\n    return !isEqual(currentValues, unref(initialValues));\n  });\n\n  function calculateFlags() {\n    const states = pathsState.value;\n\n    return keysOf(MERGE_STRATEGIES).reduce(\n      (acc, flag) => {\n        const mergeMethod = MERGE_STRATEGIES[flag];\n        acc[flag] = states[mergeMethod](s => s[flag]);\n\n        return acc;\n      },\n      {} as Record<keyof Omit<FieldMeta<unknown>, 'initialValue'>, boolean>,\n    );\n  }\n\n  const flags = reactive(calculateFlags());\n\n  watchEffect(() => {\n    const value = calculateFlags();\n    flags.touched = value.touched;\n    flags.valid = value.valid;\n    flags.pending = value.pending;\n  });\n\n  return computed(() => {\n    return {\n      initialValues: unref(initialValues) as Partial<TValues>,\n      ...flags,\n      valid: flags.valid && !keysOf(errors.value).length,\n      dirty: isDirty.value,\n    };\n  });\n}\n\ninterface SetFormInitialValuesOpts {\n  updateFields?: boolean;\n  force?: boolean;\n}\n\n/**\n * Manages the initial values prop\n */\nfunction useFormInitialValues<TValues extends GenericObject>(\n  pathsState: Ref<PathState<unknown>[]>,\n  formValues: TValues,\n  opts?: FormOptions<TValues>,\n) {\n  const values = resolveInitialValues(opts) as PartialDeep<TValues>;\n  // these are the mutable initial values as the fields are mounted/unmounted\n  const initialValues = ref(values) as Ref<PartialDeep<TValues>>;\n  // these are the original initial value as provided by the user initially, they don't keep track of conditional fields\n  // this is important because some conditional fields will overwrite the initial values for other fields who had the same name\n  // like array fields, any push/insert operation will overwrite the initial values because they \"create new fields\"\n  // so these are the values that the reset function should use\n  // these only change when the user explicitly changes the initial values or when the user resets them with new values.\n  const originalInitialValues = ref<PartialDeep<TValues>>(deepCopy(values)) as Ref<PartialDeep<TValues>>;\n\n  function setInitialValues(values: PartialDeep<TValues>, opts?: SetFormInitialValuesOpts) {\n    if (opts?.force) {\n      initialValues.value = deepCopy(values);\n      originalInitialValues.value = deepCopy(values);\n    } else {\n      initialValues.value = merge(deepCopy(initialValues.value) || {}, deepCopy(values));\n      originalInitialValues.value = merge(deepCopy(originalInitialValues.value) || {}, deepCopy(values));\n    }\n\n    if (!opts?.updateFields) {\n      return;\n    }\n\n    // update the pristine non-touched fields\n    // those are excluded because it's unlikely you want to change the form values using initial values\n    // we mostly watch them for API population or newly inserted fields\n    // if the user API is taking too much time before user interaction they should consider disabling or hiding their inputs until the values are ready\n    pathsState.value.forEach(state => {\n      const wasTouched = state.touched;\n      if (wasTouched) {\n        return;\n      }\n\n      const newValue = getFromPath(initialValues.value, toValue(state.path));\n      setInPath(formValues, toValue(state.path), deepCopy(newValue));\n    });\n  }\n\n  return {\n    initialValues,\n    originalInitialValues,\n    setInitialValues,\n  };\n}\n\nfunction mergeValidationResults<TValue extends GenericObject>(\n  a: ValidationResult<TValue>,\n  b?: ValidationResult<TValue>,\n): ValidationResult<TValue> {\n  if (!b) {\n    return a;\n  }\n\n  return {\n    valid: a.valid && b.valid,\n    errors: [...a.errors, ...b.errors],\n  };\n}\n\nexport function useFormContext<\n  TValues extends GenericObject = GenericObject,\n  TOutput extends GenericObject = TValues,\n>(): FormContext<TValues, TOutput> {\n  return inject(PublicFormContextKey) as FormContext<TValues, TOutput>;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useFormErrors.ts",
    "content": "import { computed } from 'vue';\nimport { FormContextKey } from './symbols';\nimport { FormErrors } from './types';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Gives access to all form errors\n */\nexport function useFormErrors<TValues extends Record<string, unknown> = Record<string, unknown>>() {\n  const form = injectWithSelf(FormContextKey);\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return computed(() => {\n    return (form?.errors.value || {}) as FormErrors<TValues>;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useFormValues.ts",
    "content": "import { computed } from 'vue';\nimport { FormContextKey } from './symbols';\nimport { FormContext } from './types';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Gives access to a form's values\n */\nexport function useFormValues<TValues extends Record<string, any> = Record<string, any>>() {\n  const form = injectWithSelf(FormContextKey) as FormContext<TValues> | undefined;\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return computed(() => {\n    return form?.values || ({} as Partial<TValues>);\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useIsFieldDirty.ts",
    "content": "import { computed, MaybeRefOrGetter } from 'vue';\nimport { resolveFieldOrPathState } from './utils';\n\n/**\n * If a field is dirty or not\n */\nexport function useIsFieldDirty(path?: MaybeRefOrGetter<string>) {\n  const fieldOrPath = resolveFieldOrPathState(path);\n\n  return computed(() => {\n    if (!fieldOrPath) {\n      return false;\n    }\n    return ('meta' in fieldOrPath ? fieldOrPath.meta.dirty : fieldOrPath?.value?.dirty) ?? false;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useIsFieldTouched.ts",
    "content": "import { MaybeRefOrGetter, computed } from 'vue';\nimport { resolveFieldOrPathState } from './utils';\n\n/**\n * If a field is touched or not\n */\nexport function useIsFieldTouched(path?: MaybeRefOrGetter<string>) {\n  const fieldOrPath = resolveFieldOrPathState(path);\n\n  return computed(() => {\n    if (!fieldOrPath) {\n      return false;\n    }\n\n    return ('meta' in fieldOrPath ? fieldOrPath.meta.touched : fieldOrPath?.value?.touched) ?? false;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useIsFieldValid.ts",
    "content": "import { computed, MaybeRefOrGetter } from 'vue';\nimport { resolveFieldOrPathState } from './utils';\n\n/**\n * If a field is validated and is valid\n */\nexport function useIsFieldValid(path?: MaybeRefOrGetter<string>) {\n  const fieldOrPath = resolveFieldOrPathState(path);\n\n  return computed(() => {\n    if (!fieldOrPath) {\n      return false;\n    }\n\n    return ('meta' in fieldOrPath ? fieldOrPath.meta.valid : fieldOrPath?.value?.valid) ?? false;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useIsFormDirty.ts",
    "content": "import { computed } from 'vue';\nimport { FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * If the form is dirty or not\n */\nexport function useIsFormDirty() {\n  const form = injectWithSelf(FormContextKey);\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return computed(() => {\n    return form?.meta.value.dirty ?? false;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useIsFormTouched.ts",
    "content": "import { computed } from 'vue';\nimport { FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * If the form is touched or not\n */\nexport function useIsFormTouched() {\n  const form = injectWithSelf(FormContextKey);\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return computed(() => {\n    return form?.meta.value.touched ?? false;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useIsFormValid.ts",
    "content": "import { computed } from 'vue';\nimport { FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * If the form has been validated and is valid\n */\nexport function useIsFormValid() {\n  const form = injectWithSelf(FormContextKey);\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return computed(() => {\n    return form?.meta.value.valid ?? false;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useIsSubmitting.ts",
    "content": "import { computed } from 'vue';\nimport { FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * If the form is submitting or not\n */\nexport function useIsSubmitting() {\n  const form = injectWithSelf(FormContextKey);\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return computed(() => {\n    return form?.isSubmitting.value ?? false;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useIsValidating.ts",
    "content": "import { computed } from 'vue';\nimport { FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * If the form is validating or not\n */\nexport function useIsValidating() {\n  const form = injectWithSelf(FormContextKey);\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return computed(() => {\n    return form?.isValidating.value ?? false;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useResetForm.ts",
    "content": "import { FormContextKey } from './symbols';\nimport { FormState, ResetFormOpts } from './types';\nimport { injectWithSelf, warn } from './utils';\n\nexport function useResetForm<TValues extends Record<string, unknown> = Record<string, unknown>>() {\n  const form = injectWithSelf(FormContextKey);\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return function resetForm(state?: Partial<FormState<TValues>>, opts?: ResetFormOpts) {\n    if (!form) {\n      return;\n    }\n\n    return form.resetForm(state, opts);\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useSetFieldError.ts",
    "content": "import { inject, MaybeRefOrGetter, toValue } from 'vue';\nimport { FieldContextKey, FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Sets a field's error message\n */\nexport function useSetFieldError(path?: MaybeRefOrGetter<string>) {\n  const form = injectWithSelf(FormContextKey);\n  // We don't want to use self injected context as it doesn't make sense\n  const field = path ? undefined : inject(FieldContextKey);\n\n  return function setFieldError(message: string | string[] | undefined) {\n    if (path && form) {\n      form.setFieldError(toValue(path), message);\n      return;\n    }\n\n    if (field) {\n      field.setErrors(message || []);\n      return;\n    }\n\n    if (__DEV__) {\n      warn(\n        `Could not set error message since there is no form context or a field named \"${toValue(\n          path,\n        )}\", did you forget to call \"useField\" or \"useForm\"?`,\n      );\n    }\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useSetFieldTouched.ts",
    "content": "import { inject, MaybeRefOrGetter, toValue } from 'vue';\nimport { FieldContextKey, FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Sets a field's touched meta state\n */\nexport function useSetFieldTouched(path?: MaybeRefOrGetter<string>) {\n  const form = injectWithSelf(FormContextKey);\n  // We don't want to use self injected context as it doesn't make sense\n  const field = path ? undefined : inject(FieldContextKey);\n\n  return function setFieldTouched(touched: boolean) {\n    if (path && form) {\n      form.setFieldTouched(toValue(path), touched);\n      return;\n    }\n\n    if (field) {\n      field.setTouched(touched);\n      return;\n    }\n\n    if (__DEV__) {\n      warn(\n        `Could not set touched state since there is no form context or a field named \"${toValue(\n          path,\n        )}\", did you forget to call \"useField\" or \"useForm\"?`,\n      );\n    }\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useSetFieldValue.ts",
    "content": "import { inject, MaybeRefOrGetter, toValue } from 'vue';\nimport { FieldContextKey, FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Sets a field's value\n */\nexport function useSetFieldValue<TValue = unknown>(path?: MaybeRefOrGetter<string>) {\n  const form = injectWithSelf(FormContextKey);\n  // We don't want to use self injected context as it doesn't make sense\n  const field = path ? undefined : inject(FieldContextKey);\n\n  return function setFieldValue(value: TValue, shouldValidate = true) {\n    if (path && form) {\n      form.setFieldValue(toValue(path), value, shouldValidate);\n      return;\n    }\n\n    if (field) {\n      field.setValue(value, shouldValidate);\n      return;\n    }\n\n    if (__DEV__) {\n      warn(\n        `Could not set value since there is no form context or a field named \"${toValue(\n          path,\n        )}\", did you forget to call \"useField\" or \"useForm\"?`,\n      );\n    }\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useSetFormErrors.ts",
    "content": "import { FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Sets multiple fields errors\n */\nexport function useSetFormErrors() {\n  const form = injectWithSelf(FormContextKey);\n\n  function setFormErrors(fields: Record<string, string | string[] | undefined>) {\n    if (form) {\n      form.setErrors(fields);\n      return;\n    }\n\n    if (__DEV__) {\n      warn(\n        `Could not set errors because a form was not detected, did you forget to use \"useForm\" in a parent component?`,\n      );\n    }\n  }\n\n  return setFormErrors;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useSetFormTouched.ts",
    "content": "import { FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Sets multiple fields touched or all fields in the form\n */\nexport function useSetFormTouched() {\n  const form = injectWithSelf(FormContextKey);\n\n  function setFormTouched(fields: Record<string, boolean> | boolean) {\n    if (form) {\n      form.setTouched(fields);\n      return;\n    }\n\n    if (__DEV__) {\n      warn(\n        `Could not set touched state because a form was not detected, did you forget to use \"useForm\" in a parent component?`,\n      );\n    }\n  }\n\n  return setFormTouched;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useSetFormValues.ts",
    "content": "import { FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Sets multiple fields values\n */\nexport function useSetFormValues<TValues extends Record<string, unknown> = Record<string, unknown>>() {\n  const form = injectWithSelf(FormContextKey);\n\n  function setFormValues(fields: TValues, shouldValidate = true) {\n    if (form) {\n      form.setValues(fields, shouldValidate);\n      return;\n    }\n\n    if (__DEV__) {\n      warn(\n        `Could not set form values because a form was not detected, did you forget to use \"useForm\" in a parent component?`,\n      );\n    }\n  }\n\n  return setFormValues;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useSubmitCount.ts",
    "content": "import { computed } from 'vue';\nimport { FormContextKey } from './symbols';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * The number of form's submission count\n */\nexport function useSubmitCount() {\n  const form = injectWithSelf(FormContextKey);\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return computed(() => {\n    return form?.submitCount.value ?? 0;\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useSubmitForm.ts",
    "content": "import { FormContextKey } from './symbols';\nimport { FormContext, SubmissionHandler } from './types';\nimport { injectWithSelf, warn } from './utils';\n\nexport function useSubmitForm<TValues extends Record<string, unknown> = Record<string, unknown>>(\n  cb: SubmissionHandler<TValues>,\n) {\n  const form = injectWithSelf(FormContextKey) as FormContext<TValues> | undefined;\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  const onSubmit = form ? form.handleSubmit(cb) : undefined;\n\n  return function submitForm(e?: Event) {\n    if (!onSubmit) {\n      return;\n    }\n\n    return onSubmit(e);\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useValidateField.ts",
    "content": "import { MaybeRefOrGetter, inject, toValue, unref } from 'vue';\nimport { FieldContextKey, FormContextKey } from './symbols';\nimport { ValidationResult } from './types';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Validates a single field\n */\nexport function useValidateField<TOutput>(path?: MaybeRefOrGetter<string>) {\n  const form = injectWithSelf(FormContextKey);\n  const field = path ? undefined : inject(FieldContextKey);\n\n  return function validateField(): Promise<ValidationResult<TOutput>> {\n    if (field) {\n      return field.validate() as Promise<ValidationResult<TOutput>>;\n    }\n\n    if (form && path) {\n      return form?.validateField(toValue(path));\n    }\n\n    if (__DEV__) {\n      warn(`field with name ${unref(path)} was not found`);\n    }\n\n    return Promise.resolve({\n      errors: [],\n      valid: true,\n    });\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/src/useValidateForm.ts",
    "content": "import { FormContextKey } from './symbols';\nimport { FormContext, FormValidationResult } from './types';\nimport { injectWithSelf, warn } from './utils';\n\n/**\n * Validate multiple fields\n */\nexport function useValidateForm<TValues extends Record<string, unknown> = Record<string, unknown>>() {\n  const form = injectWithSelf(FormContextKey) as FormContext<TValues> | undefined;\n  if (!form) {\n    if (__DEV__) {\n      warn('No vee-validate <Form /> or `useForm` was detected in the component tree');\n    }\n  }\n\n  return function validateField(): Promise<FormValidationResult<TValues>> {\n    if (!form) {\n      return Promise.resolve({ results: {}, errors: {}, valid: true, source: 'none' });\n    }\n\n    return form.validate();\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/src/utils/assertions.ts",
    "content": "import { Locator } from '../types';\nimport { isCallable, isObject } from '../../../shared';\nimport { IS_ABSENT } from '../symbols';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\n\nexport const isClient = typeof window !== 'undefined';\n\nexport function isLocator(value: unknown): value is Locator {\n  return isCallable(value) && !!(value as Locator).__locatorRef;\n}\n\nexport function isStandardSchema(value: unknown): value is StandardSchemaV1 {\n  return isObject(value) && '~standard' in (value as unknown as StandardSchemaV1);\n}\n\nexport function hasCheckedAttr(type: unknown) {\n  return type === 'checkbox' || type === 'radio';\n}\n\nexport function isContainerValue(value: unknown): value is Record<string, unknown> {\n  return isObject(value) || Array.isArray(value);\n}\n\n/**\n * True if the value is an empty object or array\n */\nexport function isEmptyContainer(value: unknown): boolean {\n  if (Array.isArray(value)) {\n    return value.length === 0;\n  }\n\n  return isObject(value) && Object.keys(value).length === 0;\n}\n\n/**\n * Checks if the path opted out of nested fields using `[fieldName]` syntax\n */\nexport function isNotNestedPath(path: string) {\n  return /^\\[.+\\]$/i.test(path);\n}\n\n/**\n * Checks if an element is a native HTML5 multi-select input element\n */\nexport function isNativeMultiSelect(el: HTMLElement): el is HTMLSelectElement {\n  return isNativeSelect(el) && el.multiple;\n}\n\n/**\n * Checks if an element is a native HTML5 select input element\n */\nexport function isNativeSelect(el: HTMLElement): el is HTMLSelectElement {\n  return el.tagName === 'SELECT';\n}\n\n/**\n * Checks if a tag name with attrs object will render a native multi-select element\n */\nexport function isNativeMultiSelectNode(tag: string, attrs: Record<string, unknown>) {\n  // The falsy value array is the values that Vue won't add the `multiple` prop if it has one of these values\n  const hasTruthyBindingValue =\n    ![false, null, undefined, 0].includes(attrs.multiple as boolean) && !Number.isNaN(attrs.multiple);\n\n  return tag === 'select' && 'multiple' in attrs && hasTruthyBindingValue;\n}\n\n/**\n * Checks if a node should have a `:value` binding or not\n *\n * These nodes should not have a value binding\n * For files, because they are not reactive\n * For multi-selects because the value binding will reset the value\n */\nexport function shouldHaveValueBinding(tag: string, attrs: Record<string, unknown>) {\n  return !isNativeMultiSelectNode(tag, attrs) && attrs.type !== 'file' && !hasCheckedAttr(attrs.type);\n}\n\nexport function isFormSubmitEvent(evt: unknown): evt is Event & { target: HTMLFormElement } {\n  return isEvent(evt) && (evt as any).target && 'submit' in (evt as any).target;\n}\n\nexport function isEvent(evt: unknown): evt is Event {\n  if (!evt) {\n    return false;\n  }\n\n  if (typeof Event !== 'undefined' && isCallable(Event) && evt instanceof Event) {\n    return true;\n  }\n\n  // this is for IE and Cypress #3161\n  /* istanbul ignore next */\n  if (evt && (evt as Event).srcElement) {\n    return true;\n  }\n\n  return false;\n}\n\nexport function isPropPresent(obj: Record<string, unknown>, prop: string) {\n  return prop in obj && obj[prop] !== IS_ABSENT;\n}\n\n/**\n * Compares if two values are the same borrowed from:\n * https://github.com/epoberezkin/fast-deep-equal\n * We added a case for file matching since `Object.keys` doesn't work with Files.\n *\n * NB: keys with the value undefined are ignored in the evaluation and considered equal to missing keys.\n * */\nexport function isEqual(a: any, b: any) {\n  if (a === b) return true;\n\n  if (a && b && typeof a === 'object' && typeof b === 'object') {\n    if (a.constructor !== b.constructor) return false;\n\n    // eslint-disable-next-line no-var\n    var length, i, keys;\n    if (Array.isArray(a)) {\n      length = a.length;\n\n      if (length != b.length) return false;\n      for (i = length; i-- !== 0; ) if (!isEqual(a[i], b[i])) return false;\n      return true;\n    }\n\n    if (a instanceof Map && b instanceof Map) {\n      if (a.size !== b.size) return false;\n      for (i of a.entries()) if (!b.has(i[0])) return false;\n      for (i of a.entries()) if (!isEqual(i[1], b.get(i[0]))) return false;\n      return true;\n    }\n\n    // We added this part for file comparison, arguably a little naive but should work for most cases.\n    // #3911\n    if (isFile(a) && isFile(b)) {\n      if (a.size !== b.size) return false;\n      if (a.name !== b.name) return false;\n      if (a.lastModified !== b.lastModified) return false;\n      if (a.type !== b.type) return false;\n\n      return true;\n    }\n\n    if (a instanceof Set && b instanceof Set) {\n      if (a.size !== b.size) return false;\n      for (i of a.entries()) if (!b.has(i[0])) return false;\n      return true;\n    }\n\n    if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {\n      length = (a as any).length;\n\n      if (length != (b as any).length) return false;\n      for (i = length; i-- !== 0; ) if ((a as any)[i] !== (b as any)[i]) return false;\n      return true;\n    }\n\n    if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;\n    if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();\n    if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();\n\n    // Remove undefined values before object comparison\n    a = normalizeObject(a);\n    b = normalizeObject(b);\n\n    keys = Object.keys(a);\n    length = keys.length;\n    if (length !== Object.keys(b).length) return false;\n\n    for (i = length; i-- !== 0; ) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;\n\n    for (i = length; i-- !== 0; ) {\n      // eslint-disable-next-line no-var\n      var key = keys[i];\n      if (!isEqual(a[key], b[key])) return false;\n    }\n\n    return true;\n  }\n\n  // true if both NaN, false otherwise\n  return a !== a && b !== b;\n}\n\n/**\n * Returns a new object where keys with an `undefined` value are removed.\n *\n * @param a object to normalize\n */\nfunction normalizeObject(a: Record<PropertyKey, unknown>) {\n  return Object.fromEntries(Object.entries(a).filter(([, value]) => value !== undefined));\n}\n\nexport function isFile(a: unknown): a is File {\n  if (!isClient) {\n    return false;\n  }\n\n  return a instanceof File;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/utils/common.ts",
    "content": "import {\n  computed,\n  getCurrentInstance,\n  inject,\n  InjectionKey,\n  ref,\n  Ref,\n  warn as vueWarning,\n  watch,\n  nextTick,\n  MaybeRefOrGetter,\n  toValue,\n} from 'vue';\nimport { klona as deepCopy } from 'klona/full';\nimport { isIndex, isNullOrUndefined, isObject, toNumber } from '../../../shared';\nimport { isContainerValue, isEmptyContainer, isEqual, isNotNestedPath } from './assertions';\nimport { GenericObject, IssueCollection, MaybePromise } from '../types';\nimport { FormContextKey, FieldContextKey } from '../symbols';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\nimport { getDotPath } from '@standard-schema/utils';\n\nexport function cleanupNonNestedPath(path: string) {\n  if (isNotNestedPath(path)) {\n    return path.replace(/\\[|\\]/gi, '');\n  }\n\n  return path;\n}\n\ntype NestedRecord = Record<string, unknown> | { [k: string]: NestedRecord };\n\n/**\n * Gets a nested property value from an object\n */\nexport function getFromPath<TValue = unknown>(object: NestedRecord | undefined, path: string): TValue | undefined;\nexport function getFromPath<TValue = unknown, TFallback = TValue>(\n  object: NestedRecord | undefined,\n  path: string,\n  fallback?: TFallback,\n): TValue | TFallback;\nexport function getFromPath<TValue = unknown, TFallback = TValue>(\n  object: NestedRecord | undefined,\n  path: string,\n  fallback?: TFallback,\n): TValue | TFallback | undefined {\n  if (!object) {\n    return fallback;\n  }\n\n  if (isNotNestedPath(path)) {\n    return object[cleanupNonNestedPath(path)] as TValue | undefined;\n  }\n\n  const resolvedValue = (path || '')\n    .split(/\\.|\\[(\\d+)\\]/)\n    .filter(Boolean)\n    .reduce((acc, propKey) => {\n      if (isContainerValue(acc) && propKey in acc) {\n        return acc[propKey];\n      }\n\n      return fallback;\n    }, object as unknown);\n\n  return resolvedValue as TValue | undefined;\n}\n\n/**\n * Sets a nested property value in a path, creates the path properties if it doesn't exist\n */\nexport function setInPath(object: NestedRecord, path: string, value: unknown): void {\n  if (isNotNestedPath(path)) {\n    object[cleanupNonNestedPath(path)] = value;\n    return;\n  }\n\n  const keys = path.split(/\\.|\\[(\\d+)\\]/).filter(Boolean);\n  let acc: Record<string, unknown> = object;\n  for (let i = 0; i < keys.length; i++) {\n    // Last key, set it\n    if (i === keys.length - 1) {\n      acc[keys[i]] = value;\n      return;\n    }\n\n    // Key does not exist, create a container for it\n    if (!(keys[i] in acc) || isNullOrUndefined(acc[keys[i]])) {\n      // container can be either an object or an array depending on the next key if it exists\n      acc[keys[i]] = isIndex(keys[i + 1]) ? [] : {};\n    }\n\n    acc = acc[keys[i]] as Record<string, unknown>;\n  }\n}\n\nfunction unset(object: Record<string, unknown> | unknown[], key: string | number) {\n  if (Array.isArray(object) && isIndex(key)) {\n    object.splice(Number(key), 1);\n    return;\n  }\n\n  if (isObject(object)) {\n    delete object[key];\n  }\n}\n\n/**\n * Removes a nested property from object\n */\nexport function unsetPath(object: NestedRecord, path: string): void {\n  if (isNotNestedPath(path)) {\n    delete object[cleanupNonNestedPath(path)];\n    return;\n  }\n\n  const keys = path.split(/\\.|\\[(\\d+)\\]/).filter(Boolean);\n  let acc: Record<string, unknown> = object;\n  for (let i = 0; i < keys.length; i++) {\n    // Last key, unset it\n    if (i === keys.length - 1) {\n      unset(acc, keys[i]);\n      break;\n    }\n\n    // Key does not exist, exit\n    if (!(keys[i] in acc) || isNullOrUndefined(acc[keys[i]])) {\n      break;\n    }\n\n    acc = acc[keys[i]] as Record<string, unknown>;\n  }\n\n  const pathValues: (unknown | Record<string, unknown>)[] = keys.map((_, idx) => {\n    return getFromPath(object, keys.slice(0, idx).join('.'));\n  });\n\n  for (let i = pathValues.length - 1; i >= 0; i--) {\n    if (!isEmptyContainer(pathValues[i])) {\n      continue;\n    }\n\n    if (i === 0) {\n      unset(object, keys[0]);\n      continue;\n    }\n\n    unset(pathValues[i - 1] as Record<string, unknown>, keys[i - 1]);\n  }\n}\n\n/**\n * A typed version of Object.keys\n */\nexport function keysOf<TRecord extends Record<string, unknown>>(record: TRecord): (keyof TRecord)[] {\n  return Object.keys(record);\n}\n\n// Uses same component provide as its own injections\n// Due to changes in https://github.com/vuejs/vue-next/pull/2424\nexport function injectWithSelf<T>(symbol: InjectionKey<T>, def: T | undefined = undefined): T | undefined {\n  const vm = getCurrentInstance() as any;\n\n  return vm?.provides[symbol as any] || inject(symbol, def);\n}\n\nexport function warn(message: string) {\n  vueWarning(`[vee-validate]: ${message}`);\n}\n\nexport function resolveNextCheckboxValue<T>(currentValue: T, checkedValue: T, uncheckedValue: T): T;\nexport function resolveNextCheckboxValue<T>(currentValue: T[], checkedValue: T, uncheckedValue: T): T[];\nexport function resolveNextCheckboxValue<T>(currentValue: T | T[], checkedValue: T, uncheckedValue: T): T | T[] {\n  if (Array.isArray(currentValue)) {\n    const newVal = [...currentValue];\n    // Use isEqual since checked object values can possibly fail the equality check #3883\n    const idx = newVal.findIndex(v => isEqual(v, checkedValue));\n    idx >= 0 ? newVal.splice(idx, 1) : newVal.push(checkedValue);\n\n    return newVal;\n  }\n\n  return isEqual(currentValue, checkedValue) ? uncheckedValue : checkedValue;\n}\n\n// https://github.com/bameyrick/throttle-typescript\ntype ThrottledFunction<T extends (...args: any) => any> = (...args: Parameters<T>) => ReturnType<T>;\n\n/**\n * Creates a throttled function that only invokes the provided function (`func`) at most once per within a given number of milliseconds\n * (`limit`)\n */\nexport function throttle<T extends (...args: any) => any>(func: T, limit: number): ThrottledFunction<T> {\n  let inThrottle: boolean;\n  let lastResult: ReturnType<T>;\n\n  return function (this: any, ...args: any[]): ReturnType<T> {\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\n    const context = this;\n\n    if (!inThrottle) {\n      inThrottle = true;\n\n      setTimeout(() => (inThrottle = false), limit);\n\n      lastResult = func.apply(context, args);\n    }\n\n    return lastResult;\n  };\n}\n\nexport function debounceAsync<TFunction extends (...args: any) => Promise<any>, TResult = ReturnType<TFunction>>(\n  inner: TFunction,\n  ms = 0,\n): (...args: Parameters<TFunction>) => Promise<TResult> {\n  let timer: number | null = null;\n  let resolves: any[] = [];\n\n  return function (...args: Parameters<TFunction>) {\n    // Run the function after a certain amount of time\n    if (timer) {\n      clearTimeout(timer);\n    }\n\n    // @ts-expect-error timer is a number\n    timer = setTimeout(() => {\n      // Get the result of the inner function, then apply it to the resolve function of\n      // each promise that has been created since the last time the inner function was run\n      const result = inner(...(args as any));\n\n      resolves.forEach(r => r(result));\n      resolves = [];\n    }, ms);\n\n    return new Promise<TResult>(resolve => resolves.push(resolve));\n  };\n}\n\nexport function applyModelModifiers<TValue = unknown>(value: TValue, modifiers: unknown): TValue {\n  if (!isObject(modifiers)) {\n    return value;\n  }\n\n  if (modifiers.number) {\n    return toNumber(value as string) as TValue;\n  }\n\n  return value;\n}\n\nexport function withLatest<\n  TFunction extends (...args: any[]) => Promise<any>,\n  TResult = Awaited<ReturnType<TFunction>>,\n>(fn: TFunction, onDone: (result: TResult, args: Parameters<TFunction>) => TResult) {\n  let latestRun: Promise<TResult> | undefined;\n\n  return async function runLatest(...args: Parameters<TFunction>) {\n    const pending = fn(...args);\n    latestRun = pending;\n    const result = await pending;\n    if (pending !== latestRun) {\n      return result;\n    }\n\n    latestRun = undefined;\n\n    return onDone(result, args);\n  };\n}\n\nexport function computedDeep<TValue = unknown>({ get, set }: { get(): TValue; set(value: TValue): void }): Ref<TValue> {\n  const baseRef = ref(deepCopy(get())) as Ref<TValue>;\n\n  watch(\n    get,\n    newValue => {\n      if (isEqual(newValue, baseRef.value)) {\n        return;\n      }\n\n      baseRef.value = deepCopy(newValue);\n    },\n    {\n      deep: true,\n    },\n  );\n\n  watch(\n    baseRef,\n    newValue => {\n      if (isEqual(newValue, get())) {\n        return;\n      }\n\n      set(deepCopy(newValue));\n    },\n    {\n      deep: true,\n    },\n  );\n\n  return baseRef;\n}\n\nexport function normalizeErrorItem(message: string | string[] | null | undefined) {\n  return Array.isArray(message) ? message : message ? [message] : [];\n}\n\nexport function resolveFieldOrPathState(path?: MaybeRefOrGetter<string>) {\n  const form = injectWithSelf(FormContextKey);\n  const state = path ? computed(() => form?.getPathState(toValue(path))) : undefined;\n  const field = path ? undefined : inject(FieldContextKey);\n\n  if (!field && !state?.value) {\n    if (__DEV__) {\n      warn(`field with name ${toValue(path)} was not found`);\n    }\n  }\n\n  return state || field;\n}\n\nexport function omit<TObj extends GenericObject>(obj: TObj, keys: (keyof GenericObject)[]) {\n  const target = {} as TObj;\n\n  for (const key in obj) {\n    if (!keys.includes(key)) {\n      target[key] = obj[key];\n    }\n  }\n\n  return target;\n}\n\nexport function debounceNextTick<\n  TFunction extends (...args: any[]) => MaybePromise<any>,\n  TResult = ReturnType<TFunction>,\n>(inner: TFunction): (...args: Parameters<TFunction>) => Promise<TResult> {\n  let lastTick: Promise<any> | null = null;\n  let resolves: any[] = [];\n\n  return function (...args: Parameters<TFunction>) {\n    // Run the function after a certain amount of time\n\n    const thisTick = nextTick(() => {\n      if (lastTick !== thisTick) {\n        return;\n      }\n\n      // Get the result of the inner function, then apply it to the resolve function of\n      // each promise that has been created since the last time the inner function was run\n      const result = inner(...(args as any));\n\n      resolves.forEach(r => r(result));\n      resolves = [];\n      lastTick = null;\n    });\n\n    lastTick = thisTick;\n\n    return new Promise<TResult>(resolve => resolves.push(resolve));\n  };\n}\n\nfunction _combineIssueItems<TItem extends StandardSchemaV1.Issue | IssueCollection>(\n  items: TItem[] | readonly TItem[],\n  getPath: (item: TItem) => string,\n) {\n  const issueMap: Record<string, IssueCollection> = {};\n  for (const item of items) {\n    const path = getPath(item);\n    if (!issueMap[path]) {\n      issueMap[path] = {\n        path,\n        messages: [],\n      };\n    }\n\n    if ('messages' in item) {\n      issueMap[path].messages.push(...item.messages);\n    } else {\n      issueMap[path].messages.push(item.message);\n    }\n  }\n\n  return Object.values(issueMap);\n}\n\n/**\n * Aggregates standard schema issues by path.\n */\nexport function combineStandardIssues(\n  issues: StandardSchemaV1.Issue[] | readonly StandardSchemaV1.Issue[],\n): IssueCollection[] {\n  return _combineIssueItems(issues, issue => (issue.path ? getDotPath(issue) ?? '' : ''));\n}\n"
  },
  {
    "path": "packages/vee-validate/src/utils/events.ts",
    "content": "import { hasCheckedAttr, isNativeMultiSelect, isNativeSelect, isEvent } from './assertions';\nimport { getBoundValue, hasValueBinding } from './vnode';\n\nfunction parseInputValue(el: HTMLInputElement) {\n  if (el.type === 'range') {\n    return Number.isNaN(el.valueAsNumber) ? el.value : el.valueAsNumber;\n  }\n\n  return el.value;\n}\n\nexport function normalizeEventValue(value: Event | unknown): unknown {\n  if (!isEvent(value)) {\n    return value;\n  }\n\n  const input = value.target as HTMLInputElement;\n  // Vue sets the current bound value on `_value` prop\n  // for checkboxes it it should fetch the value binding type as is (boolean instead of string)\n  if (hasCheckedAttr(input.type) && hasValueBinding(input)) {\n    return getBoundValue(input);\n  }\n\n  if (input.type === 'file' && input.files) {\n    const files = Array.from(input.files);\n\n    return input.multiple ? files : files[0];\n  }\n\n  if (isNativeMultiSelect(input)) {\n    return Array.from(input.options)\n      .filter(opt => opt.selected && !opt.disabled)\n      .map(getBoundValue);\n  }\n\n  // makes sure we get the actual `option` bound value\n  // #3440\n  if (isNativeSelect(input)) {\n    const selectedOption = Array.from(input.options).find(opt => opt.selected);\n\n    return selectedOption ? getBoundValue(selectedOption) : input.value;\n  }\n\n  return parseInputValue(input);\n}\n"
  },
  {
    "path": "packages/vee-validate/src/utils/index.ts",
    "content": "export * from './assertions';\nexport * from './common';\nexport * from './events';\nexport * from './rules';\nexport * from './vnode';\n"
  },
  {
    "path": "packages/vee-validate/src/utils/rules.ts",
    "content": "import { isLocator } from './assertions';\nimport { getFromPath, keysOf } from './common';\nimport { Locator } from '../types';\nimport { isObject } from '../../../shared';\n\n/**\n * Normalizes the given rules expression.\n */\nexport function normalizeRules(\n  rules: undefined | string | Record<string, unknown | unknown[] | Record<string, unknown>>,\n): Record<string, unknown[] | Record<string, unknown>> {\n  const acc: Record<string, unknown[] | Record<string, unknown>> = {};\n  Object.defineProperty(acc, '_$$isNormalized', {\n    value: true,\n    writable: false,\n    enumerable: false,\n    configurable: false,\n  });\n\n  if (!rules) {\n    return acc;\n  }\n\n  // Object is already normalized, skip.\n  if (isObject(rules) && rules._$$isNormalized) {\n    return rules as typeof acc;\n  }\n\n  if (isObject(rules)) {\n    return Object.keys(rules).reduce((prev, curr) => {\n      const params = normalizeParams(rules[curr]);\n\n      if (rules[curr] !== false) {\n        prev[curr] = buildParams(params);\n      }\n\n      return prev;\n    }, acc);\n  }\n\n  /* istanbul ignore if */\n  if (typeof rules !== 'string') {\n    return acc;\n  }\n\n  return rules.split('|').reduce((prev, rule) => {\n    const parsedRule = parseRule(rule);\n    if (!parsedRule.name) {\n      return prev;\n    }\n\n    prev[parsedRule.name] = buildParams(parsedRule.params);\n\n    return prev;\n  }, acc);\n}\n\n/**\n * Normalizes a rule param.\n */\nfunction normalizeParams(params: unknown) {\n  if (params === true) {\n    return [] as unknown[];\n  }\n\n  if (Array.isArray(params)) {\n    return params as unknown[];\n  }\n\n  if (isObject(params)) {\n    return params;\n  }\n\n  return [params];\n}\n\nfunction buildParams(provided: unknown[] | Record<string, unknown>) {\n  const mapValueToLocator = (value: unknown) => {\n    // A target param using interpolation\n    if (typeof value === 'string' && value[0] === '@') {\n      return createLocator(value.slice(1));\n    }\n\n    return value;\n  };\n\n  if (Array.isArray(provided)) {\n    return provided.map(mapValueToLocator);\n  }\n\n  // #3073\n  if (provided instanceof RegExp) {\n    return [provided];\n  }\n\n  return Object.keys(provided).reduce(\n    (prev, key) => {\n      prev[key] = mapValueToLocator(provided[key]);\n\n      return prev;\n    },\n    {} as Record<string, unknown>,\n  );\n}\n\n/**\n * Parses a rule string expression.\n */\nexport const parseRule = (rule: string) => {\n  let params: string[] = [];\n  const name = rule.split(':')[0];\n\n  if (rule.includes(':')) {\n    params = rule.split(':').slice(1).join(':').split(',');\n  }\n\n  return { name, params };\n};\n\nfunction createLocator(value: string): Locator {\n  const locator: Locator = (crossTable: Record<string, unknown>) => {\n    const val = getFromPath(crossTable, value) ?? crossTable[value];\n\n    return val;\n  };\n\n  locator.__locatorRef = value;\n\n  return locator;\n}\n\nexport function extractLocators(params: Record<string, unknown> | unknown[]): Locator[] {\n  if (Array.isArray(params)) {\n    return params.filter(isLocator);\n  }\n\n  return keysOf(params)\n    .filter(key => isLocator(params[key]))\n    .map(key => params[key] as unknown as Locator);\n}\n"
  },
  {
    "path": "packages/vee-validate/src/utils/vnode.ts",
    "content": "import { SetupContext } from 'vue';\n\ntype HTMLElementWithValueBinding = HTMLElement & { _value: unknown };\n\nexport function normalizeChildren(\n  tag: string | undefined | null,\n  context: SetupContext<any>,\n  slotProps: () => Record<string, unknown>,\n) {\n  if (!context.slots.default) {\n    return context.slots.default;\n  }\n\n  if (typeof tag === 'string' || !tag) {\n    return context.slots.default(slotProps());\n  }\n\n  return {\n    default: () => context.slots.default?.(slotProps()),\n  };\n}\n\n/**\n * Vue adds a `_value` prop at the moment on the input elements to store the REAL value on them, real values are different than the `value` attribute\n * as they do not get casted to strings unlike `el.value` which preserves user-code behavior\n */\nexport function getBoundValue(el: HTMLElement): unknown {\n  if (hasValueBinding(el)) {\n    return el._value;\n  }\n\n  return undefined;\n}\n\n/**\n * Vue adds a `_value` prop at the moment on the input elements to store the REAL value on them, real values are different than the `value` attribute\n * as they do not get casted to strings unlike `el.value` which preserves user-code behavior\n */\nexport function hasValueBinding(el: HTMLElement): el is HTMLElementWithValueBinding {\n  return '_value' in el;\n}\n"
  },
  {
    "path": "packages/vee-validate/src/validate.ts",
    "content": "import { resolveRule } from './defineRule';\nimport { klona as deepCopy } from 'klona/full';\nimport { isLocator, normalizeRules, keysOf, getFromPath, isStandardSchema, combineStandardIssues } from './utils';\nimport { getConfig } from './config';\nimport {\n  ValidationResult,\n  GenericValidateFunction,\n  FlattenAndMapPathsValidationResult,\n  FormValidationResult,\n  RawFormSchema,\n  GenericObject,\n  Path,\n} from './types';\nimport { isCallable, FieldValidationMetaInfo } from '../../shared';\nimport { StandardSchemaV1 } from '@standard-schema/spec';\n\n/**\n * Used internally\n */\ninterface FieldValidationContext<TInput = unknown, TOutput = TInput> {\n  name: string;\n  label?: string;\n  rules:\n    | GenericValidateFunction<TInput>\n    | GenericValidateFunction<TInput>[]\n    | StandardSchemaV1<TInput, TOutput>\n    | string\n    | Record<string, unknown>;\n  bails: boolean;\n  formData: Record<string, unknown>;\n}\n\ninterface ValidationOptions {\n  name?: string;\n  label?: string;\n  values?: Record<string, unknown>;\n  bails?: boolean;\n}\n\n/**\n * Validates a value against the rules.\n */\nexport async function validate<TInput, TOutput>(\n  value: TInput,\n  rules:\n    | string\n    | Record<string, unknown | unknown[]>\n    | GenericValidateFunction<TInput>\n    | GenericValidateFunction<TInput>[]\n    | StandardSchemaV1<TInput, TOutput>,\n  options: ValidationOptions = {},\n): Promise<ValidationResult<TOutput>> {\n  const shouldBail = options?.bails;\n  const field: FieldValidationContext<TInput, TOutput> = {\n    name: options?.name || '{field}',\n    rules,\n    label: options?.label,\n    bails: shouldBail ?? true,\n    formData: options?.values || {},\n  };\n\n  const result = await _validate(field, value);\n\n  return {\n    ...result,\n    valid: !result.errors.length,\n  };\n}\n\n/**\n * Starts the validation process.\n */\nasync function _validate<TInput = unknown, TOutput = TInput>(\n  field: FieldValidationContext<TInput, TOutput>,\n  value: TInput,\n) {\n  const rules = field.rules;\n  if (isStandardSchema(rules)) {\n    return validateFieldWithStandardSchema(value, { ...field, rules });\n  }\n\n  // if a generic function or chain of generic functions\n  if (isCallable(rules) || Array.isArray(rules)) {\n    const ctx = {\n      field: field.label || field.name,\n      name: field.name,\n      label: field.label,\n      form: field.formData,\n      value,\n    };\n\n    // Normalize the pipeline\n    const pipeline = Array.isArray(rules) ? rules : [rules];\n    const length = pipeline.length;\n    const errors: ReturnType<typeof _generateFieldError>[] = [];\n\n    for (let i = 0; i < length; i++) {\n      const rule = pipeline[i];\n      const result = await rule(value, ctx);\n      const isValid = typeof result !== 'string' && !Array.isArray(result) && result;\n      if (isValid) {\n        continue;\n      }\n\n      if (Array.isArray(result)) {\n        errors.push(...result);\n      } else {\n        const message = typeof result === 'string' ? result : _generateFieldError(ctx);\n        errors.push(message);\n      }\n\n      if (field.bails) {\n        return {\n          errors,\n        };\n      }\n    }\n\n    return {\n      errors,\n    };\n  }\n\n  const normalizedContext = {\n    ...field,\n    rules: normalizeRules(rules),\n  };\n  const errors: ReturnType<typeof _generateFieldError>[] = [];\n  const rulesKeys = Object.keys(normalizedContext.rules);\n  const length = rulesKeys.length;\n  for (let i = 0; i < length; i++) {\n    const rule = rulesKeys[i];\n    const result = await _test(normalizedContext, value, {\n      name: rule,\n      params: normalizedContext.rules[rule],\n    });\n\n    if (result.error) {\n      errors.push(result.error);\n      if (field.bails) {\n        return {\n          errors,\n        };\n      }\n    }\n  }\n\n  return {\n    errors,\n  };\n}\n\n/**\n * Handles yup validation\n */\nasync function validateFieldWithStandardSchema(\n  value: unknown,\n  context: FieldValidationContext<any> & { rules: StandardSchemaV1 },\n) {\n  const result = await context.rules['~standard'].validate(value);\n  if (!result.issues) {\n    return {\n      value: result.value,\n      errors: [],\n    };\n  }\n\n  const messages: string[] = [];\n  for (const error of result.issues) {\n    if (error.message) {\n      messages.push(error.message);\n    }\n  }\n\n  return {\n    errors: messages,\n  };\n}\n\n/**\n * Tests a single input value against a rule.\n */\nasync function _test(\n  field: FieldValidationContext,\n  value: unknown,\n  rule: { name: string; params: Record<string, unknown> | unknown[] },\n) {\n  const validator = resolveRule(rule.name);\n  if (!validator) {\n    throw new Error(`No such validator '${rule.name}' exists.`);\n  }\n\n  const params = fillTargetValues(rule.params, field.formData);\n  const ctx: FieldValidationMetaInfo = {\n    field: field.label || field.name,\n    name: field.name,\n    label: field.label,\n    value,\n    form: field.formData,\n    rule: {\n      ...rule,\n      params,\n    },\n  };\n\n  const result = await validator(value, params, ctx);\n\n  if (typeof result === 'string') {\n    return {\n      error: result,\n    };\n  }\n\n  return {\n    error: result ? undefined : _generateFieldError(ctx),\n  };\n}\n\n/**\n * Generates error messages.\n */\nfunction _generateFieldError(fieldCtx: FieldValidationMetaInfo) {\n  const message = getConfig().generateMessage;\n  if (!message) {\n    return 'Field is invalid';\n  }\n\n  return message(fieldCtx);\n}\n\nfunction fillTargetValues(params: unknown[] | Record<string, unknown>, crossTable: Record<string, unknown>) {\n  const normalize = (value: unknown) => {\n    if (isLocator(value)) {\n      return value(crossTable);\n    }\n\n    return value;\n  };\n\n  if (Array.isArray(params)) {\n    return params.map(normalize);\n  }\n\n  return Object.keys(params).reduce(\n    (acc, param) => {\n      acc[param] = normalize(params[param]);\n\n      return acc;\n    },\n    {} as Record<string, unknown>,\n  );\n}\n\nexport async function validateStandardSchema<TValues extends GenericObject, TOutput extends GenericObject = TValues>(\n  schema: StandardSchemaV1<TValues, TOutput>,\n  values: TValues,\n): Promise<FormValidationResult<TValues, TOutput>> {\n  const validationResult = await schema['~standard'].validate(deepCopy(values));\n\n  const results: Partial<FlattenAndMapPathsValidationResult<TValues, TOutput>> = {};\n  const errors: Partial<Record<Path<TValues>, string>> = {};\n  if (!validationResult.issues) {\n    return {\n      valid: true,\n      results: {},\n      errors: {},\n      values: validationResult.value,\n      source: 'schema',\n    };\n  }\n\n  const combinedIssues = combineStandardIssues(validationResult.issues || []);\n\n  for (const error of combinedIssues) {\n    const messages = error.messages;\n    const path = error.path as Path<TValues>;\n\n    results[path] = { valid: !messages.length, errors: messages };\n    if (messages.length) {\n      errors[path] = messages[0];\n    }\n  }\n\n  return {\n    valid: !combinedIssues.length,\n    results,\n    errors,\n    values: undefined,\n    source: 'schema',\n  };\n}\n\nexport async function validateObjectSchema<TValues extends GenericObject, TOutput extends GenericObject>(\n  schema: RawFormSchema<TValues>,\n  values: TValues | undefined,\n  opts?: Partial<{ names: Record<string, { name: string; label: string }>; bailsMap: Record<string, boolean> }>,\n): Promise<FormValidationResult<TValues, TOutput>> {\n  const paths = keysOf(schema) as Path<TValues>[];\n  const validations = paths.map(async path => {\n    const strings = opts?.names?.[path];\n    const fieldResult = await validate(getFromPath(values as any, path), schema[path], {\n      name: strings?.name || path,\n      label: strings?.label,\n      values: values as any,\n      bails: opts?.bailsMap?.[path] ?? true,\n    });\n\n    return {\n      ...fieldResult,\n      path,\n    };\n  });\n\n  let isAllValid = true;\n  const validationResults = await Promise.all(validations);\n\n  const results: Partial<FlattenAndMapPathsValidationResult<TValues, TOutput>> = {};\n  const errors: Partial<Record<Path<TValues>, string>> = {};\n  for (const result of validationResults) {\n    results[result.path] = {\n      valid: result.valid,\n      errors: result.errors,\n    };\n\n    if (!result.valid) {\n      isAllValid = false;\n      errors[result.path] = result.errors[0];\n    }\n  }\n\n  return {\n    valid: isAllValid,\n    results,\n    errors,\n    source: 'schema',\n  };\n}\n"
  },
  {
    "path": "packages/vee-validate/tests/.eslintrc.json",
    "content": "{\n  \"rules\": {\n    \"@typescript-eslint/no-explicit-any\": \"off\"\n  }\n}\n"
  },
  {
    "path": "packages/vee-validate/tests/ErrorMessage.spec.ts",
    "content": "import { defineRule, ErrorMessage } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\n\ndescribe('<ErrorMessage />', () => {\n  const REQUIRED_MESSAGE = `This field is required`;\n  defineRule('required', (value: string) => {\n    if (!value) {\n      return REQUIRED_MESSAGE;\n    }\n\n    return true;\n  });\n\n  test('does not render if no errors are present', async () => {\n    const wrapper = mountWithHoc({\n      components: {\n        ErrorMessage,\n      },\n      template: `\n      <VForm>\n        <Field name=\"field\" rules=\"required\" />\n        <ErrorMessage name=\"field\" id=\"error\" />\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    expect(wrapper.$el.querySelector('#error')).toBe(null);\n  });\n\n  test('shows error messages for a field', async () => {\n    const wrapper = mountWithHoc({\n      components: {\n        ErrorMessage,\n      },\n      template: `\n      <VForm>\n        <Field name=\"field\" rules=\"required\" />\n        <ErrorMessage name=\"field\" id=\"error\" />\n      </VForm>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    setValue(input, '');\n    await flushPromises();\n\n    const error = wrapper.$el.querySelector('#error');\n    expect(error.tagName).toBe('SPAN');\n    await flushPromises();\n\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n    setValue(input, '12');\n    await flushPromises();\n\n    // was removed\n    expect(wrapper.$el.querySelector('#error')).toBe(null);\n  });\n\n  test('render with \"as\" prop', async () => {\n    const wrapper = mountWithHoc({\n      components: {\n        ErrorMessage,\n      },\n      template: `\n      <VForm>\n        <Field name=\"field\" rules=\"required\" />\n        <ErrorMessage as=\"div\" name=\"field\" id=\"error\" />\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    const error = wrapper.$el.querySelector('#error');\n    expect(error.tagName).toBe('DIV');\n\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('render with \"as\" prop and child nodes', async () => {\n    const wrapper = mountWithHoc({\n      components: {\n        ErrorMessage,\n      },\n      template: `\n      <VForm>\n        <Field name=\"field\" rules=\"required\" />\n        <ErrorMessage as=\"div\" name=\"field\" id=\"error\" v-slot=\"{ message }\">\n          <span>icon</span>\n          <span>{{ message }}</span>\n        </ErrorMessage>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n\n    const error = wrapper.$el.querySelector('#error');\n    expect(error.tagName).toBe('DIV');\n    expect(error.textContent).toContain(REQUIRED_MESSAGE);\n  });\n\n  test('render with scoped slots', async () => {\n    const wrapper = mountWithHoc({\n      components: {\n        ErrorMessage,\n      },\n      template: `\n      <VForm>\n        <Field name=\"field\" rules=\"required\" />\n        <ErrorMessage name=\"field\" v-slot=\"{ message }\">\n          <p id=\"error\">{{ message }}</p>\n        </ErrorMessage>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    const error = wrapper.$el.querySelector('#error');\n    expect(error.tagName).toBe('P');\n\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/Field.spec.ts",
    "content": "import { defineRule, configure } from '@/vee-validate';\nimport { mountWithHoc, setValue, dispatchEvent, setChecked, flushPromises, dispatchFileEvent } from './helpers';\nimport { computed, reactive, ref, Ref } from 'vue';\nimport { ModelComp } from './helpers/ModelComp';\nimport { z } from 'zod';\n\nvi.useFakeTimers();\n\nbeforeEach(() => {\n  configure({\n    bails: true,\n    validateOnBlur: true,\n    validateOnChange: true,\n    validateOnInput: false,\n    validateOnModelUpdate: true,\n    generateMessage: undefined,\n  });\n});\n\ndescribe('<Field />', () => {\n  const REQUIRED_MESSAGE = `This field is required`;\n  defineRule('required', (value: string) => {\n    if (!value) {\n      return REQUIRED_MESSAGE;\n    }\n\n    return true;\n  });\n\n  defineRule('email', (email: string) => {\n    return email === 'email' ? true : 'The field must be a valid email';\n  });\n\n  defineRule('min', (value: string, [min]: any) => {\n    return value && value.length >= min ? true : 'This field must be at least 3 characters';\n  });\n\n  // FIXME: typing here should be more lax\n  defineRule('confirmed', (value: string, [target]: any) => {\n    return value === target ? true : 'inputs do not match';\n  });\n\n  defineRule('confirmedObj', (value: string, { target }: any) => {\n    return value === target ? true : 'inputs do not match';\n  });\n\n  test('renders an input by default', () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <Field name=\"field\" />\n    `,\n    });\n\n    expect(wrapper.$el.tagName).toBe(`INPUT`);\n  });\n\n  test('renders the as prop', () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <Field name=\"field\" as=\"div\" />\n    `,\n    });\n\n    expect(wrapper.$el.tagName).toBe(`DIV`);\n  });\n\n  test('renderless if no as prop and default slot exists', () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <Field name=\"field\" v-slot=\"{ field }\">\n        <select v-bind=\"field\">\n          <option>1</option>\n        </select>\n      </Field>\n    `,\n    });\n\n    expect(wrapper.$el.tagName).toBe(undefined);\n  });\n\n  test('accepts functions to be passed as rules', async () => {\n    const isRequired = (val: any) => (val ? true : 'Field is required');\n\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          rules: isRequired,\n        };\n      },\n      template: `\n      <div>\n        <Field name=\"field\" :rules=\"rules\" v-slot=\"{ errors, field, meta }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span>{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    const error = wrapper.$el.querySelector('span');\n    expect(error.textContent).toBe('');\n    setValue(input, '');\n    await flushPromises();\n    expect(error.textContent).toBe('Field is required');\n  });\n\n  test('accepts objects to be passed as rules', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          rules: { required: true, min: [3], confirmedObj: { target: '@other' } },\n        };\n      },\n      template: `\n      <VForm>\n        <Field name=\"field\" :rules=\"rules\" v-slot=\"{ errors, field }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"fieldError\">{{ errors[0] }}</span>\n        </Field>\n\n        <Field name=\"other\" rules=\"required\" v-slot=\"{ errors, field }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span>{{ errors[0] }}</span>\n        </Field>\n      </VForm>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    const error = wrapper.$el.querySelector('#fieldError');\n    expect(error.textContent).toBe('');\n    setValue(input, '1');\n    await flushPromises();\n    expect(error.textContent).toBe('This field must be at least 3 characters');\n    setValue(input, '123');\n    await flushPromises();\n    expect(error.textContent).toBe('inputs do not match');\n  });\n\n  test('listens for input and blur events to set meta flags', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"field\" rules=\"required\" v-slot=\"{ errors, field, meta }\">\n          <input v-bind=\"field\" type=\"text\">\n          <pre id=\"pre\">{{ meta }}</pre>\n        </Field>\n      </div>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    const pre = wrapper.$el.querySelector('pre');\n\n    expect(pre.textContent).toContain('\"touched\": false');\n    expect(pre.textContent).toContain('\"dirty\": false');\n    dispatchEvent(input, 'blur');\n    await flushPromises();\n    expect(pre.textContent).toContain('\"touched\": true');\n    expect(pre.textContent).toContain('\"dirty\": false');\n    dispatchEvent(input, 'input');\n    await flushPromises();\n    expect(pre.textContent).toContain('\"dirty\": true');\n  });\n\n  test('listens for change events', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ errors }\">\n        <Field name=\"select\" as=\"select\" rules=\"required\">\n          <option value=\"\">0</option>\n          <option value=\"1\">1</option>\n        </Field>\n        <span id=\"error\">{{ errors.select }}</span>\n      </VForm>\n    `,\n    });\n\n    const select = wrapper.$el.querySelector('select');\n    const error = wrapper.$el.querySelector('#error');\n\n    setValue(select, '');\n    await flushPromises();\n    // validation triggered on change.\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n\n    setValue(select, '1');\n    await flushPromises();\n\n    expect(error.textContent).toBe('');\n  });\n\n  test('validates initially with validateOnMount prop', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"field\" validateOnMount rules=\"required\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n\n    // flush the pending validation.\n    await flushPromises();\n\n    expect(error.textContent).toContain(REQUIRED_MESSAGE);\n  });\n\n  test('watches rules and re-validates', async () => {\n    let rules!: Ref<any>;\n    const wrapper = mountWithHoc({\n      setup() {\n        rules = ref({ required: true });\n\n        return {\n          rules,\n        };\n      },\n      template: `\n        <div>\n          <Field name=\"field\" :rules=\"rules\" v-slot=\"{ field, errors }\">\n            <input v-bind=\"field\" type=\"text\">\n            <span id=\"error\">{{ errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    const error = wrapper.$el.querySelector('#error');\n    setValue(input, '1');\n    // flush the pending validation.\n    await flushPromises();\n\n    expect(error.textContent).toBe('');\n\n    rules.value = {\n      required: false,\n      min: 3,\n    };\n\n    await flushPromises();\n    expect(error.textContent).toBe('This field must be at least 3 characters');\n  });\n\n  test('validates custom components', async () => {\n    const wrapper = mountWithHoc({\n      components: {\n        TextInput: {\n          props: ['value'],\n          template: `\n            <div>\n              <input id=\"input\" :value=\"value\" @input=\"$emit('change', $event.target.value)\">\n            </div>\n          `,\n        },\n      },\n      template: `\n        <div>\n          <Field name=\"field\" rules=\"required\" v-slot=\"{ field, errors }\">\n            <TextInput ref=\"input\" v-bind=\"field\" />\n            <span id=\"error\">{{ errors && errors[0] }}</span>\n          </Field>\n        </div>\n      `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('#input');\n\n    expect(error.textContent).toBe('');\n\n    setValue(input, '');\n    await flushPromises();\n\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n\n    setValue(input, 'val');\n    await flushPromises();\n    expect(error.textContent).toBe('');\n  });\n\n  test('validates target fields using targeted params', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm>\n        <Field rules=\"required\" name=\"confirmation\" />\n\n        <Field name=\"password\" rules=\"required|confirmed:@confirmation\" v-slot=\"{ field, errors }\">\n          <input type=\"password\" v-bind=\"field\">\n          <span id=\"err\">{{ errors[0] }}</span>\n        </Field>\n      </VForm>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#err');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    expect(error.textContent).toBeFalsy();\n    setValue(inputs[0], 'val');\n    await flushPromises();\n    // the password input hasn't changed yet.\n    expect(error.textContent).toBeFalsy();\n    setValue(inputs[1], '12');\n    await flushPromises();\n    // the password input was interacted with and should be validated.\n    expect(error.textContent).toBeTruthy();\n\n    setValue(inputs[1], 'val');\n    await flushPromises();\n    // the password input now matches the confirmation.\n    expect(error.textContent).toBeFalsy();\n\n    setValue(inputs[0], 'val1');\n    await flushPromises();\n    expect(error.textContent).toBeTruthy();\n  });\n\n  test('validates file input in scoped slots', async () => {\n    defineRule('atLeastOne', (files: File[]) => {\n      return files && files.length >= 1;\n    });\n\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"field\" rules=\"required|atLeastOne\" v-slot=\"{ field, errors }\">\n          <input type=\"file\" v-bind=\"field\">\n          <p id=\"error\">{{ errors[0] }}</p>\n        </Field>\n      </div>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    dispatchEvent(input, 'change');\n    await flushPromises();\n\n    const error = wrapper.$el.querySelector('#error');\n    expect(error.textContent).toBeTruthy();\n  });\n\n  test('validates file input by rendering', async () => {\n    defineRule('atLeastOne', (files: File[]) => {\n      return files && files.length >= 1;\n    });\n\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ errors }\">\n        <Field name=\"field\" rules=\"required|atLeastOne\" type=\"file\" />\n        <span id=\"error\">{{ errors.field }}</span>\n      </VForm>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    dispatchEvent(input, 'change');\n    await flushPromises();\n\n    const error = wrapper.$el.querySelector('#error');\n    expect(error.textContent).toBeTruthy();\n  });\n\n  test('file values are normalized depending', async () => {\n    const onSubmit = vi.fn();\n\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm @submit=\"onSubmit\">\n        <Field name=\"single\" type=\"file\" />\n        <Field name=\"multiple\" type=\"file\" multiple />\n\n        <button>submit</button>\n      </VForm>\n    `,\n      setup() {\n        return {\n          onSubmit,\n        };\n      },\n    });\n\n    await flushPromises();\n    const getInput = (name: string) => wrapper.$el.querySelector(`input[name=\"${name}\"]`) as HTMLInputElement;\n    const button = wrapper.$el.querySelector(`button`) as HTMLElement;\n\n    await dispatchFileEvent(getInput('single'), 'test.jpg');\n    await dispatchFileEvent(getInput('multiple'), ['one.jpg', 'two.jpg']);\n\n    button.click();\n    await flushPromises();\n\n    expect(onSubmit).toHaveBeenLastCalledWith(\n      expect.objectContaining({\n        single: expect.any(File),\n        multiple: expect.arrayContaining([expect.any(File), expect.any(File)]),\n      }),\n      expect.anything(),\n    );\n  });\n\n  test('setting bails prop to false disables exit on first error', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field :bails=\"false\" name=\"field\" rules=\"email|min:3\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <p v-for=\"error in errors\">{{ error }}</p>\n        </Field>\n      </div>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    setValue(input, '1');\n    await flushPromises();\n\n    const errors = wrapper.$el.querySelectorAll('p');\n    expect(errors).toHaveLength(2);\n    expect(errors[0].textContent).toBe('The field must be a valid email');\n    expect(errors[1].textContent).toBe('This field must be at least 3 characters');\n  });\n\n  test('standard schema can be used', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const rules = z.string().min(8);\n\n        return {\n          rules,\n        };\n      },\n      template: `\n      <div>\n        <Field name=\"field\" :rules=\"rules\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <p>{{ errors[0] }}</p>\n        </Field>\n      </div>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    const error = wrapper.$el.querySelector('p');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(error.textContent).toBe('Too small: expected string to have >=8 characters');\n    setValue(input, '12345678');\n    await flushPromises();\n    expect(error.textContent).toBe('');\n  });\n\n  test('avoids race conditions between successive validations', async () => {\n    // A decreasing timeout (the most recent validation will finish before new ones).\n    defineRule('longRunning', (value: unknown): Promise<boolean | string> => {\n      return new Promise(resolve => {\n        setTimeout(() => {\n          resolve(value === 42 ? true : 'No Life');\n        }, 20);\n      });\n    });\n\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"field\" rules=\"required|longRunning\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <p>{{ errors[0] }}</p>\n        </Field>\n      </div>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    const error = wrapper.$el.querySelector('p');\n\n    setValue(input, '123');\n    setValue(input, '12');\n    setValue(input, '');\n    vi.advanceTimersByTime(100);\n    await flushPromises();\n    // LAST message should be the required one.\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('resets validation state using handleReset() in slot scope props', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"field\" rules=\"required\" v-slot=\"{ field, errors, handleReset }\">\n          <input type=\"text\" v-bind=\"field\">\n          <span id=\"error\">{{ errors && errors[0] }}</span>\n          <button @click=\"handleReset\">Reset</button>\n        </Field>\n      </div>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('input');\n\n    expect(error.textContent).toBe('');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n    setValue(input, '123');\n    await flushPromises();\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(error.textContent).toBe('');\n    expect(input.value).toBe('');\n  });\n\n  test('resets validation state using resetField() in slot scope props', async () => {\n    const resetMessage = 'field is bad';\n    const resetValue = 'val';\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"field\" rules=\"required\" v-slot=\"{ field, errors, resetField, meta }\">\n          <input type=\"text\" v-bind=\"field\">\n          <span id=\"error\">{{ errors && errors[0] }}</span>\n          <span id=\"touched\">{{ meta.touched.toString() }}</span>\n          <span id=\"dirty\">{{ meta.dirty.toString() }}</span>\n          <button @click=\"resetField({ value: '${resetValue}', touched: true, errors: ['${resetMessage}'] })\">Reset</button>\n        </Field>\n      </div>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('input');\n    const dirty = wrapper.$el.querySelector('#dirty');\n    const touched = wrapper.$el.querySelector('#touched');\n\n    expect(error.textContent).toBe('');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n    expect(dirty.textContent).toBe('true');\n    expect(touched.textContent).toBe('false');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(error.textContent).toBe(resetMessage);\n    expect(input.value).toBe(resetValue);\n    expect(dirty.textContent).toBe('false');\n    expect(touched.textContent).toBe('true');\n  });\n\n  test('handleInput() updates the model', async () => {\n    let inputValue!: Ref<string>;\n    const wrapper = mountWithHoc({\n      setup() {\n        inputValue = ref('');\n        return {\n          value: inputValue,\n        };\n      },\n      template: `\n      <div>\n        <Field v-model=\"value\" name=\"field\" v-slot=\"{ handleInput }\">\n          <input :value=\"value\" @input=\"handleInput\" />\n        </Field>\n      </div>\n    `,\n    });\n\n    await flushPromises();\n    const input = wrapper.$el.querySelector('input');\n    setValue(input, '1234');\n    await flushPromises();\n    expect(inputValue.value).toBe('1234');\n\n    inputValue.value = '455';\n    await flushPromises();\n    expect(input.value).toBe('455');\n  });\n\n  test('generateMessage is invoked with custom fn rules', async () => {\n    configure({\n      generateMessage: ({ field }) => `${field} is bad`,\n    });\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          rules: () => false,\n        };\n      },\n      template: `\n      <div>\n        <Field :rules=\"rules\" name=\"field\" v-slot=\"{ field, errors }\">\n          <input type=\"text\" v-bind=\"field\">\n          <p id=\"error\">{{ errors[0] }}</p>\n        </Field>\n      </div>\n    `,\n    });\n\n    await flushPromises();\n    const input = wrapper.$el.querySelector('input');\n    const error = wrapper.$el.querySelector('#error');\n    setValue(input, '1234');\n    await flushPromises();\n    expect(error.textContent).toBe('field is bad');\n  });\n\n  test('can customize validation triggers via global config', async () => {\n    configure({\n      validateOnChange: false,\n      validateOnInput: true,\n    });\n\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"field\" rules=\"required\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('input');\n    input.value = '';\n    dispatchEvent(input, 'change');\n    await flushPromises();\n    // nothing got triggered\n    expect(error.textContent).toBe('');\n\n    input.value = '';\n    dispatchEvent(input, 'input');\n    await flushPromises();\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('can customize validation triggers via props', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"field\" rules=\"required\" v-slot=\"{ field, errors }\" validateOnInput :validateOnChange=\"false\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('input');\n    input.value = '';\n    dispatchEvent(input, 'change');\n    await flushPromises();\n    // nothing got triggered\n    expect(error.textContent).toBe('');\n\n    input.value = '';\n    dispatchEvent(input, 'input');\n    await flushPromises();\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('can show custom labels for fields in messages', async () => {\n    configure({\n      generateMessage: ({ field }) => `${field} is bad`,\n    });\n\n    defineRule('noMessage', (value: number) => {\n      return value === 48;\n    });\n\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"_bad_field_name\" label=\"nice name\" rules=\"noMessage\" v-slot=\"{ field, errors }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('input');\n    setValue(input, '3');\n    await flushPromises();\n    expect(error.textContent).toBe('nice name is bad');\n  });\n\n  test('can set touched meta', async () => {\n    mountWithHoc({\n      template: `\n      <Field name=\"field\" v-slot=\"{ meta, setTouched }\">\n        <span>{{ meta.touched }}</span>\n        <button @click=\"setTouched(true)\">Set Meta</button>\n      </Field>\n    `,\n    });\n\n    await flushPromises();\n    const span = document.querySelector('span');\n    expect(span?.textContent).toBe('false');\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(span?.textContent).toBe('true');\n  });\n\n  // #3053\n  test('labels can be set dynamically', async () => {\n    const label = ref('label');\n    const message = (field: string) => `${field} is not valid`;\n\n    mountWithHoc({\n      setup() {\n        const rules = (_: any, { field }: any) => message(field);\n\n        return {\n          rules,\n          label,\n        };\n      },\n      template: `\n        <Field name=\"field\" :rules=\"rules\" :label=\"label\" v-slot=\"{ errors, field }\">\n          <input v-bind=\"field\" type=\"text\">\n          <span>{{ errors[0] }}</span>\n        </Field>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    setValue(input, '1');\n    await flushPromises();\n    expect(document.querySelector('span')?.textContent).toBe(message(label.value));\n\n    label.value = 'updated';\n    await flushPromises();\n    setValue(input, '2');\n    await flushPromises();\n    expect(document.querySelector('span')?.textContent).toBe(message(label.value));\n  });\n\n  // #3048\n  test('proxies native listeners', async () => {\n    const onBlur = vi.fn();\n    mountWithHoc({\n      setup() {\n        return {\n          onBlur,\n        };\n      },\n      template: `\n      <Field name=\"field\" @blur=\"onBlur\" />\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    dispatchEvent(input as HTMLInputElement, 'blur');\n    expect(onBlur).toHaveBeenCalledTimes(1);\n  });\n\n  test('can customize checkboxes unchecked value', async () => {\n    const spy = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        return { onSubmit: spy };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\">\n        <Field name=\"terms\" type=\"checkbox\" :unchecked-value=\"false\" :value=\"true\" /> Coffee\n\n        <button type=\"submit\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const input = wrapper.$el.querySelector('input');\n    setChecked(input, true);\n    await flushPromises();\n    setChecked(input, false);\n    await flushPromises();\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(spy).toHaveBeenCalledWith(expect.objectContaining({ terms: false }), expect.anything());\n  });\n\n  // #3105\n  test('single checkboxes without forms toggles their value with v-model', async () => {\n    let model!: Ref<boolean>;\n    const wrapper = mountWithHoc({\n      setup() {\n        model = ref(false);\n\n        return { model };\n      },\n      template: `\n      <div>\n        <Field name=\"terms\" type=\"checkbox\" v-model=\"model\" :unchecked-value=\"false\" :value=\"true\" /> Dinner?\n      </div>\n    `,\n    });\n\n    await flushPromises();\n    const input = wrapper.$el.querySelector('input');\n    setChecked(input, true);\n    await flushPromises();\n    expect(model.value).toBe(true);\n    setChecked(input, false);\n    await flushPromises();\n    expect(model.value).toBe(false);\n  });\n\n  // #3107\n  test('sets initial value with v-model', async () => {\n    const modelValue = 'allo';\n    const wrapper = mountWithHoc({\n      setup() {\n        const model = ref(modelValue);\n\n        return { model };\n      },\n      template: `\n      <div>\n        <Field name=\"whatever\" v-model=\"model\" />\n      </div>\n    `,\n    });\n\n    await flushPromises();\n    const input = wrapper.$el.querySelector('input');\n    expect(input.value).toBe(modelValue);\n  });\n\n  test('resetField should reset the valid flag to false if the rules are incorrect', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"whatever\" v-slot=\"{ meta, field, resetField }\" rules=\"required\">\n          <input v-bind=\"field\" />\n          <span id=\"meta\">{{ meta.valid ? 'valid' : 'invalid' }}</span>\n          <button @click=\"resetField\">Reset</button>\n        </Field>\n      </div>\n    `,\n    });\n\n    await flushPromises();\n    const input = wrapper.$el.querySelector('input');\n    const meta = wrapper.$el.querySelector('#meta');\n\n    expect(meta?.textContent).toBe('invalid');\n    setValue(input, '');\n    await flushPromises();\n    expect(meta?.textContent).toBe('invalid');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(meta?.textContent).toBe('invalid');\n  });\n\n  test('valid flag is synced with the field errors array length', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"whatever\" v-slot=\"{ meta, field, resetField }\" rules=\"required\">\n          <input v-bind=\"field\" />\n          <span id=\"meta\">{{ meta.valid ? 'valid' : 'invalid' }}</span>\n          <button @click=\"resetField({ errors: ['bad'] })\">Reset</button>\n        </Field>\n      </div>\n    `,\n    });\n\n    await flushPromises();\n    const meta = wrapper.$el.querySelector('#meta');\n    expect(meta?.textContent).toBe('invalid');\n    const input = wrapper.$el.querySelector('input');\n    setValue(input, '');\n    await flushPromises();\n    expect(meta?.textContent).toBe('invalid');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(meta?.textContent).toBe('invalid');\n  });\n\n  test('can set multiple field errors', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"whatever\" v-slot=\"{ field, errors, setErrors }\" rules=\"required\">\n          <input v-bind=\"field\" />\n          <ul>\n            <li v-for=\"error in errors\">{{ error }}</li>\n          </ul>\n          <button type=\"button\" @click=\"setErrors(['bad', 'wrong'])\">Set errors</button>\n        </Field>\n      </div>\n    `,\n    });\n\n    await flushPromises();\n    const list = document.querySelector('ul');\n    expect(list?.children).toHaveLength(0);\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(list?.children).toHaveLength(2);\n    expect(list?.textContent).toBe('badwrong');\n  });\n\n  // #3230\n  test('v-model.number should not ignore the validation triggers', async () => {\n    const errorMessage = 'Field is invalid';\n    let model!: Ref<string | number>;\n    const wrapper = mountWithHoc({\n      setup() {\n        model = ref('');\n        const isAlwaysInvalid = () => errorMessage;\n\n        return { model, isAlwaysInvalid };\n      },\n      template: `\n      <div>\n        <Field v-model.number=\"model\" name=\"field\" :rules=\"isAlwaysInvalid\" v-slot=\"{ field, errors }\" :validateOnModelUpdate=\"false\">\n          <input v-bind=\"field\" id=\"input\" type=\"text\">\n          <span id=\"error\">{{ errors[0] }}</span>\n        </Field>\n      </div>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('#input');\n    input.value = '310';\n    dispatchEvent(input, 'input');\n    await flushPromises();\n    expect(model.value).toBe(310);\n    expect(error.textContent).toBe('');\n\n    dispatchEvent(input, 'blur');\n    await flushPromises();\n    expect(error.textContent).toBe(errorMessage);\n  });\n\n  //  #3312\n  test('v-model on a non-existent nested prop should still emit model events', async () => {\n    const form = reactive({});\n    const wrapper = mountWithHoc({\n      setup() {\n        return { form };\n      },\n      template: `\n      <div>\n        <Field v-model=\"form.field\" name=\"field\" />\n      </div>\n    `,\n    });\n\n    await flushPromises();\n    const input = wrapper.$el.querySelector('input');\n    input.value = 'hello';\n    dispatchEvent(input, 'input');\n    await flushPromises();\n    expect((form as any).field).toBe('hello');\n  });\n\n  // #3440\n  test('should preserve select input options value type', async () => {\n    const value = ref();\n\n    mountWithHoc({\n      setup() {\n        return {\n          value,\n        };\n      },\n      template: `\n        <Field as=\"select\" v-model=\"value\" name=\"hello\">\n          <option id=\"true\" :value=\"true\">Yes</option>\n          <option id=\"false\" :value=\"false\">No</option>\n        </Field>\n    `,\n    });\n\n    await flushPromises();\n    const select = document.querySelector('select') as HTMLSelectElement;\n    const optTrue = document.querySelector('#true') as HTMLOptionElement;\n    const optFalse = document.querySelector('#false') as HTMLOptionElement;\n\n    optTrue.selected = true;\n    dispatchEvent(select, 'change');\n    await flushPromises();\n    expect(value.value).toBe(true);\n\n    optFalse.selected = true;\n    dispatchEvent(select, 'change');\n    await flushPromises();\n    expect(value.value).toBe(false);\n  });\n\n  // #3468\n  test('should avoid setting the absent value to Vue', async () => {\n    const form = ref({});\n    mountWithHoc({\n      setup() {\n        return {\n          form,\n        };\n      },\n      template: `\n        <Field v-model=\"form.value\" name=\"hello\" />\n      `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    setValue(input, '1234');\n    await flushPromises();\n    expect(input.value).toBe('1234');\n    form.value = {};\n    await flushPromises();\n    expect(input.value).toBe('');\n  });\n\n  // #3485\n  test('computed rules should not generate errors unless the field was validated before', async () => {\n    const isRequired = ref(false);\n    const rules = computed(() => (isRequired.value ? 'required' : ''));\n    mountWithHoc({\n      setup() {\n        return {\n          rules,\n        };\n      },\n      template: `\n        <Field name=\"field\" :rules=\"rules\" v-slot=\"{ errorMessage, field }\">\n          <input v-bind=\"field\" />\n          <span>{{ errorMessage }}</span>\n        </Field>\n      `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    const error = document.querySelector('span') as HTMLInputElement;\n    isRequired.value = true;\n    await flushPromises();\n    expect(error.textContent).toBe('');\n    isRequired.value = false;\n    await flushPromises();\n    expect(error.textContent).toBe('');\n    setValue(input, '');\n    await flushPromises();\n    isRequired.value = true;\n    await flushPromises();\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('resets validation state using refs and exposed API', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"field\" ref=\"field\" rules=\"required\" v-slot=\"{ errors, field }\">\n          <input type=\"text\" v-bind=\"field\">\n          <span id=\"error\">{{ errors && errors[0] }}</span>\n        </Field>\n\n        <button @click=\"$refs.field.reset()\">Reset</button>\n      </div>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('input');\n\n    expect(error.textContent).toBe('');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n    setValue(input, '123');\n    await flushPromises();\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(error.textContent).toBe('');\n    expect(input.value).toBe('');\n  });\n\n  test('should have correct field object binding properties based on file type', async () => {\n    const textualType = vi.fn();\n    const fileType = vi.fn();\n    const checkboxType = vi.fn();\n    const radioType = vi.fn();\n\n    mountWithHoc({\n      template: `\n      <div>\n        <Field name=\"text\" v-slot=\"{ field }\">\n          {{ textualType(field) }}\n        </Field>\n        <Field name=\"file\" type=\"file\" v-slot=\"{ field }\">\n          {{ fileType(field) }}\n        </Field>\n        <Field name=\"checkbox\" type=\"checkbox\" v-slot=\"{ field }\">\n          {{ checkboxType(field) }}\n        </Field>\n        <Field name=\"radio\" type=\"radio\" v-slot=\"{ field }\">\n          {{ radioType(field) }}\n        </Field>\n      </div>\n    `,\n      setup() {\n        return {\n          textualType,\n          fileType,\n          checkboxType,\n          radioType,\n        };\n      },\n    });\n\n    await flushPromises();\n    const lastCallOf = (fn: ReturnType<typeof vi.fn>) => fn.mock.calls[fn.mock.calls.length - 1][0];\n    expect(lastCallOf(textualType)).toHaveProperty('value');\n    expect(lastCallOf(fileType)).not.toHaveProperty('value');\n    expect(lastCallOf(checkboxType)).toHaveProperty('checked');\n    expect(lastCallOf(checkboxType)).not.toHaveProperty('value');\n    expect(lastCallOf(radioType)).toHaveProperty('checked');\n    expect(lastCallOf(radioType)).not.toHaveProperty('value');\n  });\n\n  describe('componentField', () => {\n    test('provides bindable object to components', async () => {\n      mountWithHoc({\n        components: {\n          ModelComp,\n        },\n        template: `\n          <Field name=\"name\" v-slot=\"{ componentField, errorMessage, value }\" rules=\"required\">\n            <ModelComp v-bind=\"componentField\" />\n            <span id=\"errors\">{{ errorMessage }}</span>\n            <span id=\"values\">{{ value }}</span>\n          </Field>\n        `,\n      });\n\n      await flushPromises();\n      const errorEl = document.getElementById('errors');\n      const valuesEl = document.getElementById('values');\n      const inputEl = document.querySelector('input') as HTMLInputElement;\n      expect(inputEl.getAttribute('name')).toBe('name');\n      setValue(inputEl, '');\n      dispatchEvent(inputEl, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('This field is required');\n      setValue(inputEl, '123');\n      dispatchEvent(inputEl, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('');\n      expect(valuesEl?.textContent).toBe('123');\n    });\n  });\n\n  // #4285\n  test('handle blur should respect the validate on blur config', async () => {\n    mountWithHoc({\n      template: `\n        <Field name=\"field\" rules=\"required\" v-slot=\"{ errorMessage, handleBlur }\" validateOnBlur>\n          <input @blur=\"handleBlur\" />\n          <span>{{ errorMessage }}</span>\n        </Field>\n      `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    const error = document.querySelector('span') as HTMLInputElement;\n    dispatchEvent(input, 'blur');\n    await flushPromises();\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/FieldArray.spec.ts",
    "content": "import { Form, defineRule, useField } from '@/vee-validate';\nimport { toRef, ref, defineComponent } from 'vue';\nimport * as z from 'zod';\nimport { mountWithHoc, setValue, getValue, dispatchEvent, flushPromises } from './helpers';\n\nconst REQUIRED_MESSAGE = 'REQUIRED';\n\ntest('warns if no form is detected', async () => {\n  const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n    // NOOP\n  });\n\n  mountWithHoc({\n    template: `\n      <FieldArray name=\"users\" />\n    `,\n  });\n\n  await flushPromises();\n  expect(spy).toHaveBeenCalled();\n  spy.mockRestore();\n});\n\ntest('warns if no name path is provided', async () => {\n  const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n    // NOOP\n  });\n\n  mountWithHoc({\n    template: `\n      <VForm>\n        <FieldArray />\n      </VForm>\n      `,\n  });\n\n  await flushPromises();\n  expect(spy).toHaveBeenCalled();\n  spy.mockRestore();\n});\n\ntest('adds items to the end of the array with push()', async () => {\n  const onSubmit = vi.fn();\n  mountWithHoc({\n    setup() {\n      const initialValues = {\n        users: [{ name: '111' }, { name: '222' }, { name: '333' }],\n      };\n\n      return {\n        onSubmit,\n        initialValues,\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\" :initial-values=\"initialValues\">\n        <FieldArray name=\"users\" v-slot=\"{ remove, push, fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <label :for=\"'name_' + idx\">Name</label>\n            <Field :id=\"'name_' + idx\" :name=\"'users[' + idx + '].name'\" />\n            <ErrorMessage :name=\"'users[' + idx + '].name'\" />\n\n            <button class=\"remove\" type=\"button\" @click=\"remove(idx)\">X</button>\n          </fieldset>\n\n          <button class=\"add\" type=\"button\" @click=\"push({ name: 'new' })\">Add User +</button>\n        </FieldArray>\n\n        <button class=\"submit\" type=\"submit\">Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const submitBtn = document.querySelector('.submit') as HTMLButtonElement;\n  const inputs = Array.from(document.querySelectorAll('input')) as HTMLInputElement[];\n  const removeBtn = document.querySelectorAll('.remove')[1] as HTMLButtonElement; // remove the second item\n  setValue(inputs[0], '111');\n  setValue(inputs[1], '222');\n  setValue(inputs[2], '333');\n  await flushPromises();\n  removeBtn.click();\n  await flushPromises();\n  (submitBtn as HTMLButtonElement).click();\n  await flushPromises();\n  expect(onSubmit).toHaveBeenLastCalledWith(\n    expect.objectContaining({\n      users: [{ name: '111' }, { name: '333' }],\n    }),\n    expect.anything(),\n  );\n\n  dispatchEvent('.add', 'click');\n  await flushPromises();\n  (submitBtn as HTMLButtonElement).click();\n  await flushPromises();\n  expect(onSubmit).toHaveBeenLastCalledWith(\n    expect.objectContaining({\n      users: [{ name: '111' }, { name: '333' }, { name: 'new' }],\n    }),\n    expect.anything(),\n  );\n});\n\ntest('array fields should update their values when swapped', async () => {\n  mountWithHoc({\n    setup() {\n      const initial = {\n        users: [\n          {\n            name: 'first',\n          },\n          {\n            name: 'second',\n          },\n          {\n            name: 'third',\n          },\n        ],\n      };\n\n      return {\n        initial,\n      };\n    },\n    template: `\n      <VForm :initial-values=\"initial\">\n\n        <FieldArray name=\"users\" v-slot=\"{ remove, push, fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <Field :id=\"\\`name_\\${idx}\\`\" :name=\"\\`users[\\${idx}].name\\`\" />\n            <button :class=\"\\`remove_\\${idx}\\`\" type=\"button\" @click=\"remove(idx)\">X</button>\n          </fieldset>\n\n          <button class=\"add\" type=\"button\" @click=\"push({ name: '' })\">Add User +</button>\n        </FieldArray>\n\n        <button type=\"submit\">Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  expect(document.querySelectorAll('input')).toHaveLength(3);\n  dispatchEvent('.remove_0', 'click');\n  await flushPromises();\n  expect(document.querySelectorAll('input')).toHaveLength(2);\n  expect(getValue('#name_0')).toBe('second');\n\n  dispatchEvent('.add', 'click');\n  await flushPromises();\n  expect(document.querySelectorAll('input')).toHaveLength(3);\n  expect(getValue('#name_2')).toBe('');\n});\n\ntest('can swap array fields with swap helper', async () => {\n  const onSubmit = vi.fn();\n  mountWithHoc({\n    setup() {\n      const schema = z.object({\n        users: z.array(\n          z.object({\n            name: z.string().min(1, REQUIRED_MESSAGE),\n          }),\n        ),\n      });\n\n      const initial = {\n        users: [\n          {\n            name: 'first',\n          },\n          {\n            name: 'second',\n          },\n          {\n            name: 'third',\n          },\n        ],\n      };\n\n      return {\n        initial,\n        schema,\n        onSubmit,\n      };\n    },\n    template: `\n    <VForm @submit=\"onSubmit\" :validation-schema=\"schema\" :initial-values=\"initial\">\n      <FieldArray name=\"users\" v-slot=\"{ swap, fields }\">\n          <div v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <button class=\"up\" @click=\"swap(idx, idx - 1)\" type=\"button\">⬆️</button>\n\n            <Field :name=\"'users[' + idx + '].name'\" />\n            <ErrorMessage :class=\"'error-' + idx\" :name=\"'users[' + idx + '].name'\" />\n          </div>\n      </FieldArray>\n\n      <button class=\"submit\" type=\"submit\">Submit</button>\n    </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const inputAt = (idx: number) => (document.querySelectorAll('input') || [])[idx] as HTMLInputElement;\n  const errorAt = (idx: number) => document.querySelector(`.error-${idx}`) as HTMLElement;\n  const upButtonAt = (idx: number) => (document.querySelectorAll('.up') || [])[idx] as HTMLElement;\n  const submitBtn = () => document.querySelector('.submit') as HTMLButtonElement;\n\n  expect(getValue(inputAt(0))).toBe('first');\n  expect(getValue(inputAt(1))).toBe('second');\n  expect(getValue(inputAt(2))).toBe('third');\n\n  setValue(inputAt(1), '');\n  await flushPromises();\n  expect(errorAt(1)?.textContent).toBe(REQUIRED_MESSAGE);\n\n  upButtonAt(2).click();\n  await flushPromises();\n  expect(getValue(inputAt(1))).toBe('third');\n  // undefined because it should be unmounted\n  expect(errorAt(1)?.textContent).toBe(undefined);\n\n  expect(getValue(inputAt(2))).toBe('');\n  expect(errorAt(2)?.textContent).toBe(REQUIRED_MESSAGE);\n\n  setValue(inputAt(2), 'edited');\n  await flushPromises();\n\n  submitBtn().click();\n  await flushPromises();\n\n  expect(onSubmit).toHaveBeenCalledTimes(1);\n  expect(onSubmit).toHaveBeenLastCalledWith(\n    expect.objectContaining({\n      users: [\n        {\n          name: 'first',\n        },\n        {\n          name: 'third',\n        },\n        {\n          name: 'edited',\n        },\n      ],\n    }),\n    expect.anything(),\n  );\n});\n\ntest('fields have isFirst and isLast flags to help with conditions', async () => {\n  mountWithHoc({\n    setup() {\n      const initial = {\n        users: [\n          {\n            name: 'first',\n          },\n          {\n            name: 'second',\n          },\n          {\n            name: 'third',\n          },\n        ],\n      };\n\n      return {\n        initial,\n      };\n    },\n    template: `\n    <VForm :initial-values=\"initial\">\n      <FieldArray name=\"users\" v-slot=\"{ swap, fields, push, remove }\">\n          <div v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <button class=\"up\" @click=\"swap(idx, idx - 1)\" :disabled=\"field.isFirst\" type=\"button\">⬆️</button>\n            <button class=\"down\" @click=\"swap(idx, idx + 1)\" :disabled=\"field.isLast\" type=\"button\">⬇️</button>\n            <button class=\"remove\" type=\"button\" @click=\"remove(idx)\">X</button>\n\n\n            <Field :name=\"'users[' + idx + '].name'\" />\n          </div>\n          <button class=\"add\" type=\"button\" @click=\"push({ name: '' })\">Add User +</button>\n      </FieldArray>\n\n    </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const upButtonAt = (idx: number) => (document.querySelectorAll('.up') || [])[idx] as HTMLButtonElement;\n  const downButtonAt = (idx: number) => (document.querySelectorAll('.down') || [])[idx] as HTMLButtonElement;\n  const rmButtonAt = (idx: number) => (document.querySelectorAll('.remove') || [])[idx] as HTMLButtonElement;\n  const addButton = () => document.querySelector('.add') as HTMLButtonElement;\n\n  expect(upButtonAt(0).disabled).toBe(true);\n  expect(upButtonAt(1).disabled).toBe(false);\n  expect(upButtonAt(2).disabled).toBe(false);\n\n  expect(downButtonAt(0).disabled).toBe(false);\n  expect(downButtonAt(1).disabled).toBe(false);\n  expect(downButtonAt(2).disabled).toBe(true);\n\n  addButton().click();\n  await flushPromises();\n\n  expect(upButtonAt(0).disabled).toBe(true);\n  expect(upButtonAt(1).disabled).toBe(false);\n  expect(upButtonAt(2).disabled).toBe(false);\n  expect(upButtonAt(3).disabled).toBe(false);\n\n  expect(downButtonAt(0).disabled).toBe(false);\n  expect(downButtonAt(1).disabled).toBe(false);\n  expect(downButtonAt(2).disabled).toBe(false);\n  expect(downButtonAt(3).disabled).toBe(true);\n\n  rmButtonAt(2).click();\n  await flushPromises();\n\n  expect(upButtonAt(0).disabled).toBe(true);\n  expect(upButtonAt(1).disabled).toBe(false);\n  expect(upButtonAt(2).disabled).toBe(false);\n\n  expect(downButtonAt(0).disabled).toBe(false);\n  expect(downButtonAt(1).disabled).toBe(false);\n  expect(downButtonAt(2).disabled).toBe(true);\n});\n\ntest('can insert new items at specific index', async () => {\n  mountWithHoc({\n    setup() {\n      const initial = {\n        users: [\n          {\n            name: 'first',\n          },\n          {\n            name: 'second',\n          },\n          {\n            name: 'third',\n          },\n        ],\n      };\n\n      return {\n        initial,\n      };\n    },\n    template: `\n    <VForm :initial-values=\"initial\">\n      <FieldArray name=\"users\" v-slot=\"{ fields, insert }\">\n          <div v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <Field :name=\"'users[' + idx + '].name'\" />\n          </div>\n          <button class=\"insert\" type=\"button\" @click=\"insert(1, { name: 'inserted' })\">Add User +</button>\n      </FieldArray>\n    </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const inputAt = (idx: number) => (document.querySelectorAll('input') || [])[idx] as HTMLInputElement;\n  const insertButton = () => document.querySelector('.insert') as HTMLButtonElement;\n\n  expect(getValue(inputAt(1))).toBe('second');\n  expect(getValue(inputAt(2))).toBe('third');\n\n  insertButton().click();\n  await flushPromises();\n\n  expect(getValue(inputAt(1))).toBe('inserted');\n  expect(getValue(inputAt(2))).toBe('second');\n  expect(getValue(inputAt(3))).toBe('third');\n});\n\ntest('can replace all the items in the field array', async () => {\n  mountWithHoc({\n    setup() {\n      const initial = {\n        users: [\n          {\n            name: 'first',\n          },\n          {\n            name: 'second',\n          },\n          {\n            name: 'third',\n          },\n        ],\n      };\n\n      return {\n        initial,\n      };\n    },\n    template: `\n    <VForm :initial-values=\"initial\">\n      <FieldArray name=\"users\" v-slot=\"{ fields, replace }\">\n          <div v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <Field :name=\"'users[' + idx + '].name'\" />\n          </div>\n          <button class=\"replace\" type=\"button\" @click=\"replace([{ name: 'replaced' }])\">Replace</button>\n      </FieldArray>\n    </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const inputAt = (idx: number) => (document.querySelectorAll('input') || [])[idx] as HTMLInputElement;\n  const replaceButton = () => document.querySelector('.replace') as HTMLButtonElement;\n\n  expect(getValue(inputAt(0))).toBe('first');\n  expect(getValue(inputAt(1))).toBe('second');\n  expect(getValue(inputAt(2))).toBe('third');\n\n  replaceButton().click();\n  await flushPromises();\n\n  expect(getValue(inputAt(0))).toBe('replaced');\n  expect(getValue(inputAt(1))).toBe(undefined);\n  expect(getValue(inputAt(2))).toBe(undefined);\n});\n\ntest('can update an item value at a given array index', async () => {\n  mountWithHoc({\n    setup() {\n      const initial = {\n        users: [\n          {\n            name: 'first',\n          },\n          {\n            name: 'second',\n          },\n          {\n            name: 'third',\n          },\n        ],\n      };\n\n      return {\n        initial,\n      };\n    },\n    template: `\n    <VForm :initial-values=\"initial\">\n      <FieldArray name=\"users\" v-slot=\"{ fields, update }\">\n          <div v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <Field :name=\"'users[' + idx + '].name'\" />\n          </div>\n          <button class=\"update\" type=\"button\" @click=\"update(1, { name: 'updated' })\">Update</button>\n      </FieldArray>\n    </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const inputAt = (idx: number) => (document.querySelectorAll('input') || [])[idx] as HTMLInputElement;\n  const updateButton = () => document.querySelector('.update') as HTMLButtonElement;\n\n  expect(getValue(inputAt(1))).toBe('second');\n\n  updateButton().click();\n  await flushPromises();\n\n  expect(getValue(inputAt(1))).toBe('updated');\n});\n\ntest('can update an item value directly with .value setter', async () => {\n  const onSubmit = vi.fn();\n  mountWithHoc({\n    setup() {\n      const initial = {\n        users: [\n          {\n            name: 'first',\n          },\n        ],\n      };\n\n      return {\n        initial,\n        onSubmit,\n      };\n    },\n    template: `\n    <VForm :initial-values=\"initial\" @submit=\"onSubmit\">\n      <FieldArray name=\"users\" v-slot=\"{ fields }\">\n          <div v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <input v-model=\"fields[idx].value.name\" />\n          </div>\n      </FieldArray>\n\n      <button>Submit</button>\n    </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const inputAt = (idx: number) => (document.querySelectorAll('input') || [])[idx] as HTMLInputElement;\n\n  expect(getValue(inputAt(0))).toBe('first');\n  setValue(inputAt(0), 'updated');\n  await flushPromises();\n  expect(getValue(inputAt(0))).toBe('updated');\n  document.querySelector('button')?.click();\n  await flushPromises();\n\n  expect(onSubmit).toHaveBeenLastCalledWith(\n    expect.objectContaining({\n      users: [\n        {\n          name: 'updated',\n        },\n      ],\n    }),\n    expect.anything(),\n  );\n});\n\ntest('adds items to the start of the array with prepend()', async () => {\n  const onSubmit = vi.fn();\n  mountWithHoc({\n    setup() {\n      const initialValues = {\n        users: [{ name: '111' }, { name: '222' }],\n      };\n\n      return {\n        onSubmit,\n        initialValues,\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\" :initial-values=\"initialValues\">\n        <FieldArray name=\"users\" v-slot=\"{ remove, prepend, fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <label :for=\"'name_' + idx\">Name</label>\n            <Field :id=\"'name_' + idx\" :name=\"'users[' + idx + '].name'\" />\n            <ErrorMessage :name=\"'users[' + idx + '].name'\" />\n\n            <button class=\"remove\" type=\"button\" @click=\"remove(idx)\">X</button>\n          </fieldset>\n\n          <button class=\"prepend\" type=\"button\" @click=\"prepend({ name: 'new' })\">Add User +</button>\n        </FieldArray>\n\n        <button class=\"submit\" type=\"submit\">Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const submitBtn = document.querySelector('.submit') as HTMLButtonElement;\n  const inputAt = (idx: number) => (document.querySelectorAll('input') || [])[idx] as HTMLInputElement;\n\n  expect(getValue(inputAt(0))).toBe('111');\n  expect(getValue(inputAt(1))).toBe('222');\n  dispatchEvent('.prepend', 'click');\n  await flushPromises();\n  expect(getValue(inputAt(0))).toBe('new');\n  expect(getValue(inputAt(1))).toBe('111');\n  expect(getValue(inputAt(2))).toBe('222');\n  (submitBtn as HTMLButtonElement).click();\n  await flushPromises();\n  expect(onSubmit).toHaveBeenLastCalledWith(\n    expect.objectContaining({\n      users: [{ name: 'new' }, { name: '111' }, { name: '222' }],\n    }),\n    expect.anything(),\n  );\n});\n\n// #3664\ntest('clears old errors path when item is removed when no form schema is present', async () => {\n  const onSubmit = vi.fn();\n  mountWithHoc({\n    setup() {\n      const initialValues = {\n        users: [{ name: '' }, { name: '' }, { name: '' }],\n      };\n\n      const schema = z.string().min(1, REQUIRED_MESSAGE);\n\n      return {\n        onSubmit,\n        schema,\n        initialValues,\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\" :initial-values=\"initialValues\" v-slot=\"{ errors }\">\n        <FieldArray name=\"users\" v-slot=\"{ remove, push, fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <label :for=\"'name_' + idx\">Name</label>\n            <Field :id=\"'name_' + idx\" :name=\"'users[' + idx + '].name'\" :rules=\"schema\" />\n            <ErrorMessage :name=\"'users[' + idx + '].name'\" />\n\n            <button class=\"remove\" type=\"button\" @click=\"remove(idx)\">X</button>\n          </fieldset>\n        </FieldArray>\n\n\n        <ul class=\"errors\">\n          <li v-for=\"error in errors\">{{ error }}</li>\n        </ul>\n\n        <button class=\"submit\" type=\"submit\">Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const submitBtn = document.querySelector('.submit') as HTMLButtonElement;\n  const errorList = document.querySelector('ul') as HTMLUListElement;\n  const removeBtnAt = (idx: number) => document.querySelectorAll('.remove')[idx] as HTMLButtonElement; // remove the second item\n\n  submitBtn.click();\n  await flushPromises();\n  expect(errorList.children).toHaveLength(3);\n  removeBtnAt(1).click();\n  await flushPromises();\n\n  expect(errorList.children).toHaveLength(2);\n});\n\n// #3748\ntest('clears old errors path when last item is removed and value update validation is on', async () => {\n  const onSubmit = vi.fn();\n  defineRule('required', (v: any) => (v ? true : REQUIRED_MESSAGE));\n  const InputField = defineComponent({\n    props: {\n      rules: {\n        type: String,\n        required: true,\n      },\n      name: {\n        type: String,\n        required: true,\n      },\n      label: String,\n      type: { type: String, default: 'text' },\n    },\n    setup(props) {\n      const { value, handleChange, errors } = useField(toRef(props, 'name'), props.rules, {\n        label: props.label,\n        type: props.type as 'checkbox',\n      });\n\n      return {\n        value,\n        errors,\n        handleChange,\n      };\n    },\n    template: `\n      <label :for=\"name\">{{ label }}</label>\n      <input :type=\"type\" :name=\"name\" :value=\"value\" @input=\"handleChange\" />\n      <span>{{ errors[0] }}</span>\n      `,\n  });\n\n  mountWithHoc({\n    components: {\n      InputField,\n    },\n    setup() {\n      const initialValues = {\n        users: ['first', 'second', 'third'],\n      };\n\n      const schema = z.string().min(1, REQUIRED_MESSAGE);\n\n      return {\n        onSubmit,\n        schema,\n        initialValues,\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\" :initial-values=\"initialValues\" v-slot=\"{ errors }\">\n        <FieldArray name=\"users\" v-slot=\"{ remove, push, fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <label :for=\"'name_' + idx\">Name</label>\n            <InputField :name=\"'users[' + idx + ']'\" rules=\"required\" />\n\n            <button class=\"remove\" type=\"button\" @click=\"remove(idx)\">X</button>\n          </fieldset>\n        </FieldArray>\n\n\n        <ul class=\"errors\">\n          <li v-for=\"error in errors\">{{ error }}</li>\n        </ul>\n\n        <button class=\"submit\" type=\"submit\">Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const submitBtn = document.querySelector('.submit') as HTMLButtonElement;\n  const errorList = document.querySelector('ul') as HTMLUListElement;\n  const removeBtnAt = (idx: number) => document.querySelectorAll('.remove')[idx] as HTMLButtonElement; // remove the second item\n\n  submitBtn.click();\n  await flushPromises();\n  expect(errorList.children).toHaveLength(0);\n  removeBtnAt(2).click();\n  await flushPromises();\n\n  expect(errorList.children).toHaveLength(0);\n});\n\n// 4017\ntest('keeps the errors intact if an item was removed in the middle of the list', async () => {\n  defineRule('required', (v: any) => (v ? true : REQUIRED_MESSAGE));\n  const InputField = defineComponent({\n    props: {\n      rules: {\n        type: null,\n        required: true,\n      },\n      name: {\n        type: String,\n        required: true,\n      },\n      label: String,\n      type: { type: String, default: 'text' },\n    },\n    setup(props) {\n      const { value, handleChange, errors } = useField(toRef(props, 'name'), props.rules, {\n        label: props.label,\n      });\n\n      return {\n        value,\n        errors,\n        handleChange,\n      };\n    },\n    template: `\n      <label :for=\"name\">{{ label }}</label>\n      <input :type=\"type\" :name=\"name\" :value=\"value\" @input=\"handleChange\" />\n      <span>{{ errors[0] }}</span>\n      `,\n  });\n\n  mountWithHoc({\n    components: {\n      InputField,\n    },\n    setup() {\n      const initialValues = {\n        users: ['', '', ''],\n      };\n\n      const schema = z.string().min(1, REQUIRED_MESSAGE);\n\n      return {\n        schema,\n        initialValues,\n      };\n    },\n    template: `\n      <VForm :initial-values=\"initialValues\" v-slot=\"{ errors }\">\n        <FieldArray name=\"users\" v-slot=\"{ remove, push, fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <label :for=\"'name_' + idx\">Name</label>\n            <InputField :name=\"'users[' + idx + ']'\" :rules=\"schema\" />\n\n            <button class=\"remove\" type=\"button\" @click=\"remove(idx)\">X</button>\n          </fieldset>\n        </FieldArray>\n\n\n        <ul class=\"errors\">\n          <li v-for=\"error in errors\">{{ error }}</li>\n        </ul>\n\n        <button class=\"submit\" type=\"submit\">Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const errorList = document.querySelector('ul') as HTMLUListElement;\n  const removeBtnAt = (idx: number) => document.querySelectorAll('.remove')[idx] as HTMLButtonElement; // remove the second item\n\n  await flushPromises();\n  expect(errorList.children).toHaveLength(0);\n  removeBtnAt(1).click();\n  await flushPromises();\n\n  expect(errorList.children).toHaveLength(0);\n});\n\ntest('moves items around the array with move()', async () => {\n  const onSubmit = vi.fn();\n  mountWithHoc({\n    setup() {\n      const initialValues = {\n        users: [{ name: '1' }, { name: '2' }, { name: '3' }, { name: '4' }],\n      };\n\n      return {\n        onSubmit,\n        initialValues,\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\" :initial-values=\"initialValues\">\n        <FieldArray name=\"users\" v-slot=\"{ move, fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <label :for=\"'name_' + idx\">Name</label>\n            <Field :id=\"'name_' + idx\" :name=\"'users[' + idx + '].name'\" />\n            <ErrorMessage :name=\"'users[' + idx + '].name'\" />\n\n            <button class=\"move\" type=\"button\" @click=\"move(idx, 0)\">Move</button>\n          </fieldset>\n        </FieldArray>\n\n        <button class=\"submit\" type=\"submit\">Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const submitBtn = document.querySelector('.submit') as HTMLButtonElement;\n  const inputAt = (idx: number) => (document.querySelectorAll('input') || [])[idx] as HTMLInputElement;\n  const moveElAt = (idx: number) => (document.querySelectorAll('.move') || [])[idx] as HTMLInputElement;\n\n  expect(getValue(inputAt(0))).toBe('1');\n  expect(getValue(inputAt(1))).toBe('2');\n  expect(getValue(inputAt(2))).toBe('3');\n  expect(getValue(inputAt(3))).toBe('4');\n  dispatchEvent(moveElAt(3), 'click');\n  await flushPromises();\n  expect(getValue(inputAt(0))).toBe('4');\n  expect(getValue(inputAt(1))).toBe('1');\n  expect(getValue(inputAt(2))).toBe('2');\n  expect(getValue(inputAt(3))).toBe('3');\n  (submitBtn as HTMLButtonElement).click();\n  await flushPromises();\n  expect(onSubmit).toHaveBeenLastCalledWith(\n    expect.objectContaining({\n      users: [{ name: '4' }, { name: '1' }, { name: '2' }, { name: '3' }],\n    }),\n    expect.anything(),\n  );\n});\n\n// #3782\ntest('removing an item marks the form as dirty', async () => {\n  const onSubmit = vi.fn();\n  mountWithHoc({\n    setup() {\n      const initialValues = {\n        users: [{ name: '1' }, { name: '2' }, { name: '3' }],\n      };\n\n      return {\n        onSubmit,\n        initialValues,\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\" :initial-values=\"initialValues\" v-slot=\"{ meta }\">\n        <FieldArray name=\"users\" v-slot=\"{ remove, fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <label :for=\"'name_' + idx\">Name</label>\n            <Field :id=\"'name_' + idx\" :name=\"'users[' + idx + '].name'\" />\n\n            <button class=\"remove\" type=\"button\" @click=\"remove(idx)\">X</button>\n          </fieldset>\n        </FieldArray>\n\n        <pre>{{ meta.dirty }}</pre>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const getDirtyPre = () => document.querySelector('pre') as HTMLElement;\n  const removeBtnAt = (idx: number) => (document.querySelectorAll('.remove') || [])[idx] as HTMLInputElement;\n\n  await expect(getDirtyPre().textContent).toBe('false');\n  dispatchEvent(removeBtnAt(2), 'click');\n  await flushPromises();\n\n  await expect(getDirtyPre().textContent).toBe('true');\n});\n\ntest('clean up form registration on unmount', async () => {\n  const shown = ref(true);\n  mountWithHoc({\n    setup() {\n      const initialValues = {\n        users: [{ name: '1' }, { name: '2' }, { name: '3' }],\n      };\n\n      return {\n        initialValues,\n        shown,\n      };\n    },\n    template: `\n      <VForm :initial-values=\"initialValues\">\n        <FieldArray v-if=\"shown\" name=\"users\" v-slot=\"{ remove, fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <label :for=\"'name_' + idx\">Name</label>\n            <Field :id=\"'name_' + idx\" :name=\"'users[' + idx + '].name'\" />\n\n          </fieldset>\n        </FieldArray>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  shown.value = false;\n  await flushPromises();\n  expect(1).toBe(1);\n});\n\n// #3874\ntest('adding or removing fields should update form dirty correctly', async () => {\n  mountWithHoc({\n    setup() {\n      const initialValues = {\n        users: [''],\n      };\n\n      return {\n        initialValues,\n      };\n    },\n    template: `\n      <VForm v-slot=\"{ meta }\" :initial-values=\"initialValues\">\n        <FieldArray name=\"users\" v-slot=\"{ remove, fields, push }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <label :for=\"'name_' + idx\">Name</label>\n            <Field :id=\"'name_' + idx\" :name=\"'users[' + idx + ']'\" />\n\n            </fieldset>\n            <button id=\"push\" type=\"button\" @click=\"push('')\"></button>\n            <button id=\"remove\"  type=\"button\"  @click=\"remove(1)\"></button>\n        </FieldArray>\n\n        <pre id=\"dirty\">{{ meta.dirty }}</pre>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const pushBtn = document.querySelector('#push') as HTMLElement;\n  const removeBtn = document.querySelector('#remove') as HTMLElement;\n  const dirty = document.querySelector('#dirty') as HTMLElement;\n\n  expect(dirty?.textContent).toBe('false');\n  pushBtn.click();\n  await flushPromises();\n  expect(dirty.textContent).toBe('true');\n  removeBtn.click();\n  await flushPromises();\n  expect(dirty.textContent).toBe('false');\n});\n\n// #4115\ntest('removing fields with `v-if` should clean up their state properly', async () => {\n  const showFields = ref(true);\n  const formRef = ref<InstanceType<typeof Form>>();\n  const initialValues = {\n    users: [\n      { name: 'test 1', amount: 123 },\n      { name: 'test 2', amount: 567 },\n    ],\n  };\n  mountWithHoc({\n    setup() {\n      return {\n        initialValues,\n        formRef,\n        showFields,\n      };\n    },\n    template: `\n      <VForm ref=\"formRef\" :initial-values=\"initialValues\">\n        <FieldArray name=\"users\" v-slot=\"{ fields }\">\n          <fieldset v-for=\"(field, idx) in fields\" :key=\"field.key\">\n            <legend>User #{{ idx }}</legend>\n            <template v-if=\"showFields\">\n              <Field :name=\"'users[' + idx + '].name'\" />\n              <Field :name=\"'users[' + idx + '].amount'\" />\n            </template>\n          </fieldset>\n        </FieldArray>\n\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  expect(formRef.value?.getValues()).toEqual(initialValues);\n  showFields.value = false;\n  await flushPromises();\n  expect(formRef.value?.getValues()).toEqual({});\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/Form.spec.ts",
    "content": "import { defineRule, Field, Form, useField, useForm, useIsValidating } from '@/vee-validate';\nimport { computed, defineComponent, onErrorCaptured, ref, Ref } from 'vue';\nimport * as z from 'zod';\nimport { InvalidSubmissionContext, PrivateFormContext } from '../src/types';\nimport { dispatchEvent, flushPromises, mountWithHoc, setChecked, setValue } from './helpers';\n\ndescribe('<Form />', () => {\n  const REQUIRED_MESSAGE = `This field is required`;\n  const MIN_MESSAGE = `This field is short`;\n  defineRule('required', (value: unknown) => {\n    if (!value) {\n      return REQUIRED_MESSAGE;\n    }\n\n    return true;\n  });\n  defineRule('min', (value: unknown, args: any[]) => {\n    if (!value || String(value).length <= args[0]) {\n      return MIN_MESSAGE;\n    }\n\n    return true;\n  });\n\n  test('renders the as prop', () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <VForm />\n      </div>\n    `,\n    });\n\n    expect(wrapper.$el.innerHTML).toBe(`<form novalidate=\"\"></form>`);\n  });\n\n  test('observes the current state of providers', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ meta }\">\n        <Field name=\"field\" rules=\"required\" type=\"text\" />\n\n        <span id=\"state\">{{ meta.valid }}</span>\n      </VForm>\n    `,\n    });\n\n    const stateSpan = wrapper.$el.querySelector('#state');\n    const input = wrapper.$el.querySelector('input');\n    setValue(input, '');\n\n    await flushPromises();\n    // initially the field valid flag is false.\n    expect(stateSpan.textContent).toBe('false');\n\n    setValue(input, 'value');\n    await flushPromises();\n\n    expect(stateSpan.textContent).toBe('true');\n  });\n\n  test('submit handler only executes if observer is valid', async () => {\n    let calls = 0;\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          submit() {\n            calls++;\n          },\n        };\n      },\n      template: `\n      <VForm @submit=\"submit\" v-slot=\"{ errors }\">\n        <Field name=\"field\" rules=\"required\" />\n        <span id=\"error\">{{ errors.field }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('input');\n    await flushPromises();\n    expect(error.textContent).toBe('');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(calls).toBe(0);\n\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n    setValue(input, '12');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n\n    expect(error.textContent).toBe('');\n    expect(calls).toBe(1);\n  });\n\n  test('handles reset event', async () => {\n    let isReset = false;\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          reset: () => {\n            isReset = true;\n          },\n        };\n      },\n      template: `\n      <VForm @reset=\"reset\" v-slot=\"{ errors }\">\n        <Field rules=\"required\" name=\"field\" />\n        <span id=\"error\">{{ errors.field }}</span>\n\n        <button id=\"submit\">Validate</button>\n        <button id=\"reset\" type=\"reset\">Reset</button>\n      </VForm>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('input');\n\n    expect(error.textContent).toBe('');\n\n    wrapper.$el.querySelector('#submit').click();\n    await flushPromises();\n\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n\n    setValue(input, 'value');\n    await flushPromises();\n    wrapper.$el.querySelector('#reset').click();\n    await flushPromises();\n\n    // value was reset\n    expect(input.value).toBe('');\n    // errors were cleared\n    expect(error.textContent).toBe('');\n    expect(isReset).toBe(true);\n  });\n\n  test('handles reset with resetForm slot prop', async () => {\n    const resetError = 'Field is wrong';\n    const resetValue = 'I was reset';\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ errors, resetForm, meta, values }\">\n        <Field rules=\"required\" name=\"field\" />\n        <span id=\"error\">{{ errors.field }}</span>\n        <span id=\"dirty\">{{ meta.dirty.toString() }}</span>\n        <span id=\"touched\">{{ meta.touched.toString() }}</span>\n\n        <button id=\"submit\">Validate</button>\n        <button id=\"reset\" type=\"button\" @click=\"resetForm({ values: { field: '${resetValue}' }, errors: { field: '${resetError}' }, touched: { field: true } })\">Reset</button>\n      </VForm>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const input = wrapper.$el.querySelector('input');\n\n    expect(error.textContent).toBe('');\n\n    wrapper.$el.querySelector('#submit').click();\n    await flushPromises();\n\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n\n    setValue(input, 'value');\n    await flushPromises();\n    wrapper.$el.querySelector('#reset').click();\n    await flushPromises();\n\n    // value was reset\n    expect(input.value).toBe(resetValue);\n    // errors were cleared\n    expect(error.textContent).toBe(resetError);\n    expect(wrapper.$el.querySelector('#dirty').textContent).toBe('false');\n    expect(wrapper.$el.querySelector('#touched').textContent).toBe('true');\n  });\n\n  test('initial values can be set with initialValues prop', async () => {\n    const initialValues = {\n      field: 'hello',\n    };\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          initialValues,\n        };\n      },\n      template: `\n      <VForm :initialValues=\"initialValues\">\n        <Field rules=\"required\" name=\"field\" />\n\n        <button id=\"submit\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    const input = wrapper.$el.querySelector('input');\n\n    expect(input.value).toBe(initialValues.field);\n  });\n\n  test('having no submit listener will submit the form natively', async () => {\n    const submitMock = vi.fn();\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ errors }\">\n        <Field name=\"field\" rules=\"required\" />\n        <span id=\"error\">{{ errors.field }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    const form = wrapper.$el;\n    form.submit = submitMock;\n    const input = wrapper.$el.querySelector('input');\n    await flushPromises();\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(submitMock).toHaveBeenCalledTimes(0);\n\n    setValue(input, '12');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n\n    expect(submitMock).toHaveBeenCalledTimes(1);\n  });\n\n  test('can be renderless', async () => {\n    const submitMock = vi.fn();\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <VForm as=\"\" v-slot=\"{ errors, submitForm }\">\n          <form @submit=\"submitForm\">\n            <Field name=\"field\" rules=\"required\" />\n            <span id=\"error\">{{ errors.field }}</span>\n\n            <button>Validate</button>\n          </form>\n        </VForm>\n      </div>\n    `,\n    });\n\n    const form = wrapper.$el.querySelector('form');\n    form.submit = submitMock;\n    const input = wrapper.$el.querySelector('input');\n    await flushPromises();\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(submitMock).toHaveBeenCalledTimes(0);\n\n    setValue(input, '12');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n\n    expect(submitMock).toHaveBeenCalledTimes(1);\n  });\n\n  test('can be renderless with null', async () => {\n    const submitMock = vi.fn();\n    const wrapper = mountWithHoc({\n      template: `\n      <div>\n        <VForm :as=\"null\" v-slot=\"{ errors, submitForm }\">\n          <form @submit=\"submitForm\">\n            <Field name=\"field\" rules=\"required\" />\n            <span id=\"error\">{{ errors.field }}</span>\n\n            <button>Validate</button>\n          </form>\n        </VForm>\n      </div>\n    `,\n    });\n\n    const form = wrapper.$el.querySelector('form');\n    form.submit = submitMock;\n    const input = wrapper.$el.querySelector('input');\n    await flushPromises();\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(submitMock).toHaveBeenCalledTimes(0);\n\n    setValue(input, '12');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n\n    expect(submitMock).toHaveBeenCalledTimes(1);\n  });\n\n  test('validation schema with yup', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          email: z.string().email(),\n          password: z.string().min(8),\n        });\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validationSchema=\"schema\" v-slot=\"{ errors }\">\n        <Field id=\"email\" name=\"email\" />\n        <span id=\"emailErr\">{{ errors.email }}</span>\n\n        <Field id=\"password\" name=\"password\" type=\"password\" />\n        <span id=\"passwordErr\">{{ errors.password }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    const email = wrapper.$el.querySelector('#email');\n    const password = wrapper.$el.querySelector('#password');\n    const emailError = wrapper.$el.querySelector('#emailErr');\n    const passwordError = wrapper.$el.querySelector('#passwordErr');\n\n    wrapper.$el.querySelector('button').click();\n\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('Invalid input: expected string, received undefined');\n    expect(passwordError.textContent).toBe('Invalid input: expected string, received undefined');\n\n    setValue(email, 'hello@');\n    setValue(password, '1234');\n\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('Invalid email address');\n    expect(passwordError.textContent).toBe('Too small: expected string to have >=8 characters');\n\n    setValue(email, 'hello@email.com');\n    setValue(password, '12346789');\n\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('');\n    expect(passwordError.textContent).toBe('');\n  });\n\n  test('validation schema to validate form', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = {\n          field: 'required',\n          other: 'required',\n        };\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validationSchema=\"schema\" v-slot=\"{ errors }\">\n        <Field name=\"field\" />\n        <span id=\"field\">{{ errors.field }}</span>\n\n        <Field name=\"other\" />\n        <span id=\"other\">{{ errors.other }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    const first = wrapper.$el.querySelector('#field');\n    const second = wrapper.$el.querySelector('#other');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n\n    expect(first.textContent).toBe(REQUIRED_MESSAGE);\n    expect(second.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('cross field validation with yup schema', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z\n          .object({\n            password: z.string().min(1, REQUIRED_MESSAGE),\n            confirmation: z.string().min(1, REQUIRED_MESSAGE),\n          })\n          .refine(data => data.password === data.confirmation, {\n            message: 'Passwords must match',\n            path: ['confirmation'],\n          });\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validationSchema=\"schema\" v-slot=\"{ errors }\">\n        <Field id=\"password\" name=\"password\" />\n        <span id=\"field\">{{ errors.password }}</span>\n\n        <Field id=\"confirmation\" name=\"confirmation\" />\n        <span id=\"confirmationError\">{{ errors.confirmation }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    const password = wrapper.$el.querySelector('#password');\n    const confirmation = wrapper.$el.querySelector('#confirmation');\n    const confirmationError = wrapper.$el.querySelector('#confirmationError');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n\n    setValue(password, 'hello@');\n    setValue(confirmation, '1234');\n    await flushPromises();\n    expect(confirmationError.textContent).toBe('Passwords must match');\n\n    setValue(password, '1234');\n    setValue(confirmation, '1234');\n    await flushPromises();\n    expect(confirmationError.textContent).toBe('');\n  });\n\n  test('supports radio inputs', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = {\n          drink: 'required',\n        };\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\" v-slot=\"{ errors }\">\n        <Field name=\"drink\" type=\"radio\" value=\"\" /> Coffee\n        <Field name=\"drink\" type=\"radio\" value=\"Tea\" /> Tea\n        <Field name=\"drink\" type=\"radio\" value=\"Coke\" /> Coke\n\n        <span id=\"err\">{{ errors.drink }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    const err = wrapper.$el.querySelector('#err');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(err.textContent).toBe(REQUIRED_MESSAGE);\n    setChecked(inputs[2]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    setChecked(inputs[0]);\n    await flushPromises();\n    expect(err.textContent).toBe(REQUIRED_MESSAGE);\n\n    setChecked(inputs[1]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n  });\n\n  test('supports radio inputs with check after submit', async () => {\n    const initialValues = { test: 'one' };\n\n    const showFields = ref(true);\n    const result = ref();\n\n    const wrapper = mountWithHoc({\n      setup() {\n        const values = ['one', 'two', 'three'];\n        const onSubmit = (formData: Record<string, any>) => {\n          result.value = formData.test;\n        };\n\n        return {\n          values,\n          onSubmit,\n          initialValues,\n          showFields,\n          result,\n        };\n      },\n      template: `\n      <VForm  @submit=\"onSubmit\"  >\n\n        <label v-for=\"(value, index) in values\" v-bind:key=\"index\">\n          <div v-if=\"showFields\">\n            <Field name=\"test\" type=\"radio\" :value=\"value\" /> {{value}}\n          </div>\n        </label>\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    // const err = wrapper.$el.querySelector('#err');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    setChecked(inputs[1]);\n    await flushPromises();\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    showFields.value = false;\n    await flushPromises();\n    expect(result.value).toBe('two');\n  });\n\n  test('supports radio inputs with check after submit (nested)', async () => {\n    const initialValues = { test: { fieldOne: { option: 'one' } } };\n\n    const showFields = ref(true);\n    const result = ref();\n\n    const wrapper = mountWithHoc({\n      setup() {\n        const values = ['one', 'two', 'three'];\n        const onSubmit = (formData: Record<string, any>) => {\n          result.value = formData.test;\n        };\n\n        return {\n          values,\n          onSubmit,\n          initialValues,\n          showFields,\n          result,\n        };\n      },\n      template: `\n      <VForm  @submit=\"onSubmit\" :initialValues=\"initialValues\" >\n        <label v-for=\"(value, index) in values\" v-bind:key=\"index\">\n          <div v-if=\"showFields\">\n            <Field name=\"test.fieldOne.option\" type=\"radio\" :value=\"value\" /> {{value}}\n          </div>\n        </label>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    // const err = wrapper.$el.querySelector('#err');\n    const inputs = wrapper.$el.querySelectorAll('input');\n    await flushPromises();\n    expect(inputs[0].checked).toBe(true);\n\n    setChecked(inputs[1]);\n    await flushPromises();\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    showFields.value = false;\n    await flushPromises();\n    expect(result.value.fieldOne.option).toBe('two');\n  });\n\n  test('supports checkboxes inputs', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = {\n          drink: 'required',\n        };\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\" v-slot=\"{ errors, values }\">\n        <Field name=\"drink\" type=\"checkbox\" value=\"\" /> Coffee\n        <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" /> Tea\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" /> Coke\n\n        <span id=\"err\">{{ errors.drink }}</span>\n        <span id=\"values\">{{ values.drink && values.drink.toString() }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    const err = wrapper.$el.querySelector('#err');\n    const values = wrapper.$el.querySelector('#values');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(err.textContent).toBe(REQUIRED_MESSAGE);\n    setChecked(inputs[2]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    setChecked(inputs[0]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    setChecked(inputs[1]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    expect(values.textContent).toBe(['Coke', '', 'Tea'].toString());\n\n    setChecked(inputs[1], false);\n    await flushPromises();\n    expect(values.textContent).toBe(['Coke', ''].toString());\n  });\n\n  test('supports a single checkbox', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = {\n          drink: 'required',\n        };\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\" v-slot=\"{ errors, values }\">\n        <Field name=\"drink\" type=\"checkbox\" :value=\"true\" /> Coffee\n\n        <span id=\"err\">{{ errors.drink }}</span>\n        <span id=\"value\">{{ typeof values.drink }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    const err = wrapper.$el.querySelector('#err');\n    const value = wrapper.$el.querySelector('#value');\n    const input = wrapper.$el.querySelector('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(err.textContent).toBe(REQUIRED_MESSAGE);\n    setChecked(input, true);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n    expect(value.textContent).toBe('boolean');\n    setChecked(input, false);\n    await flushPromises();\n    expect(err.textContent).toBe(REQUIRED_MESSAGE);\n    expect(value.textContent).toBe('undefined');\n  });\n\n  test('unmounted fields gets unregistered and their values cleaned up', async () => {\n    const showFields = ref(true);\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = computed(() => ({\n          field: showFields.value ? 'required' : '',\n          drink: 'required',\n        }));\n\n        return {\n          schema,\n          showFields,\n        };\n      },\n      template: `\n      <VForm :validationSchema=\"schema\" v-slot=\"{ errors, values }\">\n        <template v-if=\"showFields\">\n          <Field name=\"field\" />\n          <Field name=\"nested.field\" />\n          <Field name=\"[non-nested.field]\" />\n          <Field name=\"drink\" type=\"checkbox\" value=\"\" /> Coffee\n          <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" /> Tea\n        </template>\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" /> Coke\n\n        <span id=\"errors\">{{ errors }}</span>\n        <span id=\"values\">{{ values }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const errors = wrapper.$el.querySelector('#errors');\n    const values = wrapper.$el.querySelector('#values');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(errors.textContent).toBeTruthy();\n    setChecked(inputs[4]);\n    setChecked(inputs[5]);\n    setValue(inputs[0], 'test');\n    setValue(inputs[1], '12');\n    setValue(inputs[2], '12');\n    await flushPromises();\n    expect(JSON.parse(values.textContent)).toEqual({\n      drink: ['Tea', 'Coke'],\n      field: 'test',\n      'non-nested.field': '12',\n      nested: { field: '12' },\n    });\n\n    showFields.value = false;\n    await flushPromises();\n    expect(errors.textContent).toBe('{}');\n    expect(JSON.parse(values.textContent)).toEqual({ drink: ['Coke'] });\n  });\n\n  test('unmounted fields gets unregistered and submitted values do not include them', async () => {\n    let showFields!: Ref<boolean>;\n    const spy = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        showFields = ref(true);\n\n        return {\n          showFields,\n          onSubmit(values: any) {\n            spy(values);\n          },\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ errors }\">\n        <template v-if=\"showFields\">\n          <Field name=\"field\" rules=\"required\" />\n          <Field name=\"nested.field\" rules=\"required\" />\n          <Field name=\"[non-nested.field]\" rules=\"required\" />\n          <Field name=\"drink\" type=\"checkbox\" value=\"\" rules=\"required\" /> Coffee\n          <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" rules=\"required\" /> Tea\n        </template>\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" rules=\"required\" /> Coke\n\n        <span id=\"errors\">{{ errors }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const errors = wrapper.$el.querySelector('#errors');\n    const button = wrapper.$el.querySelector('button');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(errors.textContent).toBeTruthy();\n    setChecked(inputs[4]);\n    setChecked(inputs[5]);\n    setValue(inputs[0], 'test');\n    setValue(inputs[1], '12');\n    setValue(inputs[2], '12');\n    await flushPromises();\n    button.click();\n    await flushPromises();\n    expect(spy).toHaveBeenLastCalledWith({\n      drink: ['Tea', 'Coke'],\n      field: 'test',\n      'non-nested.field': '12',\n      nested: { field: '12' },\n    });\n\n    showFields.value = false;\n    await flushPromises();\n    expect(errors.textContent).toBe('{}');\n    button.click();\n    await flushPromises();\n    expect(spy).toHaveBeenLastCalledWith({ drink: ['Coke'] });\n  });\n\n  test('unmounted fields gets unregistered and their values are kept if configured on the form level', async () => {\n    const showFields = ref(true);\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = computed(() => ({\n          field: showFields.value ? 'required' : '',\n          drink: 'required',\n        }));\n\n        return {\n          schema,\n          showFields,\n        };\n      },\n      template: `\n      <VForm :validationSchema=\"schema\" v-slot=\"{ errors, values }\" keep-values>\n        <template v-if=\"showFields\">\n          <Field name=\"field\" />\n          <Field name=\"nested.field\" />\n          <Field name=\"[non-nested.field]\" />\n          <Field name=\"drink\" type=\"checkbox\" value=\"\" /> Coffee\n          <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" /> Tea\n        </template>\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" /> Coke\n\n        <span id=\"errors\">{{ errors }}</span>\n        <span id=\"values\">{{ values }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const errors = wrapper.$el.querySelector('#errors');\n    const values = wrapper.$el.querySelector('#values');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(errors.textContent).toBeTruthy();\n    setChecked(inputs[4]);\n    setChecked(inputs[5]);\n    setValue(inputs[0], 'test');\n    setValue(inputs[1], '12');\n    setValue(inputs[2], '12');\n    await flushPromises();\n    const expected = {\n      drink: ['Tea', 'Coke'],\n      field: 'test',\n      'non-nested.field': '12',\n      nested: { field: '12' },\n    };\n    expect(JSON.parse(values.textContent)).toEqual(expected);\n\n    showFields.value = false;\n    await flushPromises();\n    // errors were cleared\n    expect(errors.textContent).toBe('{}');\n    expect(JSON.parse(values.textContent)).toEqual(expected);\n  });\n\n  test('unmounted fields gets unregistered and their submitted values are kept if configured on the form level', async () => {\n    let showFields!: Ref<boolean>;\n    const spy = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        showFields = ref(true);\n\n        return {\n          showFields,\n          onSubmit(values: any) {\n            spy(values);\n          },\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ errors }\" keep-values>\n        <template v-if=\"showFields\">\n          <Field name=\"field\" rules=\"required\" />\n          <Field name=\"nested.field\" rules=\"required\" />\n          <Field name=\"[non-nested.field]\" rules=\"required\" />\n          <Field name=\"drink\" type=\"checkbox\" value=\"\" rules=\"required\" /> Coffee\n          <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" rules=\"required\" /> Tea\n        </template>\n\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" rules=\"required\" /> Coke\n\n        <span id=\"errors\">{{ errors }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const errors = wrapper.$el.querySelector('#errors');\n    const button = wrapper.$el.querySelector('button');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(errors.textContent).toBeTruthy();\n    setChecked(inputs[4]);\n    setChecked(inputs[5]);\n    setValue(inputs[0], 'test');\n    setValue(inputs[1], '12');\n    setValue(inputs[2], '12');\n    await flushPromises();\n    button.click();\n    await flushPromises();\n    const expected = {\n      drink: ['Tea', 'Coke'],\n      field: 'test',\n      'non-nested.field': '12',\n      nested: { field: '12' },\n    };\n    expect(spy).toHaveBeenLastCalledWith(expected);\n\n    showFields.value = false;\n    await flushPromises();\n    expect(errors.textContent).toBe('{}');\n    button.click();\n    await flushPromises();\n    expect(spy).toHaveBeenLastCalledWith(expected);\n  });\n\n  test('unmounted fields gets unregistered and their values are kept if configured on the field level', async () => {\n    const showFields = ref(true);\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = computed(() => ({\n          field: showFields.value ? 'required' : '',\n          drink: 'required',\n        }));\n\n        return {\n          schema,\n          showFields,\n        };\n      },\n      template: `\n      <VForm :validationSchema=\"schema\" v-slot=\"{ errors, values }\">\n        <template v-if=\"showFields\">\n          <Field name=\"field\" />\n          <Field name=\"nested.field\" keep-value />\n          <Field name=\"[non-nested.field]\" keep-value />\n          <Field name=\"drink\" type=\"checkbox\" value=\"\" /> Coffee\n          <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" keep-value /> Tea\n        </template>\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" /> Coke\n\n        <span id=\"errors\">{{ errors }}</span>\n        <span id=\"values\">{{ values }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const errors = wrapper.$el.querySelector('#errors');\n    const values = wrapper.$el.querySelector('#values');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(errors.textContent).toBeTruthy();\n    setChecked(inputs[4]);\n    setChecked(inputs[5]);\n    setValue(inputs[0], 'test');\n    setValue(inputs[1], '12');\n    setValue(inputs[2], '12');\n    await flushPromises();\n    expect(JSON.parse(values.textContent)).toEqual({\n      drink: ['Tea', 'Coke'],\n      field: 'test',\n      'non-nested.field': '12',\n      nested: { field: '12' },\n    });\n\n    showFields.value = false;\n    await flushPromises();\n    // errors were cleared\n    expect(errors.textContent).toBe('{}');\n    expect(JSON.parse(values.textContent)).toEqual({\n      drink: ['Tea', 'Coke'],\n      'non-nested.field': '12',\n      nested: { field: '12' },\n    });\n  });\n\n  test('unmounted fields gets unregistered and their submitted values are kept if configured on the field level', async () => {\n    let showFields!: Ref<boolean>;\n    const spy = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        showFields = ref(true);\n\n        return {\n          showFields,\n          onSubmit(values: any) {\n            spy(values);\n          },\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ errors }\">\n        <template v-if=\"showFields\">\n          <Field name=\"field\" rules=\"required\" />\n          <Field name=\"nested.field\" rules=\"required\" keep-value />\n          <Field name=\"[non-nested.field]\" rules=\"required\" keep-value />\n          <Field name=\"drink\" type=\"checkbox\" value=\"\" rules=\"required\" /> Coffee\n          <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" rules=\"required\" keep-value /> Tea\n        </template>\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" rules=\"required\" /> Coke\n\n        <span id=\"errors\">{{ errors }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const errors = wrapper.$el.querySelector('#errors');\n    const button = wrapper.$el.querySelector('button');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(errors.textContent).toBeTruthy();\n    setChecked(inputs[4]);\n    setChecked(inputs[5]);\n    setValue(inputs[0], 'test');\n    setValue(inputs[1], '12');\n    setValue(inputs[2], '12');\n    await flushPromises();\n    button.click();\n    await flushPromises();\n    expect(spy).toHaveBeenLastCalledWith({\n      drink: ['Tea', 'Coke'],\n      field: 'test',\n      'non-nested.field': '12',\n      nested: { field: '12' },\n    });\n\n    showFields.value = false;\n    await flushPromises();\n    expect(errors.textContent).toBe('{}');\n    button.click();\n    await flushPromises();\n    expect(spy).toHaveBeenLastCalledWith({\n      drink: ['Tea', 'Coke'],\n      'non-nested.field': '12',\n      nested: { field: '12' },\n    });\n  });\n\n  test('can specify which fields get their value kept with field setting priority', async () => {\n    const showFields = ref(true);\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = computed(() => ({\n          field: showFields.value ? 'required' : '',\n          drink: 'required',\n        }));\n\n        return {\n          schema,\n          showFields,\n        };\n      },\n      template: `\n      <VForm :validationSchema=\"schema\" v-slot=\"{ errors, values }\" keep-values>\n        <template v-if=\"showFields\">\n          <Field name=\"field\" />\n          <Field name=\"nested.field\" :keep-value=\"false\" />\n          <Field name=\"[non-nested.field]\" :keep-value=\"false\" />\n          <Field name=\"drink\" type=\"checkbox\" value=\"\" /> Coffee\n          <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" :keep-value=\"false\" /> Tea\n          <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" /> Coke\n        </template>\n\n        <span id=\"errors\">{{ errors }}</span>\n        <span id=\"values\">{{ values }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const errors = wrapper.$el.querySelector('#errors');\n    const values = wrapper.$el.querySelector('#values');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(errors.textContent).toBeTruthy();\n    setChecked(inputs[4]);\n    setChecked(inputs[5]);\n    setValue(inputs[0], 'test');\n    setValue(inputs[1], '12');\n    setValue(inputs[2], '12');\n    await flushPromises();\n    expect(JSON.parse(values.textContent)).toEqual({\n      drink: ['Tea', 'Coke'],\n      field: 'test',\n      'non-nested.field': '12',\n      nested: { field: '12' },\n    });\n\n    showFields.value = false;\n    await flushPromises();\n    // errors were cleared\n    expect(errors.textContent).toBe('{}');\n    expect(JSON.parse(values.textContent)).toEqual({\n      drink: ['Coke'],\n      field: 'test',\n    });\n  });\n\n  test('checkboxes with zod schema', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          drink: z.array(z.string()).min(1),\n        });\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\" v-slot=\"{ errors, values }\">\n        <Field name=\"drink\" type=\"checkbox\" value=\"\" /> Coffee\n        <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" /> Tea\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" /> Coke\n\n        <span id=\"err\">{{ errors.drink }}</span>\n        <span id=\"values\">{{ values.drink && values.drink.toString() }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    const err = wrapper.$el.querySelector('#err');\n    const values = wrapper.$el.querySelector('#values');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(err.textContent).toBe('Invalid input: expected array, received undefined');\n    setChecked(inputs[2]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    setChecked(inputs[0]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    setChecked(inputs[1]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    expect(values.textContent).toBe(['Coke', '', 'Tea'].toString());\n\n    setChecked(inputs[1], false);\n    await flushPromises();\n    expect(values.textContent).toBe(['Coke', ''].toString());\n  });\n\n  test('checkboxes with object values', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          drink: z.array(z.any()).min(1),\n        });\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\" v-slot=\"{ errors, values }\">\n        <Field name=\"drink\" type=\"checkbox\" :value=\"{ id: '' }\" /> Coffee\n        <Field name=\"drink\" type=\"checkbox\" :value=\"{ id: 'tea' }\" /> Tea\n        <Field name=\"drink\" type=\"checkbox\" :value=\"{ id: 'coke' }\" /> Coke\n\n        <span id=\"err\">{{ errors.drink }}</span>\n        <span id=\"values\">{{ JSON.stringify(values.drink) }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    const err = wrapper.$el.querySelector('#err');\n    const values = wrapper.$el.querySelector('#values');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(err.textContent).toBe('Invalid input: expected array, received undefined');\n    setChecked(inputs[2]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    setChecked(inputs[0]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    setChecked(inputs[1]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n\n    expect(values.textContent).toBe(JSON.stringify([{ id: 'coke' }, { id: '' }, { id: 'tea' }]));\n\n    setChecked(inputs[1], false);\n    await flushPromises();\n    expect(values.textContent).toBe(JSON.stringify([{ id: 'coke' }, { id: '' }]));\n  });\n\n  test('checkboxes v-model value syncing', async () => {\n    const drinks = ref<string[]>([]);\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          drink: z.array(z.string()).min(1),\n        });\n\n        return {\n          schema,\n          drinks,\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\" v-slot=\"{ errors, values }\">\n        <Field v-model=\"drinks\" name=\"drink\" type=\"checkbox\" value=\"\" validateOnModelUpdate /> Coffee\n        <Field v-model=\"drinks\" name=\"drink\" type=\"checkbox\" value=\"Tea\" validateOnModelUpdate /> Tea\n        <Field v-model=\"drinks\" name=\"drink\" type=\"checkbox\" value=\"Coke\" validateOnModelUpdate /> Coke\n\n        <span id=\"err\">{{ errors.drink }}</span>\n        <span id=\"values\">{{ values.drink && values.drink.toString() }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    const err = wrapper.$el.querySelector('#err');\n    const values = wrapper.$el.querySelector('#values');\n    const inputs = wrapper.$el.querySelectorAll('input');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(err.textContent).toBe('Too small: expected array to have >=1 items');\n    setChecked(inputs[1]);\n    await flushPromises();\n    expect(err.textContent).toBe('');\n    expect(drinks.value).toEqual(['Tea']);\n\n    drinks.value = [];\n    await flushPromises();\n    expect(err.textContent).toBe('Too small: expected array to have >=1 items');\n    expect(values.textContent).toBe('');\n\n    drinks.value = ['Coke'];\n    await flushPromises();\n    expect(err.textContent).toBe('');\n    expect(values.textContent).toBe(['Coke'].toString());\n  });\n\n  test('isSubmitting state', async () => {\n    let throws = false;\n    const wrapper = mountWithHoc({\n      setup() {\n        onErrorCaptured(() => false);\n        return {\n          onSubmit() {\n            return new Promise((resolve, reject) => {\n              if (throws) {\n                setTimeout(() => {\n                  reject(new Error('Sorry'));\n                }, 500);\n                return;\n              }\n\n              setTimeout(resolve, 1000);\n            });\n          },\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ isSubmitting }\">\n\n        <button id=\"submit\">Submit</button>\n        <span id=\"submitting\">{{ isSubmitting }}</span>\n      </VForm>\n    `,\n    });\n\n    const submit = wrapper.$el.querySelector('#submit');\n    const submitting = wrapper.$el.querySelector('#submitting');\n    submit.click();\n    await flushPromises();\n    expect(submitting.textContent).toBe('true');\n    vi.advanceTimersByTime(1001);\n    await flushPromises();\n    expect(submitting.textContent).toBe('false');\n\n    throws = true;\n    submit.click();\n    await flushPromises();\n    expect(submitting.textContent).toBe('true');\n    vi.advanceTimersByTime(501);\n    await flushPromises();\n    expect(submitting.textContent).toBe('false');\n  });\n\n  test('isValidating state', async () => {\n    const spy = vi.fn((isValidating: boolean) => isValidating);\n\n    const Input = defineComponent({\n      components: {\n        Field,\n      },\n      template: `<Field name=\"field\" />`,\n      setup() {\n        const isValidating = useIsValidating();\n\n        useField('field', () => {\n          spy(isValidating.value);\n          return true;\n        });\n      },\n    });\n    const wrapper = mountWithHoc({\n      components: {\n        Input,\n      },\n      template: `\n      <VForm v-slot=\"{ validate }\">\n        <Input />\n        <button @click=\"validate\">Validate</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const button = wrapper.$el.querySelector('button');\n    button.click();\n\n    await flushPromises();\n    expect(spy).toHaveLastReturnedWith(true);\n  });\n\n  test('aggregated meta reactivity', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ meta }\">\n        <Field name=\"field\" rules=\"required\"  />\n\n        <button :disabled=\"!meta.valid\" id=\"submit\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    const submitBtn = wrapper.$el.querySelector('#submit');\n    const input = wrapper.$el.querySelector('input');\n    await flushPromises();\n    expect(submitBtn.disabled).toBe(true);\n    setValue(input, '12');\n    await flushPromises();\n    expect(submitBtn.disabled).toBe(false);\n  });\n\n  test('nested object fields', async () => {\n    const fn = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          onSubmit(values: any) {\n            fn(values);\n          },\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ values }\">\n        <Field name=\"user.name\" rules=\"required\"  />\n        <Field name=\"user.addresses.0\" id=\"address\" rules=\"required\"  />\n        <pre>{{ values }}</pre>\n\n        <button id=\"submit\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    const submitBtn = wrapper.$el.querySelector('#submit');\n    const name = wrapper.$el.querySelector('input');\n    const address = wrapper.$el.querySelector('#address');\n    const pre = wrapper.$el.querySelector('pre');\n    setValue(name, '12');\n    setValue(address, 'abc');\n    await flushPromises();\n    expect(pre.textContent).toBe(JSON.stringify({ user: { name: '12', addresses: ['abc'] } }, null, 2));\n    submitBtn.click();\n    await flushPromises();\n    expect(fn).toHaveBeenCalledWith({ user: { name: '12', addresses: ['abc'] } });\n  });\n\n  test('nested object fields validation with yup nested objects', async () => {\n    const fn = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          schema: z.object({\n            user: z.object({\n              name: z.string().min(1, REQUIRED_MESSAGE),\n              addresses: z.array(z.string().min(3, REQUIRED_MESSAGE)).min(1, REQUIRED_MESSAGE),\n            }),\n          }),\n          onSubmit(values: any) {\n            fn(values);\n          },\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ errors }\" :validation-schema=\"schema\">\n        <Field name=\"user.name\" />\n        <span id=\"nameErr\">{{ errors['user.name'] }}</span>\n        <Field name=\"user.addresses[0]\" id=\"address\" />\n        <span id=\"addrErr\">{{ errors['user.addresses[0]'] }}</span>\n\n        <button id=\"submit\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    const submitBtn = wrapper.$el.querySelector('#submit');\n    const name = wrapper.$el.querySelector('input');\n    const nameErr = wrapper.$el.querySelector('#nameErr');\n    const address = wrapper.$el.querySelector('#address');\n    const addrErr = wrapper.$el.querySelector('#addrErr');\n    submitBtn.click();\n    await flushPromises();\n\n    expect(fn).not.toHaveBeenCalled();\n    expect(nameErr.textContent).toBeTruthy();\n    expect(addrErr.textContent).toBeTruthy();\n    setValue(name, '12');\n    setValue(address, 'abc');\n    await flushPromises();\n    expect(nameErr.textContent).toBe('');\n    expect(addrErr.textContent).toBe('');\n    submitBtn.click();\n    await flushPromises();\n\n    expect(fn).toHaveBeenCalledWith({ user: { name: '12', addresses: ['abc'] } });\n  });\n\n  test('can opt out of nested object fields', async () => {\n    const fn = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          onSubmit(values: any) {\n            fn(values);\n          },\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ values }\">\n        <Field name=\"[user.name]\" rules=\"required\"  />\n        <Field name=\"[user.addresses.0]\" id=\"address\" rules=\"required\"  />\n        <pre>{{ values }}</pre>\n\n        <button id=\"submit\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    const submitBtn = wrapper.$el.querySelector('#submit');\n    const name = wrapper.$el.querySelector('input');\n    const address = wrapper.$el.querySelector('#address');\n    const pre = wrapper.$el.querySelector('pre');\n    setValue(name, '12');\n    setValue(address, 'abc');\n    await flushPromises();\n    expect(pre.textContent).toBe(JSON.stringify({ 'user.name': '12', 'user.addresses.0': 'abc' }, null, 2));\n    submitBtn.click();\n    await flushPromises();\n    expect(fn).toHaveBeenCalledWith({ 'user.name': '12', 'user.addresses.0': 'abc' });\n  });\n\n  test('validate fields on mount with validateOnMount = true', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          email: z.string().email(),\n          password: z.string().min(8),\n        });\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validationSchema=\"schema\" validateOnMount v-slot=\"{ errors }\">\n        <Field id=\"email\" name=\"email\" />\n        <span id=\"emailErr\">{{ errors.email }}</span>\n\n        <Field id=\"password\" name=\"password\" type=\"password\" />\n        <span id=\"passwordErr\">{{ errors.password }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n\n    const emailError = wrapper.$el.querySelector('#emailErr');\n    const passwordError = wrapper.$el.querySelector('#passwordErr');\n\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('Invalid input: expected string, received undefined');\n    expect(passwordError.textContent).toBe('Invalid input: expected string, received undefined');\n  });\n\n  test('sets individual field error message with setFieldError()', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm ref=\"form\" v-slot=\"{ errors }\">\n        <Field id=\"email\" name=\"email\" />\n        <span id=\"emailErr\">{{ errors.email }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const emailError = wrapper.$el.querySelector('#emailErr');\n    (wrapper.$refs as any)?.form.setFieldError('email', 'WRONG');\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('WRONG');\n  });\n\n  test('sets multiple field error messages with setErrors()', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm ref=\"form\" v-slot=\"{ errors }\">\n        <Field id=\"email\" name=\"email\" />\n        <span id=\"emailErr\">{{ errors.email }}</span>\n\n        <Field id=\"password\" name=\"password\" type=\"password\" />\n        <span id=\"passwordErr\">{{ errors.password }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const emailError = wrapper.$el.querySelector('#emailErr');\n    const passwordError = wrapper.$el.querySelector('#passwordErr');\n\n    (wrapper.$refs as any)?.form.setErrors({\n      email: 'WRONG',\n      password: 'WRONG AGAIN',\n    });\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('WRONG');\n    expect(passwordError.textContent).toBe('WRONG AGAIN');\n  });\n\n  test('sets error message with setFieldError for checkboxes', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm ref=\"form\" v-slot=\"{ errors }\">\n        <Field name=\"drink\" type=\"checkbox\" value=\"\" /> Coffee\n        <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" /> Tea\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" /> Coke\n\n        <span id=\"err\">{{ errors.drink }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const error = wrapper.$el.querySelector('#err');\n    (wrapper.$refs as any)?.form.setFieldError('drink', 'WRONG');\n    await flushPromises();\n    expect(error.textContent).toBe('WRONG');\n  });\n\n  test('sets individual field value with setFieldValue()', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm ref=\"form\">\n        <Field id=\"email\" name=\"email\" />\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const value = 'example@gmail.com';\n    const email = wrapper.$el.querySelector('#email');\n    (wrapper.$refs as any)?.form.setFieldValue('email', value);\n    await flushPromises();\n    expect(email.value).toBe(value);\n  });\n\n  test('sets multiple fields values with setValues()', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm ref=\"form\">\n        <Field id=\"email\" name=\"email\" />\n        <Field id=\"password\" name=\"password\" />\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const values = {\n      email: 'example@gmail.com',\n      password: '12345',\n    };\n    const inputs = wrapper.$el.querySelectorAll('input');\n    (wrapper.$refs as any)?.form.setValues(values);\n    await flushPromises();\n    expect(inputs[0].value).toBe(values.email);\n    expect(inputs[1].value).toBe(values.password);\n  });\n\n  test('sets non-plain object field with setValues()', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm ref=\"form\">\n        <Field id=\"nonPlain\" name=\"nonPlain\" />\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n\n    class NonPlain {\n      field = 5;\n    }\n    const nonPlain = new NonPlain();\n    (wrapper.$refs as any)?.form.setValues({\n      nonPlain,\n    });\n\n    const realValues = (wrapper.$refs as any).form.getValues();\n    await flushPromises();\n    expect(realValues.nonPlain).toBeInstanceOf(NonPlain);\n    expect(realValues.nonPlain).toStrictEqual(nonPlain);\n  });\n\n  test('handles submit with handleSubmit and passing the event object', async () => {\n    const spy = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          email: z.string().email(),\n          password: z.string().min(8),\n        });\n\n        return {\n          schema,\n          onSubmit: spy,\n        };\n      },\n      template: `\n      <VForm as=\"div\" :validationSchema=\"schema\" v-slot=\"{ errors, handleSubmit }\">\n        <form @submit=\"handleSubmit($event, onSubmit)\">\n          <Field id=\"email\" name=\"email\" />\n          <span id=\"emailErr\">{{ errors.email }}</span>\n\n          <Field id=\"password\" name=\"password\" type=\"password\" />\n          <span id=\"passwordErr\">{{ errors.password }}</span>\n\n          <button>Validate</button>\n        </form>\n      </VForm>\n    `,\n    });\n\n    const email = wrapper.$el.querySelector('#email');\n    const password = wrapper.$el.querySelector('#password');\n    const emailError = wrapper.$el.querySelector('#emailErr');\n    const passwordError = wrapper.$el.querySelector('#passwordErr');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('Invalid input: expected string, received undefined');\n    expect(passwordError.textContent).toBe('Invalid input: expected string, received undefined');\n    expect(spy).toHaveBeenCalledTimes(0);\n\n    setValue(email, 'hello@email.com');\n    setValue(password, '12346789');\n    wrapper.$el.querySelector('button').click();\n\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('');\n    expect(passwordError.textContent).toBe('');\n    expect(spy).toHaveBeenCalledTimes(1);\n  });\n\n  test('handles submit with handleSubmit without the event object', async () => {\n    const spy = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          email: z.string().email(),\n          password: z.string().min(8),\n        });\n\n        return {\n          schema,\n          onSubmit: spy,\n        };\n      },\n      template: `\n      <VForm as=\"div\" :validationSchema=\"schema\" v-slot=\"{ errors, handleSubmit }\">\n        <form @submit.prevent.stop=\"handleSubmit(onSubmit)\">\n          <Field id=\"email\" name=\"email\" />\n          <span id=\"emailErr\">{{ errors.email }}</span>\n\n          <Field id=\"password\" name=\"password\" type=\"password\" />\n          <span id=\"passwordErr\">{{ errors.password }}</span>\n\n          <button>Validate</button>\n        </form>\n      </VForm>\n    `,\n    });\n\n    const email = wrapper.$el.querySelector('#email');\n    const password = wrapper.$el.querySelector('#password');\n    const emailError = wrapper.$el.querySelector('#emailErr');\n    const passwordError = wrapper.$el.querySelector('#passwordErr');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('Invalid input: expected string, received undefined');\n    expect(passwordError.textContent).toBe('Invalid input: expected string, received undefined');\n    expect(spy).toHaveBeenCalledTimes(0);\n\n    setValue(email, 'hello@email.com');\n    setValue(password, '12346789');\n    wrapper.$el.querySelector('button').click();\n\n    await flushPromises();\n\n    expect(emailError.textContent).toBe('');\n    expect(passwordError.textContent).toBe('');\n    expect(spy).toHaveBeenCalledTimes(1);\n  });\n\n  test('sets meta touched with setFieldTouched for checkboxes', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm ref=\"form\" v-slot=\"{ meta }\">\n        <Field name=\"drink\" type=\"checkbox\" value=\"\" /> Coffee\n        <Field name=\"drink\" type=\"checkbox\" value=\"Tea\" /> Tea\n        <Field name=\"drink\" type=\"checkbox\" value=\"Coke\" /> Coke\n\n        <span id=\"meta\">{{ meta.touched }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const meta = wrapper.$el.querySelector('#meta');\n    expect(meta?.textContent).toBe('false');\n    (wrapper.$refs as any)?.form.setFieldTouched('drink', true);\n    await flushPromises();\n    expect(meta?.textContent).toBe('true');\n  });\n\n  test('sets initial errors with initialErrors', async () => {\n    const errors = {\n      password: 'too short',\n      email: 'wrong',\n    };\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          errors,\n        };\n      },\n      template: `\n      <VForm ref=\"form\" :initial-errors=\"errors\">\n        <Field id=\"email\" name=\"email\" />\n        <ErrorMessage name=\"email\" />\n        <Field id=\"password\" name=\"password\" />\n        <ErrorMessage name=\"password\" />\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const errorEls = wrapper.$el.querySelectorAll('span');\n    await flushPromises();\n    expect(errorEls[0].textContent).toBe(errors.email);\n    expect(errorEls[1].textContent).toBe(errors.password);\n  });\n\n  test('sets touched with initial touched', async () => {\n    const touched = {\n      email: true,\n    };\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          touched,\n        };\n      },\n      template: `\n      <VForm ref=\"form\" :initial-touched=\"touched\">\n        <Field id=\"email\" name=\"email\"  v-slot=\"{ meta, field }\">\n          <input v-bind=\"field\" />\n          <span>{{ meta.touched }}</span>\n        </Field>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const meta = wrapper.$el.querySelector('span');\n    await flushPromises();\n    expect(meta.textContent).toBe('true');\n  });\n\n  test('counts the number of submission attempts', async () => {\n    const spy = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          onSubmit: spy,\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ submitCount }\">\n        <Field id=\"email\" name=\"email\" />\n        <span>{{ submitCount }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const countSpan = wrapper.$el.querySelector('span');\n    expect(countSpan.textContent).toBe('0');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(countSpan.textContent).toBe('1');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(countSpan.textContent).toBe('2');\n    expect(spy).toHaveReturnedTimes(2);\n  });\n\n  test('can reset the submit count to whatever value with resetForm', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          onSubmit: vi.fn(),\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ submitCount, resetForm }\">\n        <Field id=\"email\" name=\"email\" />\n        <span>{{ submitCount }}</span>\n\n        <button>Submit</button>\n        <button type=\"button\" id=\"reset\" @click=\"resetForm({ submitCount: 5 })\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const countSpan = wrapper.$el.querySelector('span');\n    expect(countSpan.textContent).toBe('0');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(countSpan.textContent).toBe('1');\n    wrapper.$el.querySelector('#reset').click();\n    await flushPromises();\n    expect(countSpan.textContent).toBe('5');\n  });\n\n  // #3084\n  test('reset should not toggle the checkbox values', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm>\n        <Field name=\"field\" type=\"checkbox\" :value=\"true\" />\n\n        <button type=\"reset\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const input = wrapper.$el.querySelector('input');\n    const btn = wrapper.$el.querySelector('button');\n    setChecked(input, true);\n    await flushPromises();\n    btn.click();\n    await flushPromises();\n    expect(input.checked).toBe(false);\n\n    btn.click();\n    await flushPromises();\n    expect(input.checked).toBe(false);\n  });\n\n  // #3166\n  test('fields replacing others with the same name should have their value set correctly', async () => {\n    const data = [\n      {\n        id: 1,\n        title: 'this is a test no 1',\n      },\n      {\n        id: 2,\n        title: 'this is a test no 2',\n      },\n      {\n        id: 3,\n        title: 'this is a test no 3',\n      },\n      {\n        id: 4,\n        title: 'this is a test no 4',\n      },\n    ];\n    let setModified!: (field: { id: number; title: string }) => void;\n    mountWithHoc({\n      setup() {\n        const fields = ref(data);\n        const modified = ref({ id: -1, title: '' });\n        setModified = (item: { id: number; title: string }) => {\n          modified.value = { ...item };\n        };\n\n        return {\n          fields,\n          setModified,\n          modified,\n        };\n      },\n      template: `\n        <VForm>\n          <ul>\n            <li v-for=\"field in fields\" :key=\"field.id\">\n              <Field v-if=\"modified.id === field.id\" name=\"test\" v-model=\"modified.title\" type=\"text\" />\n            </li>\n          </ul>\n        </VForm>\n    `,\n    });\n\n    await flushPromises();\n\n    const input = () => document.querySelector('input');\n    setModified(data[3]);\n    await flushPromises();\n    expect(input()?.value).toBe(data[3].title);\n\n    setModified(data[2]);\n    await flushPromises();\n    expect(input()?.value).toBe(data[2].title);\n  });\n\n  test('resetForm should reset the meta flag', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm  v-slot=\"{ meta, resetForm }\">\n        <Field id=\"email\" name=\"email\" rules=\"required\" />\n        <Field id=\"password\" name=\"password\" rules=\"required\" />\n\n        <span id=\"meta\">{{ meta.valid ? 'valid' : 'invalid' }}</span>\n        <button type=\"button\" @click=\"resetForm()\">Reset</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const span = wrapper.$el.querySelector('#meta');\n    const input = wrapper.$el.querySelector('input');\n    expect(span.textContent).toBe('invalid');\n    setValue(input, '');\n    await flushPromises();\n\n    expect(span.textContent).toBe('invalid');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(span.textContent).toBe('invalid');\n  });\n\n  test('resetForm should reset the meta flag based on the errors length', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm :initial-values=\"{ email: '2', password: '3' }\"  v-slot=\"{ meta, resetForm }\">\n        <Field id=\"email\" name=\"email\" rules=\"required\" />\n        <Field id=\"password\" name=\"password\" rules=\"required\" />\n\n        <span id=\"meta\">{{ meta.valid ? 'valid' : 'invalid' }}</span>\n        <button type=\"button\" @click=\"resetForm({ errors: { email: 'bad' } })\">Reset</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const span = wrapper.$el.querySelector('#meta');\n    expect(span.textContent).toBe('valid');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(span.textContent).toBe('invalid');\n  });\n\n  test('valid flag should reflect the accurate form validity', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm  v-slot=\"{ meta, resetForm }\">\n        <Field id=\"email\" name=\"email\" rules=\"required\" />\n        <Field id=\"password\" name=\"password\" rules=\"required\" />\n\n        <span id=\"meta\">{{ meta.valid ? 'valid' : 'invalid' }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const span = wrapper.$el.querySelector('#meta');\n    expect(span.textContent).toBe('invalid');\n\n    const email = wrapper.$el.querySelector('#email');\n    setValue(email, '');\n    await flushPromises();\n    // the email field is invalid\n    expect(span.textContent).toBe('invalid');\n\n    // should be valid now\n    setValue(email, 'example@test.com');\n    await flushPromises();\n    // still invalid because the password is invalid\n    expect(span.textContent).toBe('invalid');\n\n    const password = wrapper.$el.querySelector('#password');\n    setValue(password, '12');\n    await flushPromises();\n    expect(span.textContent).toBe('valid');\n  });\n\n  // #3228\n  test('should not validate touched fields with yup schema if other fields value change', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          email: z.string().min(1, REQUIRED_MESSAGE),\n          password: z.string().min(1, REQUIRED_MESSAGE),\n        });\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\"  v-slot=\"{ errors }\">\n        <Field id=\"email\" name=\"email\" :validate-on-blur=\"false\" />\n        <Field id=\"password\" name=\"password\" :validate-on-blur=\"false\" />\n\n        <span>{{ errors.email }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const span = wrapper.$el.querySelector('span');\n    const email = wrapper.$el.querySelector('#email');\n    const password = wrapper.$el.querySelector('#password');\n    // the field is now blurred\n    dispatchEvent(email, 'blur');\n    await flushPromises();\n    // no error messages for email\n    expect(span.textContent).toBe('');\n\n    // should be valid now\n    setValue(password, '');\n    await flushPromises();\n    // again there should be no error messages for email, only the password\n    expect(span.textContent).toBe('');\n  });\n\n  test('can set multiple field errors on the form level', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ setFieldError }\">\n        <Field name=\"whatever\" v-slot=\"{ field, errors, setErrors }\" rules=\"required\">\n          <input v-bind=\"field\" />\n          <ul>\n            <li v-for=\"error in errors\">{{ error }}</li>\n          </ul>\n          <button type=\"button\" @click=\"setFieldError('whatever', ['bad', 'wrong'])\">Set errors</button>\n        </Field>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const list = document.querySelector('ul');\n    expect(list?.children).toHaveLength(0);\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(list?.children).toHaveLength(2);\n    expect(list?.textContent).toBe('badwrong');\n  });\n\n  test('supports computed yup schemas', async () => {\n    mountWithHoc({\n      setup() {\n        const acceptList = ref(['1', '2']);\n        const schema = computed(() => {\n          return z.object({\n            password: z.string().refine(val => acceptList.value.includes(val), {\n              message: 'not allowed',\n            }),\n          });\n        });\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\" v-slot=\"{ errors }\">\n        <Field name=\"password\" />\n        <span>{{ errors.password }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    expect(document.querySelector('span')?.textContent).toBe('');\n    setValue(input, '3');\n    await flushPromises();\n    // 3 is not allowed yet\n    expect(document.querySelector('span')?.textContent).toBeTruthy();\n    await flushPromises();\n    // field is re-validated\n    setValue(input, '2');\n    await flushPromises();\n\n    expect(document.querySelector('span')?.textContent).toBe('');\n  });\n\n  test('re-validates when a computed yup schema changes', async () => {\n    const acceptList = ref(['1', '2']);\n    function addItem(item: string) {\n      acceptList.value.push(item);\n    }\n\n    mountWithHoc({\n      setup() {\n        const schema = computed(() => {\n          // register dependency\n          acceptList.value.length;\n\n          return z\n            .object({\n              password: z.string(),\n            })\n            .refine(val => acceptList.value.includes(val.password), {\n              message: 'not allowed',\n              path: ['password'],\n            });\n        });\n\n        return {\n          schema,\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\" v-slot=\"{ errors }\">\n        <Field name=\"password\" />\n        <span>{{ errors.password }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    expect(document.querySelector('span')?.textContent).toBe('');\n    setValue(input, '3');\n    await flushPromises();\n    // 3 is not allowed yet\n    expect(document.querySelector('span')?.textContent).toBe('not allowed');\n\n    // field is re-validated automatically\n    addItem('3');\n    await flushPromises();\n    expect(document.querySelector('span')?.textContent).toBe('');\n  });\n\n  test('submitting forms should touch fields', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          onSubmit: vi.fn(),\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ meta }\">\n        <Field id=\"email\" name=\"email\" rules=\"required\" />\n        <Field id=\"password\" name=\"password\" rules=\"required\" v-slot=\"fieldProps\">\n          <input v-bind=\"fieldProps.field\" />\n          <span id=\"fieldMeta\">{{ fieldProps.meta.touched ? 'touched' : 'untouched' }}</span>\n        </Field>\n\n        <span id=\"meta\">{{ meta.touched ? 'touched' : 'untouched' }}</span>\n        <button type=\"submit\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const formMeta = wrapper.$el.querySelector('#meta');\n    const fieldMeta = wrapper.$el.querySelector('#fieldMeta');\n    expect(formMeta.textContent).toBe('untouched');\n    expect(fieldMeta.textContent).toBe('untouched');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(formMeta.textContent).toBe('touched');\n    expect(fieldMeta.textContent).toBe('touched');\n  });\n\n  test('non-rendered fields defined in yup schema are not ignored', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          email: z.string().min(1, REQUIRED_MESSAGE),\n          password: z.string().min(1, REQUIRED_MESSAGE),\n        });\n\n        return {\n          onSubmit: vi.fn(),\n          schema,\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" :validation-schema=\"schema\" v-slot=\"{ errors }\">\n        <Field name=\"email\" />\n        <span id=\"passwordError\">{{ errors.password }}</span>\n\n        <button type=\"submit\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const passwordError = wrapper.$el.querySelector('#passwordError');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(passwordError.textContent).toBeTruthy();\n  });\n\n  test('non-rendered fields defined in schema are not ignored', async () => {\n    const submit = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = {\n          email: 'required',\n          password: 'required',\n        };\n\n        return {\n          onSubmit: submit,\n          schema,\n        };\n      },\n      template: `\n      <VForm @submit=\"onSubmit\" :validation-schema=\"schema\" v-slot=\"{ errors }\">\n        <Field name=\"email\" />\n        <span id=\"passwordError\">{{ errors.password }}</span>\n\n        <button type=\"submit\">Submit</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const passwordError = wrapper.$el.querySelector('#passwordError');\n\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(passwordError.textContent).toBeTruthy();\n    expect(submit).not.toHaveBeenCalled();\n  });\n\n  test('setting errors for non-existing fields creates them as virtual', async () => {\n    const errorMessage = 'bad pw';\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ errors, setFieldError }\">\n        <span id=\"passwordError\">{{ errors.password }}</span>\n        <button type=\"button\" @click=\"setFieldError('password', '${errorMessage}')\">Set error</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const passwordError = wrapper.$el.querySelector('#passwordError');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(passwordError.textContent).toBe(errorMessage);\n  });\n\n  test('setting values for non-existing fields creates them as virtual', async () => {\n    const value = '123';\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ values, setFieldValue }\">\n        <span id=\"passwordValue\">{{ values.password }}</span>\n        <button type=\"button\" @click=\"setFieldValue('password', '${value}')\">Set value</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const passwordValue = wrapper.$el.querySelector('#passwordValue');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(passwordValue.textContent).toBe(value);\n  });\n\n  test('reset virtual fields errors and values', async () => {\n    const errorMessage = 'bad pw';\n    const value = '123';\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ errors, values, setFieldError, setFieldValue, resetForm }\">\n        <span id=\"passwordError\">{{ errors.password }}</span>\n        <span id=\"passwordValue\">{{ values.password }}</span>\n\n        <button id=\"setError\" type=\"button\" @click=\"setFieldError('password', '${errorMessage}')\">Set error</button>\n        <button id=\"setValue\" type=\"button\" @click=\"setFieldValue('password', '${value}')\">Set value</button>\n\n        <button id=\"reset\" type=\"button\" @click=\"resetForm()\">Reset</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const passwordError = wrapper.$el.querySelector('#passwordError');\n    const passwordValue = wrapper.$el.querySelector('#passwordValue');\n    wrapper.$el.querySelector('#setValue').click();\n    await flushPromises();\n    wrapper.$el.querySelector('#setError').click();\n    await flushPromises();\n    expect(passwordError.textContent).toBe(errorMessage);\n    expect(passwordValue.textContent).toBe(value);\n    wrapper.$el.querySelector('#reset').click();\n    await flushPromises();\n    expect(passwordError.textContent).toBe('');\n    expect(passwordValue.textContent).toBe('');\n  });\n\n  test('reset virtual field state to specific value and error', async () => {\n    const errorMessage = 'bad pw';\n    const value = '123';\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ errors, values, resetForm }\">\n        <span id=\"passwordError\">{{ errors.password }}</span>\n        <span id=\"passwordValue\">{{ values.password }}</span>\n        <button id=\"reset\" type=\"button\" @click=\"resetForm({ values: { password: '${value}' }, errors: { password: '${errorMessage}' } })\">Reset</button>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const passwordError = wrapper.$el.querySelector('#passwordError');\n    const passwordValue = wrapper.$el.querySelector('#passwordValue');\n    expect(passwordError.textContent).toBe('');\n    expect(passwordValue.textContent).toBe('');\n    wrapper.$el.querySelector('#reset').click();\n    await flushPromises();\n    expect(passwordError.textContent).toBe(errorMessage);\n    expect(passwordValue.textContent).toBe(value);\n  });\n\n  // #3332\n  test('field bails prop should work with validation schema', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          schema: {\n            fname: 'required|min:3',\n          },\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\">\n        <Field name=\"fname\" :bails=\"false\" v-slot=\"{ field, errors }\">\n          <input type=\"text\" v-bind=\"field\" />\n          <div v-for=\"error in errors\" :key=\"error\" class=\"error\">\n            {{ error }}\n          </div>\n        </Field>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const input = wrapper.$el.querySelector('input');\n    setValue(input, '');\n    await flushPromises();\n    expect(document.querySelectorAll('.error')).toHaveLength(2);\n  });\n\n  // #3342\n  test('field with pre-register errors should be checked on register', async () => {\n    const isShown = ref(false);\n    const modelValue = ref('');\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          isShown,\n          modelValue,\n          schema: {\n            fname: 'required',\n          },\n        };\n      },\n      template: `\n      <VForm :validation-schema=\"schema\" v-slot=\"{ errors }\">\n        <Field v-if=\"isShown\" name=\"fname\" v-model=\"modelValue\" />\n        <span>{{ errors.fname }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const span = wrapper.$el.querySelector('span');\n    expect(span.textContent).toBe(REQUIRED_MESSAGE);\n    modelValue.value = 'hello';\n    isShown.value = true;\n\n    await flushPromises();\n    // field was re-checked\n    expect(span.textContent).toBe('');\n  });\n\n  test('field errors should be removed when its unmounted', async () => {\n    const isShown = ref(true);\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          isShown,\n        };\n      },\n      template: `\n      <VForm v-slot=\"{ errors }\">\n        <Field v-if=\"isShown\" name=\"fname\"  rules=\"required\"/>\n        <span>{{ errors.fname }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const span = wrapper.$el.querySelector('span');\n    setValue(wrapper.$el.querySelector('input'), '');\n    await flushPromises();\n    expect(span.textContent).toBe(REQUIRED_MESSAGE);\n    isShown.value = false;\n\n    await flushPromises();\n    // field was re-checked\n    expect(span.textContent).toBe('');\n  });\n\n  test('uncontrolled fields are excluded from form state', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        return {};\n      },\n      template: `\n      <VForm  v-slot=\"{ errors, meta }\">\n        <Field name=\"fname\" :controlled=\"false\" v-slot=\"{ errorMessage, field }\" rules=\"required\">\n          <input v-bind=\"field\" />\n          <span id=\"fieldError\">{{ errorMessage }}</span>\n        </Field>\n        <span id=\"formError\">{{ errors.fname }}</span>\n        <span id=\"meta\">{{ meta.valid }}</span>\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const formError = wrapper.$el.querySelector('#formError');\n    const fieldError = wrapper.$el.querySelector('#fieldError');\n    const meta = wrapper.$el.querySelector('#meta');\n\n    expect(formError.textContent).toBe('');\n    expect(fieldError.textContent).toBe('');\n    expect(meta.textContent).toBe('true');\n\n    setValue(wrapper.$el.querySelector('input'), '');\n    await flushPromises();\n\n    expect(formError.textContent).toBe('');\n    expect(fieldError.textContent).toBe(REQUIRED_MESSAGE);\n    expect(meta.textContent).toBe('true');\n  });\n\n  // #3424\n  test('Checkbox with v-model should not propagate the empty value symbol', async () => {\n    const value = ref('');\n    mountWithHoc({\n      setup() {\n        return {\n          value,\n        };\n      },\n      template: `\n      <VForm>\n        <Field name=\"check\" type=\"checkbox\" v-model=\"value\" value=\"CHECKED\" />\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    setChecked(input, true);\n    await flushPromises();\n    expect(value.value).toBe('CHECKED');\n\n    setChecked(input, false);\n    await flushPromises();\n\n    expect(value.value).toBe(undefined);\n  });\n\n  // #3429\n  test('Two fields of the same name should not override each other value when either is mounted', async () => {\n    const isHidden = ref(false);\n    const value = ref('');\n    mountWithHoc({\n      setup() {\n        return {\n          value,\n          isHidden,\n        };\n      },\n      template: `\n      <VForm>\n        <Field name=\"name\" type=\"text\" v-model=\"value\" />\n        <Field v-if=\"isHidden\" name=\"name\" type=\"text\" v-model=\"value\" />\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    setValue(input, '1234');\n    await flushPromises();\n    isHidden.value = true;\n    await flushPromises();\n    expect(input.value).toBe(value.value);\n  });\n\n  // #4200\n  test('Falsy model value should still have priority over form value', async () => {\n    const value = ref(0);\n    mountWithHoc({\n      setup() {\n        const initials = { age: 2 };\n        return {\n          value,\n          initials,\n        };\n      },\n      template: `\n      <VForm :initial-values=\"initials\">\n        <Field name=\"age\" type=\"number\" v-model=\"value\" />\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    expect(input.value).toBe('0');\n  });\n\n  test('handles invalid submissions', async () => {\n    const invalidSpy = vi.fn();\n    const validSpy = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          email: z.string().min(1, REQUIRED_MESSAGE).email(),\n          password: z.string().min(1, REQUIRED_MESSAGE),\n        });\n\n        return {\n          schema,\n          onInvalidSubmit: invalidSpy,\n          onSubmit: validSpy,\n        };\n      },\n      template: `\n      <VForm :validationSchema=\"schema\" @invalid-submit=\"onInvalidSubmit\" @submit=\"onSubmit\" v-slot=\"{ errors }\">\n        <Field id=\"email\" name=\"email\" />\n        <span id=\"emailErr\">{{ errors.email }}</span>\n\n        <Field id=\"password\" name=\"password\" type=\"password\" />\n        <span id=\"passwordErr\">{{ errors.password }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n    });\n\n    const expectedEmailError = 'Invalid input: expected string, received undefined';\n    const expectedPasswordError = 'Invalid input: expected string, received undefined';\n    await flushPromises();\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(invalidSpy).toHaveBeenCalledTimes(1);\n    expect(invalidSpy).toHaveBeenLastCalledWith({\n      values: {\n        email: undefined,\n        password: undefined,\n      },\n      errors: {\n        email: expectedEmailError,\n        password: expectedPasswordError,\n      },\n      evt: expect.anything(),\n      results: {\n        email: {\n          valid: false,\n          errors: [expectedEmailError],\n        },\n        password: {\n          valid: false,\n          errors: [expectedPasswordError],\n        },\n      },\n    } as InvalidSubmissionContext);\n    expect(validSpy).not.toHaveBeenCalled();\n  });\n\n  test('handles invalid submissions with submitForm', async () => {\n    const invalidSpy = vi.fn();\n    const validSpy = vi.fn();\n    const wrapper = mountWithHoc({\n      setup() {\n        const schema = z.object({\n          email: z.string().min(1, REQUIRED_MESSAGE).email(),\n          password: z.string().min(1, REQUIRED_MESSAGE),\n        });\n\n        return {\n          schema,\n          onInvalidSubmit: invalidSpy,\n          onSubmit: validSpy,\n        };\n      },\n      template: `\n      <VForm v-slot=\"{ submitForm, errors }\" :validationSchema=\"schema\" @invalid-submit=\"onInvalidSubmit\">\n        <form @submit=\"submitForm\">\n            <Field id=\"email\" name=\"email\" />\n            <span id=\"emailErr\">{{ errors.email }}</span>\n\n            <Field id=\"password\" name=\"password\" type=\"password\" />\n            <span id=\"passwordErr\">{{ errors.password }}</span>\n\n            <button>Submit</button>\n        </form>\n      </VForm>\n    `,\n    });\n\n    const expectedEmailError = 'Invalid input: expected string, received undefined';\n    const expectedPasswordError = 'Invalid input: expected string, received undefined';\n    await flushPromises();\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(invalidSpy).toHaveBeenCalledTimes(1);\n    expect(invalidSpy).toHaveBeenLastCalledWith({\n      values: {\n        email: undefined,\n        password: undefined,\n      },\n      errors: {\n        email: expectedEmailError,\n        password: expectedPasswordError,\n      },\n      evt: expect.anything(),\n      results: {\n        email: {\n          valid: false,\n          errors: [expectedEmailError],\n        },\n        password: {\n          valid: false,\n          errors: [expectedPasswordError],\n        },\n      },\n    } as InvalidSubmissionContext);\n    expect(validSpy).not.toHaveBeenCalled();\n  });\n\n  // #3551\n  test('resets checkboxes according to initial values', async () => {\n    const wrapper = mountWithHoc({\n      setup() {\n        return {\n          values: {\n            terms: true,\n            termsUnslotted: true,\n            array: ['coffee', 'tea'],\n          },\n        };\n      },\n      template: `\n      <VForm v-slot=\"{  resetForm }\" :initial-values=\"values\">\n        <Field v-slot=\"{ field }\" name=\"terms\" type=\"checkbox\" :value=\"true\" :unchecked-value=\"false\">\n          <label>\n            <input type=\"checkbox\" name=\"terms\" v-bind=\"field\" :value=\"true\" :unchecked-value=\"false\" />\n          </label>\n        </Field>\n\n        <Field name=\"termsUnslotted\" type=\"checkbox\" :value=\"true\" :unchecked-value=\"false\"></Field>\n\n        <Field name=\"array\" type=\"checkbox\" value=\"coffee\"></Field>\n        <Field name=\"array\" type=\"checkbox\" value=\"tea\"></Field>\n\n        <button id=\"reset1\" type=\"button\" @click=\"resetForm()\">Reset</button>\n        <button id=\"reset2\" type=\"button\" @click=\"resetForm({ values: { terms: false, termsUnslotted: true, array: ['coffee'] } })\">Reset</button>\n      </VForm>\n    `,\n    });\n\n    const inputAt = (idx: number) => wrapper.$el.querySelectorAll('input')[idx] as HTMLInputElement;\n    expect(inputAt(0).checked).toBe(true);\n    expect(inputAt(1).checked).toBe(true);\n    expect(inputAt(2).checked).toBe(true);\n    expect(inputAt(3).checked).toBe(true);\n\n    dispatchEvent('#reset1', 'click');\n    await flushPromises();\n    expect(inputAt(0).checked).toBe(true);\n    expect(inputAt(1).checked).toBe(true);\n    expect(inputAt(2).checked).toBe(true);\n    expect(inputAt(3).checked).toBe(true);\n\n    dispatchEvent('#reset2', 'click');\n    await flushPromises();\n    expect(inputAt(0).checked).toBe(false);\n    expect(inputAt(1).checked).toBe(true);\n    expect(inputAt(2).checked).toBe(true);\n    expect(inputAt(3).checked).toBe(false);\n  });\n\n  // #3895 #3894\n  test('single checkbox component with v-model in a form', async () => {\n    const value = ref(false);\n    const Checkbox = defineComponent({\n      props: { value: Boolean, modelValue: Boolean },\n      template: `<input type=\"checkbox\" @change=\"handleChange\" :checked=\"checked\" :value=\"true\" />`,\n      setup() {\n        const { handleChange, checked } = useField('field', undefined, {\n          type: 'checkbox',\n          uncheckedValue: false,\n          checkedValue: true,\n          syncVModel: true,\n        });\n\n        return {\n          handleChange,\n          checked,\n        };\n      },\n    });\n    const wrapper = mountWithHoc({\n      components: {\n        Checkbox,\n      },\n      setup() {\n        return {\n          value,\n        };\n      },\n      template: `\n      <VForm>\n        <Checkbox v-model=\"value\" />\n      </VForm>\n    `,\n    });\n\n    await flushPromises();\n    const inputAt = (idx: number) => wrapper.$el.querySelectorAll('input')[idx] as HTMLInputElement;\n    expect(value.value).toBe(false);\n    setChecked(inputAt(0), true);\n    await flushPromises();\n    expect(value.value).toBe(true);\n  });\n\n  test('resets a single field  resetField() to initial state in slot scope props', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ resetField }\">\n        <Field name=\"field\" rules=\"required\" v-slot=\"{ field, errors, meta }\">\n          <input type=\"text\" v-bind=\"field\">\n          <span id=\"error\">{{ errors && errors[0] }}</span>\n          <span id=\"touched\">{{ meta.touched }}</span>\n          <button @click=\"resetField('field')\" type=\"button\">Reset</button>\n        </Field>\n      </VForm>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const touched = wrapper.$el.querySelector('#touched');\n    const input = wrapper.$el.querySelector('input');\n\n    expect(error.textContent).toBe('');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n    setValue(input, '123');\n    dispatchEvent(input, 'blur');\n    await flushPromises();\n    expect(touched.textContent).toBe('true');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(error.textContent).toBe('');\n    expect(input.value).toBe('');\n    expect(touched.textContent).toBe('false');\n  });\n\n  test('resets a single field resetField() to specific state in slot scope props', async () => {\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm v-slot=\"{ resetField }\">\n        <Field name=\"field\" rules=\"required\" v-slot=\"{ field, errors, meta }\">\n          <input type=\"text\" v-bind=\"field\">\n          <span id=\"error\">{{ errors && errors[0] }}</span>\n          <span id=\"touched\">{{ meta.touched }}</span>\n          <button @click=\"resetField('field', { value: 'test', touched: true })\" type=\"button\">Reset</button>\n        </Field>\n      </VForm>\n    `,\n    });\n\n    const error = wrapper.$el.querySelector('#error');\n    const touched = wrapper.$el.querySelector('#touched');\n    const input = wrapper.$el.querySelector('input');\n\n    expect(error.textContent).toBe('');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(error.textContent).toBe(REQUIRED_MESSAGE);\n    setValue(input, '123');\n    dispatchEvent(input, 'blur');\n    await flushPromises();\n    expect(touched.textContent).toBe('true');\n    wrapper.$el.querySelector('button').click();\n    await flushPromises();\n    expect(error.textContent).toBe('');\n    expect(input.value).toBe('test');\n    expect(touched.textContent).toBe('true');\n  });\n\n  test('exposes values and meta with getValues and getMeta exposed APIs', async () => {\n    const formRef = ref<InstanceType<typeof Form>>();\n    const wrapper = mountWithHoc({\n      template: `\n      <VForm ref=\"formRef\">\n        <Field name=\"field\" rules=\"required|min:3\" />\n      </VForm>\n    `,\n      setup() {\n        return {\n          formRef,\n        };\n      },\n    });\n\n    const input = wrapper.$el.querySelector('input');\n    setValue(input, '1');\n    dispatchEvent(input, 'blur');\n    await flushPromises();\n\n    expect(formRef.value?.getValues()).toEqual({ field: '1' });\n    expect(formRef.value?.getMeta()).toEqual({\n      touched: true,\n      dirty: true,\n      valid: false,\n      pending: false,\n      initialValues: {},\n    });\n    expect(formRef.value?.getErrors()).toEqual({ field: MIN_MESSAGE });\n  });\n});\n\n// #3963\ntest('unmounted radio fields gets unregistered and their submitted values are kept if configured on the form level', async () => {\n  let showFields!: Ref<boolean>;\n  const spy = vi.fn();\n  const wrapper = mountWithHoc({\n    setup() {\n      showFields = ref(true);\n\n      return {\n        showFields,\n        onSubmit(values: any) {\n          spy(values);\n        },\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ errors }\" keep-values>\n        <template v-if=\"showFields\">\n          <Field name=\"drink\"  type=\"radio\" value=\"\" rules=\"required\" /> Coffee\n          <Field name=\"drink\"  type=\"radio\" value=\"Tea\" rules=\"required\" /> Tea\n        </template>\n\n        <Field name=\"drink\"  type=\"radio\" value=\"Coke\" rules=\"required\" /> Coke\n\n        <span id=\"errors\">{{ errors }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const errors = wrapper.$el.querySelector('#errors');\n  const button = wrapper.$el.querySelector('button');\n  const inputs = wrapper.$el.querySelectorAll('input');\n\n  wrapper.$el.querySelector('button').click();\n  await flushPromises();\n  expect(errors.textContent).toBeTruthy();\n  setChecked(inputs[1]);\n\n  await flushPromises();\n  button.click();\n  await flushPromises();\n  const expected = {\n    drink: 'Tea',\n  };\n  expect(spy).toHaveBeenLastCalledWith(expected);\n\n  showFields.value = false;\n  await flushPromises();\n  expect(errors.textContent).toBe('{}');\n  button.click();\n  await flushPromises();\n  expect(spy).toHaveBeenLastCalledWith(expected);\n});\n\n// #3963\ntest('unmounted radio fields gets unregistered and their submitted values are removed', async () => {\n  let showFields!: Ref<boolean>;\n  const spy = vi.fn();\n  const wrapper = mountWithHoc({\n    setup() {\n      showFields = ref(true);\n\n      return {\n        showFields,\n        onSubmit(values: any) {\n          spy(values);\n        },\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ errors }\">\n        <template v-if=\"showFields\">\n          <Field name=\"drink\" type=\"radio\" value=\"\" /> Coffee\n          <Field name=\"drink\" type=\"radio\" value=\"Tea\" /> Tea\n        </template>\n\n        <Field name=\"drink\"  type=\"radio\" value=\"Coke\" /> Coke\n\n        <span id=\"errors\">{{ errors }}</span>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const errors = wrapper.$el.querySelector('#errors');\n  const button = wrapper.$el.querySelector('button');\n  const inputs = wrapper.$el.querySelectorAll('input');\n\n  wrapper.$el.querySelector('button').click();\n  await flushPromises();\n  expect(errors.textContent).toBeTruthy();\n  setChecked(inputs[1]);\n\n  await flushPromises();\n  button.click();\n  await flushPromises();\n  expect(spy).toHaveBeenLastCalledWith({ drink: 'Tea' });\n\n  showFields.value = false;\n  await flushPromises();\n  expect(errors.textContent).toBe('{}');\n  button.click();\n  await flushPromises();\n  expect(spy).toHaveBeenLastCalledWith({});\n});\n\n// #3963\ntest('unmounted radio fields gets unregistered and their values are removed if configured on the field level', async () => {\n  const showFields = ref(true);\n\n  const wrapper = mountWithHoc({\n    setup() {\n      return {\n        showFields,\n      };\n    },\n    template: `\n      <VForm v-slot=\"{ errors, values }\" keep-values>\n        <template v-if=\"showFields\">\n          <Field name=\"drink\"  type=\"radio\" value=\"\" rules=\"required\" /> Coffee\n          <Field name=\"drink\"  type=\"radio\" value=\"Tea\" rules=\"required\" :keep-value=\"false\" /> Tea\n        </template>\n\n        <Field name=\"drink\"  type=\"radio\" value=\"Coke\" rules=\"required\" /> Coke\n\n        <span id=\"errors\">{{ errors }}</span>\n        <span id=\"values\">{{ values }}</span>\n\n        <button>Validate</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const errors = wrapper.$el.querySelector('#errors');\n  const values = wrapper.$el.querySelector('#values');\n  const inputs = wrapper.$el.querySelectorAll('input');\n\n  wrapper.$el.querySelector('button').click();\n  await flushPromises();\n  expect(errors.textContent).toBeTruthy();\n  setChecked(inputs[1]);\n\n  await flushPromises();\n  expect(JSON.parse(values.textContent)).toEqual({\n    drink: 'Tea',\n  });\n\n  showFields.value = false;\n  await flushPromises();\n  // errors were cleared\n  expect(errors.textContent).toBe('{}');\n  expect(JSON.parse(values.textContent)).toEqual({});\n});\n\n// #4247\ntest('unmounted fields should not be validated when keep-values is on', async () => {\n  let showFields!: Ref<boolean>;\n  const spy = vi.fn();\n  const wrapper = mountWithHoc({\n    setup() {\n      showFields = ref(true);\n\n      return {\n        showFields,\n        onSubmit(values: any) {\n          spy(values);\n        },\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\" v-slot=\"{ errors }\" keep-values>\n        <template v-if=\"showFields\">\n          <Field name=\"test\" rules=\"required\" />\n        </template>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const button = wrapper.$el.querySelector('button');\n  const inputs = wrapper.$el.querySelectorAll('input');\n\n  wrapper.$el.querySelector('button').click();\n  await flushPromises();\n  setValue(inputs[0], '');\n\n  showFields.value = false;\n  await flushPromises();\n  button.click();\n  await flushPromises();\n  const expected = {\n    test: '',\n  };\n  expect(spy).toHaveBeenLastCalledWith(expected);\n});\n\n// #4308\ntest('radio fields with single field component binding', async () => {\n  const submit = vi.fn();\n  const model = ref('');\n  const wrapper = mountWithHoc({\n    setup() {\n      return {\n        onSubmit: submit,\n        model,\n      };\n    },\n    template: `\n      <VForm @submit=\"onSubmit\">\n        <Field name=\"drink\" type=\"radio\" v-model=\"model\" v-slot=\"{ field }\">\n          <input type=\"radio\" value=\"Coffee\" v-bind=\"field\" />\n          <input type=\"radio\" value=\"Tea\" v-bind=\"field\" />\n        </Field>\n\n        <button>Submit</button>\n      </VForm>\n    `,\n  });\n\n  const inputs = wrapper.$el.querySelectorAll('input');\n  const button = wrapper.$el.querySelector('button');\n\n  wrapper.$el.querySelector('button').click();\n  await flushPromises();\n\n  setChecked(inputs[0]);\n  await flushPromises();\n  button.click();\n  await flushPromises();\n  expect(model.value).toBe('Coffee');\n  expect(submit).toHaveBeenLastCalledWith({ drink: 'Coffee' }, expect.anything());\n  setChecked(inputs[1]);\n  await flushPromises();\n  button.click();\n  await flushPromises();\n  expect(model.value).toBe('Tea');\n  expect(submit).toHaveBeenLastCalledWith({ drink: 'Tea' }, expect.anything());\n});\n\n// #4643\ntest('removes proper pathState when field is unmounting', async () => {\n  const renderTemplateField = ref(false);\n  let form!: PrivateFormContext;\n\n  mountWithHoc({\n    template: `\n      <form>\n        <Field v-if=\"renderTemplateField\" name=\"foo\" rules=\"required\" />\n      </form>\n    `,\n    setup() {\n      form = useForm() as unknown as PrivateFormContext;\n      useField('foo');\n      return { renderTemplateField };\n    },\n  });\n\n  expect(form.meta.value.valid).toBe(true);\n  expect(form.getAllPathStates()).toMatchObject([{ id: 0, path: 'foo' }]);\n\n  renderTemplateField.value = true;\n  await flushPromises();\n\n  expect(form.meta.value.valid).toBe(false);\n  expect(form.getAllPathStates()).toMatchObject([\n    { id: 0, path: 'foo' },\n    { id: 1, path: 'foo' },\n  ]);\n\n  renderTemplateField.value = false;\n  await flushPromises();\n\n  expect(form.meta.value.valid).toBe(true);\n  expect(form.getAllPathStates()).toMatchObject([{ id: 0, path: 'foo' }]);\n});\n\ntest('handles onSubmit with generic object from zod schema', async () => {\n  const schema = z.object({\n    email: z.string().email(),\n    password: z.string().min(8),\n  });\n\n  type FormValues = z.infer<typeof schema>;\n\n  const submitSpy = vi.fn((values: FormValues) => {\n    void values.email;\n    void values.password;\n  });\n\n  mountWithHoc({\n    setup() {\n      return {\n        schema,\n        onSubmit: submitSpy,\n      };\n    },\n    template: `\n      <VForm :validation-schema=\"schema\" @submit=\"onSubmit\">\n        <Field name=\"email\" type=\"email\" />\n        <Field name=\"password\" type=\"password\" />\n        <button>Submit</button>\n      </VForm>\n    `,\n  });\n\n  await flushPromises();\n  const email = document.querySelector('input[type=\"email\"]') as HTMLInputElement;\n  const password = document.querySelector('input[type=\"password\"]') as HTMLInputElement;\n\n  setValue(email, 'test@example.com');\n  setValue(password, 'password123');\n\n  document.querySelector('button')?.click();\n  await flushPromises();\n\n  expect(submitSpy).toHaveBeenCalledWith(\n    {\n      email: 'test@example.com',\n      password: 'password123',\n    },\n    expect.anything(),\n  );\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/define.spec.ts",
    "content": "import { defineRule, validate } from '@/vee-validate';\n\ntest('passing a non-function as the validate method will throw', () => {\n  expect(() => {\n    defineRule('noFn', '' as unknown as (value: any) => boolean);\n  }).toThrow();\n});\n\ntest('define global validations using string ids', async () => {\n  defineRule('test-direct', (value, _, { field }) => {\n    if (value === '1') {\n      return 'Cannot be 1';\n    }\n\n    if (value === '2') {\n      return `${field} Cannot be 2`;\n    }\n\n    return true;\n  });\n\n  let result = await validate('1', 'test-direct');\n  expect(result.errors[0]).toBe('Cannot be 1');\n\n  result = await validate('2', 'test-direct', { name: 'test' });\n  expect(result.errors[0]).toBe('test Cannot be 2');\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/helpers/ModelComp.ts",
    "content": "export const ModelComp = {\n  props: ['modelValue', 'name', 'test'],\n  emits: ['blur', 'update:modelValue'],\n  inheritAttrs: false,\n  template: `<input type=\"text\" :name=\"name\" :value=\"modelValue\" @input=\"$emit('update:modelValue', $event.target.value)\" @blur=\"$emit('blur')\">\n  <div v-if=\"test\">{{ test }}</div>`,\n};\n\nexport const CustomModelComp = {\n  props: ['value', 'name', 'test'],\n  emits: ['blur', 'update:value'],\n  inheritAttrs: false,\n  template: `<input type=\"text\" :name=\"name\" :value=\"value\" @input=\"$emit('update:value', $event.target.value)\" @blur=\"$emit('blur')\">\n  <div v-if=\"test\">{{ test }}</div>`,\n};\n"
  },
  {
    "path": "packages/vee-validate/tests/helpers/index.ts",
    "content": "import { createApp, ComponentPublicInstance } from 'vue';\nimport flushP from 'flush-promises';\nimport { Field, Form, ErrorMessage, FieldArray } from '@/vee-validate';\n\nexport function mount(component: Record<string, any>) {\n  const app = createApp(component);\n  // app.config.devtools = false;\n\n  document.body.innerHTML = `<div id=\"app\"></div>`;\n\n  const vm = app.mount('#app');\n\n  return vm;\n}\n\nexport function mountWithHoc(component: Record<string, any>) {\n  component.components = {\n    ...(component.components || {}),\n    Field,\n    VForm: Form,\n    ErrorMessage,\n    FieldArray,\n  };\n\n  return mount(component);\n}\n\nconst HTML_TAGS = ['INPUT', 'SELECT'];\n\nexport function setValue(node: ComponentPublicInstance | HTMLInputElement, value: any) {\n  if (HTML_TAGS.includes((node as any).tagName)) {\n    const input = node as HTMLInputElement;\n    input.value = value;\n    input.dispatchEvent(new window.Event('input'));\n    input.dispatchEvent(new window.Event('change'));\n    return;\n  }\n\n  (node as any).$emit('input', value);\n}\n\nexport function getValue(selectorOrNode: HTMLElement | string) {\n  if (typeof selectorOrNode === 'string') {\n    const el = document.querySelector(selectorOrNode) as HTMLInputElement | null;\n    return el?.value;\n  }\n\n  return (selectorOrNode as HTMLInputElement)?.value;\n}\n\nexport function setChecked(node: HTMLInputElement, status?: boolean) {\n  node.checked = status !== undefined ? status : !node.checked;\n  node.dispatchEvent(new window.Event('change'));\n  node.dispatchEvent(new window.Event('input'));\n}\n\nexport function dispatchEvent(node: ComponentPublicInstance | HTMLElement | string, eventName: string) {\n  if (typeof node === 'string') {\n    const el = document.querySelector(node) as HTMLElement | null;\n    el?.dispatchEvent(new window.Event(eventName));\n    return;\n  }\n\n  if ('tagName' in node) {\n    const input = node as HTMLElement;\n    input.dispatchEvent(new window.Event(eventName));\n    return;\n  }\n\n  (node as any).$emit(eventName);\n}\n\n/**\n * Ensures promises and timers are flushed properly including debounce time\n */\nexport async function flushPromises() {\n  await flushP();\n  vi.advanceTimersByTime(5);\n  await flushP();\n}\n\nexport async function dispatchFileEvent(input: HTMLInputElement, name: string | string[]) {\n  const createFile = (filename: string) =>\n    new File([new ArrayBuffer(2e5)], filename, { lastModified: 0, type: 'image/jpeg' });\n\n  const files = Array.isArray(name) ? name.map(createFile) : [createFile(name)];\n  const event = new Event('change');\n\n  Object.defineProperty(event, 'target', {\n    get() {\n      return {\n        type: 'file',\n        multiple: input.multiple,\n        files,\n      };\n    },\n  });\n\n  input.dispatchEvent(event);\n  await flushPromises();\n}\n\nexport async function runInSetup(cb: () => any) {\n  mountWithHoc({\n    setup() {\n      cb();\n    },\n    template: `\n        <div></div>\n    `,\n  });\n}\n"
  },
  {
    "path": "packages/vee-validate/tests/useField.spec.ts",
    "content": "import { FieldContext, FormContext, useField, useForm } from '@/vee-validate';\nimport { defineComponent, onMounted, ref } from 'vue';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\n\ndescribe('useField()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const MIN_MESSAGE = 'Field must be at least 3';\n  test('validates when value changes', async () => {\n    mountWithHoc({\n      setup() {\n        const { value, errorMessage } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ errorMessage }}</span>\n    `,\n    });\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n\n    setValue(input as any, '');\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test.skip('warns when nested value changes', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        const { value, errorMessage } = useField<any>('field', undefined, {\n          initialValue: { name: 'test' },\n        });\n\n        onMounted(() => {\n          value.value.name = '';\n        });\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n      <span>{{ errorMessage }}</span>\n    `,\n    });\n\n    await flushPromises();\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('valid flag is correct after reset', async () => {\n    mountWithHoc({\n      setup() {\n        const {\n          value: value1,\n          meta: meta1,\n          resetField: reset1,\n        } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n        const {\n          value: value2,\n          meta: meta2,\n          resetField: reset2,\n        } = useField('field', val => (!val || (val as string).length >= 3 ? true : MIN_MESSAGE));\n\n        return {\n          value1,\n          value2,\n          meta1,\n          meta2,\n          reset1,\n          reset2,\n        };\n      },\n      template: `\n      <input id=\"input1\" name=\"field\" v-model=\"value1\" />\n      <span id=\"meta1\">{{ meta1.valid ? 'valid' : 'invalid' }}</span>\n      <button id=\"r1\" @click=\"reset1()\">Reset</button>\n      <input id=\"input2\" name=\"field\" v-model=\"value2\" />\n      <span id=\"meta2\">{{ meta2.valid ? 'valid' : 'invalid' }}</span>\n      <button id=\"r2\" @click=\"reset2()\">Reset</button>\n    `,\n    });\n\n    const input1 = document.querySelector('#input1') as HTMLInputElement;\n    const meta1 = document.querySelector('#meta1');\n    const input2 = document.querySelector('#input2') as HTMLInputElement;\n    const meta2 = document.querySelector('#meta2');\n\n    await flushPromises();\n    expect(meta1?.textContent).toBe('invalid');\n    expect(meta2?.textContent).toBe('valid');\n\n    setValue(input1, '12');\n    setValue(input2, '12');\n    await flushPromises();\n    expect(meta1?.textContent).toBe('valid');\n    expect(meta2?.textContent).toBe('invalid');\n\n    // trigger reset\n    (document.querySelector('#r1') as HTMLButtonElement).click();\n    (document.querySelector('#r2') as HTMLButtonElement).click();\n    await flushPromises();\n    expect(meta1?.textContent).toBe('invalid');\n    expect(meta2?.textContent).toBe('valid');\n  });\n\n  test('valid flag is synced with fields errors length', async () => {\n    mountWithHoc({\n      setup() {\n        const { value, meta, resetField } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          value,\n          meta,\n          resetField,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span id=\"meta\">{{ meta.valid ? 'valid' : 'invalid' }}</span>\n      <button @click=\"resetField({ errors: ['bad'] })\">Reset</button>\n    `,\n    });\n\n    await flushPromises();\n    const meta = document.querySelector('#meta');\n    const input = document.querySelector('input') as HTMLInputElement;\n\n    expect(meta?.textContent).toBe('invalid');\n\n    setValue(input, '12');\n    await flushPromises();\n    expect(meta?.textContent).toBe('valid');\n\n    // trigger reset\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(meta?.textContent).toBe('invalid');\n  });\n\n  test('dirty flag is false after reset', async () => {\n    mountWithHoc({\n      setup() {\n        const { value, meta, resetField } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          value,\n          meta,\n          resetField,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span id=\"meta\">{{ meta.dirty ? 'dirty' : 'clean' }}</span>\n      <button @click=\"resetField()\">Reset</button>\n    `,\n    });\n\n    const input = document.querySelector('input') as HTMLInputElement;\n    const meta = document.querySelector('#meta');\n\n    await flushPromises();\n    expect(meta?.textContent).toBe('clean');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(meta?.textContent).toBe('dirty');\n\n    // trigger reset\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(meta?.textContent).toBe('clean');\n  });\n\n  test('dirty flag is false after reset with a new value', async () => {\n    mountWithHoc({\n      setup() {\n        const { value, meta, resetField } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          value,\n          meta,\n          resetField,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span id=\"meta\">{{ meta.dirty ? 'dirty' : 'clean' }}</span>\n      <button @click=\"resetField({ value: '12' })\">Reset</button>\n    `,\n    });\n\n    const input = document.querySelector('input') as HTMLInputElement;\n    const meta = document.querySelector('#meta');\n\n    await flushPromises();\n    expect(meta?.textContent).toBe('clean');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(meta?.textContent).toBe('dirty');\n\n    // trigger reset\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(meta?.textContent).toBe('clean');\n  });\n\n  // #3891\n  test('dirty flag is false after reset with a new value when a form is present', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value, meta, resetField } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          value,\n          meta,\n          resetField,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span id=\"meta\">{{ meta.dirty ? 'dirty' : 'clean' }}</span>\n      <button @click=\"resetField({ value: '12' })\">Reset</button>\n    `,\n    });\n\n    const input = document.querySelector('input') as HTMLInputElement;\n    const meta = document.querySelector('#meta');\n\n    await flushPromises();\n    expect(meta?.textContent).toBe('clean');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(meta?.textContent).toBe('dirty');\n\n    // trigger reset\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(meta?.textContent).toBe('clean');\n  });\n\n  describe('has validation modes', () => {\n    test('silent mode does not generate messages', async () => {\n      let validateFn!: ReturnType<typeof useField>['validate'];\n      mountWithHoc({\n        setup() {\n          const { errorMessage, validate } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n          validateFn = validate;\n\n          return {\n            errorMessage,\n          };\n        },\n        template: `\n      <span>{{ errorMessage }}</span>\n    `,\n      });\n      const error = document.querySelector('span');\n      expect(error?.textContent).toBe('');\n\n      // won't show any errors\n      await validateFn({ mode: 'silent' });\n      await flushPromises();\n      expect(error?.textContent).toBe('');\n    });\n\n    test('validated-only mode only generates messages when it was validated before by user action', async () => {\n      let validateFn!: ReturnType<typeof useField>['validate'];\n      mountWithHoc({\n        setup() {\n          const { errorMessage, validate, value, setErrors } = useField('field', val =>\n            val ? true : REQUIRED_MESSAGE,\n          );\n          validateFn = validate;\n          // marks it as dirty/touched\n          value.value = '';\n          onMounted(() => {\n            setErrors('');\n          });\n\n          return {\n            errorMessage,\n          };\n        },\n        template: `\n      <span>{{ errorMessage }}</span>\n    `,\n      });\n      const error = document.querySelector('span');\n      expect(error?.textContent).toBe('');\n\n      // won't show any errors\n      await validateFn({ mode: 'validated-only' });\n      await flushPromises();\n      expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n    });\n\n    test('force mode always generates new error messages', async () => {\n      let validateFn!: ReturnType<typeof useField>['validate'];\n      mountWithHoc({\n        setup() {\n          const { errorMessage, validate } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n          validateFn = validate;\n\n          return {\n            errorMessage,\n          };\n        },\n        template: `\n      <span>{{ errorMessage }}</span>\n    `,\n      });\n      const error = document.querySelector('span');\n      expect(error?.textContent).toBe('');\n\n      // won't show any errors\n      await validateFn({ mode: 'force' });\n      await flushPromises();\n      expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n    });\n  });\n\n  describe('generic function chains', () => {\n    test('when bails is true', async () => {\n      mountWithHoc({\n        setup() {\n          const {\n            value: value1,\n            meta: meta1,\n            errors: errors1,\n            resetField: reset1,\n          } = useField('field', [\n            val => (val ? true : REQUIRED_MESSAGE),\n            val => ((val as string)?.length >= 3 ? true : MIN_MESSAGE),\n          ]);\n          const {\n            value: value2,\n            meta: meta2,\n            errors: errors2,\n            resetField: reset2,\n          } = useField('field', [\n            val => ((val as string)?.length >= 3 ? true : MIN_MESSAGE),\n            val => (val ? true : REQUIRED_MESSAGE),\n          ]);\n\n          return {\n            value1,\n            value2,\n            meta1,\n            meta2,\n            errors1,\n            errors2,\n            reset1,\n            reset2,\n          };\n        },\n        template: `\n        <input id=\"input1\" name=\"field\" v-model=\"value1\" />\n        <span id=\"meta1\">{{ meta1.valid ? 'valid' : 'invalid' }}</span>\n        <span id=\"errors1\">{{ errors1.length }}</span>\n        <span v-for=\"(e, idx) in errors1\" :id=\"'errormessage1' + idx\">{{ e }}</span>\n        <button id=\"r1\" @click=\"reset1()\">Reset</button>\n        <input id=\"input2\" name=\"field\" v-model=\"value2\" />\n        <span id=\"meta2\">{{ meta2.valid ? 'valid' : 'invalid' }}</span>\n        <span id=\"errors2\">{{ errors2.length }}</span>\n        <span v-for=\"(e, idx) in errors2\" :id=\"'errormessage2' + idx\">{{ e }}</span>\n        <button id=\"r2\" @click=\"reset2()\">Reset</button>\n      `,\n      });\n\n      const input1 = document.querySelector('#input1') as HTMLInputElement;\n      const meta1 = document.querySelector('#meta1');\n      const errors1 = document.querySelector('#errors1');\n      const input2 = document.querySelector('#input2') as HTMLInputElement;\n      const meta2 = document.querySelector('#meta2');\n      const errors2 = document.querySelector('#errors2');\n\n      await flushPromises();\n\n      expect(meta1?.textContent).toBe('invalid');\n      expect(meta2?.textContent).toBe('invalid');\n      setValue(input1, '');\n      setValue(input2, '');\n\n      await flushPromises();\n\n      let errorMessage10 = document.querySelector('#errormessage10');\n      let errorMessage20 = document.querySelector('#errormessage20');\n\n      expect(meta1?.textContent).toBe('invalid');\n      expect(meta2?.textContent).toBe('invalid');\n      expect(errors1?.textContent).toBe('1');\n      expect(errors2?.textContent).toBe('1');\n      expect(errorMessage10?.textContent).toBe(REQUIRED_MESSAGE);\n      expect(errorMessage20?.textContent).toBe(MIN_MESSAGE);\n\n      setValue(input1, '12');\n      setValue(input2, '12');\n\n      await flushPromises();\n\n      errorMessage10 = document.querySelector('#errormessage10');\n      errorMessage20 = document.querySelector('#errormessage20');\n\n      expect(meta1?.textContent).toBe('invalid');\n      expect(meta2?.textContent).toBe('invalid');\n      expect(errors1?.textContent).toBe('1');\n      expect(errors2?.textContent).toBe('1');\n      expect(errorMessage10?.textContent).toBe(MIN_MESSAGE);\n      expect(errorMessage20?.textContent).toBe(MIN_MESSAGE);\n\n      setValue(input1, '123');\n      setValue(input2, '123');\n\n      await flushPromises();\n\n      expect(meta1?.textContent).toBe('valid');\n      expect(meta2?.textContent).toBe('valid');\n      expect(errors1?.textContent).toBe('0');\n      expect(errors2?.textContent).toBe('0');\n\n      // trigger reset\n      (document.querySelector('#r1') as HTMLButtonElement).click();\n      (document.querySelector('#r2') as HTMLButtonElement).click();\n      await flushPromises();\n      expect(meta1?.textContent).toBe('invalid');\n      expect(meta2?.textContent).toBe('invalid');\n    });\n\n    test('when bails is false', async () => {\n      mountWithHoc({\n        setup() {\n          const {\n            value: value1,\n            meta: meta1,\n            errors: errors1,\n            resetField: reset1,\n          } = useField(\n            'field',\n            [val => (val ? true : REQUIRED_MESSAGE), val => ((val as string)?.length >= 3 ? true : MIN_MESSAGE)],\n            { bails: false },\n          );\n          const {\n            value: value2,\n            meta: meta2,\n            errors: errors2,\n            resetField: reset2,\n          } = useField(\n            'field',\n            [val => ((val as string)?.length >= 3 ? true : MIN_MESSAGE), val => (val ? true : REQUIRED_MESSAGE)],\n            { bails: false },\n          );\n\n          return {\n            value1,\n            value2,\n            meta1,\n            meta2,\n            errors1,\n            errors2,\n            reset1,\n            reset2,\n          };\n        },\n        template: `\n        <input id=\"input1\" name=\"field\" v-model=\"value1\" />\n        <span id=\"meta1\">{{ meta1.valid ? 'valid' : 'invalid' }}</span>\n        <span id=\"errors1\">{{ errors1.length }}</span>\n        <span v-for=\"(e, idx) in errors1\" :id=\"'errormessage1' + idx\">{{ e }}</span>\n        <button id=\"r1\" @click=\"reset1()\">Reset</button>\n        <input id=\"input2\" name=\"field\" v-model=\"value2\" />\n        <span id=\"meta2\">{{ meta2.valid ? 'valid' : 'invalid' }}</span>\n        <span id=\"errors2\">{{ errors2.length }}</span>\n        <span v-for=\"(e, idx) in errors2\" :id=\"'errormessage2' + idx\">{{ e }}</span>\n        <button id=\"r2\" @click=\"reset2()\">Reset</button>\n      `,\n      });\n\n      const input1 = document.querySelector('#input1') as HTMLInputElement;\n      const meta1 = document.querySelector('#meta1');\n      const errors1 = document.querySelector('#errors1');\n      const input2 = document.querySelector('#input2') as HTMLInputElement;\n      const meta2 = document.querySelector('#meta2');\n      const errors2 = document.querySelector('#errors2');\n\n      await flushPromises();\n\n      expect(meta1?.textContent).toBe('invalid');\n      expect(meta2?.textContent).toBe('invalid');\n      setValue(input1, '');\n      setValue(input2, '');\n\n      await flushPromises();\n\n      let errorMessage10 = document.querySelector('#errormessage10');\n      const errorMessage11 = document.querySelector('#errormessage11');\n      let errorMessage20 = document.querySelector('#errormessage20');\n      const errorMessage21 = document.querySelector('#errormessage21');\n\n      expect(meta1?.textContent).toBe('invalid');\n      expect(meta2?.textContent).toBe('invalid');\n      expect(errors1?.textContent).toBe('2');\n      expect(errors2?.textContent).toBe('2');\n      expect(errorMessage10?.textContent).toBe(REQUIRED_MESSAGE);\n      expect(errorMessage11?.textContent).toBe(MIN_MESSAGE);\n      expect(errorMessage20?.textContent).toBe(MIN_MESSAGE);\n      expect(errorMessage21?.textContent).toBe(REQUIRED_MESSAGE);\n\n      setValue(input1, '12');\n      setValue(input2, '12');\n\n      await flushPromises();\n\n      errorMessage10 = document.querySelector('#errormessage10');\n      errorMessage20 = document.querySelector('#errormessage20');\n\n      expect(meta1?.textContent).toBe('invalid');\n      expect(meta2?.textContent).toBe('invalid');\n      expect(errors1?.textContent).toBe('1');\n      expect(errors2?.textContent).toBe('1');\n      expect(errorMessage10?.textContent).toBe(MIN_MESSAGE);\n      expect(errorMessage20?.textContent).toBe(MIN_MESSAGE);\n\n      setValue(input1, '123');\n      setValue(input2, '123');\n\n      await flushPromises();\n\n      expect(meta1?.textContent).toBe('valid');\n      expect(meta2?.textContent).toBe('valid');\n      expect(errors1?.textContent).toBe('0');\n      expect(errors2?.textContent).toBe('0');\n\n      // trigger reset\n      (document.querySelector('#r1') as HTMLButtonElement).click();\n      (document.querySelector('#r2') as HTMLButtonElement).click();\n      await flushPromises();\n      expect(meta1?.textContent).toBe('invalid');\n      expect(meta2?.textContent).toBe('invalid');\n    });\n  });\n\n  test('emits model events for v-model support and syncing', async () => {\n    const model = ref('');\n    const InputComponent = defineComponent({\n      props: {\n        modelValue: String,\n      },\n      setup() {\n        const { value, errorMessage } = useField('field', undefined, { syncVModel: true });\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n        <input v-model=\"value\" />\n      `,\n    });\n\n    mountWithHoc({\n      components: {\n        InputComponent,\n      },\n      setup() {\n        return {\n          model,\n        };\n      },\n      template: `\n      <InputComponent v-model=\"model\" />\n    `,\n    });\n\n    const input = document.querySelector('input');\n\n    setValue(input as any, '123');\n    await flushPromises();\n    expect(model.value).toBe('123');\n    model.value = '321';\n    await flushPromises();\n    expect(input?.value).toBe('321');\n  });\n\n  test('uses initial model value when sync v-model is set', async () => {\n    const model = ref('test');\n    const InputComponent = defineComponent({\n      props: {\n        modelValue: String,\n      },\n      setup() {\n        const { value, errorMessage } = useField('field', undefined, { syncVModel: true });\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n        <input v-model=\"value\" />\n      `,\n    });\n\n    mountWithHoc({\n      components: {\n        InputComponent,\n      },\n      setup() {\n        return {\n          model,\n        };\n      },\n      template: `\n      <InputComponent v-model=\"model\" />\n    `,\n    });\n\n    const input = document.querySelector('input');\n\n    await flushPromises();\n    expect(model.value).toBe('test');\n    expect(input?.value).toBe('test');\n  });\n\n  // #4333\n  test('should emit modified values with model modifiers being applied as a prop', async () => {\n    const model = ref('');\n    const InputComponent = defineComponent({\n      props: {\n        modelValue: String,\n        modelModifiers: null,\n      },\n      setup() {\n        const { value, errorMessage } = useField('field', undefined, { syncVModel: true });\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n        <input v-model=\"value\" />\n      `,\n    });\n\n    const onModelUpdated = vi.fn();\n\n    mountWithHoc({\n      components: {\n        InputComponent,\n      },\n      setup() {\n        return {\n          onModelUpdated,\n          model,\n        };\n      },\n      template: `\n      <InputComponent :model-value=\"model\" @update:model-value=\"onModelUpdated\" :model-modifiers=\"{ number: true }\" />\n    `,\n    });\n\n    const input = document.querySelector('input');\n\n    setValue(input as any, '123');\n    await flushPromises();\n    expect(onModelUpdated).toHaveBeenLastCalledWith(123);\n  });\n\n  test('can disable model events', async () => {\n    const model = ref('');\n    const InputComponent = defineComponent({\n      props: {\n        modelValue: String,\n      },\n      setup() {\n        const { value, errorMessage } = useField('field', undefined, {\n          syncVModel: false,\n        });\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n        <input v-model=\"value\" />\n      `,\n    });\n\n    mountWithHoc({\n      components: {\n        InputComponent,\n      },\n      setup() {\n        return {\n          model,\n        };\n      },\n      template: `\n      <InputComponent v-model=\"model\" />\n    `,\n    });\n\n    const input = document.querySelector('input');\n\n    setValue(input as any, '123');\n    await flushPromises();\n    expect(model.value).toBe('');\n    model.value = '321';\n    await flushPromises();\n    expect(input?.value).toBe('123');\n  });\n\n  test('emits model events for custom models support and syncing', async () => {\n    const model = ref('');\n    const InputComponent = defineComponent({\n      props: {\n        textVal: String,\n      },\n      setup() {\n        const { value, errorMessage } = useField('field', undefined, {\n          syncVModel: 'textVal',\n        });\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n        <input v-model=\"value\" />\n      `,\n    });\n\n    mountWithHoc({\n      components: {\n        InputComponent,\n      },\n      setup() {\n        return {\n          model,\n        };\n      },\n      template: `\n      <InputComponent v-model:textVal=\"model\" />\n    `,\n    });\n\n    const input = document.querySelector('input');\n\n    setValue(input as any, '123');\n    await flushPromises();\n    expect(model.value).toBe('123');\n    model.value = '321';\n    await flushPromises();\n    expect(input?.value).toBe('321');\n  });\n\n  // #3906\n  test('only latest validation run messages are used', async () => {\n    function validator(value: string | undefined) {\n      if (!value) {\n        return true;\n      }\n\n      if (value.toLowerCase().startsWith('b')) {\n        return 'not b';\n      }\n\n      return new Promise<string | boolean>(resolve => {\n        setTimeout(() => {\n          if (value.toLowerCase().startsWith('a')) {\n            resolve('not a');\n            return;\n          }\n\n          resolve(true);\n        }, 100);\n      });\n    }\n\n    mountWithHoc({\n      setup() {\n        const { value, errorMessage } = useField<string>('field', validator);\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ errorMessage }}</span>\n    `,\n    });\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n\n    setValue(input as any, 'a');\n    await flushPromises();\n    setValue(input as any, 'b');\n    await flushPromises();\n    vi.advanceTimersByTime(200);\n    await flushPromises();\n    expect(error?.textContent).toBe('not b');\n  });\n\n  test('allows explicit forms to be provided via the form option', async () => {\n    let form1!: FormContext;\n    let form2!: FormContext;\n    let field1!: FieldContext;\n    let field2!: FieldContext;\n    mountWithHoc({\n      setup() {\n        form1 = useForm();\n        form2 = useForm();\n        field1 = useField('field', undefined, {\n          form: form1,\n        });\n        field2 = useField('field', undefined, {\n          form: form2,\n        });\n\n        return {};\n      },\n      template: `\n      <div></div>\n    `,\n    });\n\n    await flushPromises();\n    field1.value.value = '1';\n    field2.value.value = '2';\n    await flushPromises();\n\n    expect(form1.values.field).toBe('1');\n    expect(form2.values.field).toBe('2');\n  });\n\n  test('allows lazy name expressions', async () => {\n    const nameRef = ref('first');\n    mountWithHoc({\n      setup() {\n        const { name } = useField(() => nameRef.value);\n\n        return {\n          name,\n        };\n      },\n      template: `\n      <span>{{ name }}</span>\n    `,\n    });\n\n    const name = document.querySelector('span');\n\n    await flushPromises();\n    expect(name?.textContent).toBe('first');\n    nameRef.value = 'second';\n    await flushPromises();\n    expect(name?.textContent).toBe('second');\n  });\n\n  test('handle change validates the field by default', async () => {\n    let field!: FieldContext;\n    const validator = vi.fn(val => (val ? true : REQUIRED_MESSAGE));\n    mountWithHoc({\n      setup() {\n        field = useField('field', validator);\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    expect(validator).toHaveBeenCalledTimes(1);\n    expect(field.errorMessage.value).toBe(undefined);\n    field.handleChange('');\n    await flushPromises();\n    expect(field.errorMessage.value).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('handle change can be configured to not validate the field', async () => {\n    let field!: FieldContext;\n    const validator = vi.fn(val => (val ? true : REQUIRED_MESSAGE));\n    mountWithHoc({\n      setup() {\n        field = useField('field', validator, { validateOnValueUpdate: false });\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    expect(validator).toHaveBeenCalledTimes(1);\n    expect(field.errorMessage.value).toBe(undefined);\n    field.handleChange('', false);\n    await flushPromises();\n\n    expect(validator).toHaveBeenCalledTimes(2);\n    expect(field.errorMessage.value).toBe(undefined);\n  });\n\n  test('handleChange parses input[type=number] value', async () => {\n    let field!: FieldContext;\n\n    mountWithHoc({\n      setup() {\n        field = useField('field', undefined);\n        const { handleChange } = field;\n\n        return {\n          handleChange,\n        };\n      },\n      template: `<input type=\"number\" @change=\"handleChange\" />`,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    setValue(input, '0.00');\n    await flushPromises();\n    expect(field.value.value).toBe('0.00');\n\n    setValue(input, '');\n    await flushPromises();\n    expect(field.value.value).toBe('');\n  });\n\n  test('handleChange parses input[type=range] value', async () => {\n    let field!: FieldContext;\n\n    mountWithHoc({\n      setup() {\n        field = useField('field', undefined);\n        const { handleChange } = field;\n\n        return {\n          handleChange,\n        };\n      },\n      template: `<input type=\"range\" min=\"0\" max=\"1000\" step=\"100\" @change=\"handleChange\" />`,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input') as HTMLInputElement;\n    setValue(input, '500');\n    await flushPromises();\n    expect(field.value.value).toBe(500);\n\n    setValue(input, '0');\n    await flushPromises();\n    expect(field.value.value).toBe(0);\n  });\n\n  test('a validator can return multiple messages', async () => {\n    let field!: FieldContext;\n    const validator = vi.fn(val => (val ? true : [REQUIRED_MESSAGE, 'second']));\n\n    mountWithHoc({\n      setup() {\n        field = useField('field', validator);\n\n        return {};\n      },\n    });\n\n    await flushPromises();\n    expect(field.errors.value).toHaveLength(0);\n    await field.validate();\n    await flushPromises();\n    expect(field.errors.value).toHaveLength(2);\n    expect(field.errors.value).toEqual([REQUIRED_MESSAGE, 'second']);\n  });\n\n  // #4323\n  test('resetField should not validate', async () => {\n    let field!: FieldContext;\n    const validator = vi.fn(val => (val ? true : REQUIRED_MESSAGE));\n\n    mountWithHoc({\n      setup() {\n        useForm();\n        field = useField('field', validator);\n\n        return {};\n      },\n    });\n\n    await flushPromises();\n    expect(field.errors.value).toHaveLength(0);\n    field.resetField({ value: '' });\n    await flushPromises();\n    expect(field.errors.value).toHaveLength(0);\n  });\n\n  // #4603\n  test('should not remove field value if field with same path was created between scheduling and execution of previous field unset operation', async () => {\n    vi.useFakeTimers();\n    let form!: FormContext;\n    mountWithHoc({\n      setup() {\n        form = useForm();\n        const toggle = ref(false);\n        const value = ref('');\n\n        onMounted(async () => {\n          await new Promise(resolve => {\n            setTimeout(() => resolve(null), 1000);\n          });\n\n          toggle.value = true;\n          value.value = 'test';\n        });\n        return { form, toggle, value };\n      },\n      template: `\n      <template v-if=\"!toggle\">\n        <CustomField name=\"field\" :model-value=\"value\" />\n      </template>\n      <template v-if=\"toggle\">\n        <CustomField name=\"field\" :model-value=\"value\" />\n      </template>\n      `,\n      components: {\n        CustomField: {\n          props: {\n            name: String,\n            modelValue: String,\n          },\n          setup(props: any) {\n            useField(props.name, undefined, {\n              initialValue: props.modelValue,\n            });\n          },\n          template: `<input type=\"text\" :value=\"modelValue\" :name=\"name\" />`,\n        },\n      },\n    });\n\n    await flushPromises();\n    vi.advanceTimersByTime(1000);\n    await flushPromises();\n\n    expect(form.values.field).toEqual('test');\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useFieldArray.spec.ts",
    "content": "import { useForm, useFieldArray, FieldEntry, FormContext, FieldArrayContext, useField } from '@/vee-validate';\nimport { defineComponent, nextTick, onMounted, Ref } from 'vue';\nimport * as z from 'zod';\nimport { mountWithHoc, flushPromises, setValue } from './helpers';\n\ntest('can update a field entry model directly', async () => {\n  mountWithHoc({\n    setup() {\n      useForm({\n        initialValues: {\n          users: ['1'],\n        },\n      });\n\n      const { fields } = useFieldArray('users');\n      onMounted(() => {\n        const item = fields.value[0];\n        item.value = 'test';\n      });\n\n      return {\n        fields,\n      };\n    },\n    template: `\n      <p>{{ fields[0].value }}</p>\n    `,\n  });\n\n  await flushPromises();\n  expect(document.querySelector('p')?.innerHTML).toBe('test');\n});\n\ntest('can update a field entry deep model directly and validate it', async () => {\n  let fields!: Ref<FieldEntry<{ name: string }>[]>;\n  mountWithHoc({\n    setup() {\n      const { errors } = useForm({\n        validateOnMount: true,\n        validationSchema: z.object({\n          users: z.array(\n            z.object({\n              name: z.string().min(1),\n            }),\n          ),\n        }),\n        initialValues: {\n          users: [{ name: '' }],\n        },\n      });\n\n      fields = useFieldArray<{ name: string }>('users').fields;\n\n      return {\n        fields,\n        errors,\n      };\n    },\n    template: `\n      <p>{{ fields[0].value.name }}</p>\n      <span>{{ errors }}</span>\n    `,\n  });\n\n  await flushPromises();\n  expect(document.querySelector('p')?.innerHTML).toBe('');\n  expect(document.querySelector('span')?.innerHTML).toBeTruthy();\n\n  const item = fields.value[0];\n  item.value.name = 'test';\n\n  await flushPromises();\n  expect(document.querySelector('p')?.innerHTML).toBe('test');\n  expect(document.querySelector('span')?.innerHTML).toBe('{}');\n});\n\ntest('warns when updating a no-longer existing item', async () => {\n  const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n    // NOOP\n  });\n  mountWithHoc({\n    setup() {\n      useForm({\n        initialValues: {\n          users: ['1'],\n        },\n      });\n\n      const { remove, fields } = useFieldArray('users');\n      onMounted(async () => {\n        const item = fields.value[0];\n        remove(0);\n        await nextTick();\n        item.value = 'test';\n      });\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n\n  expect(spy).toHaveBeenCalled();\n  spy.mockRestore();\n});\n\ntest('warns when no form context is present', async () => {\n  const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n    // NOOP\n  });\n  mountWithHoc({\n    setup() {\n      const { push } = useFieldArray('users');\n      push('');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n\n  expect(spy).toHaveBeenCalled();\n  spy.mockRestore();\n});\n\ntest('duplicate calls yields the same instance', async () => {\n  let removeFn!: (idx: number) => void;\n  mountWithHoc({\n    setup() {\n      useForm({\n        initialValues: {\n          users: ['one'],\n        },\n      });\n\n      const { fields, push } = useFieldArray('users');\n      const { fields: fields2, remove } = useFieldArray('users');\n\n      removeFn = remove;\n\n      onMounted(() => {\n        push('two');\n      });\n\n      return {\n        fields,\n        fields2,\n      };\n    },\n    template: `\n      <p id=\"arr1\">{{ fields.map(f => f.value).join(', ') }}</p>\n      <p id=\"arr2\">{{ fields2.map(f => f.value).join(', ') }}</p>\n    `,\n  });\n\n  await flushPromises();\n  expect(document.querySelector('#arr1')?.innerHTML).toBe('one, two');\n  expect(document.querySelector('#arr2')?.innerHTML).toBe('one, two');\n  removeFn(0);\n  await flushPromises();\n  expect(document.querySelector('#arr1')?.innerHTML).toBe('two');\n  expect(document.querySelector('#arr2')?.innerHTML).toBe('two');\n});\n\n// #4096\ntest('array push should trigger a silent validation', async () => {\n  let form!: FormContext;\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      form = useForm<any>({\n        initialValues: {\n          users: ['one'],\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(form.meta.value.valid).toBe(true);\n  arr.push('');\n  await flushPromises();\n  expect(form.meta.value.valid).toBe(false);\n});\n\ntest('array push noop when path is not an array', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: 'test',\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.push('');\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n});\n\n// #4096\ntest('array prepend should trigger a silent validation', async () => {\n  let form!: FormContext;\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      form = useForm<any>({\n        initialValues: {\n          users: ['one'],\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(form.meta.value.valid).toBe(true);\n  arr.prepend('');\n  await flushPromises();\n  expect(form.meta.value.valid).toBe(false);\n});\n\ntest('array prepend noop when path is not an array', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: 'test',\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.prepend('');\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n});\n\n// #4096\ntest('array insert should trigger a silent validation', async () => {\n  let form!: FormContext;\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      form = useForm<any>({\n        initialValues: {\n          users: ['one', 'two'],\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(form.meta.value.valid).toBe(true);\n  arr.insert(1, '');\n  await flushPromises();\n  expect(form.meta.value.valid).toBe(false);\n});\n\ntest('array insert noop when path is not an array', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: 'test',\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.insert(0, '');\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n});\n\ntest('array move noop when path is not an array', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: 'test',\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.move(0, 1);\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n});\n\ntest('array swap noop when path is not an array', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: 'test',\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.swap(0, 1);\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n});\n\ntest('array remove noop when path is not an array', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: 'test',\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.remove(0);\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n});\n\ntest('array update noop when path is not an array', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: 'test',\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.update(0, '');\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n});\n\ntest('array push initializes the array if undefined', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: undefined,\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.push('');\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(1);\n});\n\ntest('array prepend initializes the array if undefined', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: undefined,\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.prepend('');\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(1);\n});\n\ntest('array move initializes the array if undefined', async () => {\n  let arr!: FieldArrayContext;\n  mountWithHoc({\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: undefined,\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n    },\n    template: `\n      <div></div>\n    `,\n  });\n\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n  arr.move(0, 0);\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(0);\n});\n\n// #4557\ntest('errors are available to the newly inserted items', async () => {\n  let arr!: FieldArrayContext;\n  const InputText = defineComponent({\n    props: {\n      name: {\n        type: String,\n        required: true,\n      },\n    },\n    setup(props) {\n      const { value, errorMessage } = useField(() => props.name);\n\n      return {\n        value,\n        errorMessage,\n      };\n    },\n    template: '<input v-model=\"value\" /> <span>{{errorMessage}}</span>',\n  });\n\n  mountWithHoc({\n    components: { InputText },\n    setup() {\n      useForm<any>({\n        initialValues: {\n          users: ['one', 'three'],\n        },\n        validationSchema: z.object({\n          users: z.array(z.string().min(1)),\n        }),\n      });\n\n      arr = useFieldArray('users');\n\n      return {\n        fields: arr.fields,\n      };\n    },\n    template: `\n      <div>\n        <InputText v-for=\"(field, idx) in fields\" :key=\"field.key\" :name=\"'users[' + idx + ']'\"  />\n      </div>\n    `,\n  });\n  const inputAt = (idx: number) => (document.querySelectorAll('input') || [])[idx] as HTMLInputElement;\n  const spanAt = (idx: number) => (document.querySelectorAll('span') || [])[idx] as HTMLSpanElement;\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(2);\n  arr.insert(1, '');\n  await flushPromises();\n  expect(arr.fields.value).toHaveLength(3);\n  setValue(inputAt(1), '');\n  await flushPromises();\n  expect(spanAt(1).textContent).toBeTruthy();\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useFieldError.spec.ts",
    "content": "import { useField, useFieldError, useForm } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\nimport { defineComponent } from 'vue';\n\ndescribe('useFieldError()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const validate = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('gives access to a single field error message', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value } = useField('test', validate);\n        const message = useFieldError('test');\n\n        return {\n          value,\n          message,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ message }}</span>\n    `,\n    });\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    setValue(input as any, '');\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('gives access to a single field error message in a child component with specifying a path', async () => {\n    const CustomErrorComponent = defineComponent({\n      template: '<span>{{ message }}</span>',\n      setup() {\n        const message = useFieldError();\n\n        return {\n          message,\n        };\n      },\n    });\n    mountWithHoc({\n      components: {\n        CustomErrorComponent,\n      },\n      setup() {\n        useForm();\n        const { value } = useField('test', validate);\n\n        return {\n          value,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <CustomErrorComponent />\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    setValue(input as any, '');\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('gives access to array fields error message', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value } = useField('test', validate);\n        useField('test', validate);\n        const message = useFieldError('test');\n\n        return {\n          value,\n          message,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ message }}</span>\n    `,\n    });\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    setValue(input as any, '');\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('returns undefined if field not found', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const message = useFieldError('something');\n\n        return {\n          message,\n        };\n      },\n      template: `\n      <span>{{ message }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('');\n  });\n\n  test('returns undefined if form is not found', async () => {\n    mountWithHoc({\n      setup() {\n        const message = useFieldError('something');\n\n        return {\n          message,\n        };\n      },\n      template: `\n      <span>{{ message }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('');\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useFieldValue.spec.ts",
    "content": "import { useField, useFieldValue, useForm } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\nimport { defineComponent } from 'vue';\n\ndescribe('useFieldValue()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const validate = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('gives access to a single field value', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value, setValue } = useField('test', validate);\n        const currValue = useFieldValue('test');\n\n        return {\n          value,\n          currValue,\n          setValue,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ currValue }}</span>\n      <button @click=\"setValue('5')\"></button>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const valueSpan = document.querySelector('span');\n    const inputValue = '1234';\n    setValue(input as any, inputValue);\n    await flushPromises();\n    expect(valueSpan?.textContent).toBe(inputValue);\n\n    // test value setting\n    const btn = document.querySelector('button');\n    btn?.click();\n    await flushPromises();\n    expect(input?.value).toBe('5');\n  });\n\n  test('gives access to a single field value in a child component without specifying a path', async () => {\n    const CustomChildValueDisplay = defineComponent({\n      template: '<span>{{ value }}</span>',\n      setup() {\n        const value = useFieldValue();\n\n        return {\n          value,\n        };\n      },\n    });\n\n    mountWithHoc({\n      components: {\n        CustomChildValueDisplay,\n      },\n      setup() {\n        useForm();\n        const { value } = useField('test');\n\n        return {\n          value,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <CustomChildValueDisplay />\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const inputValue = '1234';\n    setValue(input as any, inputValue);\n    await flushPromises();\n    const valueSpan = document.querySelector('span');\n    expect(valueSpan?.textContent).toBe(inputValue);\n  });\n\n  test('returns undefined if field not found', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const value = useFieldValue('something');\n\n        return {\n          value,\n        };\n      },\n      template: `\n      <span>{{ value }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('');\n  });\n\n  test('returns undefined if form is not found', async () => {\n    mountWithHoc({\n      setup() {\n        const value = useFieldValue('something');\n\n        return {\n          value,\n        };\n      },\n      template: `\n      <span>{{ value }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('');\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useForm.spec.ts",
    "content": "import {\n  FieldMeta,\n  FormContext,\n  FormMeta,\n  useField,\n  useForm,\n  defineRule,\n  configure,\n  FieldContext,\n} from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises, dispatchEvent } from './helpers';\nimport * as z from 'zod';\nimport { onMounted, ref, Ref } from 'vue';\nimport { ModelComp, CustomModelComp } from './helpers/ModelComp';\n\ndescribe('useForm()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n\n  test('sets individual field error message', async () => {\n    let fieldMeta!: FieldMeta<unknown>;\n    mountWithHoc({\n      setup() {\n        const { setFieldError } = useForm({ initialValues: { field: 'test' } });\n        const { errorMessage, meta } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n        fieldMeta = meta;\n\n        return {\n          errorMessage,\n          setFieldError,\n        };\n      },\n      template: `\n      <span>{{ errorMessage }}</span>\n      <button @click=\"setFieldError('field', 'WRONG')\">Set Field Error</button>\n    `,\n    });\n\n    const error = document.querySelector('span');\n    await flushPromises();\n    expect(error?.textContent).toBe('');\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(error?.textContent).toBe('WRONG');\n    expect(fieldMeta.valid).toBe(false);\n  });\n\n  test('can clear individual field error messages', async () => {\n    let setFieldError!: FormContext['setFieldError'];\n    mountWithHoc({\n      setup() {\n        const form = useForm();\n        setFieldError = form.setFieldError;\n        const { errorMessage } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          errorMessage,\n          setFieldError,\n        };\n      },\n      template: `\n      <span>{{ errorMessage }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    setFieldError('field', 'WRONG');\n    await flushPromises();\n    expect(error?.textContent).toBe('WRONG');\n    setFieldError('field', undefined);\n    await flushPromises();\n    expect(error?.textContent).toBe('');\n  });\n\n  test('sets multiple field error messages', async () => {\n    mountWithHoc({\n      setup() {\n        const { setErrors } = useForm();\n        const { errorMessage: err1 } = useField('field1', val => (val ? true : REQUIRED_MESSAGE));\n        const { errorMessage: err2 } = useField('field2', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          err1,\n          err2,\n          setErrors,\n        };\n      },\n      template: `\n      <span>{{ err1 }}</span>\n      <span>{{ err2 }}</span>\n      <button @click=\"setErrors({ field1: 'WRONG', field2: 'WRONG AGAIN', field3: 'huh' })\">Set Field Error</button>\n    `,\n    });\n\n    const errors = document.querySelectorAll('span');\n    await flushPromises();\n    expect(errors[0]?.textContent).toBe('');\n    expect(errors[1]?.textContent).toBe('');\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(errors[0]?.textContent).toBe('WRONG');\n    expect(errors[1]?.textContent).toBe('WRONG AGAIN');\n  });\n\n  test('sets individual field touched meta', async () => {\n    mountWithHoc({\n      setup() {\n        const { setFieldTouched, meta: formMeta } = useForm();\n        const { meta } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          meta,\n          formMeta,\n          setFieldTouched,\n        };\n      },\n      template: `\n      <span id=\"field\">{{ meta.touched }}</span>\n      <span id=\"form\">{{ formMeta.touched }}</span>\n      <button @click=\"setFieldTouched('field', true)\">Set Meta</button>\n    `,\n    });\n\n    const fieldMeta = document.querySelector('#field');\n    const formMeta = document.querySelector('#form');\n    await flushPromises();\n    expect(fieldMeta?.textContent).toBe('false');\n    expect(formMeta?.textContent).toBe('false');\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(fieldMeta?.textContent).toBe('true');\n    expect(formMeta?.textContent).toBe('true');\n  });\n\n  test('sets multiple fields touched meta', async () => {\n    mountWithHoc({\n      setup() {\n        const { setTouched, meta: formMeta } = useForm();\n        const { meta: meta1 } = useField('field1', val => (val ? true : REQUIRED_MESSAGE));\n        const { meta: meta2 } = useField('field2', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          meta1,\n          meta2,\n          formMeta,\n          setTouched,\n        };\n      },\n      template: `\n      <span>{{ meta1.touched }}</span>\n      <span>{{ meta2.touched }}</span>\n      <span>{{ formMeta.touched }}</span>\n      <button @click=\"setTouched({ field1: true, field2: false, field3: false })\">Set Meta</button>\n    `,\n    });\n\n    const meta = document.querySelectorAll('span');\n\n    await flushPromises();\n    expect(meta[0]?.textContent).toBe('false');\n    expect(meta[1]?.textContent).toBe('false');\n    expect(meta[2]?.textContent).toBe('false');\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(meta[0]?.textContent).toBe('true');\n    expect(meta[1]?.textContent).toBe('false');\n    expect(meta[2]?.textContent).toBe('true');\n  });\n\n  // #4359\n  test('setValues should validate by default', async () => {\n    let form!: FormContext<any>;\n    mountWithHoc({\n      setup() {\n        form = useForm({ validationSchema: z.object({ field: z.string().min(1, REQUIRED_MESSAGE) }) });\n        form.defineField('field');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    expect(form.errors.value.field).toBe(undefined);\n\n    form.setValues({ field: '' });\n    await flushPromises();\n    expect(form.errors.value.field).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('setValues should not validate if passed false as second arg', async () => {\n    let form!: FormContext<any>;\n    mountWithHoc({\n      setup() {\n        form = useForm({ validationSchema: z.object({ field: z.string().min(1, REQUIRED_MESSAGE) }) });\n        form.defineField('field');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    expect(form.errors.value.field).toBe(undefined);\n\n    form.setValues({ field: '' }, false);\n    await flushPromises();\n    expect(form.errors.value.field).toBe(undefined);\n  });\n\n  test('has a validate() method that returns an aggregate of validation results using field rules', async () => {\n    let validate: any;\n    mountWithHoc({\n      setup() {\n        const form = useForm();\n        validate = form.validate;\n        useField('field1', val => (val ? true : REQUIRED_MESSAGE));\n        useField('field2', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    const result = await validate();\n    expect(result).toEqual({\n      valid: false,\n      source: 'fields',\n      errors: {\n        field1: REQUIRED_MESSAGE,\n        field2: REQUIRED_MESSAGE,\n      },\n      results: {\n        field1: {\n          valid: false,\n          errors: [REQUIRED_MESSAGE],\n        },\n        field2: {\n          valid: false,\n          errors: [REQUIRED_MESSAGE],\n        },\n      },\n      values: {},\n    });\n  });\n\n  test('has a validate method that returns an aggregate of validation results using validation schema', async () => {\n    let validate: any;\n    mountWithHoc({\n      setup() {\n        const form = useForm({\n          validationSchema: z.object({\n            field1: z.string().min(1, 'Required'),\n            field2: z.string().min(1, 'Required'),\n          }),\n        });\n\n        validate = form.validate;\n        useField('field1');\n        useField('field2');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    const pending = validate();\n    await flushPromises();\n    const result = await pending;\n    expect(result).toEqual({\n      valid: false,\n      source: 'schema',\n      errors: {\n        field1: 'Invalid input: expected string, received undefined',\n        field2: 'Invalid input: expected string, received undefined',\n      },\n      results: {\n        field1: {\n          valid: false,\n          errors: ['Invalid input: expected string, received undefined'],\n        },\n        field2: {\n          valid: false,\n          errors: ['Invalid input: expected string, received undefined'],\n        },\n      },\n    });\n  });\n\n  test('has a validateField() method that validates a specific field', async () => {\n    let validateField: any;\n    mountWithHoc({\n      setup() {\n        const form = useForm();\n        validateField = form.validateField;\n        const { errorMessage: f1 } = useField('field1', val => (val ? true : REQUIRED_MESSAGE));\n        const { errorMessage: f2 } = useField('field2', val => (val ? true : REQUIRED_MESSAGE));\n\n        return { f1, f2 };\n      },\n      template: `<div>\n        <span id=\"f1\">{{ f1 }}</span>\n        <span id=\"f2\">{{ f2 }}</span>\n      </div>`,\n    });\n\n    await flushPromises();\n    const result = await validateField('field2');\n    expect(result).toEqual({\n      valid: false,\n      errors: [REQUIRED_MESSAGE],\n    });\n\n    expect(document.querySelector('#f2')?.textContent).toBe(REQUIRED_MESSAGE);\n    expect(document.querySelector('#f1')?.textContent).toBe('');\n  });\n\n  test('warns when validateField() is called on a non-existent field', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    let validateField: any;\n    mountWithHoc({\n      setup() {\n        const form = useForm();\n        validateField = form.validateField;\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    const result = await validateField('field2');\n    expect(result).toEqual({\n      valid: true,\n      errors: [],\n    });\n\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('hoists nested field errors to their parent if no field has it', async () => {\n    let form!: FormContext;\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          validationSchema: z.object({\n            name: z.object({\n              value: z.string().min(1, 'Required'),\n            }),\n          }),\n          validateOnMount: true,\n        });\n\n        useField('name');\n\n        return {};\n      },\n      template: `\n      <div></div>\n    `,\n    });\n\n    await flushPromises();\n    expect(form.errors.value.name).toBe('Invalid input: expected object, received undefined');\n    expect(form.meta.value.valid).toBe(false);\n  });\n\n  test('selects the deepest candidate for hoisted errors', async () => {\n    let form!: FormContext<any>;\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          validationSchema: z.object({\n            names: z.object({\n              value: z.array(z.object({ name: z.string().min(1, REQUIRED_MESSAGE) })),\n            }),\n          }),\n          validateOnMount: true,\n          initialValues: {\n            names: {\n              value: [{ name: '' }, { name: '' }, { name: '' }],\n            },\n          },\n        });\n\n        useField('names.value');\n        useField('names');\n\n        return {};\n      },\n      template: `\n      <div></div>\n    `,\n    });\n\n    await flushPromises();\n    expect(form.errors.value.names).toBe(undefined);\n    expect(form.errors.value['names.value']).toBe(REQUIRED_MESSAGE);\n    expect(form.meta.value.valid).toBe(false);\n  });\n\n  test('resets the meta valid state on reset', async () => {\n    let passwordValue!: Ref<string>;\n    mountWithHoc({\n      setup() {\n        const { meta: formMeta, resetForm, errors } = useForm();\n        const { value } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n        const { value: pwValue } = useField<string>('password', val => (val ? true : REQUIRED_MESSAGE));\n        passwordValue = pwValue;\n\n        return {\n          value,\n          formMeta,\n          resetForm,\n          errors,\n        };\n      },\n      template: `\n      <input v-model=\"value\" />\n      <span id=\"meta\">{{ formMeta.valid ? 'valid': 'invalid' }}</span>\n      <span id=\"errors\">{{ errors }}</span>\n      <button @click=\"resetForm()\">Reset Meta</button>\n    `,\n    });\n\n    await flushPromises();\n    const span = document.querySelector('#meta');\n    const errors = document.querySelector('#errors');\n    const input = document.querySelector('input') as HTMLInputElement;\n    expect(span?.textContent).toBe('invalid');\n    setValue(input, '12');\n    await flushPromises();\n    // still other field is invalid\n    expect(span?.textContent).toBe('invalid');\n    // but the error is silent so errors should be empty\n    expect(errors?.textContent).toBe('{}');\n\n    passwordValue.value = '12';\n    await flushPromises();\n    // now both should be valid\n    expect(span?.textContent).toBe('valid');\n    expect(errors?.textContent).toBe('{}');\n\n    document.querySelector('button')?.click();\n    await flushPromises();\n    // validation was run again silently\n    expect(span?.textContent).toBe('invalid');\n    expect(errors?.textContent).toBe('{}');\n  });\n\n  test('resets the meta valid state on reset with the errors length', async () => {\n    mountWithHoc({\n      setup() {\n        const { meta: formMeta, resetForm } = useForm();\n        const { value } = useField('field', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          value,\n          formMeta,\n          resetForm,\n        };\n      },\n      template: `\n      <input v-model=\"value\" />\n      <span id=\"meta\">{{ formMeta.valid ? 'valid': 'invalid' }}</span>\n      <button @click=\"resetForm({ errors: { field: 'test' } })\">Reset Meta</button>\n    `,\n    });\n\n    await flushPromises();\n    const span = document.querySelector('#meta');\n    expect(span?.textContent).toBe('invalid');\n\n    const input = document.querySelector('input') as HTMLInputElement;\n    setValue(input, '12');\n    await flushPromises();\n    expect(span?.textContent).toBe('valid');\n\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(span?.textContent).toBe('invalid');\n  });\n\n  test('resets the meta dirty on reset', async () => {\n    mountWithHoc({\n      setup() {\n        const { meta: formMeta, resetForm } = useForm();\n        const { meta: meta1, value } = useField('field1', val => (val ? true : REQUIRED_MESSAGE));\n        const { meta: meta2 } = useField('field2', val => (val ? true : REQUIRED_MESSAGE));\n\n        return {\n          meta1,\n          meta2,\n          formMeta,\n          resetForm,\n          value,\n        };\n      },\n      template: `\n      <input v-model=\"value\">\n      <span>{{ meta1.dirty }}</span>\n      <span>{{ meta2.dirty }}</span>\n      <span>{{ formMeta.dirty }}</span>\n      <button @click=\"resetForm()\">Reset</button>\n    `,\n    });\n\n    const meta = document.querySelectorAll('span');\n    const input = document.querySelector('input') as HTMLInputElement;\n\n    await flushPromises();\n    expect(meta[0]?.textContent).toBe('false');\n    expect(meta[1]?.textContent).toBe('false');\n    expect(meta[2]?.textContent).toBe('false');\n\n    setValue(input, '1');\n    await flushPromises();\n    expect(meta[0]?.textContent).toBe('true');\n    expect(meta[1]?.textContent).toBe('false');\n    expect(meta[2]?.textContent).toBe('true');\n\n    document.querySelector('button')?.click();\n    await flushPromises();\n    expect(meta[0]?.textContent).toBe('false');\n    expect(meta[1]?.textContent).toBe('false');\n    expect(meta[2]?.textContent).toBe('false');\n  });\n\n  // #3906\n  test('only latest schema validation run messages are used', async () => {\n    function validator(value: string | undefined) {\n      if (!value) {\n        return true;\n      }\n\n      if (value.toLowerCase().startsWith('b')) {\n        return 'not b';\n      }\n\n      return new Promise<string | boolean>(resolve => {\n        setTimeout(() => {\n          if (value.toLowerCase().startsWith('a')) {\n            resolve('not a');\n            return;\n          }\n\n          resolve(true);\n        }, 100);\n      });\n    }\n\n    mountWithHoc({\n      setup() {\n        const { errors, defineField } = useForm({\n          validationSchema: {\n            test: validator,\n          },\n        });\n\n        const [model, props] = defineField('test');\n\n        return {\n          model,\n          errors,\n          props,\n        };\n      },\n      template: `\n        <input name=\"field\" v-model=\"model\" v-bind=\"props\" />\n        <span>{{ errors.test }}</span>\n      `,\n    });\n\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n\n    setValue(input as any, 'a');\n    await flushPromises();\n    setValue(input as any, 'b');\n    await flushPromises();\n    vi.advanceTimersByTime(200);\n    await flushPromises();\n    expect(error?.textContent).toBe('not b');\n  });\n\n  // #3862\n  test('exposes controlled only values', async () => {\n    const spy = vi.fn();\n    const initial = {\n      field: '111',\n      createdAt: Date.now(),\n    };\n    mountWithHoc({\n      setup() {\n        const { controlledValues, handleSubmit } = useForm({\n          initialValues: initial,\n        });\n\n        const onSubmit = handleSubmit(values => {\n          spy({ values, controlled: controlledValues.value });\n        });\n\n        useField('field');\n\n        onMounted(onSubmit);\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n    expect(spy).toHaveBeenCalledTimes(1);\n    expect(spy).toHaveBeenLastCalledWith(\n      expect.objectContaining({\n        values: initial,\n        controlled: { field: initial.field },\n      }),\n    );\n  });\n\n  // #3862\n  test('exposes controlled only via submission handler withControlled', async () => {\n    const spy = vi.fn();\n    const initial = {\n      field: '111',\n      createdAt: Date.now(),\n    };\n    mountWithHoc({\n      setup() {\n        const { handleSubmit } = useForm({\n          initialValues: initial,\n        });\n\n        const onSubmit = handleSubmit.withControlled(values => {\n          spy({ values });\n        });\n\n        useField('field');\n\n        onMounted(onSubmit);\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n    expect(spy).toHaveBeenCalledTimes(1);\n    expect(spy).toHaveBeenLastCalledWith(\n      expect.objectContaining({\n        values: { field: initial.field },\n      }),\n    );\n  });\n\n  // #3981 #3982\n  test('fields validated meta should not be mutated when silently validating fields', async () => {\n    let meta!: FieldMeta<any>;\n\n    mountWithHoc({\n      setup() {\n        const { validate } = useForm({\n          validationSchema: z.object({\n            name: z.string().min(1),\n          }),\n        });\n\n        const field = useField('name');\n        meta = field.meta;\n\n        onMounted(() => {\n          validate({ mode: 'silent' });\n          validate({ mode: 'validated-only' });\n        });\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n    expect(meta.validated).toBe(false);\n  });\n\n  // #4320\n  test('Initial values are merged with previous values to ensure meta.dirty is stable', async () => {\n    let meta!: Ref<FormMeta<any>>;\n\n    mountWithHoc({\n      setup() {\n        const { resetForm, meta: fm } = useForm();\n        useField('name');\n        useField('email');\n\n        meta = fm;\n\n        onMounted(() => {\n          resetForm({ values: { name: 'test' } });\n        });\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n    expect(meta.value.dirty).toBe(false);\n  });\n\n  // #3991\n  test('initial value should not be mutable if nested field model is used', async () => {\n    let model!: Ref<{ name: string }>;\n    let formMeta!: Ref<FormMeta<{ field: { name: string } }>>;\n    let reset!: () => void;\n\n    mountWithHoc({\n      setup() {\n        const { meta, resetForm } = useForm({\n          initialValues: { field: { name: '1' } },\n          validationSchema: z.object({\n            name: z.string().min(1),\n            field: z.object({\n              name: z.string().min(1),\n            }),\n          }),\n        });\n\n        const field = useField<{ name: string }>('field');\n        model = field.value;\n        formMeta = meta;\n        reset = resetForm;\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n    expect(formMeta.value.initialValues?.field?.name).toBe('1');\n    model.value.name = 'test';\n    await flushPromises();\n    expect(model.value).toEqual({ name: 'test' });\n    expect(formMeta.value.initialValues?.field?.name).toBe('1');\n    reset();\n    await flushPromises();\n    expect(model.value).toEqual({ name: '1' });\n    expect(formMeta.value.initialValues?.field?.name).toBe('1');\n\n    model.value.name = 'test';\n    await flushPromises();\n    expect(model.value).toEqual({ name: 'test' });\n    expect(formMeta.value.initialValues?.field?.name).toBe('1');\n  });\n\n  describe('defineField', () => {\n    test('creates bindable object to components', async () => {\n      mountWithHoc({\n        components: {\n          ModelComp,\n        },\n        setup() {\n          const { defineField, values, errors } = useForm({\n            validationSchema: z.object({\n              name: z.string().min(1),\n            }),\n          });\n\n          const [model, props] = defineField('name');\n\n          return { props, model, values, errors };\n        },\n        template: `\n        <ModelComp v-model=\"model\" v-bind=\"props\" />\n        <span id=\"errors\">{{ errors.name }}</span>\n        <span id=\"values\">{{ values.name }}</span>\n      `,\n      });\n\n      await flushPromises();\n      const errorEl = document.getElementById('errors');\n      const valuesEl = document.getElementById('values');\n      setValue(document.querySelector('input') as any, '');\n      dispatchEvent(document.querySelector('input') as any, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('Too small: expected string to have >=1 characters');\n      setValue(document.querySelector('input') as any, '123');\n      dispatchEvent(document.querySelector('input') as any, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('');\n      expect(valuesEl?.textContent).toBe('123');\n    });\n\n    test('can configure the validation events', async () => {\n      mountWithHoc({\n        components: {\n          ModelComp,\n        },\n        setup() {\n          const { defineField, values, errors } = useForm({\n            validationSchema: z.object({\n              name: z.string().min(1),\n            }),\n          });\n\n          const [model, props] = defineField('name', { validateOnModelUpdate: false });\n\n          return { props, model, values, errors };\n        },\n        template: `\n        <ModelComp v-model=\"model\" v-bind=\"props\" />\n        <span id=\"errors\">{{ errors.name }}</span>\n        <span id=\"values\">{{ values.name }}</span>\n      `,\n      });\n\n      await flushPromises();\n      const errorEl = document.getElementById('errors');\n      const valuesEl = document.getElementById('values');\n      const input = document.querySelector('input') as HTMLInputElement;\n      setValue(input, '');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('');\n      dispatchEvent(input, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('Too small: expected string to have >=1 characters');\n      setValue(input, '123');\n      dispatchEvent(input, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('');\n      expect(valuesEl?.textContent).toBe('123');\n    });\n\n    test('can pass extra props', async () => {\n      mountWithHoc({\n        components: {\n          ModelComp,\n        },\n        setup() {\n          const { defineField } = useForm({\n            validationSchema: z.object({\n              name: z.string().min(1),\n            }),\n          });\n\n          const [model, props] = defineField('name', {\n            validateOnModelUpdate: true,\n            props: state => ({ test: state.valid ? 'valid' : 'invalid' }),\n          });\n\n          return { model, props };\n        },\n        template: `\n        <ModelComp v-model=\"model\" v-bind=\"props\" />\n      `,\n      });\n\n      await flushPromises();\n      setValue(document.querySelector('input') as any, '');\n      await flushPromises();\n      expect(document.body.innerHTML).toContain('invalid');\n      setValue(document.querySelector('input') as any, '123');\n      await flushPromises();\n      expect(document.body.innerHTML).toContain('valid');\n    });\n\n    test('can have lazy config', async () => {\n      mountWithHoc({\n        components: {\n          ModelComp,\n        },\n        setup() {\n          const { defineField } = useForm({\n            validationSchema: z.object({\n              name: z.string().min(1),\n            }),\n          });\n\n          const [model, props] = defineField('name', state => ({\n            props: { test: state.valid ? 'valid' : 'invalid' },\n            validateOnModelUpdate: true,\n          }));\n\n          return { model, props };\n        },\n        template: `\n        <ModelComp v-model=\"model\" v-bind=\"props\" />\n      `,\n      });\n\n      await flushPromises();\n      setValue(document.querySelector('input') as any, '');\n      await flushPromises();\n      expect(document.body.innerHTML).toContain('invalid');\n      setValue(document.querySelector('input') as any, '123');\n      await flushPromises();\n      expect(document.body.innerHTML).toContain('valid');\n    });\n\n    test('works with custom model', async () => {\n      mountWithHoc({\n        components: {\n          CustomModelComp,\n        },\n        setup() {\n          const { defineField, values, errors } = useForm({\n            validationSchema: z.object({\n              name: z.string().min(1),\n            }),\n          });\n\n          const [model, props] = defineField('name');\n\n          return { model, props, values, errors };\n        },\n        template: `\n        <CustomModelComp v-model:value=\"model\" v-bind=\"props\" />\n        <span id=\"errors\">{{ errors.name }}</span>\n        <span id=\"values\">{{ values.name }}</span>\n      `,\n      });\n\n      await flushPromises();\n      const errorEl = document.getElementById('errors');\n      const valuesEl = document.getElementById('values');\n      setValue(document.querySelector('input') as any, '');\n      dispatchEvent(document.querySelector('input') as any, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('Too small: expected string to have >=1 characters');\n      setValue(document.querySelector('input') as any, '123');\n      dispatchEvent(document.querySelector('input') as any, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('');\n      expect(valuesEl?.textContent).toBe('123');\n    });\n\n    test('creates bindable object to HTML inputs', async () => {\n      mountWithHoc({\n        setup() {\n          const { defineField, values, errors } = useForm({\n            validationSchema: z.object({\n              name: z.string().min(1),\n            }),\n          });\n\n          const [model, props] = defineField('name');\n\n          return { model, props, values, errors };\n        },\n        template: `\n        <input v-model=\"model\" v-bind=\"props\" />\n        <span id=\"errors\">{{ errors.name }}</span>\n        <span id=\"values\">{{ values.name }}</span>\n      `,\n      });\n\n      await flushPromises();\n      const errorEl = document.getElementById('errors');\n      const valuesEl = document.getElementById('values');\n      setValue(document.querySelector('input') as any, '');\n      dispatchEvent(document.querySelector('input') as any, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('Too small: expected string to have >=1 characters');\n      setValue(document.querySelector('input') as any, '123');\n      dispatchEvent(document.querySelector('input') as any, 'blur');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('');\n      expect(valuesEl?.textContent).toBe('123');\n    });\n\n    test('can configure the validation events', async () => {\n      mountWithHoc({\n        setup() {\n          const { defineField, values, errors } = useForm({\n            validationSchema: z.object({\n              name: z.string().min(1),\n            }),\n          });\n\n          const [model, props] = defineField('name', { validateOnInput: true });\n\n          return { model, props, values, errors };\n        },\n        template: `\n        <input v-model=\"model\" v-bind=\"props\" />\n        <span id=\"errors\">{{ errors.name }}</span>\n        <span id=\"values\">{{ values.name }}</span>\n      `,\n      });\n\n      await flushPromises();\n      const errorEl = document.getElementById('errors');\n      const valuesEl = document.getElementById('values');\n      setValue(document.querySelector('input') as any, '');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('Too small: expected string to have >=1 characters');\n      setValue(document.querySelector('input') as any, '123');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('');\n      expect(valuesEl?.textContent).toBe('123');\n    });\n\n    test('can pass extra props', async () => {\n      mountWithHoc({\n        setup() {\n          const { defineField } = useForm({\n            validationSchema: z.object({\n              name: z.string().min(1),\n            }),\n          });\n\n          const [model, props] = defineField('name', {\n            validateOnInput: true,\n            props: state => ({ 'aria-valid': state.valid ? 'true' : 'false' }),\n          });\n\n          return { model, props };\n        },\n        template: `\n        <input v-model=\"model\" v-bind=\"props\" />\n      `,\n      });\n\n      await flushPromises();\n      setValue(document.querySelector('input') as any, '');\n      await flushPromises();\n      expect(document.body.innerHTML).toContain('aria-valid=\"false\"');\n      setValue(document.querySelector('input') as any, '123');\n      await flushPromises();\n      expect(document.body.innerHTML).toContain('aria-valid=\"true\"');\n    });\n\n    test('can have lazy config', async () => {\n      mountWithHoc({\n        components: {\n          ModelComp,\n        },\n        setup() {\n          const { defineField } = useForm({\n            validationSchema: z.object({\n              name: z.string().min(1),\n            }),\n          });\n\n          const [model, props] = defineField('name', state => ({\n            props: { 'aria-valid': state.valid ? 'true' : 'false' },\n            validateOnModelUpdate: true,\n          }));\n\n          return { model, props };\n        },\n        template: `\n        <input v-model=\"model\" v-bind=\"props\" />\n      `,\n      });\n\n      await flushPromises();\n      setValue(document.querySelector('input') as any, '');\n      await flushPromises();\n      expect(document.body.innerHTML).toContain('aria-valid=\"false\"');\n      setValue(document.querySelector('input') as any, '123');\n      await flushPromises();\n      expect(document.body.innerHTML).toContain('aria-valid=\"true\"');\n    });\n\n    test('can specify a label', async () => {\n      defineRule('required', (value: string) => {\n        return !!value;\n      });\n\n      configure({\n        generateMessage: ({ field }) => `${field} is bad`,\n      });\n\n      mountWithHoc({\n        setup() {\n          const { defineField, values, errors } = useForm({\n            validationSchema: {\n              name: 'required',\n            },\n          });\n\n          const [model, props] = defineField('name', { validateOnInput: true, label: 'First Name' });\n\n          return { model, props, values, errors };\n        },\n        template: `\n        <input v-model=\"model\" v-bind=\"props\" />\n        <span id=\"errors\">{{ errors.name }}</span>\n      `,\n      });\n\n      await flushPromises();\n      const errorEl = document.getElementById('errors');\n      setValue(document.querySelector('input') as any, '');\n      await flushPromises();\n      expect(errorEl?.textContent).toBe('First Name is bad');\n    });\n  });\n\n  // #4341\n  test('undefined field value should be the same as missing value when it comes to dirty', async () => {\n    let form!: FormContext<any>;\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          initialValues: {\n            fname: '',\n          },\n        });\n\n        useField('fname');\n        useField('lname');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    expect(form.meta.value.dirty).toBe(false);\n  });\n\n  // #4678\n  test('form is marked as dirty when key is removed', async () => {\n    let form!: FormContext<any>;\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          initialValues: {\n            fname: {\n              key1: 'value1',\n              key2: 'value2',\n            },\n          },\n        });\n\n        useField('fname');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    form.setFieldValue('fname', { key1: 'value1' });\n    await flushPromises();\n    expect(form.meta.value.dirty).toBe(true);\n  });\n\n  describe('error paths can have dot or square bracket for the same field', () => {\n    test('path is bracket, mutations are dot', async () => {\n      let field!: FieldContext<unknown>;\n      let errorSetter!: FormContext['setFieldError'];\n      mountWithHoc({\n        setup() {\n          const { setFieldError } = useForm();\n          field = useField('users[0].test');\n          errorSetter = setFieldError;\n          return {};\n        },\n        template: `<div></div>`,\n      });\n\n      await flushPromises();\n      expect(field.errorMessage.value).toBe(undefined);\n      await flushPromises();\n      errorSetter('users.0.test', 'error');\n      await flushPromises();\n      expect(field.errorMessage.value).toBe('error');\n    });\n\n    test('path is dot, mutations are bracket', async () => {\n      let field!: FieldContext<unknown>;\n      let errorSetter!: FormContext['setFieldError'];\n      mountWithHoc({\n        setup() {\n          const { setFieldError } = useForm();\n          field = useField('users.0.test');\n          errorSetter = setFieldError;\n          return {};\n        },\n        template: `<div></div>`,\n      });\n\n      await flushPromises();\n      expect(field.errorMessage.value).toBe(undefined);\n      await flushPromises();\n      errorSetter('users[0].test', 'error');\n      await flushPromises();\n      expect(field.errorMessage.value).toBe('error');\n    });\n  });\n\n  test('can query field touched state', async () => {\n    let form!: FormContext<any>;\n    mountWithHoc({\n      setup() {\n        form = useForm();\n        useField('fname');\n        useField('nested.lname');\n        useField('nested.fname');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    expect(form.meta.value.touched).toBe(false);\n    expect(form.isFieldTouched('fname')).toBe(false);\n    expect(form.isFieldTouched('nested')).toBe(false);\n    form.setFieldTouched('fname', true);\n    form.setFieldTouched('nested.lname', true);\n    await flushPromises();\n    expect(form.meta.value.touched).toBe(true);\n    expect(form.isFieldTouched('fname')).toBe(true);\n    expect(form.isFieldTouched('nested')).toBe(true);\n  });\n\n  test('can query field dirty state', async () => {\n    let form!: FormContext<any>;\n    mountWithHoc({\n      setup() {\n        form = useForm();\n        useField('fname');\n        useField('nested.lname');\n        useField('nested.fname');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    expect(form.meta.value.dirty).toBe(false);\n    expect(form.isFieldDirty('fname')).toBe(false);\n    expect(form.isFieldDirty('nested')).toBe(false);\n    form.setFieldValue('fname', 'value');\n    form.setFieldValue('nested.lname', 'value');\n    await flushPromises();\n    expect(form.meta.value.dirty).toBe(true);\n    expect(form.isFieldDirty('fname')).toBe(true);\n    expect(form.isFieldDirty('nested')).toBe(true);\n  });\n\n  test('can query field valid state', async () => {\n    let form!: FormContext<any>;\n    mountWithHoc({\n      setup() {\n        form = useForm();\n        useField('fname');\n        useField('nested.lname');\n        useField('nested.fname');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    expect(form.meta.value.valid).toBe(true);\n    expect(form.isFieldValid('fname')).toBe(true);\n    expect(form.isFieldValid('nested')).toBe(true);\n    form.setFieldError('fname', 'ERROR');\n    form.setFieldError('nested.lname', 'ERROR');\n    await flushPromises();\n    expect(form.meta.value.valid).toBe(false);\n    expect(form.isFieldValid('fname')).toBe(false);\n    expect(form.isFieldValid('nested')).toBe(false);\n  });\n\n  // #4438\n  test('silent validation should not mark a field as validated', async () => {\n    let form!: FormContext<any>;\n    const showFields = ref(false);\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          validationSchema: z.object({\n            fname: z.string().min(1),\n            lname: z.string().min(1),\n          }),\n        });\n\n        return {\n          showFields,\n        };\n      },\n      template: `<div>\n        <template v-if=\"showFields\">\n          <Field name=\"fname\" />\n          <Field name=\"lname\" />\n        </template>\n\n      </div>`,\n    });\n\n    await flushPromises();\n    showFields.value = true;\n    await flushPromises();\n    expect(form.errors.value.fname).toBe(undefined);\n    expect(form.errors.value.lname).toBe(undefined);\n\n    setValue(document.querySelector('input') as any, '123');\n    await flushPromises();\n    expect(form.errors.value.fname).toBe(undefined);\n    expect(form.errors.value.lname).toBe(undefined);\n  });\n\n  test('values can be reset to specifically only include the provided fields', async () => {\n    let form!: FormContext<{ fname: string; lname: string }>;\n\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          initialValues: { fname: '123', lname: '456' },\n        });\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n\n    form.resetForm({ values: { fname: 'test' } }, { force: true });\n    expect(form.values.lname).toBeUndefined();\n    expect(form.values.fname).toBe('test');\n  });\n\n  test('reset should be able to set initial values to undefined with force: true', async () => {\n    let form!: FormContext<{ lname: string; fname: string }>;\n\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          initialValues: { fname: '123', lname: '456' },\n        });\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n\n    // FAIL\n    form.resetForm({ values: { lname: '789' } }, { force: true });\n    expect(form.meta.value.initialValues?.fname).toBeUndefined(); // This is not undefined. It stayed at value '123'\n    expect(form.meta.value.initialValues?.lname).toBe('789');\n\n    // FAIL\n    form.resetForm({ values: {} }, { force: true });\n    expect(form.meta.value.initialValues?.fname).toBeUndefined();\n    expect(form.meta.value.initialValues?.lname).toBeUndefined();\n\n    // PASS\n    form.resetForm({ values: { lname: undefined, fname: undefined } }, { force: true });\n    expect(form.meta.value.initialValues?.fname).toBeUndefined();\n    expect(form.meta.value.initialValues?.lname).toBeUndefined();\n  });\n\n  test('reset should not make unspecified values undefined', async () => {\n    let form!: FormContext<{ fname: string; lname: string }>;\n\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          initialValues: { fname: '123', lname: '456' },\n        });\n\n        form.defineField('fname');\n        form.defineField('lname');\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n\n    form.resetForm({ values: { fname: 'test' } });\n    expect(form.values.lname).toBe('456');\n    expect(form.values.fname).toBe('test');\n  });\n\n  test('reset field should make the dirty state false', async () => {\n    let form!: FormContext<{ fname: string; lname: string }>;\n\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          initialValues: { fname: '123', lname: '456' },\n        });\n\n        form.defineField('fname');\n        form.defineField('lname');\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n\n    form.resetField('fname', { value: 'test' });\n    expect(form.meta.value.dirty).toBe(false);\n  });\n\n  test('defineField respects global model config', async () => {\n    let form!: FormContext<{ fname: string; lname: string }>;\n    let model!: Ref<string>;\n    configure({\n      validateOnModelUpdate: false,\n    });\n\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          initialValues: { fname: '123', lname: '456' },\n          validationSchema: z.object({\n            fname: z.string().min(1),\n            lname: z.string().min(1),\n          }),\n        });\n\n        const field = form.defineField('fname');\n        model = field[0];\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n    model.value = '';\n    await flushPromises();\n    await expect(form.errors.value.fname).toBe(undefined);\n  });\n\n  test('checks if both source and target are POJO before setting properties', async () => {\n    let form!: FormContext<{ file: { name: string; size: number } }>;\n    const f1 = new File([''], 'f1.text');\n    const f2 = { name: 'f2.text', size: 123 };\n\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          initialValues: { file: f1 },\n        });\n\n        form.defineField('file');\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n    expect(form.values.file).toBeInstanceOf(File);\n    expect(form.values.file).toBe(f1);\n    form.setValues({ file: f2 });\n    expect(form.values.file).toEqual(f2);\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useFormErrors.spec.ts",
    "content": "import { useField, useForm, useFormErrors } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\n\ndescribe('useFormErrors()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const validate = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('gives access to all form errors', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value } = useField('test', validate);\n        const messages = useFormErrors();\n\n        return {\n          value,\n          messages,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ messages.test }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    setValue(input as any, '');\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('returns empty object and warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        const messages = useFormErrors();\n\n        return {\n          messages,\n        };\n      },\n      template: `\n      <span>{{ messages }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('{}');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useFormValues.spec.ts",
    "content": "import { useField, useForm, useFormValues } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\n\ndescribe('useFormValues()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const validate = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('gives access to all form values', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value } = useField('test', validate);\n        const values = useFormValues();\n\n        return {\n          value,\n          values,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ values.test }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const valueSpan = document.querySelector('span');\n    const inputValue = '1234';\n    setValue(input as any, inputValue);\n    await flushPromises();\n    expect(valueSpan?.textContent).toBe(inputValue);\n  });\n\n  test('returns empty object and warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        const values = useFormValues();\n\n        return {\n          values,\n        };\n      },\n      template: `\n      <span>{{ values }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const valuesSpan = document.querySelector('span');\n    expect(valuesSpan?.textContent).toBe('{}');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useIsFieldDirty.spec.ts",
    "content": "import { useField, useForm, useIsFieldDirty } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\nimport { defineComponent } from 'vue';\n\ndescribe('useIsFieldDirty()', () => {\n  test('gives access to a single field isDirty status', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value, handleChange } = useField('test');\n        const isDirty = useIsFieldDirty('test');\n\n        return {\n          value,\n          isDirty,\n          handleInput: (e: any) => handleChange(e, false),\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" @input=\"handleInput\" />\n      <span>{{ isDirty.toString() }}</span>\n    `,\n    });\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n\n    setValue(input as any, '');\n    await flushPromises();\n    expect(error?.textContent).toBe('true');\n  });\n\n  test('gives access to a single field isDirty status in a child component without specifying a path', async () => {\n    const DirtyIcon = defineComponent({\n      template: '<span>{{ isDirty.toString() }}</span>',\n      setup() {\n        const isDirty = useIsFieldDirty();\n\n        return {\n          isDirty,\n        };\n      },\n    });\n    mountWithHoc({\n      components: {\n        DirtyIcon,\n      },\n      setup() {\n        useForm();\n        const { value, handleChange } = useField('test');\n\n        return {\n          value,\n          handleInput: (e: any) => handleChange(e, false),\n        };\n      },\n      template: `\n        <input name=\"field\" v-model=\"value\" @input=\"handleInput\" />\n        <DirtyIcon />\n      `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n\n    setValue(input as any, '');\n    await flushPromises();\n    expect(error?.textContent).toBe('true');\n  });\n\n  test('gives access to array fields isDirty status', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value, handleChange } = useField('test');\n        useField('test');\n        const isDirty = useIsFieldDirty('test');\n\n        return {\n          value,\n          isDirty,\n          handleInput: (e: any) => handleChange(e, false),\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" @input=\"handleInput\" />\n      <span>{{ isDirty.toString() }}</span>\n    `,\n    });\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n\n    setValue(input as any, '');\n    await flushPromises();\n    expect(error?.textContent).toBe('true');\n  });\n\n  test('returns false and warns if field does not exist', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        useForm();\n        const isDirty = useIsFieldDirty('something');\n\n        return {\n          isDirty,\n        };\n      },\n      template: `\n      <span>{{ isDirty.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('returns false and warns if form does not exist', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        const isDirty = useIsFieldDirty('something');\n\n        return {\n          isDirty,\n        };\n      },\n      template: `\n      <span>{{ isDirty.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useIsFieldTouched.spec.ts",
    "content": "import { useField, useForm, useIsFieldTouched } from '@/vee-validate';\nimport { dispatchEvent, mountWithHoc, flushPromises } from './helpers';\nimport { defineComponent } from 'vue';\n\ndescribe('useIsFieldTouched()', () => {\n  test('gives access to a single field isTouched status', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value, handleBlur } = useField('test');\n        const isTouched = useIsFieldTouched('test');\n\n        return {\n          value,\n          isTouched,\n          handleBlur,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" @blur=\"handleBlur\" />\n      <span>{{ isTouched.toString() }}</span>\n    `,\n    });\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n\n    dispatchEvent(input as any, 'blur');\n\n    await flushPromises();\n    expect(error?.textContent).toBe('true');\n  });\n\n  test('gives access to a single field isTouched status in child components without path prop', async () => {\n    const TouchedIcon = defineComponent({\n      template: '<span>{{ isTouched.toString() }}</span>',\n      setup() {\n        const isTouched = useIsFieldTouched();\n\n        return {\n          isTouched,\n        };\n      },\n    });\n    mountWithHoc({\n      components: {\n        TouchedIcon,\n      },\n      setup() {\n        useForm();\n        const { value, handleBlur } = useField('test');\n\n        return {\n          value,\n          handleBlur,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" @blur=\"handleBlur\" />\n      <TouchedIcon />\n    `,\n    });\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n\n    dispatchEvent(input as any, 'blur');\n\n    await flushPromises();\n    expect(error?.textContent).toBe('true');\n  });\n\n  test('gives access to array fields isTouched status', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value, handleBlur } = useField('test', undefined, { type: 'checkbox' });\n        useField('test', undefined, { type: 'checkbox' });\n        const isTouched = useIsFieldTouched('test');\n\n        return {\n          value,\n          isTouched,\n          handleBlur,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" @blur=\"handleBlur\" />\n      <span>{{ isTouched.toString() }}</span>\n    `,\n    });\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n\n    dispatchEvent(input as any, 'blur');\n\n    await flushPromises();\n    expect(error?.textContent).toBe('true');\n  });\n\n  test('returns false and warns if field does not exist', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        useForm();\n        const isTouched = useIsFieldTouched('something');\n\n        return {\n          isTouched,\n        };\n      },\n      template: `\n      <span>{{ isTouched.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('returns false and warns if form does not exist', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        const isTouched = useIsFieldTouched('something');\n\n        return {\n          isTouched,\n        };\n      },\n      template: `\n      <span>{{ isTouched.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useIsFieldValid.spec.ts",
    "content": "import { useField, useIsFieldValid, useForm } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\nimport { defineComponent } from 'vue';\n\ndescribe('useIsFieldValid()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const validate = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('returns the validity of a single field', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value } = useField('test', validate);\n        const isValid = useIsFieldValid('test');\n\n        return {\n          value,\n          isValid,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ isValid.toString() }}</span>\n    `,\n    });\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const span = document.querySelector('span');\n    setValue(input as any, '');\n    await flushPromises();\n    expect(span?.textContent).toBe('false');\n    setValue(input as any, '12');\n    await flushPromises();\n    expect(span?.textContent).toBe('true');\n  });\n\n  test('returns the validity of a single field in child components without specifying a path', async () => {\n    const ValidIcon = defineComponent({\n      template: '<span>{{ isValid.toString() }}</span>',\n      setup() {\n        const isValid = useIsFieldValid();\n\n        return {\n          isValid,\n        };\n      },\n    });\n    mountWithHoc({\n      components: {\n        ValidIcon,\n      },\n      setup() {\n        useForm();\n        const { value } = useField('test', validate);\n\n        return {\n          value,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <ValidIcon />\n    `,\n    });\n\n    await flushPromises();\n\n    const input = document.querySelector('input');\n    const span = document.querySelector('span');\n    setValue(input as any, '');\n    await flushPromises();\n    expect(span?.textContent).toBe('false');\n    setValue(input as any, '12');\n    await flushPromises();\n    expect(span?.textContent).toBe('true');\n  });\n\n  test('returns the validity of array fields', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value } = useField('test', validate);\n        useField('test', validate);\n        const isValid = useIsFieldValid('test');\n\n        return {\n          value,\n          isValid,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ isValid.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const span = document.querySelector('span');\n    setValue(input as any, '');\n    await flushPromises();\n    expect(span?.textContent).toBe('false');\n    setValue(input as any, '12');\n    await flushPromises();\n    expect(span?.textContent).toBe('true');\n  });\n\n  test('returns false and warns if field is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        useForm();\n        const isValid = useIsFieldValid('test');\n\n        return {\n          isValid,\n        };\n      },\n      template: `\n      <span>{{ isValid.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const span = document.querySelector('span');\n    expect(span?.textContent).toBe('false');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('returns false and warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        const isValid = useIsFieldValid('test');\n\n        return {\n          isValid,\n        };\n      },\n      template: `\n      <span>{{ isValid.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const span = document.querySelector('span');\n    expect(span?.textContent).toBe('false');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useIsFormDirty.spec.ts",
    "content": "import { useField, useForm, useIsFormDirty } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\n\ndescribe('useIsFormDirty()', () => {\n  test('gives access to the forms isDirty status', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value, handleChange } = useField('test');\n        const isDirty = useIsFormDirty();\n\n        return {\n          value,\n          isDirty,\n          handleInput: (e: any) => handleChange(e, false),\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" @input=\"handleInput\" />\n      <span>{{ isDirty.toString()  }}</span>\n    `,\n    });\n\n    const input = document.querySelector('input');\n    const dirty = document.querySelector('span');\n    expect(dirty?.textContent).toBe('false');\n\n    setValue(input as any, '');\n    await flushPromises();\n    expect(dirty?.textContent).toBe('true');\n  });\n\n  test('returns false and warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        const isDirty = useIsFormDirty();\n\n        return {\n          isDirty,\n        };\n      },\n      template: `\n      <span>{{ isDirty.toString() }}</span>\n    `,\n    });\n\n    const dirty = document.querySelector('span');\n\n    await flushPromises();\n    expect(dirty?.textContent).toBe('false');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useIsFormTouched.spec.ts",
    "content": "import { useField, useForm, useIsFormTouched } from '@/vee-validate';\nimport { dispatchEvent, mountWithHoc, flushPromises } from './helpers';\n\ndescribe('useIsFormTouched()', () => {\n  test('gives access to the forms isTouched status', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value, handleBlur } = useField('test');\n        const isTouched = useIsFormTouched();\n\n        return {\n          value,\n          isTouched,\n          handleBlur,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" @blur=\"handleBlur\" />\n      <span>{{ isTouched.toString()  }}</span>\n    `,\n    });\n\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n\n    dispatchEvent(input as any, 'blur');\n    await flushPromises();\n    expect(error?.textContent).toBe('true');\n  });\n\n  test('returns false and warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        const isTouched = useIsFormTouched();\n\n        return {\n          isTouched,\n        };\n      },\n      template: `\n      <span>{{ isTouched.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('false');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useIsFormValid.spec.ts",
    "content": "import { useIsFormValid, useField, useForm } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\n\ndescribe('useIsFormValid()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const validate = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('returns validity of the form', async () => {\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value } = useField('test', validate);\n        const isValid = useIsFormValid();\n\n        return {\n          value,\n          isValid,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ isValid.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const span = document.querySelector('span');\n    setValue(input as any, '');\n    await flushPromises();\n    expect(span?.textContent).toBe('false');\n    setValue(input as any, '12');\n    await flushPromises();\n    expect(span?.textContent).toBe('true');\n  });\n\n  test('returns false and warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        const isValid = useIsFormValid();\n\n        return {\n          isValid,\n        };\n      },\n      template: `\n      <span>{{ isValid.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const span = document.querySelector('span');\n    expect(span?.textContent).toBe('false');\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useIsSubmitting.spec.ts",
    "content": "import { useField, useForm, useIsSubmitting } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\n\ndescribe('useIsSubmitting()', () => {\n  const validate = (): Promise<false> =>\n    new Promise(resolve => {\n      setTimeout(() => {\n        resolve(false);\n      }, 10);\n    });\n\n  test('indicates if a form is submitting', async () => {\n    mountWithHoc({\n      setup() {\n        const { submitForm } = useForm();\n        useField('test', validate);\n        const isSubmitting = useIsSubmitting();\n\n        return {\n          isSubmitting,\n          submitForm,\n        };\n      },\n      template: `\n      <button @click=\"submitForm\">Submit</button>\n      <span>{{ isSubmitting.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const button = document.querySelector('button');\n    const submitText = document.querySelector('span');\n    expect(submitText?.textContent).toBe('false');\n    button?.click();\n\n    await flushPromises();\n    expect(submitText?.textContent).toBe('true');\n    vi.runAllTimers();\n    await flushPromises();\n    expect(submitText?.textContent).toBe('false');\n  });\n\n  test('returns false and warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    mountWithHoc({\n      setup() {\n        const isSubmitting = useIsSubmitting();\n\n        return {\n          isSubmitting,\n        };\n      },\n      template: `\n      <span>{{ isSubmitting.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const submitText = document.querySelector('span');\n    expect(submitText?.textContent).toBe('false');\n    expect(console.warn).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useIsValidating.spec.ts",
    "content": "import { useForm, useIsValidating } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\nimport { expect } from 'vitest';\nimport * as z from 'zod';\n\ndescribe('useIsValidating()', () => {\n  test.skip('indicates if a form is validating', async () => {\n    const spy = vi.fn((isValidating: boolean) => isValidating);\n\n    mountWithHoc({\n      setup() {\n        const isValidating = useIsValidating();\n        const { validate } = useForm({\n          validationSchema: z\n            .object({\n              name: z.string(),\n            })\n            .superRefine(() => {\n              spy(isValidating.value);\n            })\n            .default({ name: '' }),\n        });\n\n        return {\n          validate,\n        };\n      },\n      template: `\n      <button @click=\"validate\">Submit</button>\n    `,\n    });\n\n    await flushPromises();\n    // triggered by validateObjectSchema method\n    expect(spy).toHaveBeenCalledTimes(1);\n    const button = document.querySelector('button');\n    button?.click();\n\n    await flushPromises();\n    // triggered by formCtx validate method\n    expect(spy).toHaveBeenCalledTimes(2);\n    expect(spy).toHaveLastReturnedWith(true);\n  });\n\n  test('returns false and warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    mountWithHoc({\n      setup() {\n        const isValidating = useIsValidating();\n\n        return {\n          isValidating,\n        };\n      },\n      template: `\n      <span>{{ isValidating.toString() }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const validatingText = document.querySelector('span');\n    expect(validatingText?.textContent).toBe('false');\n    expect(console.warn).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useResetForm.spec.ts",
    "content": "import { FormContext, useField, useForm, useResetForm } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\n\ndescribe('useResetForm()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const validate = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('resets a form', async () => {\n    let resetForm: any;\n    let value: any;\n    let errorMessage: any;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const field = useField('test', validate);\n        value = field.value;\n        errorMessage = field.errorMessage;\n        resetForm = useResetForm();\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ errorMessage }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    setValue(input as any, '');\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n\n    const inputValue = '123';\n\n    resetForm({\n      values: {\n        test: inputValue,\n      },\n    });\n\n    await flushPromises();\n    expect(error?.textContent).toBe('');\n    expect(input?.value).toBe(inputValue);\n  });\n\n  test('warns if the form does not exist', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let resetForm: any;\n\n    mountWithHoc({\n      setup() {\n        resetForm = useResetForm();\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    resetForm({\n      values: {\n        test: 'someValue',\n      },\n    });\n\n    await flushPromises();\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('resets a form with passed options', async () => {\n    let resetForm: any;\n    let form!: FormContext<{ fname: string; lname: string }>;\n\n    mountWithHoc({\n      setup() {\n        form = useForm({\n          initialValues: { fname: '123', lname: '456' },\n        });\n\n        resetForm = useResetForm();\n\n        return {};\n      },\n      template: `\n        <div></div>\n      `,\n    });\n\n    await flushPromises();\n\n    resetForm({ values: { fname: 'test' } }, { force: true });\n    expect(form.values.lname).toBeUndefined();\n    expect(form.values.fname).toBe('test');\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useSetFieldError.spec.ts",
    "content": "import { useField, useSetFieldError, useForm } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\nimport { defineComponent } from 'vue';\n\ndescribe('useSetFieldError()', () => {\n  test('sets a single field error message', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let setError!: ReturnType<typeof useSetFieldError>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value, errorMessage } = useField('test');\n        setError = useSetFieldError('test');\n\n        return {\n          value,\n          errorMessage,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ errorMessage }}</span>\n    `,\n    });\n    await flushPromises();\n    const msg = 'Field is required';\n\n    const error = document.querySelector('span');\n    setError(msg);\n    await flushPromises();\n    expect(error?.textContent).toBe(msg);\n    expect(spy).not.toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('sets a single field error message in a child component without specifying a path', async () => {\n    let setError!: ReturnType<typeof useSetFieldError>;\n    const CustomSetErrorComponent = defineComponent({\n      template: '<button></button>',\n      setup() {\n        setError = useSetFieldError();\n\n        return {};\n      },\n    });\n    mountWithHoc({\n      components: {\n        CustomSetErrorComponent,\n      },\n      setup() {\n        useForm();\n        const { errorMessage } = useField('test');\n\n        return {\n          errorMessage,\n        };\n      },\n      template: `\n      <span>{{ errorMessage }}</span>\n      <CustomSetErrorComponent />\n    `,\n    });\n\n    await flushPromises();\n    const msg = 'Field is required';\n    const error = document.querySelector('span');\n    setError(msg);\n    await flushPromises();\n    expect(error?.textContent).toBe(msg);\n  });\n\n  test('warns if field not found', async () => {\n    let setError!: ReturnType<typeof useSetFieldError>;\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        setError = useSetFieldError('something');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    setError('ERROR');\n    await flushPromises();\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useSetFieldTouched.spec.ts",
    "content": "import { useField, useForm, useSetFieldTouched } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\nimport { defineComponent } from 'vue';\n\ndescribe('useSetFieldTouched()', () => {\n  test('sets a single field touched status', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let setTouched!: ReturnType<typeof useSetFieldTouched>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { meta } = useField('test');\n        setTouched = useSetFieldTouched('test');\n\n        return {\n          meta,\n        };\n      },\n      template: `\n      <span>{{ meta.touched.toString() }}</span>\n    `,\n    });\n    await flushPromises();\n\n    const touched = document.querySelector('span');\n    expect(touched?.textContent).toBe('false');\n    setTouched(true);\n    await flushPromises();\n    expect(touched?.textContent).toBe('true');\n    expect(spy).not.toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('sets a single field isTouched status in child components without path prop', async () => {\n    let setTouched!: ReturnType<typeof useSetFieldTouched>;\n    const TouchedButton = defineComponent({\n      template: '<button></button>',\n      setup() {\n        setTouched = useSetFieldTouched();\n\n        return {};\n      },\n    });\n    mountWithHoc({\n      components: {\n        TouchedButton,\n      },\n      setup() {\n        useForm();\n        const { meta } = useField('test');\n\n        return {\n          meta,\n        };\n      },\n      template: `\n      <span>{{ meta.touched.toString() }}</span>\n      <TouchedButton />\n    `,\n    });\n\n    await flushPromises();\n\n    const touched = document.querySelector('span');\n    expect(touched?.textContent).toBe('false');\n    setTouched(true);\n    await flushPromises();\n    expect(touched?.textContent).toBe('true');\n  });\n\n  test('warns if field not found', async () => {\n    let setTouched!: ReturnType<typeof useSetFieldTouched>;\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        setTouched = useSetFieldTouched('something');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    setTouched(true);\n    await flushPromises();\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useSetFieldValue.spec.ts",
    "content": "import { useField, useForm, useSetFieldValue } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\nimport { defineComponent } from 'vue';\n\ndescribe('useSetFieldTouched()', () => {\n  test('sets a single field value', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let setValue!: ReturnType<typeof useSetFieldValue>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value } = useField('test');\n        setValue = useSetFieldValue('test');\n\n        return {\n          value,\n        };\n      },\n      template: `\n      <span>{{ value }}</span>\n    `,\n    });\n    await flushPromises();\n\n    const valueSpan = document.querySelector('span');\n    expect(valueSpan?.textContent).toBe('');\n    setValue('test 123');\n    await flushPromises();\n    expect(valueSpan?.textContent).toBe('test 123');\n    expect(spy).not.toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('sets a single field value in child components without path prop', async () => {\n    let setValue!: ReturnType<typeof useSetFieldValue>;\n    const ValueBtn = defineComponent({\n      template: '<button></button>',\n      setup() {\n        setValue = useSetFieldValue();\n\n        return {};\n      },\n    });\n    mountWithHoc({\n      components: {\n        ValueBtn,\n      },\n      setup() {\n        useForm();\n        const { value } = useField('test');\n\n        return {\n          value,\n        };\n      },\n      template: `\n      <span>{{ value }}</span>\n      <ValueBtn />\n    `,\n    });\n\n    await flushPromises();\n\n    const valueSpan = document.querySelector('span');\n    expect(valueSpan?.textContent).toBe('');\n    setValue('test 123');\n    await flushPromises();\n    expect(valueSpan?.textContent).toBe('test 123');\n  });\n\n  test('warns if field not found', async () => {\n    let setValue!: ReturnType<typeof useSetFieldValue>;\n\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        setValue = useSetFieldValue('something');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    setValue('test 123');\n    await flushPromises();\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useSetFormErrors.spec.ts",
    "content": "import { useForm, useSetFormErrors } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\n\ndescribe('useSetFormErrors()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n\n  test('sets multiple fields errors', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let setErrors!: ReturnType<typeof useSetFormErrors>;\n    mountWithHoc({\n      setup() {\n        const { errors } = useForm();\n        setErrors = useSetFormErrors();\n\n        return {\n          errors,\n        };\n      },\n      template: `\n      <span>{{ errors.test }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    setErrors({ test: REQUIRED_MESSAGE });\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n    expect(spy).not.toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let setErrors!: ReturnType<typeof useSetFormErrors>;\n    mountWithHoc({\n      setup() {\n        setErrors = useSetFormErrors();\n\n        return {};\n      },\n      template: `\n      <span></span>\n    `,\n    });\n\n    await flushPromises();\n    setErrors({});\n    await flushPromises();\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useSetFormTouched.spec.ts",
    "content": "import { useField, useForm, useSetFormTouched } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\n\ndescribe('useSetFormTouched()', () => {\n  test('sets multiple fields touched state', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let setTouched!: ReturnType<typeof useSetFormTouched>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { meta: test1 } = useField('test1');\n        const { meta: test2 } = useField('test2');\n        setTouched = useSetFormTouched();\n\n        return {\n          test1,\n          test2,\n        };\n      },\n      template: `\n      <span id=\"t1\">{{ test1.touched }}</span>\n      <span id=\"t2\">{{ test2.touched }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const touched1 = document.querySelector('#t1');\n    const touched2 = document.querySelector('#t2');\n    setTouched({ test1: true, test2: false });\n    await flushPromises();\n    expect(touched1?.textContent).toBe('true');\n    expect(touched2?.textContent).toBe('false');\n    expect(spy).not.toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('sets all fields touched state', async () => {\n    let setTouched!: ReturnType<typeof useSetFormTouched>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { meta: test1 } = useField('test1');\n        const { meta: test2 } = useField('test2');\n        setTouched = useSetFormTouched();\n\n        return {\n          test1,\n          test2,\n        };\n      },\n      template: `\n      <span id=\"t1\">{{ test1.touched }}</span>\n      <span id=\"t2\">{{ test2.touched }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const touched1 = document.querySelector('#t1');\n    const touched2 = document.querySelector('#t2');\n    setTouched(true);\n    await flushPromises();\n    expect(touched1?.textContent).toBe('true');\n    expect(touched2?.textContent).toBe('true');\n  });\n\n  test('warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let setTouched!: ReturnType<typeof useSetFormTouched>;\n    mountWithHoc({\n      setup() {\n        setTouched = useSetFormTouched();\n\n        return {};\n      },\n      template: `\n      <span></span>\n    `,\n    });\n\n    await flushPromises();\n    setTouched({});\n    await flushPromises();\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useSetFormValues.spec.ts",
    "content": "import { useField, useForm, useSetFormValues } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\n\ndescribe('useSetFormValues()', () => {\n  test('sets form values', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let setValues!: ReturnType<typeof useSetFormValues>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { value: test1 } = useField('test1');\n        const { value: test2 } = useField('test2');\n        setValues = useSetFormValues();\n\n        return {\n          test1,\n          test2,\n        };\n      },\n      template: `\n      <span id=\"t1\">{{ test1 }}</span>\n      <span id=\"t2\">{{ test2 }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const value1 = document.querySelector('#t1');\n    const value2 = document.querySelector('#t2');\n\n    setValues({ test1: 'test1', test2: 'test2' });\n    await flushPromises();\n    expect(value1?.textContent).toBe('test1');\n    expect(value2?.textContent).toBe('test2');\n    expect(spy).not.toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('warns if form is not found', async () => {\n    let setValues!: ReturnType<typeof useSetFormValues>;\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        setValues = useSetFormValues();\n\n        return {};\n      },\n      template: `\n      <span></span>\n    `,\n    });\n\n    await flushPromises();\n    setValues({});\n    await flushPromises();\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useSubmitCount.spec.ts",
    "content": "import { useField, useForm, useSubmitCount } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\n\ndescribe('useSubmitCount()', () => {\n  test('indicates the number of submissions', async () => {\n    mountWithHoc({\n      setup() {\n        const { submitForm } = useForm();\n        useField('test');\n        const submitCount = useSubmitCount();\n\n        return {\n          submitCount,\n          submitForm,\n        };\n      },\n      template: `\n      <button @click=\"submitForm()\">Submit</button>\n      <span>{{ submitCount }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const button = document.querySelector('button');\n    const submitText = document.querySelector('span');\n    expect(submitText?.textContent).toBe('0');\n    button?.click();\n    await flushPromises();\n    expect(submitText?.textContent).toBe('1');\n  });\n\n  test('returns 0 and warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    mountWithHoc({\n      setup() {\n        const submitCount = useSubmitCount();\n\n        return {\n          submitCount,\n        };\n      },\n      template: `\n      <span>{{ submitCount }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const submitText = document.querySelector('span');\n    expect(submitText?.textContent).toBe('0');\n    expect(console.warn).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useSubmitForm.spec.ts",
    "content": "import { useField, useForm, useSubmitForm } from '@/vee-validate';\nimport { mountWithHoc, setValue, flushPromises } from './helpers';\n\ndescribe('useSubmitForm()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const validate = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('executes a form submission callback', async () => {\n    const spy = vi.fn();\n    mountWithHoc({\n      setup() {\n        useForm();\n        const field = useField('test', validate);\n        const value = field.value;\n        const errorMessage = field.errorMessage;\n        const submitForm = useSubmitForm(spy);\n\n        return {\n          value,\n          errorMessage,\n          submitForm,\n        };\n      },\n      template: `\n      <input name=\"field\" v-model=\"value\" />\n      <span>{{ errorMessage }}</span>\n      <button @click=\"submitForm\"></button>\n    `,\n    });\n\n    await flushPromises();\n    const input = document.querySelector('input');\n    const error = document.querySelector('span');\n    const submitBtn = document.querySelector('button');\n    submitBtn?.click();\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n    expect(spy).not.toHaveBeenCalled();\n\n    const inputValue = '123';\n\n    setValue(input as any, inputValue);\n    submitBtn?.click();\n    await flushPromises();\n    expect(spy).toHaveBeenCalledWith({ test: inputValue }, expect.anything());\n  });\n\n  test('warns if the form does not exist', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n\n    mountWithHoc({\n      setup() {\n        useSubmitForm(() => {\n          // nothing...\n        });\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await flushPromises();\n    expect(spy).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useValidateField.spec.ts",
    "content": "import { useField, useForm, useValidateField } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\nimport { defineComponent } from 'vue';\n\ndescribe('useValidateField()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const rules = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('validates a single field', async () => {\n    let validate!: ReturnType<typeof useValidateField>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { errorMessage } = useField('test', rules);\n        validate = useValidateField('test');\n\n        return {\n          errorMessage,\n        };\n      },\n      template: `\n      <span>{{ errorMessage }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('');\n    await validate();\n    await flushPromises();\n\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('validates a single field from a child component without specifying a path', async () => {\n    const ValidateBtn = defineComponent({\n      setup() {\n        const validate = useValidateField();\n\n        return {\n          validate,\n        };\n      },\n      template: '<button @click=\"validate\"></button>',\n    });\n    mountWithHoc({\n      components: {\n        ValidateBtn,\n      },\n      setup() {\n        useForm();\n        const { errorMessage } = useField('test', rules);\n\n        return {\n          errorMessage,\n        };\n      },\n      template: `\n      <span>{{ errorMessage }}</span>\n      <ValidateBtn />\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('');\n    document.querySelector('button')?.click();\n    await flushPromises();\n\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test.skip('validates array fields', async () => {\n    let validate!: ReturnType<typeof useValidateField>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { errorMessage } = useField('test', rules);\n        useField('test', rules);\n        validate = useValidateField('test');\n\n        return {\n          errorMessage,\n        };\n      },\n      template: `\n      <span>{{ errorMessage }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const error = document.querySelector('span');\n    expect(error?.textContent).toBe('');\n    await validate();\n    await flushPromises();\n\n    await flushPromises();\n    expect(error?.textContent).toBe(REQUIRED_MESSAGE);\n  });\n\n  test('warns if the field does not exist', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let validate!: ReturnType<typeof useValidateField>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        validate = useValidateField('something');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await validate();\n    await flushPromises();\n    expect(console.warn).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n\n  test('warns if the form does not exist', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let validate!: ReturnType<typeof useValidateField>;\n    mountWithHoc({\n      setup() {\n        validate = useValidateField('something');\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await validate();\n    await flushPromises();\n    expect(console.warn).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/useValidateForm.spec.ts",
    "content": "import { useField, useForm, useValidateForm } from '@/vee-validate';\nimport { mountWithHoc, flushPromises } from './helpers';\n\ndescribe('useValidateForm()', () => {\n  const REQUIRED_MESSAGE = 'Field is required';\n  const rules = (val: any) => (val ? true : REQUIRED_MESSAGE);\n\n  test('validates all fields', async () => {\n    let validate!: ReturnType<typeof useValidateForm>;\n    mountWithHoc({\n      setup() {\n        useForm();\n        const { errorMessage: e1 } = useField('test', rules);\n        const { errorMessage: e2 } = useField('another', rules);\n        validate = useValidateForm();\n\n        return {\n          e1,\n          e2,\n        };\n      },\n      template: `\n      <span>{{ e1 }}</span>\n      <span>{{ e2 }}</span>\n    `,\n    });\n\n    await flushPromises();\n    const errors = Array.from(document.querySelectorAll('span'));\n    expect(errors.map(span => span.textContent)).toEqual(['', '']);\n    await validate();\n    await flushPromises();\n    expect(errors.map(span => span.textContent)).toEqual([REQUIRED_MESSAGE, REQUIRED_MESSAGE]);\n  });\n\n  test('warns if form is not found', async () => {\n    const spy = vi.spyOn(console, 'warn').mockImplementation(() => {\n      // NOOP\n    });\n    let validate!: ReturnType<typeof useValidateForm>;\n    mountWithHoc({\n      setup() {\n        validate = useValidateForm();\n\n        return {};\n      },\n      template: `<div></div>`,\n    });\n\n    await validate();\n    await flushPromises();\n    expect(console.warn).toHaveBeenCalled();\n    spy.mockRestore();\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/utils/assertions.spec.ts",
    "content": "import { isEqual } from 'packages/vee-validate/src/utils';\n\ndescribe('assertions', () => {\n  test('equal objects are equal', () => {\n    const a1 = { field1: undefined, field2: 'value2', field3: 'value3' };\n    const a2 = { field1: undefined, field3: 'value3', field2: 'value2' };\n    const a3 = { field2: 'value2', field3: 'value3', field1: undefined };\n    const a4 = { field2: 'value2', field1: undefined, field3: 'value3' };\n    const a5 = { field3: 'value3', field1: undefined, field2: 'value2' };\n    const a6 = { field3: 'value3', field2: 'value2', field1: undefined };\n\n    const b1 = { field1: undefined, field2: 'value2', field3: 'value3' };\n    const b2 = { field1: undefined, field3: 'value3', field2: 'value2' };\n    const b3 = { field2: 'value2', field3: 'value3', field1: undefined };\n    const b4 = { field2: 'value2', field1: undefined, field3: 'value3' };\n    const b5 = { field3: 'value3', field1: undefined, field2: 'value2' };\n    const b6 = { field3: 'value3', field2: 'value2', field1: undefined };\n\n    expect(isEqual(a1, b1)).toBe(true);\n    expect(isEqual(a1, b2)).toBe(true);\n    expect(isEqual(a1, b3)).toBe(true);\n    expect(isEqual(a1, b4)).toBe(true);\n    expect(isEqual(a1, b5)).toBe(true);\n    expect(isEqual(a1, b6)).toBe(true);\n\n    expect(isEqual(a2, b1)).toBe(true);\n    expect(isEqual(a2, b2)).toBe(true);\n    expect(isEqual(a2, b3)).toBe(true);\n    expect(isEqual(a2, b4)).toBe(true);\n    expect(isEqual(a2, b5)).toBe(true);\n    expect(isEqual(a2, b6)).toBe(true);\n\n    expect(isEqual(a3, b1)).toBe(true);\n    expect(isEqual(a3, b2)).toBe(true);\n    expect(isEqual(a3, b3)).toBe(true);\n    expect(isEqual(a3, b4)).toBe(true);\n    expect(isEqual(a3, b5)).toBe(true);\n    expect(isEqual(a3, b6)).toBe(true);\n\n    expect(isEqual(a4, b1)).toBe(true);\n    expect(isEqual(a4, b2)).toBe(true);\n    expect(isEqual(a4, b3)).toBe(true);\n    expect(isEqual(a4, b4)).toBe(true);\n    expect(isEqual(a4, b5)).toBe(true);\n    expect(isEqual(a4, b6)).toBe(true);\n\n    expect(isEqual(a5, b1)).toBe(true);\n    expect(isEqual(a5, b2)).toBe(true);\n    expect(isEqual(a5, b3)).toBe(true);\n    expect(isEqual(a5, b4)).toBe(true);\n    expect(isEqual(a5, b5)).toBe(true);\n    expect(isEqual(a5, b6)).toBe(true);\n\n    expect(isEqual(a6, b1)).toBe(true);\n    expect(isEqual(a6, b2)).toBe(true);\n    expect(isEqual(a6, b3)).toBe(true);\n    expect(isEqual(a6, b4)).toBe(true);\n    expect(isEqual(a6, b5)).toBe(true);\n    expect(isEqual(a6, b6)).toBe(true);\n  });\n\n  test('equal objects where A has missing keys are equal', () => {\n    const a1 = { field2: 'value2', field3: 'value3' };\n    const a2 = { field3: 'value3', field2: 'value2' };\n\n    const b1 = { field1: undefined, field2: 'value2', field3: 'value3' };\n    const b2 = { field1: undefined, field3: 'value3', field2: 'value2' };\n    const b3 = { field2: 'value2', field3: 'value3', field1: undefined };\n    const b4 = { field2: 'value2', field1: undefined, field3: 'value3' };\n    const b5 = { field3: 'value3', field1: undefined, field2: 'value2' };\n    const b6 = { field3: 'value3', field2: 'value2', field1: undefined };\n\n    expect(isEqual(a1, b1)).toBe(true);\n    expect(isEqual(a1, b2)).toBe(true);\n    expect(isEqual(a1, b3)).toBe(true);\n    expect(isEqual(a1, b4)).toBe(true);\n    expect(isEqual(a1, b5)).toBe(true);\n    expect(isEqual(a1, b6)).toBe(true);\n\n    expect(isEqual(a2, b1)).toBe(true);\n    expect(isEqual(a2, b2)).toBe(true);\n    expect(isEqual(a2, b3)).toBe(true);\n    expect(isEqual(a2, b4)).toBe(true);\n    expect(isEqual(a2, b5)).toBe(true);\n    expect(isEqual(a2, b6)).toBe(true);\n  });\n\n  test('equal objects where B has missing keys are equal', () => {\n    const a1 = { field1: undefined, field2: 'value2', field3: 'value3' };\n    const a2 = { field1: undefined, field3: 'value3', field2: 'value2' };\n    const a3 = { field2: 'value2', field3: 'value3', field1: undefined };\n    const a4 = { field2: 'value2', field1: undefined, field3: 'value3' };\n    const a5 = { field3: 'value3', field1: undefined, field2: 'value2' };\n    const a6 = { field3: 'value3', field2: 'value2', field1: undefined };\n\n    const b1 = { field2: 'value2', field3: 'value3' };\n    const b2 = { field3: 'value3', field2: 'value2' };\n\n    expect(isEqual(a1, b1)).toBe(true);\n    expect(isEqual(a1, b2)).toBe(true);\n\n    expect(isEqual(a2, b1)).toBe(true);\n    expect(isEqual(a2, b2)).toBe(true);\n\n    expect(isEqual(a3, b1)).toBe(true);\n    expect(isEqual(a3, b2)).toBe(true);\n\n    expect(isEqual(a4, b1)).toBe(true);\n    expect(isEqual(a4, b2)).toBe(true);\n\n    expect(isEqual(a5, b1)).toBe(true);\n    expect(isEqual(a5, b2)).toBe(true);\n\n    expect(isEqual(a6, b1)).toBe(true);\n    expect(isEqual(a6, b2)).toBe(true);\n  });\n\n  test('different objects are not equal', () => {\n    const a1 = { field1: undefined, field2: 'value2', field3: 'value3' };\n    const a2 = { field1: undefined, field3: 'value3', field2: 'value2' };\n    const a3 = { field2: 'value2', field3: 'value3', field1: undefined };\n    const a4 = { field2: 'value2', field1: undefined, field3: 'value3' };\n    const a5 = { field3: 'value3', field1: undefined, field2: 'value2' };\n    const a6 = { field3: 'value3', field2: 'value2', field1: undefined };\n\n    const b1 = { field1: undefined, field2: 'value2', field3: 'DIFF' };\n    const b2 = { field1: undefined, field3: 'DIFF', field2: 'value2' };\n    const b3 = { field2: 'value2', field3: 'DIFF', field1: undefined };\n    const b4 = { field2: 'value2', field1: undefined, field3: 'DIFF' };\n    const b5 = { field3: 'DIFF', field1: undefined, field2: 'value2' };\n    const b6 = { field3: 'DIFF', field2: 'value2', field1: undefined };\n\n    expect(isEqual(a1, b1)).toBe(false);\n    expect(isEqual(a1, b2)).toBe(false);\n    expect(isEqual(a1, b3)).toBe(false);\n    expect(isEqual(a1, b4)).toBe(false);\n    expect(isEqual(a1, b5)).toBe(false);\n    expect(isEqual(a1, b6)).toBe(false);\n\n    expect(isEqual(a2, b1)).toBe(false);\n    expect(isEqual(a2, b2)).toBe(false);\n    expect(isEqual(a2, b3)).toBe(false);\n    expect(isEqual(a2, b4)).toBe(false);\n    expect(isEqual(a2, b5)).toBe(false);\n    expect(isEqual(a2, b6)).toBe(false);\n\n    expect(isEqual(a3, b1)).toBe(false);\n    expect(isEqual(a3, b2)).toBe(false);\n    expect(isEqual(a3, b3)).toBe(false);\n    expect(isEqual(a3, b4)).toBe(false);\n    expect(isEqual(a3, b5)).toBe(false);\n    expect(isEqual(a3, b6)).toBe(false);\n\n    expect(isEqual(a4, b1)).toBe(false);\n    expect(isEqual(a4, b2)).toBe(false);\n    expect(isEqual(a4, b3)).toBe(false);\n    expect(isEqual(a4, b4)).toBe(false);\n    expect(isEqual(a4, b5)).toBe(false);\n    expect(isEqual(a4, b6)).toBe(false);\n\n    expect(isEqual(a5, b1)).toBe(false);\n    expect(isEqual(a5, b2)).toBe(false);\n    expect(isEqual(a5, b3)).toBe(false);\n    expect(isEqual(a5, b4)).toBe(false);\n    expect(isEqual(a5, b5)).toBe(false);\n    expect(isEqual(a5, b6)).toBe(false);\n\n    expect(isEqual(a6, b1)).toBe(false);\n    expect(isEqual(a6, b2)).toBe(false);\n    expect(isEqual(a6, b3)).toBe(false);\n    expect(isEqual(a6, b4)).toBe(false);\n    expect(isEqual(a6, b5)).toBe(false);\n    expect(isEqual(a6, b6)).toBe(false);\n  });\n\n  test('different objects where A has missing keys are not equal', () => {\n    const a1 = { field2: 'value2', field3: 'value3' };\n    const a2 = { field3: 'value3', field2: 'value2' };\n\n    const b1 = { field1: undefined, field2: 'value2', field3: 'DIFF' };\n    const b2 = { field1: undefined, field3: 'DIFF', field2: 'value2' };\n    const b3 = { field2: 'value2', field3: 'DIFF', field1: undefined };\n    const b4 = { field2: 'value2', field1: undefined, field3: 'DIFF' };\n    const b5 = { field3: 'DIFF', field1: undefined, field2: 'value2' };\n    const b6 = { field3: 'DIFF', field2: 'value2', field1: undefined };\n\n    expect(isEqual(a1, b1)).toBe(false);\n    expect(isEqual(a1, b2)).toBe(false);\n    expect(isEqual(a1, b3)).toBe(false);\n    expect(isEqual(a1, b4)).toBe(false);\n    expect(isEqual(a1, b5)).toBe(false);\n    expect(isEqual(a1, b6)).toBe(false);\n\n    expect(isEqual(a2, b1)).toBe(false);\n    expect(isEqual(a2, b2)).toBe(false);\n    expect(isEqual(a2, b3)).toBe(false);\n    expect(isEqual(a2, b4)).toBe(false);\n    expect(isEqual(a2, b5)).toBe(false);\n    expect(isEqual(a2, b6)).toBe(false);\n  });\n\n  test('different objects where B has missing keys not equal', () => {\n    const a1 = { field1: undefined, field2: 'value2', field3: 'value3' };\n    const a2 = { field1: undefined, field3: 'value3', field2: 'value2' };\n    const a3 = { field2: 'value2', field3: 'value3', field1: undefined };\n    const a4 = { field2: 'value2', field1: undefined, field3: 'value3' };\n    const a5 = { field3: 'value3', field1: undefined, field2: 'value2' };\n    const a6 = { field3: 'value3', field2: 'value2', field1: undefined };\n\n    const b1 = { field2: 'value2', field3: 'DIFF' };\n    const b2 = { field3: 'DIFF', field2: 'value2' };\n\n    expect(isEqual(a1, b1)).toBe(false);\n    expect(isEqual(a1, b2)).toBe(false);\n\n    expect(isEqual(a2, b1)).toBe(false);\n    expect(isEqual(a2, b2)).toBe(false);\n\n    expect(isEqual(a3, b1)).toBe(false);\n    expect(isEqual(a3, b2)).toBe(false);\n\n    expect(isEqual(a4, b1)).toBe(false);\n    expect(isEqual(a4, b2)).toBe(false);\n\n    expect(isEqual(a5, b1)).toBe(false);\n    expect(isEqual(a5, b2)).toBe(false);\n\n    expect(isEqual(a6, b1)).toBe(false);\n    expect(isEqual(a6, b2)).toBe(false);\n  });\n});\n"
  },
  {
    "path": "packages/vee-validate/tests/validate.spec.ts",
    "content": "import { validate, defineRule, configure } from '@/vee-validate';\nimport { numeric } from '@/rules';\nimport { getConfig } from '../src/config';\n\ntest('allows empty rules for the string format', async () => {\n  defineRule('numeric', numeric);\n  let result = await validate(100, '|numeric');\n  expect(result.errors).toHaveLength(0);\n\n  result = await validate(100, '||||numeric');\n  expect(result.errors).toHaveLength(0);\n});\n\ntest('handles targets expressed in objects', async () => {\n  defineRule('confirmed', (value: string, { target }: any) => {\n    return value === target ? true : 'must match';\n  });\n\n  let result = await validate('test', { confirmed: { target: '@other' } }, { values: { other: '' } });\n  expect(result.errors).toHaveLength(1);\n\n  result = await validate('test', { confirmed: { target: '@other' } }, { values: { other: 'test' } });\n  expect(result.errors).toHaveLength(0);\n});\n\n// #3077\ntest('target params are filled in the params in message context', async () => {\n  defineRule('lessThan', (value: number, params: any) => Number(value) < Number(params[0]));\n  const { generateMessage: original } = getConfig();\n  configure({\n    generateMessage: context => {\n      const params = context.rule?.params as any;\n      return `This value must be less than ${params[0]}`;\n    },\n  });\n\n  const result = await validate(2, 'lessThan:@other', { values: { other: 1 } });\n  expect(result.errors).toContain(`This value must be less than 1`);\n\n  configure({\n    generateMessage: original,\n  });\n});\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - 'packages/**'\n  - 'docs'\n  - '!**/tests/**'\n"
  },
  {
    "path": "scripts/build.mjs",
    "content": "import path, { dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport fs from 'fs-extra';\nimport { exec as execCb } from 'child_process';\nimport { promisify } from 'util';\nimport { rollup } from 'rollup';\nimport chalk from 'chalk';\nimport * as Terser from 'terser';\nimport { createConfig } from './config.mjs';\nimport { reportSize } from './info.mjs';\nimport { generateDts } from './generate-dts.mjs';\n\nconst exec = promisify(execCb);\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nasync function buildLocales() {\n  const localesDir = path.join(__dirname, '../packages/i18n/src/locale');\n  const files = fs.readdirSync(localesDir);\n  console.log(chalk.cyan('Building i18n...'));\n\n  for (let i = 0; i < files.length; i++) {\n    const file = files[i];\n    process.stdout.write(`${chalk.green(`Output File ${i}/${files.length}: `)} ${file}`);\n\n    const input = path.join(__dirname, '../packages/i18n/src/locale', file);\n    const out = path.join(__dirname, '../packages/i18n/dist/locale', file);\n    fs.copySync(input, out);\n    console.log('/n');\n  }\n}\n\nasync function minify({ code, pkg, bundleName }) {\n  const pkgout = path.join(__dirname, `../packages/${pkg}/dist`);\n  const output = await Terser.minify(code, {\n    compress: true,\n    mangle: true,\n  });\n\n  const fileName = bundleName.replace(/\\.js$/, '.prod.js');\n  const filePath = `${pkgout}/${fileName}.mjs`;\n  fs.outputFileSync(filePath, output.code);\n  const stats = reportSize({ code: output.code, path: filePath });\n  console.log(`${chalk.green('Output File:')} ${fileName} ${stats}`);\n}\n\nasync function build(pkg) {\n  if (pkg === 'nuxt') {\n    console.log(chalk.magenta(`Generating bundle for ${pkg}`));\n    const result =\n      process.platform === 'win32'\n        ? await exec('cd packages/nuxt && pnpm build && cd ../..')\n        : await exec('cd packages/nuxt && pnpm build && cd -');\n    console.log(result.stdout);\n    if (result.stderr) {\n      console.error(result.stderr);\n      process.exit(1);\n    }\n\n    console.log(`${chalk.magenta('✅ Bundled ' + pkg)}`);\n    return;\n  }\n\n  console.log(chalk.magenta(`Generating bundle for ${pkg}`));\n  const pkgout = path.join(__dirname, `../packages/${pkg}/dist`);\n  await fs.emptyDir(pkgout);\n\n  for (const format of ['esm', 'iife', 'cjs']) {\n    const { input, output, bundleName } = await createConfig(pkg, format);\n    const bundle = await rollup(input);\n    const {\n      output: [{ code }],\n    } = await bundle.generate(output);\n\n    const outputPath = path.join(pkgout, bundleName);\n    fs.outputFileSync(outputPath, code);\n    const stats = reportSize({ code, path: outputPath });\n\n    console.log(`${chalk.green('Output File:')} ${bundleName} ${stats}`);\n\n    if (format === 'iife') {\n      await minify({ bundleName, pkg, code });\n    }\n  }\n\n  await generateDts(pkg);\n  console.log(`${chalk.magenta('✅ Bundled ' + pkg)}`);\n\n  return true;\n}\n\n(async function Bundle() {\n  const arg = [...process.argv][2];\n  if (arg === 'vee-validate' || !arg) {\n    await build('vee-validate');\n  }\n\n  if (arg === 'rules' || !arg) {\n    await build('rules');\n  }\n\n  if (arg === 'nuxt' || !arg) {\n    await build('nuxt');\n  }\n\n  if (arg === 'i18n' || !arg) {\n    await build('i18n');\n    await buildLocales();\n  }\n\n  if (process.platform === 'win32') process.exit(0);\n})();\n"
  },
  {
    "path": "scripts/config.mjs",
    "content": "import path, { dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport typescript from '@rollup/plugin-typescript';\nimport replace from '@rollup/plugin-replace';\nimport resolve from '@rollup/plugin-node-resolve';\nimport commonjs from '@rollup/plugin-commonjs';\nimport { normalizePath, slashes } from './normalize-path.mjs';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst formatNameMap = {\n  'vee-validate': 'VeeValidate',\n  rules: 'VeeValidateRules',\n  i18n: 'VeeValidateI18n',\n};\n\nconst pkgNameMap = {\n  'vee-validate': 'vee-validate',\n  rules: 'vee-validate-rules',\n  i18n: 'vee-validate-i18n',\n};\n\nconst formatExt = {\n  esm: 'mjs',\n  iife: 'iife.js',\n  cjs: 'cjs',\n};\n\nasync function createConfig(pkg, format) {\n  const tsPlugin = typescript({\n    declarationDir: normalizePath(path.resolve(__dirname, `../packages/${pkg}/dist`)),\n  });\n\n  // An import assertion in a dynamic import\n  const { default: info } = await import(normalizePath(path.resolve(__dirname, `../packages/${pkg}/package.json`)), {\n    with: {\n      type: 'json',\n    },\n  });\n\n  const { version } = info;\n\n  const isEsm = format === 'esm';\n\n  const config = {\n    input: {\n      input: slashes(path.resolve(__dirname, `../packages/${pkg}/src/index.ts`)),\n      external: [\n        'vue',\n        isEsm ? '@vue/devtools-api' : undefined,\n        isEsm ? '@vue/devtools-kit' : undefined,\n        'vee-validate',\n      ].filter(Boolean),\n      plugins: [\n        replace({\n          preventAssignment: true,\n          values: {\n            __VERSION__: version,\n            __DEV__: isEsm ? `(process.env.NODE_ENV !== 'production')` : 'false',\n          },\n        }),\n        tsPlugin,\n        resolve({\n          dedupe: ['klona', 'klona/full'],\n        }),\n        commonjs(),\n      ],\n    },\n    output: {\n      banner: `/**\n  * vee-validate v${version}\n  * (c) ${new Date().getFullYear()} Abdelrahman Awad\n  * @license MIT\n  */`,\n      format,\n      name: format === 'iife' ? formatNameMap[pkg] : undefined,\n      globals: {\n        vue: 'Vue',\n        'vee-validate': 'VeeValidate',\n      },\n    },\n  };\n\n  config.bundleName = `${pkgNameMap[pkg]}.${formatExt[format] ?? 'js'}`;\n\n  // if (options.env) {\n  //   config.input.plugins.unshift(\n  //     replace({\n  //       'process.env.NODE_ENV': JSON.stringify(options.env)\n  //     })\n  //   );\n  // }\n\n  return config;\n}\n\nexport { formatNameMap, pkgNameMap, formatExt, createConfig };\n"
  },
  {
    "path": "scripts/copy-mds.mjs",
    "content": "import fs from 'fs-extra';\nimport path, { dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport chalk from 'chalk';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nfs.copyFileSync(path.resolve(__dirname, '../README.md'), path.resolve(__dirname, '../packages/vee-validate/README.md'));\nconsole.log(chalk.green('📄 README.md copied to packages/vee-validate'));\n\nfs.copyFileSync(path.resolve(__dirname, '../LICENSE'), path.resolve(__dirname, '../packages/vee-validate/LICENSE'));\nconsole.log(chalk.green('📄 LICENSE copied to packages/vee-validate'));\n\nfs.copyFileSync(\n  path.resolve(__dirname, '../packages/vee-validate/CHANGELOG.md'),\n  path.resolve(__dirname, '../CHANGELOG.md'),\n);\nconsole.log(chalk.green('📄 CHANGELOG.md copied to root'));\n"
  },
  {
    "path": "scripts/generate-dts.mjs",
    "content": "import ts from 'typescript';\nimport chalk from 'chalk';\nimport path, { dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport fs from 'fs-extra';\nimport { rollup } from 'rollup';\nimport dts from 'rollup-plugin-dts';\nimport tsconfig from '../tsconfig.json' with { type: 'json' };\nimport { pkgNameMap } from './config.mjs';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nexport async function generateDts(pkg) {\n  console.log(chalk.cyan(`Generating Declaration Files for ${pkg} ...`));\n  const declarationDir = `../packages/${pkg}/dist/types`;\n\n  const options = {\n    ...tsconfig,\n    declaration: true,\n    declarationMap: false,\n    emitDeclarationOnly: true,\n    declarationDir,\n  };\n\n  const host = ts.createCompilerHost(options);\n  const createdFiles = {};\n  host.writeFile = (fileName, contents) => {\n    createdFiles[fileName] = contents;\n  };\n\n  // Prepare and emit the d.ts files\n  const program = ts.createProgram([path.resolve(__dirname, `../packages/${pkg}/src/index.ts`)], options, host);\n  program.emit();\n  for (const [file, contents] of Object.entries(createdFiles)) {\n    fs.outputFileSync(path.resolve(__dirname, file), contents);\n  }\n\n  await bundleDts(declarationDir, pkg);\n}\n\nasync function bundleDts(declarationDir, pkg) {\n  let entry = path.join(__dirname, declarationDir, 'index.d.ts');\n  // if it doesn't exist then probably was nested cause of relative imports\n  if (!fs.existsSync(entry)) {\n    entry = path.resolve(__dirname, declarationDir, pkg, 'src', 'index.d.ts');\n  }\n\n  // If we cannot find the 'index.d.ts', panic!\n  if (!fs.existsSync(entry)) {\n    throw new Error('Cannot find index.d.ts at ' + entry);\n  }\n\n  // Generate .d.ts rollup\n  const config = {\n    input: entry,\n    output: { file: `packages/${pkg}/dist/${pkgNameMap[pkg]}.d.ts`, format: 'es' },\n    plugins: [dts()],\n  };\n\n  const bundle = await rollup(config);\n  await bundle.write(config.output);\n  await fs.remove(`packages/${pkg}/dist/types`);\n  console.log(`${chalk.cyan('Bundled ' + pkg + ' Declaration Files...')}`);\n}\n"
  },
  {
    "path": "scripts/info.mjs",
    "content": "import fs from 'fs-extra';\nimport { filesize } from 'filesize';\nimport { gzipSizeSync } from 'gzip-size';\n\nfunction reportSize({ path, code }) {\n  const { size } = fs.statSync(path);\n  const gzipped = gzipSizeSync(code);\n\n  return `| Size: ${filesize(size)} | Gzip: ${filesize(gzipped)}`;\n}\n\nexport { reportSize };\n"
  },
  {
    "path": "scripts/normalize-path.mjs",
    "content": "const windows = process.platform === 'win32';\n\nexport function slashes(path) {\n  return path.replace(/\\\\/g, '/');\n}\n\nexport function normalizePath(path) {\n  if (!windows) return path;\n  const normalized = slashes(path);\n  // check for absolute path: C:/...\n  return /^\\w:\\//.test(normalized) ? `file:///${normalized}` : normalized;\n}\n"
  },
  {
    "path": "scripts/release.sh",
    "content": "#!/bin/bash\n\npnpm build\npnpm changeset version\npnpm install\ngit add .\ngit commit -m \"chore(release): publish\"\npnpm changeset publish\ngit push --follow-tags\n"
  },
  {
    "path": "scripts/tag-release.mjs",
    "content": "import pkg from '../packages/vee-validate/package.json' with { type: 'json' };\nimport { execSync } from 'node:child_process';\nimport chalk from 'chalk';\n\ntry {\n  execSync(`git tag v${pkg.version}`);\n  console.log(chalk.green(`🔖 Tagged release v${pkg.version}`));\n} catch (error) {\n  console.log(chalk.red(`❌ Failed to tag release v${pkg.version}`));\n  console.log(error);\n  process.exit(1);\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\r\n  \"compilerOptions\": {\r\n    \"baseUrl\": \".\",\r\n    \"rootDir\": \".\",\r\n    \"moduleResolution\": \"node\",\r\n    \"target\": \"es2017\",\r\n    \"module\": \"esnext\",\r\n    \"lib\": [\"esnext\", \"es2017\", \"dom\"],\r\n    \"sourceMap\": true,\r\n    \"declaration\": true,\r\n    \"declarationMap\": true,\r\n    \"noImplicitAny\": true,\r\n    \"strict\": true,\r\n    \"strictNullChecks\": true,\r\n    \"strictBindCallApply\": true,\r\n    \"strictFunctionTypes\": true,\r\n    \"experimentalDecorators\": true,\r\n    \"emitDecoratorMetadata\": true,\r\n    \"esModuleInterop\": true,\r\n    \"allowSyntheticDefaultImports\": true,\r\n    \"resolveJsonModule\": true,\r\n    \"paths\": {\r\n      \"@/*\": [\"packages/*/src\"]\r\n    },\r\n    \"types\": [\"vitest/globals\"],\r\n    \"typeRoots\": [\"node_modules/@types\", \"node_modules\"]\r\n  },\r\n  \"include\": [\"packages/*/src\", \"packages/*/tests\", \"vitest.setup.ts\", \"vitest.setup.ts\"]\r\n}\r\n"
  },
  {
    "path": "vitest.config.ts",
    "content": "import { defineConfig, configDefaults } from 'vitest/config';\nimport tsconfigPaths from 'vite-tsconfig-paths';\n\nexport default defineConfig({\n  plugins: [tsconfigPaths()],\n  test: {\n    setupFiles: ['./vitest.setup.ts'],\n    environment: 'jsdom',\n    globals: true,\n    exclude: ['docs/*', ...configDefaults.exclude],\n    coverage: {\n      exclude: ['**/*/devtools.ts', 'packages/**/dist/**', 'docs/*', ...(configDefaults.coverage.exclude || [])],\n    },\n  },\n  define: {\n    __DEV__: JSON.stringify(true),\n  },\n});\n"
  },
  {
    "path": "vitest.setup.ts",
    "content": "beforeEach(() => {\n  vi.useFakeTimers();\n});\n\nafterEach(() => {\n  vi.useRealTimers();\n});\n"
  }
]