{"_id":"@swan-io/use-form","_rev":"10-2390e43ce541a0a64ad0e9ebef93db1f","name":"@swan-io/use-form","dist-tags":{"latest":"4.0.0"},"versions":{"2.0.0-rc.0":{"name":"@swan-io/use-form","version":"2.0.0-rc.0","keywords":["form","hook","react","typescript","ux","validation"],"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","_id":"@swan-io/use-form@2.0.0-rc.0","maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","bugs":{"url":"https://github.com/swan-io/use-form/issues"},"dist":{"shasum":"94bb1d3abef4534e1e4299abe2022d79d021874b","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-2.0.0-rc.0.tgz","fileCount":13,"integrity":"sha512-pSlMYuM97g+EHvE+x9H+hMN26bY7iJikKKbejwujPhc9pYQLZPpa3cV7IhyyJDB1fu9ENutJzBregUjlvleqHQ==","signatures":[{"sig":"MEYCIQDmdZ7tIsKxst08v+iCrPy6wUM4iHmyw0cPNOa9Ka6LKgIhAOeePFT4qJn4XEcHj+9d/NX0Y/0fHFxmlcQIjX4sQwIt","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":80294},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","source":"src/index.ts","gitHead":"b7b42486b3b2f6f97ac62282117d41e5f75fe6a6","scripts":{"lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","build":"yarn clean && microbundle -f cjs,es --tsconfig tsconfig.build.json","clean":"rm -rf dist","format":"prettier '**/*' --ignore-unknown --write","prepack":"yarn typecheck && yarn lint && yarn test && yarn build","typecheck":"tsc --noEmit","test:watch":"vitest --watch"},"_npmUser":{"name":"swan-io","email":"admin+npm@swan.io"},"prettier":{"plugins":["prettier-plugin-organize-imports"],"printWidth":100},"repository":{"url":"git+https://github.com/swan-io/use-form.git","type":"git"},"_npmVersion":"10.2.4","description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","browserslist":[">0.2%","not op_mini all","not dead"],"dependencies":{"@swan-io/boxed":"^2.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^24.0.0","react":"^18.2.0","eslint":"^8.56.0","vitest":"^1.2.2","prettier":"^3.2.5","react-dom":"^18.2.0","typescript":"^5.3.3","microbundle":"^0.15.1","@types/react":"^18.2.55","@testing-library/react":"^14.2.1","@typescript-eslint/parser":"^7.0.1","eslint-plugin-react-hooks":"^4.6.0","@typescript-eslint/eslint-plugin":"^7.0.1","prettier-plugin-organize-imports":"^3.2.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-form_2.0.0-rc.0_1708607634856_0.029107723375003225","host":"s3://npm-registry-packages"}},"2.0.0-rc.1":{"name":"@swan-io/use-form","version":"2.0.0-rc.1","keywords":["form","hook","react","typescript","ux","validation"],"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","_id":"@swan-io/use-form@2.0.0-rc.1","maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","bugs":{"url":"https://github.com/swan-io/use-form/issues"},"dist":{"shasum":"fe6dba8f3f36a0e4d31182a89ae5a107f8048184","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-2.0.0-rc.1.tgz","fileCount":13,"integrity":"sha512-ZuH+b/OeuuOXTqQ6PdNWtsHYB8hKNgURrqKoQY4uG4vI3xcSWJNQi6vkS8cYMAyowB1r3p7KH9sEtogN5H2bhQ==","signatures":[{"sig":"MEUCIQC02r/rpFMtIAzavnWOxVPDg0KS8uje6g0rHaoeYR9bAQIgSsgpGg1dktWZZo1ia2CbojgMfIgftizwL2WlDQ0GgXU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":80177},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","source":"src/index.ts","gitHead":"c098afca7537779f588e586879157dd72571d7e0","scripts":{"lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","build":"yarn clean && microbundle -f cjs,es --tsconfig tsconfig.build.json","clean":"rm -rf dist","format":"prettier '**/*' --ignore-unknown --write","prepack":"yarn typecheck && yarn lint && yarn test && yarn build","typecheck":"tsc --noEmit","test:watch":"vitest --watch"},"_npmUser":{"name":"swan-io","email":"admin+npm@swan.io"},"prettier":{"plugins":["prettier-plugin-organize-imports"],"printWidth":100},"repository":{"url":"git+https://github.com/swan-io/use-form.git","type":"git"},"_npmVersion":"10.2.4","description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","browserslist":[">0.2%","not op_mini all","not dead"],"dependencies":{"@swan-io/boxed":"^2.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^24.0.0","react":"^18.2.0","eslint":"^8.56.0","vitest":"^1.2.2","prettier":"^3.2.5","react-dom":"^18.2.0","typescript":"^5.3.3","microbundle":"^0.15.1","@types/react":"^18.2.55","@testing-library/react":"^14.2.1","@typescript-eslint/parser":"^7.0.1","eslint-plugin-react-hooks":"^4.6.0","@typescript-eslint/eslint-plugin":"^7.0.1","prettier-plugin-organize-imports":"^3.2.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-form_2.0.0-rc.1_1708693182733_0.7131514873757141","host":"s3://npm-registry-packages"}},"2.0.0-rc.2":{"name":"@swan-io/use-form","version":"2.0.0-rc.2","keywords":["form","hook","react","typescript","ux","validation"],"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","_id":"@swan-io/use-form@2.0.0-rc.2","maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","bugs":{"url":"https://github.com/swan-io/use-form/issues"},"dist":{"shasum":"8e7aad0257e16df2bbf5603f5e16b14820e399ee","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-2.0.0-rc.2.tgz","fileCount":13,"integrity":"sha512-F7uX/7dSbPgO4PhOk5IRKIIrKfSv7WcBRFd4UKaYrrFhvJbNg8pojNI2H8/1H8SyYwp8gCMJ3AcDUmuzovpJNg==","signatures":[{"sig":"MEYCIQCFPcfe+I12tg/bTMoD8wHdo4AFTYGb/61GSMUytjjhXgIhANFgWHKq/7al7FvMDBhlVvQT/B/SPYo7xBLf0vUNJinc","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":79824},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","source":"src/index.ts","gitHead":"43ddb14b90f99a22af565820f369abd62364e668","scripts":{"lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","build":"yarn clean && microbundle -f cjs,es --tsconfig tsconfig.build.json","clean":"rm -rf dist","format":"prettier '**/*' --ignore-unknown --write","prepack":"yarn typecheck && yarn lint && yarn test && yarn build","typecheck":"tsc --noEmit","test:watch":"vitest --watch"},"_npmUser":{"name":"swan-io","email":"admin+npm@swan.io"},"prettier":{"plugins":["prettier-plugin-organize-imports"],"printWidth":100},"repository":{"url":"git+https://github.com/swan-io/use-form.git","type":"git"},"_npmVersion":"10.2.4","description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","browserslist":[">0.2%","not op_mini all","not dead"],"dependencies":{"@swan-io/boxed":"^2.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^24.0.0","react":"^18.2.0","eslint":"^8.56.0","vitest":"^1.2.2","prettier":"^3.2.5","react-dom":"^18.2.0","typescript":"^5.3.3","microbundle":"^0.15.1","@types/react":"^18.2.55","@testing-library/react":"^14.2.1","@typescript-eslint/parser":"^7.0.1","eslint-plugin-react-hooks":"^4.6.0","@typescript-eslint/eslint-plugin":"^7.0.1","prettier-plugin-organize-imports":"^3.2.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-form_2.0.0-rc.2_1709129584496_0.7021921840389971","host":"s3://npm-registry-packages"}},"2.0.0":{"name":"@swan-io/use-form","version":"2.0.0","keywords":["form","hook","react","typescript","ux","validation"],"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","_id":"@swan-io/use-form@2.0.0","maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","bugs":{"url":"https://github.com/swan-io/use-form/issues"},"dist":{"shasum":"20363a05d4e7242d6b0b19f954f83556fd6496e4","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-2.0.0.tgz","fileCount":13,"integrity":"sha512-PctTlWCu7itDB/T32PGBFyfzVQobgPxbULkTZnDJlcL2qsuoQXeTjtmAF6ddiZajUKDtZpvYYjQdmtxJzsY8Sg==","signatures":[{"sig":"MEYCIQDhpKDnDNVyI54yJjWorDIRQeE53YOQ4HRetHzy09JqAQIhAP0f0P6ciflAxbpJd2U+KiWh4mQGaXavzjgYFFTapYjt","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":95795},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","source":"src/index.ts","gitHead":"c4d5b0beadc7280b04760ba83aa44a0b689197c7","scripts":{"lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","build":"tsup && tsc -p tsconfig.build.json --emitDeclarationOnly","format":"prettier '**/*' --ignore-unknown --write","prepack":"yarn typecheck && yarn lint && yarn test && yarn build","typecheck":"tsc --noEmit","test:watch":"vitest --watch"},"_npmUser":{"name":"swan-io","email":"admin+npm@swan.io"},"prettier":{"plugins":["prettier-plugin-organize-imports"],"printWidth":100},"repository":{"url":"git+https://github.com/swan-io/use-form.git","type":"git"},"_npmVersion":"10.2.4","description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","directories":{},"sideEffects":false,"_nodeVersion":"20.11.1","dependencies":{"@swan-io/boxed":"^2.1.1"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.2","jsdom":"^24.0.0","react":"^18.2.0","eslint":"^8.57.0","vitest":"^1.4.0","prettier":"^3.2.5","react-dom":"^18.2.0","typescript":"^5.4.3","@types/node":"^20.12.4","@types/react":"^18.2.74","@testing-library/react":"^14.2.2","@typescript-eslint/parser":"^7.5.0","eslint-plugin-react-hooks":"^4.6.0","@typescript-eslint/eslint-plugin":"^7.5.0","prettier-plugin-organize-imports":"^3.2.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-form_2.0.0_1712223546345_0.377658640649692","host":"s3://npm-registry-packages"}},"2.0.1":{"name":"@swan-io/use-form","version":"2.0.1","keywords":["form","hook","react","typescript","ux","validation"],"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","_id":"@swan-io/use-form@2.0.1","maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","bugs":{"url":"https://github.com/swan-io/use-form/issues"},"dist":{"shasum":"65a8ff5428e50081282b80c34f092537fe4d43ae","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-2.0.1.tgz","fileCount":13,"integrity":"sha512-eWUvHOhcy6Y0wR21qznCDhAzK71Wuh1Rj9JInWfs+4Nf+CdSQ2SJd/m0rthpCtC6P1HOGPw9MB7jX92Ikh69aw==","signatures":[{"sig":"MEYCIQD/QdGv1M8wmf9yYKaO26Ap+3R3W5SFC0XcrrvtzOwlbwIhANwang88zXSNEDYiFdmDngsDzbSeC/HFMeTw6mwAo+vB","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":95809},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","source":"src/index.ts","gitHead":"b82ffbc780ea0e39cf68932d9cba65db5d2d4cab","scripts":{"lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","build":"tsup && tsc -p tsconfig.build.json --emitDeclarationOnly","format":"prettier '**/*' --ignore-unknown --write","prepack":"yarn typecheck && yarn lint && yarn test && yarn build","typecheck":"tsc --noEmit","test:watch":"vitest --watch"},"_npmUser":{"name":"swan-io","email":"admin+npm@swan.io"},"prettier":{"plugins":["prettier-plugin-organize-imports"],"printWidth":100},"repository":{"url":"git+https://github.com/swan-io/use-form.git","type":"git"},"_npmVersion":"10.2.4","description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","directories":{},"sideEffects":false,"_nodeVersion":"20.11.1","dependencies":{"@swan-io/boxed":"^2.1.1"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.2","jsdom":"^24.0.0","react":"^18.2.0","eslint":"^8.57.0","vitest":"^1.4.0","prettier":"^3.2.5","react-dom":"^18.2.0","typescript":"^5.4.3","@types/node":"^20.12.4","@types/react":"^18.2.74","@testing-library/react":"^14.2.2","@typescript-eslint/parser":"^7.5.0","eslint-plugin-react-hooks":"^4.6.0","@typescript-eslint/eslint-plugin":"^7.5.0","prettier-plugin-organize-imports":"^3.2.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-form_2.0.1_1713365223835_0.7332968455294651","host":"s3://npm-registry-packages"}},"2.0.3":{"name":"@swan-io/use-form","version":"2.0.3","keywords":["form","hook","react","typescript","ux","validation"],"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","_id":"@swan-io/use-form@2.0.3","maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","dist":{"shasum":"96b51217854a87e24aaaad8277c09cf9daf9b576","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-2.0.3.tgz","fileCount":15,"integrity":"sha512-jPjsrSaN7o8HPdB5XEgFkLPx6CP7W+pH69TLE2Oxa1NzBTWyh0ziDKPH9sWsbCsJ+erxGRzZvKXNDoK1Wk5nDQ==","signatures":[{"sig":"MEUCIQCxU1mcFwCy/Rq2/P1qpT2jjW/bSoRWH/Rh6fOrSY693gIgK2WaFDgG8SBiU+74qwcsFA3poYSRGxX5lNa0qpQ/ddA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":95809},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","source":"src/index.ts","scripts":{"lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","build":"tsup && tsc -p tsconfig.build.json --emitDeclarationOnly","format":"prettier '**/*' --ignore-unknown --write","prepack":"yarn typecheck && yarn lint && yarn test && yarn build","typecheck":"tsc --noEmit","test:watch":"vitest --watch"},"_npmUser":{"name":"swan-io","email":"admin+npm@swan.io"},"prettier":{"plugins":["prettier-plugin-organize-imports"],"printWidth":100},"repository":{"url":"https://github.com/swan-io/use-form.git","type":"git"},"description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2021 Swan\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 all\ncopies 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 THE\nSOFTWARE.\n","sideEffects":false,"dependencies":{"@swan-io/boxed":"^2.2.1"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.2","jsdom":"^24.0.0","react":"^18.2.0","eslint":"^8.57.0","vitest":"^1.4.0","prettier":"^3.2.5","react-dom":"^18.2.0","typescript":"^5.4.3","@types/node":"^20.12.4","@types/react":"^18.2.74","@testing-library/react":"^14.2.2","@typescript-eslint/parser":"^7.5.0","eslint-plugin-react-hooks":"^4.6.0","@typescript-eslint/eslint-plugin":"^7.5.0","prettier-plugin-organize-imports":"^3.2.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-form_2.0.3_1713774843176_0.6203939430883845","host":"s3://npm-registry-packages"}},"2.0.4":{"name":"@swan-io/use-form","version":"2.0.4","keywords":["form","hook","react","typescript","ux","validation"],"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","_id":"@swan-io/use-form@2.0.4","maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","dist":{"shasum":"791bf5e8a1fe507b7d174b877b02e688c8c8564f","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-2.0.4.tgz","fileCount":15,"integrity":"sha512-z4K2rq+hFIS1ZHDw4Ifse/5OAS8M3lU7P+GDydQ2Q+Zki9CUVMQwvHuwQf1fn/k/dLpYd/AjrpHw7D7xFu3rTw==","signatures":[{"sig":"MEYCIQD/v2K5GvojW3fp0i9BNYVsbz+exkeflHVbgPrDs1AinwIhANHisIPgGyGCWQrO+Qrtb/NHmeHrXh3dM6iAFXpJsqLb","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":95809},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","source":"src/index.ts","scripts":{"lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","build":"tsup && tsc -p tsconfig.build.json --emitDeclarationOnly","format":"prettier '**/*' --ignore-unknown --write","prepack":"yarn typecheck && yarn lint && yarn test && yarn build","typecheck":"tsc --noEmit","test:watch":"vitest --watch"},"_npmUser":{"name":"swan-io","email":"admin+npm@swan.io"},"prettier":{"plugins":["prettier-plugin-organize-imports"],"printWidth":100},"repository":{"url":"https://github.com/swan-io/use-form.git","type":"git"},"description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2021 Swan\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 all\ncopies 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 THE\nSOFTWARE.\n","sideEffects":false,"dependencies":{"@swan-io/boxed":"^2.3.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.2","jsdom":"^24.0.0","react":"^18.2.0","eslint":"^8.57.0","vitest":"^1.4.0","prettier":"^3.2.5","react-dom":"^18.2.0","typescript":"^5.4.3","@types/node":"^20.12.4","@types/react":"^18.2.74","@testing-library/react":"^14.2.2","@typescript-eslint/parser":"^7.5.0","eslint-plugin-react-hooks":"^4.6.0","@typescript-eslint/eslint-plugin":"^7.5.0","prettier-plugin-organize-imports":"^3.2.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-form_2.0.4_1714488612443_0.8214212271143815","host":"s3://npm-registry-packages"}},"2.0.5":{"name":"@swan-io/use-form","version":"2.0.5","keywords":["form","hook","react","typescript","ux","validation"],"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","_id":"@swan-io/use-form@2.0.5","maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","dist":{"shasum":"6220148e0259fc6b1abe271d40b21ce6557d924f","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-2.0.5.tgz","fileCount":15,"integrity":"sha512-UZbrngc1JPGJQ47APmWEQ/KVBoR/gNHZJrJNoC1qr95OZnfyxBQtNPmRbuCWqWKLIR8lYejk3Iw8VY4Gbon8CQ==","signatures":[{"sig":"MEUCIB4Aj+2pRkHOMhBvilj+P27eY4Pkwqw2eMfB+ujbapBdAiEA3vvFfwoDHiZi9/rBsZjFOkqyAqUxx8aEbqbAdAvQaEA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":96999},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","source":"src/index.ts","scripts":{"lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","build":"tsup && tsc -p tsconfig.build.json --emitDeclarationOnly","format":"prettier '**/*' --ignore-unknown --write","prepack":"yarn typecheck && yarn lint && yarn test && yarn build","typecheck":"tsc --noEmit","test:watch":"vitest --watch"},"_npmUser":{"name":"swan-io","email":"admin+npm@swan.io"},"prettier":{"plugins":["prettier-plugin-organize-imports"],"printWidth":100},"repository":{"url":"https://github.com/swan-io/use-form.git","type":"git"},"description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2021 Swan\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 all\ncopies 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 THE\nSOFTWARE.\n","sideEffects":false,"dependencies":{"@swan-io/boxed":"^2.3.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.2","jsdom":"^24.0.0","react":"^18.2.0","eslint":"^8.57.0","vitest":"^1.4.0","prettier":"^3.2.5","react-dom":"^18.2.0","typescript":"^5.4.3","@types/node":"^20.12.4","@types/react":"^18.2.74","@testing-library/react":"^14.2.2","@typescript-eslint/parser":"^7.5.0","eslint-plugin-react-hooks":"^4.6.0","@typescript-eslint/eslint-plugin":"^7.5.0","prettier-plugin-organize-imports":"^3.2.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-form_2.0.5_1720600437702_0.6469810915942278","host":"s3://npm-registry-packages"}},"3.1.0":{"name":"@swan-io/use-form","version":"3.1.0","keywords":["form","hook","react","typescript","ux","validation"],"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","_id":"@swan-io/use-form@3.1.0","maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","dist":{"shasum":"5b31ae33cdc085cf9423630de06b4c9f4d176946","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-3.1.0.tgz","fileCount":15,"integrity":"sha512-X6NpZ7LCeo7eS9RVCZrtpX+3GXZFUfUZpIwtVa2GNmqTLgyDbLhN8N6zBv+dmHL9KAQ+Zng2fTCCQpCZvmDu5A==","signatures":[{"sig":"MEUCIF/Z+tEmOphTv21vmXNL5Xj85m6Gilp900VJ6mWgxb4aAiEA4qQpxI6BNUSiaoZrs5KFAZowlkoLvAN3PJI+W9UJI9Q=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":96999},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","source":"src/index.ts","scripts":{"lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","build":"tsup && tsc -p tsconfig.build.json --emitDeclarationOnly","format":"prettier '**/*' --ignore-unknown --write","prepack":"yarn typecheck && yarn lint && yarn test && yarn build","typecheck":"tsc --noEmit","test:watch":"vitest --watch"},"_npmUser":{"name":"swan-io","email":"admin+npm@swan.io"},"prettier":{"plugins":["prettier-plugin-organize-imports"],"printWidth":100},"repository":{"url":"https://github.com/swan-io/use-form.git","type":"git"},"description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","directories":{},"licenseText":"MIT License\n\nCopyright (c) 2021 Swan\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 all\ncopies 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 THE\nSOFTWARE.\n","sideEffects":false,"dependencies":{"@swan-io/boxed":"^3.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.2","jsdom":"^24.0.0","react":"^18.2.0","eslint":"^8.57.0","vitest":"^1.4.0","prettier":"^3.2.5","react-dom":"^18.2.0","typescript":"^5.4.3","@types/node":"^20.12.4","@types/react":"^18.2.74","@testing-library/react":"^14.2.2","@typescript-eslint/parser":"^7.5.0","eslint-plugin-react-hooks":"^4.6.0","@typescript-eslint/eslint-plugin":"^7.5.0","prettier-plugin-organize-imports":"^3.2.4"},"peerDependencies":{"react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-form_3.1.0_1729523011604_0.6643254036740658","host":"s3://npm-registry-packages"}},"4.0.0":{"name":"@swan-io/use-form","version":"4.0.0","license":"MIT","description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"homepage":"https://github.com/swan-io/use-form#readme","repository":{"type":"git","url":"git+https://github.com/swan-io/use-form.git"},"sideEffects":false,"source":"src/index.ts","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","keywords":["form","hook","react","typescript","ux","validation"],"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"prettier":{"printWidth":100,"plugins":["prettier-plugin-organize-imports"]},"peerDependencies":{"react":">=19.0.0"},"dependencies":{"@bloodyowl/boxed":"^3.4.0"},"devDependencies":{"@eslint/js":"^9.39.1","@testing-library/react":"^16.3.2","@types/node":"^25.8.0","@types/react":"^19.2.14","eslint":"^9.39.1","eslint-plugin-react-hooks":"^7.0.1","jsdom":"^24.0.0","prettier":"^3.2.5","prettier-plugin-organize-imports":"^3.2.4","react":"^19.2.6","react-dom":"^19.2.6","tsup":"^8.5.1","typescript":"^6.0.3","typescript-eslint":"^8.48.0","vitest":"^4.1.6"},"scripts":{"format":"prettier '**/*' --ignore-unknown --write","lint":"eslint --ext ts,tsx __tests__ src","test":"vitest --run","test:watch":"vitest --watch","typecheck":"tsc --noEmit","build":"tsup && tsc -p tsconfig.build.json --emitDeclarationOnly"},"_id":"@swan-io/use-form@4.0.0","bugs":{"url":"https://github.com/swan-io/use-form/issues"},"_integrity":"sha512-8ZrqjhNPDtMqGoTJ1VPzZcaJfvCGva6rHQm5TmCdGRUJyx18GQO08v4wgfro4SrY+UY/A0wnoGFZqlmRC4kknQ==","_resolved":"/tmp/90b75602d042738d47f39ee9c347a0ab/swan-io-use-form-4.0.0.tgz","_from":"file:swan-io-use-form-4.0.0.tgz","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-8ZrqjhNPDtMqGoTJ1VPzZcaJfvCGva6rHQm5TmCdGRUJyx18GQO08v4wgfro4SrY+UY/A0wnoGFZqlmRC4kknQ==","shasum":"ccc497268c7bcebd18e287fbfeeba51490106e0c","tarball":"https://registry.npmjs.org/@swan-io/use-form/-/use-form-4.0.0.tgz","fileCount":13,"unpackedSize":107073,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@swan-io%2fuse-form@4.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDme7pt/gPImwpWo4763DE7fG2NH6it7KPIWSJL7SwEIwIhALEKyaOoqflL9purrNKf+iKX5IVCzhLckpuhpdKNgVrl"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d8693019-736f-45ce-af45-7475f6202b6a"}},"directories":{},"maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/use-form_4.0.0_1779113410592_0.14015881716077727"},"_hasShrinkwrap":false}},"time":{"created":"2024-02-22T13:13:54.785Z","modified":"2026-05-18T14:10:11.076Z","2.0.0-rc.0":"2024-02-22T13:13:55.047Z","2.0.0-rc.1":"2024-02-23T12:59:42.889Z","2.0.0-rc.2":"2024-02-28T14:13:04.649Z","2.0.0":"2024-04-04T09:39:06.514Z","2.0.1":"2024-04-17T14:47:03.994Z","2.0.3":"2024-04-22T08:34:03.355Z","2.0.4":"2024-04-30T14:50:12.588Z","2.0.5":"2024-07-10T08:33:57.926Z","3.1.0":"2024-10-21T15:03:31.781Z","4.0.0":"2026-05-18T14:10:10.803Z"},"author":{"name":"Mathieu Acthernoene","email":"mathieu.acthernoene@swan.io"},"license":"MIT","homepage":"https://github.com/swan-io/use-form#readme","keywords":["form","hook","react","typescript","ux","validation"],"repository":{"type":"git","url":"git+https://github.com/swan-io/use-form.git"},"description":"A simple, fast and opinionated form library for React & React Native focusing on UX.","contributors":[{"name":"Frederic Godin","email":"frederic.godin@swan.io"}],"maintainers":[{"name":"swan-io","email":"admin+npm@swan.io"}],"readme":"# @swan-io/use-form\n\n[![mit licence](https://img.shields.io/dub/l/vibe-d.svg?style=for-the-badge)](https://github.com/swan-io/use-form/blob/main/LICENSE)\n[![npm version](https://img.shields.io/npm/v/@swan-io/use-form?style=for-the-badge)](https://www.npmjs.org/package/@swan-io/use-form)\n[![bundlephobia](https://img.shields.io/bundlephobia/minzip/@swan-io/use-form?label=size&style=for-the-badge)](https://bundlephobia.com/result?p=@swan-io/use-form)\n\nA simple, fast, and opinionated form library for React & React Native focusing on UX.<br>\n👉 Take a look at [the demo website](https://swan-io.github.io/use-form).\n\n## Setup\n\n```bash\n$ npm install --save @swan-io/use-form\n# --- or ---\n$ yarn add @swan-io/use-form\n```\n\n## Features\n\n- Subscription-based field updates (avoid re-render the whole form on each keystroke 🔥)\n- Validation strategies ✨\n- Field sanitization\n- Mounted-only fields validation\n- Advanced focus handling\n- Best-in-class TypeScript support\n- Sync and async form submission\n\n## Motivation\n\nWhy another React form library 🤔?<br>\nBecause, as silly as it seems, we couldn't find any existing library which fits our existing needs:\n\n- We want validation strategies per field because we fell in love with them when we read the [re-formality](https://github.com/MinimaHQ/re-formality) documentation (which is unfortunately only available for [ReScript](https://rescript-lang.org/)).\n- It should be able to handle huge forms without a single performance hiccup.\n- Validation should be simple, reusable, and testable (aka just functions).\n- It shouldn't even try to validate unmounted fields.\n- It should have built-in focus management (to improve the keyboard flow of our React Native forms).\n\n## Validation strategies ✨\n\nThe key of **good UX** is simple: validation should be executed **in continue**, feedback should be provided **when it makes sense**.\n\n### Quick example: A credit card field 💳\n\nLet's say we want to display a valid state icon (✔) when the input value is a valid credit card number but don't want to display an error until the user blurs the field (and lets the value in an invalid state).\n\n#### Something like this:\n\n![Valid credit card](docs/credit-card-valid.gif)\n![Invalid credit card](docs/credit-card-error.gif)\n\nHow do we easily achieve such magic? With the `onSuccessOrBlur` strategy 🧙‍♂️<br>\n\n```tsx\nconst {} = useForm({\n  cardNumber: { initialValue: \"\", strategy: \"onSuccessOrBlur\" },\n});\n```\n\nOf course, `onSuccessOrBlur` will not fit perfectly every use-case!<br>\nThat's precisely why every field config could declare its own `strategy`:\n\n| Strategy          | When feedback will be available?                              |\n| ----------------- | ------------------------------------------------------------- |\n| `onChange`        | On first change (as the user types or update the value)       |\n| `onSuccess`       | On first validation success                                   |\n| `onBlur`          | On first field blur                                           |\n| `onSuccessOrBlur` | On first validation success or first field blur **(default)** |\n| `onSubmit`        | On form submit                                                |\n\n#### Note that:\n\n- The strategies will only be activated after the field value update / the form submission.\n- Once the first feedback is given (the field is `valid` or should display an `error` message), the field switches to what we call _\"talkative\"_ state. After that, feedback will be updated on each value change until this field or the form is reset.\n\n## API\n\n⚠️ The API is described using TypeScript pseudocode.<br>These types are not exported by the library / are not even always valid.\n\n### useForm\n\n`useForm` takes one argument (a map of your fields configs) and returns a set of helpers (functions, components, and values) to manage your form state.\n\n```tsx\nimport { useForm } from \"@swan-io/use-form\";\n\nconst {\n  formStatus,\n  Field,\n  FieldsListener,\n  getFieldValue,\n  getFieldRef,\n  setFieldValue,\n  setFieldError,\n  focusField,\n  resetField,\n  sanitizeField,\n  validateField,\n  listenFields,\n  resetForm,\n  submitForm,\n} = useForm({\n  // Keys are used as fields names\n  fieldName: {\n    initialValue: \"\",\n    // Properties below are optional (those are the default values)\n    strategy: \"onSuccessOrBlur\",\n    isEqual: (value1, value2) => Object.is(value1, value2),\n    sanitize: (value) => value,\n    validate: (value, { focusField, getFieldValue }) => {},\n  },\n});\n```\n\n#### Field config\n\n```tsx\ntype fieldConfig = {\n  // The initial field value. It could be anything (string, number, boolean…)\n  initialValue: Value;\n\n  // The chosen strategy. See \"validation strategies\" paragraph\n  strategy: Strategy;\n\n  // Used to perform initial and current value comparison\n  isEqual: (value1: Value, value2: Value) => boolean;\n\n  // Will be run on value before validation and submission. Useful from trimming whitespaces\n  sanitize: (value: Value) => Value;\n\n  // Used to perform field validation. It could return an error message (or nothing)\n  validate: (value: Value) => ErrorMessage | void;\n};\n```\n\n#### formStatus\n\n```tsx\ntype formStatus =\n  | \"untouched\" // no field has been updated\n  | \"editing\"\n  | \"submitting\"\n  | \"submitted\";\n```\n\n#### `<Field />`\n\nA component that exposes everything you need locally as a `children` render prop.\n\n```tsx\n<Field name=\"fieldName\">\n  {\n    (props: {\n      // A ref to pass to your element (only required for focus handling)\n      ref: MutableRefObject;\n      // The field value\n      value: Value;\n      // Is the field valid?\n      valid: boolean;\n      // The field is invalid: here its error message.\n      error?: ErrorMessage;\n      // The onBlur handler (required for onBlur and onSuccessOrBlur strategies)\n      onBlur: () => void;\n      // The onChange handler (required)\n      onChange: (value: Value) => void;\n    }) => /* … */\n  }\n</Field>\n```\n\n#### `<FieldsListener />`\n\nA component that listens for fields states changes. It's useful when a part of your component needs to react to fields updates without triggering a full re-render.\n\n```tsx\n<FieldsListener names={[\"firstName\", \"lastName\"]}>\n  {\n    (states: Record<\"firstName\" | \"lastName\", {\n      // The field value\n      value: Value;\n      // Is the field valid?\n      valid: boolean;\n      // The field is invalid: here its error message.\n      error?: ErrorMessage;\n    }>) => /* … */\n  }\n</FieldsListener>\n```\n\n#### getFieldValue\n\nBy setting `sanitize: true`, you will enforce sanitization.\n\n```tsx\ntype getFieldValue = (\n  name: FieldName,\n  options?: {\n    sanitize?: boolean;\n  },\n) => Value;\n```\n\n#### getFieldRef\n\nReturn the field stable `ref`.\n\n```tsx\ntype getFieldRef = <T>(name: FieldName) => MutableRefObject<T>;\n```\n\n#### setFieldValue\n\nBy setting `validate: true`, you will enforce validation. It has no effect if the field is already _talkative_.\n\n```tsx\ntype setFieldValue = (\n  name: FieldName,\n  value: Value,\n  options?: {\n    validate?: boolean;\n  },\n) => void;\n```\n\n#### setFieldError\n\nWill make the field _talkative_.\n\n```tsx\ntype setFieldError = (name: FieldName, error?: ErrorMessage) => void;\n```\n\n#### focusField\n\nWill only work if you forward the `Field` provided `ref` to your input.\n\n```tsx\ntype focusField = (name: FieldName) => void;\n```\n\n#### resetField\n\nHide user feedback (the field is not _talkative_ anymore) and set value to `initialValue`.\n\n```tsx\ntype resetField = (name: FieldName) => void;\n```\n\n#### sanitizeField\n\nSanitize the field value.\n\n```tsx\ntype sanitizeField = (name: FieldName) => void;\n```\n\n#### validateField\n\nOnce you manually call validation, the field automatically switches to _talkative_ state.\n\n```tsx\ntype validateField = (name: FieldName) => ErrorMessage | void;\n```\n\n#### listenFields\n\nA function that listen for fields states changes. Useful when you want to apply side effects on values change.\n\n```tsx\nReact.useEffect(() => {\n  const removeListener = listenFields(\n    [\"firstName\", \"lastName\"],\n    (states: Record<\"firstName\" | \"lastName\", {\n      // The field value\n      value: Value;\n      // Is the field valid?\n      valid: boolean;\n      // The field is invalid: here its error message.\n      error?: ErrorMessage;\n    }>) => /* … */\n  );\n\n  return () => {\n    removeListener();\n  }\n}, []);\n```\n\n#### resetForm\n\nHide user feedback for all fields (they are not _talkative_ anymore). Reset values to their corresponding `initialValue` and `formStatus` to `untouched`.\n\n```tsx\ntype resetForm = () => void;\n```\n\n#### submitForm\n\nSubmit your form. Each callback could return a `Promise` to keep `formStatus` in `submitting` state.\n\n```tsx\ntype submitForm = (options?: {\n  onSuccess?: (values: OptionRecord<Values>) => Future<unknown> | Promise<unknown> | void;\n  onFailure?: (errors: Partial<Record<keyof Values, ErrorMessage>>) => void;\n  // by default, it will try to focus the first errored field (which is a good practice)\n  focusOnFirstError?: boolean;\n}) => void;\n```\n\n### combineValidators\n\nAs it's a very common case to use several validation functions per field, we export a `combineValidators` helper function that allows you to chain sync validation functions: it will run them sequentially until an error is returned.\n\n```tsx\nimport { combineValidators, useForm } from \"@swan-io/use-form\";\n\nconst validateRequired = (value: string) => {\n  if (!value) {\n    return \"required\";\n  }\n};\n\nconst validateEmail = (email: string) => {\n  if (!/.+@.+\\..{2,}/.test(email)) {\n    return \"invalid email\";\n  }\n};\n\nconst MyAwesomeForm = () => {\n  const { Field, submitForm } = useForm({\n    emailAddress: {\n      initialValue: \"\",\n      // will run each validation function until an error is returned\n      validate: combineValidators(\n        isEmailRequired && validateRequired, // validation checks could be applied conditionally\n        validateEmail,\n      ),\n    },\n  });\n\n  // …\n};\n```\n\n### toOptionalValidator\n\nVery often, we want to execute validation only if a value is not empty. By wrapping any validator (or combined validators) with `toOptionalValidator`, you can bypass the validation in such cases.\n\n```tsx\nimport { toOptionalValidator, Validator } from \"@swan-io/use-form\";\n\n// This validator will error if the string length is < 3 (even if it's an empty string)\nconst validator: Validator<string> = (value) => {\n  if (value.length < 3) {\n    return \"Must be at least 3 characters\";\n  }\n};\n\n// This validator will error if value is not empty string and if the string length is < 3\nconst optionalValidator = toOptionalValidator(validator);\n```\n\nThis function also accept a second param (required for non-string validators) to specify what is an empty value.\n\n```tsx\nimport { toOptionalValidator, Validator } from \"@swan-io/use-form\";\n\nconst validator: Validator<number> = (value) => {\n  if (value < 10) {\n    return \"Must pick at least 10 items\";\n  }\n};\n\n// This validator will also accept a value of 0, as we consider it \"empty\"\nconst optionalValidator = toOptionalValidator(validator, (value) => value === 0);\n```\n\n## Quickstart\n\n```tsx\nimport { useForm } from \"@swan-io/use-form\";\n\nconst MyAwesomeForm = () => {\n  const { Field, submitForm } = useForm({\n    firstName: {\n      initialValue: \"\",\n      strategy: \"onSuccessOrBlur\",\n      sanitize: (value) => value.trim(), // we trim value before validation and submission\n      validate: (value) => {\n        if (value === \"\") {\n          return \"First name is required\";\n        }\n      },\n    },\n  });\n\n  return (\n    <form\n      onSubmit={(event: React.FormEvent) => {\n        event.preventDefault();\n\n        submitForm({\n          onSuccess: (values) => console.log(\"values\", values), // all fields are valid\n          onFailure: (errors) => console.log(\"errors\", errors), // at least one field is invalid\n        });\n      }}\n    >\n      <Field name=\"firstName\">\n        {({ error, onBlur, onChange, valid, value }) => (\n          <>\n            <label htmlFor=\"firstName\">First name</label>\n\n            <input\n              id=\"firstName\"\n              onBlur={onBlur}\n              value={value}\n              onChange={({ target }) => {\n                onChange(target.value);\n              }}\n            />\n\n            {valid && <span>Valid</span>}\n            {error && <span>Invalid</span>}\n          </>\n        )}\n      </Field>\n\n      <button type=\"submit\">Submit</button>\n    </form>\n  );\n};\n```\n\n## More examples\n\nA full set of examples is available on [the demo website](https://swan-io.github.io/use-form) or in the [`/website` directory](https://github.com/swan-io/use-form/tree/main/website) project. Just clone the repository, install its dependencies and start it!\n\n## Acknowledgements\n\n- [re-formality](https://github.com/MinimaHQ/re-formality) for the [validation strategies](https://github.com/MinimaHQ/re-formality/blob/master/docs/02-ValidationStrategies.md) idea.\n- [react-hook-form](https://react-hook-form.com/) and [react-final-form](https://github.com/final-form/react-final-form) for their subscription pattern implementations.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/swan-io/use-form/issues"}}