{"_id":"@adbros/vue-validation","_rev":"5-2309e92e57592486efb7ef5f55d6dc94","name":"@adbros/vue-validation","dist-tags":{"latest":"0.2.3"},"versions":{"0.1.0":{"name":"@adbros/vue-validation","version":"0.1.0","keywords":["vue","validation","valibot","form","composable","vue3"],"author":{"name":"Adbros"},"license":"MIT","_id":"@adbros/vue-validation@0.1.0","maintainers":[{"name":"pivoda","email":"pavel.pivoda@gmail.com"},{"name":"paveltobias","email":"m@ptx.cz"}],"homepage":"https://github.com/adbrosaci/vue-validation#readme","bugs":{"url":"https://github.com/adbrosaci/vue-validation/issues"},"dist":{"shasum":"e0573fff356cb35a498eb58fdd6b051aaf641aca","tarball":"https://registry.npmjs.org/@adbros/vue-validation/-/vue-validation-0.1.0.tgz","fileCount":4,"integrity":"sha512-ndQ5PGcaeISr5Bo5Wga5EAT6u6aEXIOmF8/GtJmDsYqwt61NoW1QhlGwzpY4QP4YXeOoXqSU/cf/TmuCiMTZbQ==","signatures":[{"sig":"MEQCIHzv1XeQgD47Sr7odiu91+kv60s3Dvsx89kTp7jzoKcIAiAgpAtq/Z7MxhM1rCnXTppVkZXPR6CkUnFVaF6r3uFVJg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":11769},"type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"29790c676ab8873c1254565bcad37231848403cb","scripts":{"dev":"tsup src/index.ts --watch --format esm --dts","lint":"eslint src --ext .ts","build":"tsup src/index.ts --format esm --dts","release":"bumpp && npm publish"},"_npmUser":{"name":"pivoda","email":"pavel.pivoda@gmail.com"},"repository":{"url":"git+https://github.com/adbrosaci/vue-validation.git","type":"git"},"_npmVersion":"10.2.4","description":"Composable for schema-based form validation in Vue 3 using Valibot","directories":{},"_nodeVersion":"20.11.1","dependencies":{"radash":"^12.1.1","valibot":"^1.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.18","tsup":"^8.5.0","bumpp":"^10.2.0","eslint":"^9.32.0","typescript":"^5.8.3","@adbros/eslint-config":"^3.0.0-beta.1"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/vue-validation_0.1.0_1753762910254_0.8003595961347834","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@adbros/vue-validation","version":"0.2.0","keywords":["vue","validation","valibot","form","composable","vue3"],"author":{"name":"Adbros"},"license":"MIT","_id":"@adbros/vue-validation@0.2.0","maintainers":[{"name":"pivoda","email":"pavel.pivoda@gmail.com"},{"name":"paveltobias","email":"m@ptx.cz"}],"homepage":"https://github.com/adbrosaci/vue-validation#readme","bugs":{"url":"https://github.com/adbrosaci/vue-validation/issues"},"dist":{"shasum":"02aa44e7bf4a27680a85fc49f60b0e454d4b86ef","tarball":"https://registry.npmjs.org/@adbros/vue-validation/-/vue-validation-0.2.0.tgz","fileCount":4,"integrity":"sha512-SWPa2enhtvZixrazzKLFj/xkWK+tfKzPKGC4vcbeA7v2MAuaLf6LCoAAEXl1vONW7r65R6X/oGVsQJbFXvqYRw==","signatures":[{"sig":"MEUCIA9BlxudByS7CtbVNKX5erFcarXmuYzaVqnRnpLWapUPAiEAxv7nm7Y/lxjKTko9akzJ6hagcdg/jLOeyQY6xQxFNi0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12250},"type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"14ec5aa5b141c12d44c32624a96dfbdb8c488dcb","scripts":{"dev":"tsup src/index.ts --watch --format esm --dts","lint":"eslint src --ext .ts","build":"tsup src/index.ts --format esm --dts","release":"bumpp && npm publish"},"_npmUser":{"name":"pivoda","email":"pavel.pivoda@gmail.com"},"repository":{"url":"git+https://github.com/adbrosaci/vue-validation.git","type":"git"},"_npmVersion":"10.2.4","description":"Composable for schema-based form validation in Vue 3 using Valibot","directories":{},"_nodeVersion":"20.11.1","dependencies":{"radash":"^12.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.18","tsup":"^8.5.0","bumpp":"^10.2.0","eslint":"^9.32.0","typescript":"^5.8.3","@adbros/eslint-config":"^3.0.0-beta.1"},"peerDependencies":{"vue":"^3.0.0","valibot":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/vue-validation_0.2.0_1753764441369_0.45803107441066304","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@adbros/vue-validation","version":"0.2.1","keywords":["vue","validation","valibot","form","composable","vue3"],"author":{"name":"Adbros"},"license":"MIT","_id":"@adbros/vue-validation@0.2.1","maintainers":[{"name":"pivoda","email":"pavel.pivoda@gmail.com"},{"name":"paveltobias","email":"m@ptx.cz"}],"homepage":"https://github.com/adbrosaci/vue-validation#readme","bugs":{"url":"https://github.com/adbrosaci/vue-validation/issues"},"dist":{"shasum":"8e08739bb9670cfcc31877470d09948c70252f33","tarball":"https://registry.npmjs.org/@adbros/vue-validation/-/vue-validation-0.2.1.tgz","fileCount":4,"integrity":"sha512-+uzkWHSjHqgk8IgPMZbf7xC463mdqSwl4AfB071mkydHJxip3ApbSF/ipfMKoq5k1T9UNhXorFPhEo4QjvYb0A==","signatures":[{"sig":"MEUCIQDuHivNsCNR+sjE1gds6ozrWdCaYpAstGws40vA88W8iwIgcwGyaeFNxp501iFJAYg458DdNIV2D7zEIc1GSrdOWVw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12254},"type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"a0fe93951b5164d3715fc62c58a08043dcffc8d0","scripts":{"dev":"tsup src/index.ts --watch --format esm --dts","lint":"eslint src --ext .ts","build":"tsup src/index.ts --format esm --dts","release":"bumpp && npm publish"},"_npmUser":{"name":"pivoda","email":"pavel.pivoda@gmail.com"},"repository":{"url":"git+https://github.com/adbrosaci/vue-validation.git","type":"git"},"_npmVersion":"10.2.4","description":"Composable for schema-based form validation in Vue 3 using Valibot","directories":{},"_nodeVersion":"20.11.1","dependencies":{"radash":"^12.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.18","tsup":"^8.5.0","bumpp":"^10.2.0","eslint":"^9.32.0","typescript":"^5.8.3","@adbros/eslint-config":"^3.0.0-beta.1"},"peerDependencies":{"vue":"^3.0.0","valibot":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/vue-validation_0.2.1_1753764907588_0.2010386029203748","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@adbros/vue-validation","version":"0.2.2","keywords":["vue","validation","valibot","form","composable","vue3"],"author":{"name":"Adbros"},"license":"MIT","_id":"@adbros/vue-validation@0.2.2","maintainers":[{"name":"pivoda","email":"pavel.pivoda@gmail.com"},{"name":"paveltobias","email":"m@ptx.cz"}],"homepage":"https://github.com/adbrosaci/vue-validation#readme","bugs":{"url":"https://github.com/adbrosaci/vue-validation/issues"},"dist":{"shasum":"779a084536a0d1a1fb371c3c0eb7aabd25596401","tarball":"https://registry.npmjs.org/@adbros/vue-validation/-/vue-validation-0.2.2.tgz","fileCount":4,"integrity":"sha512-8PqzkuldfXKkq4Kpb2BQSrET3CRVhkiv9tzzbtsv/hRT54bjSsRdKujMCyevG5aQIGv287yFKsyhredZ1IiKJQ==","signatures":[{"sig":"MEUCIHrv/U6zA5iOFTydURcpHiLN3jcrragA0l14wS93bESqAiEAzMffcrcZWiD2wd59eU6mfGlmfpqdbPBBxYCylrl6YSQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12254},"type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f15e827e9441361e5059fa8d513d63055722f2df","scripts":{"dev":"tsup src/index.ts --watch --format esm --dts","lint":"eslint src --ext .ts","build":"tsup src/index.ts --format esm --dts","release":"bumpp && npm publish"},"_npmUser":{"name":"pivoda","email":"pavel.pivoda@gmail.com"},"repository":{"url":"git+https://github.com/adbrosaci/vue-validation.git","type":"git"},"_npmVersion":"10.2.4","description":"Composable for schema-based form validation in Vue 3 using Valibot","directories":{},"_nodeVersion":"20.11.1","dependencies":{"radash":"^12.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.18","tsup":"^8.5.0","bumpp":"^10.2.0","eslint":"^9.32.0","typescript":"^5.8.3","@adbros/eslint-config":"^3.0.0-beta.1"},"peerDependencies":{"vue":"^3.0.0","valibot":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/vue-validation_0.2.2_1753765196895_0.5201458210222616","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@adbros/vue-validation","version":"0.2.3","type":"module","publishConfig":{"access":"public"},"description":"Composable for schema-based form validation in Vue 3 using Valibot","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"repository":{"type":"git","url":"git+https://github.com/adbrosaci/vue-validation.git"},"scripts":{"build":"tsup src/index.ts --format esm --dts","dev":"tsup src/index.ts --watch --format esm --dts","lint":"eslint src --ext .ts","release":"npm run build && bumpp && npm publish"},"keywords":["vue","validation","valibot","form","composable","vue3"],"author":{"name":"Adbros"},"license":"MIT","peerDependencies":{"vue":"^3.0.0","valibot":"^1.0.0"},"devDependencies":{"@adbros/eslint-config":"^3.0.0-beta.1","bumpp":"^10.2.0","eslint":"^9.32.0","tsup":"^8.5.0","typescript":"^5.8.3","vue":"^3.5.18"},"dependencies":{"radash":"^12.1.1"},"_id":"@adbros/vue-validation@0.2.3","gitHead":"5649160b780997008e8d7f2b71ae24cde7d7d09f","bugs":{"url":"https://github.com/adbrosaci/vue-validation/issues"},"homepage":"https://github.com/adbrosaci/vue-validation#readme","_nodeVersion":"20.11.1","_npmVersion":"10.2.4","dist":{"integrity":"sha512-Py6ORhz6bPrhUmemEl4vKvaaHXDJib2RXXrnd8LE5w9HT5NOpd6cV2rfBE3bb/mZQqhws6uYBppcGnd9Dzim5Q==","shasum":"d5590cdd60bb6f56136f1588374278083d8be230","tarball":"https://registry.npmjs.org/@adbros/vue-validation/-/vue-validation-0.2.3.tgz","fileCount":4,"unpackedSize":12263,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICT+GIR/52dH2c2PZy1afzXj8//pkie2aoWo0SqWJLYyAiEAvcboHcvxzXWRLjaHCC9dZTHr9Bi2T0LwjCocWmmEAhM="}]},"_npmUser":{"name":"pivoda","email":"pavel.pivoda@gmail.com"},"directories":{},"maintainers":[{"name":"pivoda","email":"pavel.pivoda@gmail.com"},{"name":"paveltobias","email":"m@ptx.cz"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vue-validation_0.2.3_1753765362814_0.606307111776792"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-29T04:21:50.146Z","modified":"2025-07-29T05:02:43.217Z","0.1.0":"2025-07-29T04:21:50.475Z","0.2.0":"2025-07-29T04:47:21.538Z","0.2.1":"2025-07-29T04:55:07.764Z","0.2.2":"2025-07-29T04:59:57.089Z","0.2.3":"2025-07-29T05:02:43.033Z"},"bugs":{"url":"https://github.com/adbrosaci/vue-validation/issues"},"author":{"name":"Adbros"},"license":"MIT","homepage":"https://github.com/adbrosaci/vue-validation#readme","keywords":["vue","validation","valibot","form","composable","vue3"],"repository":{"type":"git","url":"git+https://github.com/adbrosaci/vue-validation.git"},"description":"Composable for schema-based form validation in Vue 3 using Valibot","maintainers":[{"name":"pivoda","email":"pavel.pivoda@gmail.com"},{"name":"paveltobias","email":"m@ptx.cz"}],"readme":"# 📋 `@adbros/vue-validation`\n\nA flexible, schema-driven form validation composable for Vue 3 using **Valibot**, with support for:\n\n* Deeply nested schemas\n* Dirty field tracking\n* Custom errors\n* Full form or per-field validation\n* `MaybeRefOrGetter` inputs\n* Composable-first design (external state as source of truth)\n* \"Reward early, punish late\" validation behavior\n\n---\n\n## 🧩 Components\n\n### 🔹 `useValidation<TSchema>()`\n\n#### Parameters\n\n* `schema: MaybeRefOrGetter<TSchema>`\n  A Valibot schema (`BaseSchema` or `BaseSchemaAsync`) defining the structure and rules for validation.\n\n* `data: MaybeRefOrGetter<Record<string, unknown>>`\n  The reactive object that holds the form data to be validated.\n\n#### Returns\n\n```ts\n{\n  handleSubmit: (onSubmit, onError?) => Promise<void>;\n  errors: ComputedRef<Record<string, string>>;\n  output: Ref<InferOutput<TSchema> | undefined>;\n\n  makeFieldDirty: (name: string) => void;\n  cleanField: (name: string) => void;\n  makeFormDirty: () => void;\n  cleanForm: () => void;\n\n  setCustomError: (field: string, message: string) => void;\n  clearCustomError: (field: string) => void;\n  clearAllCustomErrors: () => void;\n\n  validate: () => Promise<SafeParseReturn<TSchema>>;\n  silentErrors: Ref<FlatErrors<TSchema> | undefined>;\n  isDirty: (name: string) => boolean;\n  isFormValid: ComputedRef<boolean>;\n  dirtyFields: Ref<string[]>;\n  validDirtyFields: Ref<string[]>;\n}\n```\n\n---\n\n## 🧠 Behavior Summary\n\n* **Validation**: Runs automatically on schema/data changes and can be manually triggered via `validate()`.\n* **Dirty tracking**: Optionally tracks which fields have been interacted with via `makeFieldDirty()`, `makeFormDirty()` and `cleanField()`.\n* **Custom errors**: Allows adding external (non-schema) validation messages using `setCustomError()` etc.\n\n## 🔸 Key Concepts\n\n### ✅ Dirty State\n\n* Fields become **dirty** via:\n\n  * `makeFieldDirty(name)`\n  * `makeFormDirty()` (marks *all* fields dirty)\n* A dirty field is considered **valid** if no Valibot error exists for it.\n\n### ❌ Error Reporting\n\n* Errors are a computed merge of:\n\n  * Valibot field-level errors (only for dirty + invalid fields)\n  * Manually set `customErrors`\n\n---\n\n## 📥 `handleSubmit(onSubmit, onError?)`\n\nTriggers a full validation of the form and invokes the `onSubmit` callback if validation passes. Optionally calls `onError()` if the form is invalid.\n\n```ts\nawait handleSubmit(\n  async (data) => {\n    // Do something with validated `data`\n  },\n  () => {\n    // Optional error handler\n  }\n)\n```\n\n---\n\n## ✏️ Example Usage\n\n```vue\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport * as v from 'valibot'\nimport { useValidation } from '@adbros/vue-validation'\n\nconst schema = v.object({\n  username: v.pipe(\n    v.string(),\n    v.nonEmpty('Zadejte uživatelské jméno.')\n  ),\n  password: v.pipe(\n    v.string(),\n    v.nonEmpty('Zadejte heslo.')\n  ),\n})\n\nconst form = ref({\n  username: '',\n  password: '',\n})\n\nconst {\n  errors,\n  makeFieldDirty,\n  handleSubmit,\n} = useValidation(schema, form)\n\nconst submitForm = handleSubmit(\n  (values) => {\n    console.log('Success:', values);\n  },\n  () => {\n    console.warn('Form has errors', errors.value)\n  }\n)\n</script>\n\n<template>\n  <form @submit.prevent=\"submitForm\">\n    <label>\n      Uživatelské jméno\n      <input\n        v-model=\"form.username\"\n        @blur=\"makeFieldDirty('username')\"\n      />\n      <span class=\"error\" v-if=\"errors.username\">{{ errors.username }}</span>\n    </label>\n\n    <label>\n      Heslo\n      <input\n        type=\"password\"\n        v-model=\"form.password\"\n        @blur=\"makeFieldDirty('password')\"\n      />\n      <span class=\"error\" v-if=\"errors.password\">{{ errors.password }}</span>\n    </label>\n\n    <button type=\"submit\">Přihlásit se</button>\n  </form>\n</template>\n```\n\n---\n\n## 🔄 Auto Validation\n\nThe schema and data are both **deeply watched**, meaning any change triggers validation automatically unless throttled externally.\n\n---\n\n## 🔐 Type Safety\n\n* Fully type-safe thanks to `InferOutput<TSchema>` and Valibot's schema inference.\n* Validation schema and input are treated as generic inputs (`TSchema`), enabling reusable, scalable logic across forms.\n\n---\n\n## 💡 Notes\n\n* You can control the timing and granularity of field validation using your own inputs, e.g., `@blur` or `@change` events.\n* Form state (data) is kept external and not mutated internally.\n* This approach is ideal for decoupled forms, such as those using Vue's Composition API and `<script setup>` pattern.\n","readmeFilename":"README.md"}