From 5510b237cc0617bf04047e14aa4837dddc8887b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:47:02 +0000 Subject: [PATCH 1/3] Initial plan From e50e90dad6c5e559b0231e7fe7a986b981fdb5e2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:52:39 +0000 Subject: [PATCH 2/3] Convert project from JavaScript to TypeScript MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Convert src/validationFunctions.js → src/validationFunctions.ts - Convert src/formUtils.js → src/formUtils.ts - Convert src/useValidation.js → src/useValidation.ts - Convert src/index.js → src/index.ts with type re-exports - Remove manual types/index.d.ts (now auto-generated via vite-plugin-dts) - Add tsconfig.json with strict mode - Update vite.config.js to use .ts entry and dts plugin - Update package.json types field to point to dist/index.d.ts - Add typescript and vite-plugin-dts as dev dependencies - Update cypress test imports to remove .js extensions Agent-Logs-Url: https://github.com/Enterwell/react-form-validation/sessions/024b1f72-0daf-4fca-813d-93f6e09775eb Co-authored-by: AleksandarDev <643171+AleksandarDev@users.noreply.github.com> --- .../components/localRemoteValidation.cy.jsx | 4 +- package.json | 9 +- pnpm-lock.yaml | 616 ++++++++++++++++++ src/{formUtils.js => formUtils.ts} | 86 +-- src/{index.js => index.ts} | 17 +- src/{useValidation.js => useValidation.ts} | 79 ++- src/validationFunctions.js | 105 --- src/validationFunctions.ts | 107 +++ tsconfig.json | 18 + types/index.d.ts | 63 -- vite.config.js | 11 +- 11 files changed, 871 insertions(+), 244 deletions(-) rename src/{formUtils.js => formUtils.ts} (55%) rename src/{index.js => index.ts} (67%) rename src/{useValidation.js => useValidation.ts} (55%) delete mode 100644 src/validationFunctions.js create mode 100644 src/validationFunctions.ts create mode 100644 tsconfig.json delete mode 100644 types/index.d.ts diff --git a/cypress/components/localRemoteValidation.cy.jsx b/cypress/components/localRemoteValidation.cy.jsx index ecbc685..4f23764 100644 --- a/cypress/components/localRemoteValidation.cy.jsx +++ b/cypress/components/localRemoteValidation.cy.jsx @@ -5,8 +5,8 @@ import EmailComponentWithFields from '../testComponents/EmailComponentWithFields import EmailComponentWithLocalValidation from '../testComponents/EmailComponentWithLocalValidation.jsx'; import EmailComponentWithRemoteValidation from '../testComponents/EmailComponentWithRemoteValidation.jsx'; import EmailComponentWithSubmit from '../testComponents/EmailComponentWithSubmit.jsx'; -import { submitForm } from '../../src/formUtils.js'; -import { useValidation } from '../../src/useValidation.js'; +import { submitForm } from '../../src/formUtils'; +import { useValidation } from '../../src/useValidation'; const emailValidationRemote = (value) => new Promise((resolve) => setTimeout(() => resolve(isValidEmail(value)), 2000)); const testEmailValid = "matej.radovix@enterwell.net"; diff --git a/package.json b/package.json index 13f0db7..f83cab6 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,10 @@ "test": "cross-env NODE_ENV=test cypress run --component", "test:open": "cross-env NODE_ENV=test cypress open" }, - "types": "./types/index.d.ts", + "types": "./dist/index.d.ts", "main": "./dist/index.js", "files": [ - "dist", - "types" + "dist" ], "keywords": [ "react", @@ -41,7 +40,9 @@ "cypress": "15.9.0", "react": "19.2.4", "react-dom": "19.2.4", - "vite": "7.3.1" + "typescript": "^6.0.2", + "vite": "7.3.1", + "vite-plugin-dts": "^4.5.4" }, "peerDependencies": { "react": "^16.13.1 || ^17 || ^18 || ^19" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 784b56c..2ee83c5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,9 +29,15 @@ importers: react-dom: specifier: 19.2.4 version: 19.2.4(react@19.2.4) + typescript: + specifier: ^6.0.2 + version: 6.0.2 vite: specifier: 7.3.1 version: 7.3.1(@types/node@25.2.0) + vite-plugin-dts: + specifier: ^4.5.4 + version: 4.5.4(@types/node@25.2.0)(rollup@4.57.1)(typescript@6.0.2)(vite@7.3.1(@types/node@25.2.0)) packages: @@ -94,6 +100,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-transform-react-jsx-self@7.27.1': resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} @@ -300,9 +311,31 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@microsoft/api-extractor-model@7.33.5': + resolution: {integrity: sha512-Xh4dXuusndVQqVz4nEN9xOp0DyzsKxeD2FFJkSPg4arAjDSKPcy6cAc7CaeBPA7kF2wV1fuDlo2p/bNMpVr8yg==} + + '@microsoft/api-extractor@7.58.1': + resolution: {integrity: sha512-kF3GFME4lN22O5zbnXk2RP4y/4PDQdps0xKiYTipMYprkwCmmpsWLZt/N2Fkbil540cSLfJX0BW7LkHzgMVUYg==} + hasBin: true + + '@microsoft/tsdoc-config@0.18.1': + resolution: {integrity: sha512-9brPoVdfN9k9g0dcWkFeA7IH9bbcttzDJlXvkf8b2OBzd5MueR1V2wkKBL0abn0otvmkHJC6aapBOTJDDeMCZg==} + + '@microsoft/tsdoc@0.16.0': + resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} + '@rolldown/pluginutils@1.0.0-rc.2': resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.57.1': resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==} cpu: [arm] @@ -441,6 +474,39 @@ packages: cpu: [x64] os: [win32] + '@rushstack/node-core-library@5.21.0': + resolution: {integrity: sha512-LFzN+1lyWROit/P8Md6yxAth7lLYKn37oCKJHirEE2TQB25NDUM7bALf0ar+JAtwFfRCH+D+DGOA7DAzIi2r+g==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/problem-matcher@0.2.1': + resolution: {integrity: sha512-gulfhBs6n+I5b7DvjKRfhMGyUejtSgOHTclF/eONr8hcgF1APEDjhxIsfdUYYMzC3rvLwGluqLjbwCFZ8nxrog==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rig-package@0.7.2': + resolution: {integrity: sha512-9XbFWuqMYcHUso4mnETfhGVUSaADBRj6HUAAEYk50nMPn8WRICmBuCphycQGNB3duIR6EEZX3Xj3SYc2XiP+9A==} + + '@rushstack/terminal@0.22.4': + resolution: {integrity: sha512-fhtLjnXCc/4WleVbVl6aoc7jcWnU6yqjS1S8WoaNREG3ycu/viZ9R/9QM7Y/b4CDvcXoiDyMNIay7JMwBptM3g==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/ts-command-line@5.3.4': + resolution: {integrity: sha512-MLkVKVEN6/2clKTrjN2B2KqKCuPxRwnNsWY7a+FCAq2EMdkj10cM8YgiBSMeGFfzM0mDMzargpHNnNzaBi9Whg==} + + '@types/argparse@1.0.38': + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -485,10 +551,66 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@volar/language-core@2.4.28': + resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} + + '@volar/source-map@2.4.28': + resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} + + '@volar/typescript@2.4.28': + resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} + + '@vue/compiler-core@3.5.32': + resolution: {integrity: sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==} + + '@vue/compiler-dom@3.5.32': + resolution: {integrity: sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==} + + '@vue/compiler-vue2@2.7.16': + resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + + '@vue/language-core@2.2.0': + resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/shared@3.5.32': + resolution: {integrity: sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==} + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + + alien-signals@0.4.14: + resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -508,6 +630,9 @@ packages: arch@2.2.0: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + asn1@0.2.6: resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} @@ -532,6 +657,13 @@ packages: aws4@1.13.2: resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -548,6 +680,13 @@ packages: bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + brace-expansion@2.0.3: + resolution: {integrity: sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==} + + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} + browserslist@4.28.1: resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -627,6 +766,15 @@ packages: resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} engines: {node: '>=4.0.0'} + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.2.4: + resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -657,6 +805,9 @@ packages: dayjs@1.11.19: resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -678,6 +829,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} + engines: {node: '>=0.3.1'} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -698,6 +853,10 @@ packages: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -727,6 +886,9 @@ packages: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + eventemitter2@6.4.7: resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} @@ -738,6 +900,9 @@ packages: resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} engines: {node: '>=4'} + exsolve@1.0.8: + resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -750,6 +915,12 @@ packages: resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} @@ -773,6 +944,10 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} + fs-extra@11.3.4: + resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} + engines: {node: '>=14.14'} + fs-extra@9.1.0: resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} engines: {node: '>=10'} @@ -835,6 +1010,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + http-signature@1.4.0: resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==} engines: {node: '>=0.10'} @@ -846,6 +1025,10 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} @@ -854,6 +1037,10 @@ packages: resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} engines: {node: '>=10'} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -883,6 +1070,9 @@ packages: isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -894,6 +1084,9 @@ packages: engines: {node: '>=6'} hasBin: true + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema@0.4.0: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} @@ -912,6 +1105,9 @@ packages: resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} engines: {'0': node >=0.6.0} + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + listr2@3.14.0: resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} engines: {node: '>=10.0.0'} @@ -921,12 +1117,19 @@ packages: enquirer: optional: true + local-pkg@1.1.2: + resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} + engines: {node: '>=14'} + lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} lodash@4.17.23: resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} @@ -938,6 +1141,13 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -957,12 +1167,26 @@ packages: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + minimatch@10.2.3: + resolution: {integrity: sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==} + engines: {node: 18 || 20 || >=22} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -993,10 +1217,19 @@ packages: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} @@ -1014,6 +1247,12 @@ packages: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.3.0: + resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -1036,6 +1275,9 @@ packages: resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} engines: {node: '>=0.6'} + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + react-dom@19.2.4: resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} peerDependencies: @@ -1052,6 +1294,15 @@ packages: request-progress@3.0.0: resolution: {integrity: sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} @@ -1080,6 +1331,11 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -1119,11 +1375,22 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + sshpk@1.18.0: resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} engines: {node: '>=0.10.0'} hasBin: true + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -1136,6 +1403,10 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -1144,6 +1415,10 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + systeminformation@5.30.7: resolution: {integrity: sha512-33B/cftpaWdpvH+Ho9U1b08ss8GQuLxrWHelbJT1yw4M48Taj8W3ezcPuaLoIHZz5V6tVHuQPr5BprEfnBLBMw==} engines: {node: '>=8.0.0'} @@ -1196,6 +1471,19 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@6.0.2: + resolution: {integrity: sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.3: + resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -1221,6 +1509,15 @@ packages: resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} + vite-plugin-dts@4.5.4: + resolution: {integrity: sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg==} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + vite@7.3.1: resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1261,6 +1558,9 @@ packages: yaml: optional: true + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1280,6 +1580,9 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} @@ -1364,6 +1667,10 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 @@ -1524,8 +1831,52 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@microsoft/api-extractor-model@7.33.5(@types/node@25.2.0)': + dependencies: + '@microsoft/tsdoc': 0.16.0 + '@microsoft/tsdoc-config': 0.18.1 + '@rushstack/node-core-library': 5.21.0(@types/node@25.2.0) + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor@7.58.1(@types/node@25.2.0)': + dependencies: + '@microsoft/api-extractor-model': 7.33.5(@types/node@25.2.0) + '@microsoft/tsdoc': 0.16.0 + '@microsoft/tsdoc-config': 0.18.1 + '@rushstack/node-core-library': 5.21.0(@types/node@25.2.0) + '@rushstack/rig-package': 0.7.2 + '@rushstack/terminal': 0.22.4(@types/node@25.2.0) + '@rushstack/ts-command-line': 5.3.4(@types/node@25.2.0) + diff: 8.0.4 + lodash: 4.18.1 + minimatch: 10.2.3 + resolve: 1.22.11 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' + + '@microsoft/tsdoc-config@0.18.1': + dependencies: + '@microsoft/tsdoc': 0.16.0 + ajv: 8.18.0 + jju: 1.4.0 + resolve: 1.22.11 + + '@microsoft/tsdoc@0.16.0': {} + '@rolldown/pluginutils@1.0.0-rc.2': {} + '@rollup/pluginutils@5.3.0(rollup@4.57.1)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 4.57.1 + '@rollup/rollup-android-arm-eabi@4.57.1': optional: true @@ -1601,6 +1952,47 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.57.1': optional: true + '@rushstack/node-core-library@5.21.0(@types/node@25.2.0)': + dependencies: + ajv: 8.18.0 + ajv-draft-04: 1.0.0(ajv@8.18.0) + ajv-formats: 3.0.1(ajv@8.18.0) + fs-extra: 11.3.4 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.11 + semver: 7.5.4 + optionalDependencies: + '@types/node': 25.2.0 + + '@rushstack/problem-matcher@0.2.1(@types/node@25.2.0)': + optionalDependencies: + '@types/node': 25.2.0 + + '@rushstack/rig-package@0.7.2': + dependencies: + resolve: 1.22.11 + strip-json-comments: 3.1.1 + + '@rushstack/terminal@0.22.4(@types/node@25.2.0)': + dependencies: + '@rushstack/node-core-library': 5.21.0(@types/node@25.2.0) + '@rushstack/problem-matcher': 0.2.1(@types/node@25.2.0) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 25.2.0 + + '@rushstack/ts-command-line@5.3.4(@types/node@25.2.0)': + dependencies: + '@rushstack/terminal': 0.22.4(@types/node@25.2.0) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + + '@types/argparse@1.0.38': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.29.0 @@ -1660,11 +2052,75 @@ snapshots: transitivePeerDependencies: - supports-color + '@volar/language-core@2.4.28': + dependencies: + '@volar/source-map': 2.4.28 + + '@volar/source-map@2.4.28': {} + + '@volar/typescript@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue/compiler-core@3.5.32': + dependencies: + '@babel/parser': 7.29.2 + '@vue/shared': 3.5.32 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.32': + dependencies: + '@vue/compiler-core': 3.5.32 + '@vue/shared': 3.5.32 + + '@vue/compiler-vue2@2.7.16': + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + '@vue/language-core@2.2.0(typescript@6.0.2)': + dependencies: + '@volar/language-core': 2.4.28 + '@vue/compiler-dom': 3.5.32 + '@vue/compiler-vue2': 2.7.16 + '@vue/shared': 3.5.32 + alien-signals: 0.4.14 + minimatch: 9.0.9 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + optionalDependencies: + typescript: 6.0.2 + + '@vue/shared@3.5.32': {} + + acorn@8.16.0: {} + aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 indent-string: 4.0.0 + ajv-draft-04@1.0.0(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + alien-signals@0.4.14: {} + ansi-colors@4.1.3: {} ansi-escapes@4.3.2: @@ -1679,6 +2135,10 @@ snapshots: arch@2.2.0: {} + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + asn1@0.2.6: dependencies: safer-buffer: 2.1.2 @@ -1695,6 +2155,10 @@ snapshots: aws4@1.13.2: {} + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + base64-js@1.5.1: {} baseline-browser-mapping@2.9.19: {} @@ -1707,6 +2171,14 @@ snapshots: bluebird@3.7.2: {} + brace-expansion@2.0.3: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + browserslist@4.28.1: dependencies: baseline-browser-mapping: 2.9.19 @@ -1781,6 +2253,12 @@ snapshots: common-tags@1.8.2: {} + compare-versions@6.1.1: {} + + confbox@0.1.8: {} + + confbox@0.2.4: {} + convert-source-map@2.0.0: {} core-util-is@1.0.2: {} @@ -1849,6 +2327,8 @@ snapshots: dayjs@1.11.19: {} + de-indent@1.0.2: {} + debug@3.2.7(supports-color@8.1.1): dependencies: ms: 2.1.3 @@ -1863,6 +2343,8 @@ snapshots: delayed-stream@1.0.0: {} + diff@8.0.4: {} + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -1887,6 +2369,8 @@ snapshots: ansi-colors: 4.1.3 strip-ansi: 6.0.1 + entities@7.0.1: {} + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -1935,6 +2419,8 @@ snapshots: escape-string-regexp@1.0.5: {} + estree-walker@2.0.2: {} + eventemitter2@6.4.7: {} execa@4.1.0: @@ -1953,6 +2439,8 @@ snapshots: dependencies: pify: 2.3.0 + exsolve@1.0.8: {} + extend@3.0.2: {} extract-zip@2.0.1(supports-color@8.1.1): @@ -1967,6 +2455,10 @@ snapshots: extsprintf@1.3.0: {} + fast-deep-equal@3.1.3: {} + + fast-uri@3.1.0: {} + fd-slicer@1.1.0: dependencies: pend: 1.2.0 @@ -1989,6 +2481,12 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + fs-extra@11.3.4: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + fs-extra@9.1.0: dependencies: at-least-node: 1.0.0 @@ -2054,6 +2552,8 @@ snapshots: dependencies: function-bind: 1.1.2 + he@1.2.0: {} + http-signature@1.4.0: dependencies: assert-plus: 1.0.0 @@ -2064,10 +2564,16 @@ snapshots: ieee754@1.2.1: {} + import-lazy@4.0.0: {} + indent-string@4.0.0: {} ini@2.0.0: {} + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-fullwidth-code-point@3.0.0: {} is-installed-globally@0.4.0: @@ -2087,12 +2593,16 @@ snapshots: isstream@0.1.2: {} + jju@1.4.0: {} + js-tokens@4.0.0: {} jsbn@0.1.1: {} jsesc@3.1.0: {} + json-schema-traverse@1.0.0: {} + json-schema@0.4.0: {} json-stringify-safe@5.0.1: {} @@ -2112,6 +2622,8 @@ snapshots: json-schema: 0.4.0 verror: 1.10.0 + kolorist@1.8.0: {} + listr2@3.14.0(enquirer@2.4.1): dependencies: cli-truncate: 2.1.0 @@ -2125,10 +2637,18 @@ snapshots: optionalDependencies: enquirer: 2.4.1 + local-pkg@1.1.2: + dependencies: + mlly: 1.8.2 + pkg-types: 2.3.0 + quansync: 0.2.11 + lodash.once@4.1.1: {} lodash@4.17.23: {} + lodash@4.18.1: {} + log-symbols@4.1.0: dependencies: chalk: 4.1.2 @@ -2145,6 +2665,14 @@ snapshots: dependencies: yallist: 3.1.1 + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + math-intrinsics@1.1.0: {} merge-stream@2.0.0: {} @@ -2157,10 +2685,27 @@ snapshots: mimic-fn@2.1.0: {} + minimatch@10.2.3: + dependencies: + brace-expansion: 5.0.5 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.0.3 + minimist@1.2.8: {} + mlly@1.8.2: + dependencies: + acorn: 8.16.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.3 + ms@2.1.3: {} + muggle-string@0.4.1: {} + nanoid@3.3.11: {} node-releases@2.0.27: {} @@ -2185,8 +2730,14 @@ snapshots: dependencies: aggregate-error: 3.1.0 + path-browserify@1.0.1: {} + path-key@3.1.1: {} + path-parse@1.0.7: {} + + pathe@2.0.3: {} + pend@1.2.0: {} performance-now@2.1.0: {} @@ -2197,6 +2748,18 @@ snapshots: pify@2.3.0: {} + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + + pkg-types@2.3.0: + dependencies: + confbox: 0.2.4 + exsolve: 1.0.8 + pathe: 2.0.3 + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -2218,6 +2781,8 @@ snapshots: dependencies: side-channel: 1.1.0 + quansync@0.2.11: {} + react-dom@19.2.4(react@19.2.4): dependencies: react: 19.2.4 @@ -2231,6 +2796,14 @@ snapshots: dependencies: throttleit: 1.0.1 + require-from-string@2.0.2: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + restore-cursor@3.1.0: dependencies: onetime: 5.1.2 @@ -2281,6 +2854,10 @@ snapshots: semver@6.3.1: {} + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -2331,6 +2908,10 @@ snapshots: source-map-js@1.2.1: {} + source-map@0.6.1: {} + + sprintf-js@1.0.3: {} + sshpk@1.18.0: dependencies: asn1: 0.2.6 @@ -2343,6 +2924,8 @@ snapshots: safer-buffer: 2.1.2 tweetnacl: 0.14.5 + string-argv@0.3.2: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -2355,6 +2938,8 @@ snapshots: strip-final-newline@2.0.0: {} + strip-json-comments@3.1.1: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -2363,6 +2948,8 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + systeminformation@5.30.7: {} throttleit@1.0.1: {} @@ -2400,6 +2987,12 @@ snapshots: type-fest@0.8.1: {} + typescript@5.9.3: {} + + typescript@6.0.2: {} + + ufo@1.6.3: {} + undici-types@7.16.0: optional: true @@ -2421,6 +3014,25 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 + vite-plugin-dts@4.5.4(@types/node@25.2.0)(rollup@4.57.1)(typescript@6.0.2)(vite@7.3.1(@types/node@25.2.0)): + dependencies: + '@microsoft/api-extractor': 7.58.1(@types/node@25.2.0) + '@rollup/pluginutils': 5.3.0(rollup@4.57.1) + '@volar/typescript': 2.4.28 + '@vue/language-core': 2.2.0(typescript@6.0.2) + compare-versions: 6.1.1 + debug: 4.4.3(supports-color@8.1.1) + kolorist: 1.8.0 + local-pkg: 1.1.2 + magic-string: 0.30.21 + typescript: 6.0.2 + optionalDependencies: + vite: 7.3.1(@types/node@25.2.0) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + vite@7.3.1(@types/node@25.2.0): dependencies: esbuild: 0.27.2 @@ -2433,6 +3045,8 @@ snapshots: '@types/node': 25.2.0 fsevents: 2.3.3 + vscode-uri@3.1.0: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -2453,6 +3067,8 @@ snapshots: yallist@3.1.1: {} + yallist@4.0.0: {} + yauzl@2.10.0: dependencies: buffer-crc32: 0.2.13 diff --git a/src/formUtils.js b/src/formUtils.ts similarity index 55% rename from src/formUtils.js rename to src/formUtils.ts index 36eb467..bca1437 100644 --- a/src/formUtils.js +++ b/src/formUtils.ts @@ -1,35 +1,37 @@ +import type { Fields } from './useValidation'; + /** * Checks whether some value is function or not. - * - * @param {any} f Value that should be checked whether it is function or not - * @returns true if value is a function, false otherwise + * + * @param f Value that should be checked whether it is function or not + * @returns true if value is a function, false otherwise */ -const isFunction = (f) => Object.prototype.toString.call(f) == '[object Function]'; +const isFunction = (f: unknown): f is Function => Object.prototype.toString.call(f) == '[object Function]'; /** * Extracts the values from form fields' objects. - * - * @param {Object.} fields Form's fields + * + * @param fields Form's fields * @returns object containing form fields' values */ -export const extractValues = (fields) => { +export const extractValues = (fields: Fields): Record => { return Object .entries(fields) - .reduce((acc, [k, v]) => ({ ...acc, [k]: v.value }), {}); + .reduce>((acc, [k, v]) => ({ ...acc, [k]: v.value }), {}); }; /** * Sets the values of form fields without changing dirty flag. * When form is reset, these values will be used as initial values. - * - * @param {Object.} fields Form's fields - * @param {Object.} values Form's fields new values + * + * @param fields Form's fields + * @param values Form's fields new values */ -export const setValues = (fields, values) => { +export const setValues = (fields: Fields, values: Record): void => { Object .entries(fields) .forEach(([k, v]) => { - if (values.hasOwnProperty(k)) { + if (Object.prototype.hasOwnProperty.call(values, k)) { v.setValue(values[k]); } }); @@ -37,12 +39,12 @@ export const setValues = (fields, values) => { /** * Validates all forms' fields. - * - * @param {Object.} fields Form's fields - * @returns {boolean|Promise} true if there is any error in the form, false otherwise. - * Promise with same result when at least one validation function resolved to Promise. + * + * @param fields Form's fields + * @returns true if there is any error in the form, false otherwise. + * Promise with same result when at least one validation function resolved to Promise. */ -export const validateFields = (fields) => { +export const validateFields = (fields: Fields): boolean | Promise => { // Checks whether all fields have correct validation function Object .entries(fields) @@ -53,7 +55,7 @@ export const validateFields = (fields) => { }); // Validate all fields - var validationResults = + const validationResults = Object.values(fields) .map(field => field.validate(field.value)); @@ -61,8 +63,8 @@ export const validateFields = (fields) => { if (validationResults.every(result => typeof result === "boolean")) return validationResults.some(result => result); - // Resolve all validation promises and return - return new Promise((resolve, reject) => { + // Resolve all validation promises and return + return new Promise((resolve, reject) => { Promise.all(validationResults.map(result => Promise.resolve(result))) .then(results => resolve(results.some(result => result))) .catch((reason) => reject(reason)); @@ -71,20 +73,20 @@ export const validateFields = (fields) => { /** * Checks if any of the form fields are dirty (have changed from initial values). - * - * @param {Object.} fields Form's fields - * @returns {boolean} true if any field is dirty, false otherwise + * + * @param fields Form's fields + * @returns true if any field is dirty, false otherwise */ -export const isDirty = (fields) => { +export const isDirty = (fields: Fields): boolean => { return Object.values(fields).some(field => field.dirty); }; /** * Resets forms' fields to their initial values. - * - * @param {Object.} fields Form's fields + * + * @param fields Form's fields */ -export const resetFields = (fields) => { +export const resetFields = (fields: Fields): void => { // Checks whether all fields have correct validation function Object .entries(fields) @@ -94,22 +96,22 @@ export const resetFields = (fields) => { } }); - // Validates all fields + // Resets all fields Object.values(fields) .forEach((cur) => cur.reset()); }; /** - * Validates the forms' fields and invokes the provided callback with extracted + * Validates the forms' fields and invokes the provided callback with extracted * form's values. - * - * @param {Object.} fields Form's fields - * @param {function} onSubmit On submit callback - * @returns {Promise | unknown | undefined} Returns the return value of onSubmit callback, - * wrapped in Promise if at least one validation function resolved to Promise. - * Returns undefined when form is not valid and onSubmit callback is not invoked or onSubmit function returns void. + * + * @param fields Form's fields + * @param onSubmit On submit callback + * @returns Returns the return value of onSubmit callback, + * wrapped in Promise if at least one validation function resolved to Promise. + * Returns undefined when form is not valid and onSubmit callback is not invoked or onSubmit function returns void. */ -export const submitForm = (fields, onSubmit) => { +export const submitForm = (fields: Fields, onSubmit: (values: Record) => unknown): Promise | unknown | undefined => { const validationResultHasErrors = validateFields(fields); if (typeof validationResultHasErrors === "boolean") { if (validationResultHasErrors) { @@ -120,7 +122,7 @@ export const submitForm = (fields, onSubmit) => { } else { return new Promise((resolve, reject) => { validationResultHasErrors.then(hasErrors => { - if (hasErrors) resolve(); + if (hasErrors) resolve(undefined); else resolve(onSubmit(extractValues(fields))); }).catch(reject); }); @@ -129,11 +131,11 @@ export const submitForm = (fields, onSubmit) => { /** * Resets the forms' fields and invokes the provided callback. - * - * @param {Object.} fields Form's fields - * @param {function} onCancel On cancel callback + * + * @param fields Form's fields + * @param onCancel On cancel callback */ -export const cancelForm = (fields, onCancel) => { +export const cancelForm = (fields: Fields, onCancel: () => void): void => { resetFields(fields); onCancel(); }; diff --git a/src/index.js b/src/index.ts similarity index 67% rename from src/index.js rename to src/index.ts index ff27159..edf1e83 100644 --- a/src/index.js +++ b/src/index.ts @@ -1,12 +1,17 @@ -export { +export { useValidation } from './useValidation'; -export { - extractValues, - validateFields, +export type { + FieldConfig, + Field, + Fields +} from './useValidation'; +export { + extractValues, + validateFields, setValues, - resetFields, - submitForm, + resetFields, + submitForm, cancelForm, isDirty } from './formUtils'; diff --git a/src/useValidation.js b/src/useValidation.ts similarity index 55% rename from src/useValidation.js rename to src/useValidation.ts index 4b0d625..a69a552 100644 --- a/src/useValidation.js +++ b/src/useValidation.ts @@ -1,41 +1,80 @@ import { useState } from 'react'; +/** + * Configuration for the useValidation hook. + */ +export interface FieldConfig { + receiveEvent?: boolean; + reversed?: boolean; + ignoreDirtiness?: boolean; +} + +/** + * Represents the return type of the useValidation hook. + */ +export interface Field { + value: T; + error: boolean; + dirty: boolean; + setValue: (v: T) => void; + onChange: (e: unknown, config?: FieldConfig) => void; + onBlur: (event: unknown, config?: FieldConfig) => void; + validate: (v: T, config?: FieldConfig) => boolean | Promise; + reset: () => void; + props: { + value: T; + onChange: Field['onChange']; + onBlur: Field['onBlur']; + }; +} + +/** + * Represents a map of form fields. + */ +export interface Fields { + [key: string]: Field; +} + // Default configuration -const DEFAULT_CONFIG = { +const DEFAULT_CONFIG: Required = { receiveEvent: true, reversed: false, ignoreDirtiness: false -} +}; /** * Function represents the useValidation hook. - * - * @param {any} defaultValue Default value - * @param {function} validationFn Function used for value validation - * @param {Object} config Hook configuration + * + * @param defaultValue Default value + * @param validationFn Function used for value validation + * @param config Hook configuration * @returns object containing current value, error flag, onBlur and onChange callbacks, validate function and reset function */ -export const useValidation = (defaultValue, validationFn, config) => { +export const useValidation = ( + defaultValue: T, + validationFn: (v: T) => boolean | Promise, + config?: FieldConfig +): Field => { // Checks whether validation function is really function if (!(Object.prototype.toString.call(validationFn) == '[object Function]')) { throw new Error('Incorrect type of the validation function.') } - const _config = { + const _config: Required = { ...DEFAULT_CONFIG, ...config }; - const [resetToValue, setResetToValue] = useState(defaultValue); - const [value, setValue] = useState(resetToValue); + const [resetToValue, setResetToValue] = useState(defaultValue); + const [value, setValue] = useState(resetToValue); const [error, setError] = useState(false); - + // dirty compares current value with initial value const dirty = value !== resetToValue; - const onChange = (e, config) => { + const onChange = (e: unknown, config?: FieldConfig) => { const activeConfig = config ?? _config; - const v = activeConfig.receiveEvent ? e.target.value : e; + const v = activeConfig.receiveEvent ? (e as { target: { value: T } }).target.value : e as T; setValue(v); // Value is validated on change, only if previously was incorrect @@ -44,7 +83,7 @@ export const useValidation = (defaultValue, validationFn, config) => { } }; - const onBlur = (_event, config) => { + const onBlur = (_event: unknown, config?: FieldConfig) => { const activeConfig = config ?? _config; // Value is validated if it is dirty or if dirtiness should be ignored @@ -53,27 +92,27 @@ export const useValidation = (defaultValue, validationFn, config) => { } }; - const _handleSetValue = (v) => { + const _handleSetValue = (v: T) => { setResetToValue(v); setValue(v); - } + }; - const _setValidationResult = (isError, config) => { + const _setValidationResult = (isError: boolean, config?: FieldConfig): boolean => { const activeConfig = config ?? _config; // Applies the reverse logic if needed const _error = activeConfig.reversed ? !isError : isError; setError(_error); return _error; - } + }; - const validate = (v, config) => { + const validate = (v: T, config?: FieldConfig): boolean | Promise => { // Validates the value const validationResult = validationFn(v); if (typeof validationResult === "boolean") { return _setValidationResult(!validationResult, config); } else { - return new Promise((resolve, reject) => + return new Promise((resolve, reject) => Promise.resolve(validationResult) .then(result => resolve(_setValidationResult(!result, config))) .catch(reason => reject(reason))); diff --git a/src/validationFunctions.js b/src/validationFunctions.js deleted file mode 100644 index 43c7e71..0000000 --- a/src/validationFunctions.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * No error validation function. Always returns false, indicating that field's - * value is correct. - * - * @returns true - */ -export const noError = () => true; - -/** - * Checks whether two value are equal. Should not be used with complex data types - * such as object or arrays as it will compare their references. - * - * @param {any} v1 First value - * @param {any} v2 Second value - * @returns {boolean} true if values are equal (indicating that no error is present), false otherwise - */ -export const areEqual = (v1, v2) => v1 === v2; - -/** - * Checks if value is true. - * - * @param {any} v Value - * @returns {boolean} true if value is true (indicating that no error is present), false otherwise - */ -export const isTrue = (v) => typeof v === "boolean" && v; - -/** - * Checks if value is null. - * - * @param {any} v Value - * @returns {boolean} true if value is null (indicating that no error is present), false otherwise - */ -export const isNotNull = (v) => v !== null; - -/** - * Checks if value is non empty string. - * - * @param {any} v Value - * @returns {boolean} true if value is non empty string (indicating that no error is present), false otherwise - */ -export const isNonEmptyString = (v) => typeof v === "string" && v.trim() !== ''; - -/** - * Checks if value is valid number. - * - * @param {any} v Value - * @returns {boolean} true if value is valid number (indicating that no error is present), false otherwise - */ -export const isValidNumber = (v) => !Number.isNaN(parseFloat(v, 10)); - -/** - * Checks if value is positive number. - * - * @param {any} v Value - * @returns {boolean} true if value is positive number (indicating that no error is present), false otherwise - */ -export const isPositiveNumber = (v) => isValidNumber(v) && parseFloat(v, 10) >= 0; - -/** - * Checks if value is negative number. - * - * @param {any} v Value - * @returns {boolean} true if value is negative number (indicating that no error is present), false otherwise - */ -export const isNegativeNumber = (v) => isValidNumber(v) && parseFloat(v, 10) < 0; - -/** - * Checks if value is non empty array. - * - * @param {any} v Value - * @returns {boolean} true if value is non empty array (indicating that no error is present), false otherwise - */ -export const isNonEmptyArray = (v) => Array.isArray(v) && v.length > 0; - -// Source: https://stackoverflow.com/a/201378/563228 -const emailRegex = new RegExp(/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/i); - -/** - * Checks if value is non empty array. - * - * @param {any} v Value - * @returns {boolean} true if value is valid email address (RFC 5322), false otherwise - */ -export const isValidEmail = (v) => isNonEmptyString(v) && emailRegex.test(v); - -/** - * Checks if the value is a valid IPv4 or IPv6 address. - * - * @param {any} v Value - * @returns {boolean} true if the value is a valid IPv4 or IPv6 address, false otherwise - */ -export const isValidIpAddress = (v) => { - const ipv4RegExp = /^(\d{1,3}\.){3}\d{1,3}$/; - const ipv6RegExp = /^([\da-f]{1,4}:){7}[\da-f]{1,4}$/i; - - if (ipv4RegExp.test(v)) { - return v.split('.').every((part) => parseInt(part) <= 255); - } - - if (ipv6RegExp.test(v)) { - return v.split(':').every((part) => part.length <= 4); - } - - return false; -} \ No newline at end of file diff --git a/src/validationFunctions.ts b/src/validationFunctions.ts new file mode 100644 index 0000000..ba0a411 --- /dev/null +++ b/src/validationFunctions.ts @@ -0,0 +1,107 @@ +/** + * No error validation function. Always returns true, indicating that field's + * value is correct. + * + * @returns true + */ +export const noError = (): true => true; + +/** + * Checks whether two value are equal. Should not be used with complex data types + * such as object or arrays as it will compare their references. + * + * @param v1 First value + * @param v2 Second value + * @returns true if values are equal (indicating that no error is present), false otherwise + */ +export const areEqual = (v1: unknown, v2: unknown): boolean => v1 === v2; + +/** + * Checks if value is true. + * + * @param v Value + * @returns true if value is true (indicating that no error is present), false otherwise + */ +export const isTrue = (v: unknown): boolean => typeof v === "boolean" && v; + +/** + * Checks if value is null. + * + * @param v Value + * @returns true if value is null (indicating that no error is present), false otherwise + */ +export const isNotNull = (v: unknown): boolean => v !== null; + +/** + * Checks if value is non empty string. + * + * @param v Value + * @returns true if value is non empty string (indicating that no error is present), false otherwise + */ +export const isNonEmptyString = (v: unknown): boolean => typeof v === "string" && v.trim() !== ''; + +/** + * Checks if value is valid number. + * + * @param v Value + * @returns true if value is valid number (indicating that no error is present), false otherwise + */ +export const isValidNumber = (v: unknown): boolean => !Number.isNaN(parseFloat(v as string)); + +/** + * Checks if value is positive number. + * + * @param v Value + * @returns true if value is positive number (indicating that no error is present), false otherwise + */ +export const isPositiveNumber = (v: unknown): boolean => isValidNumber(v) && parseFloat(v as string) >= 0; + +/** + * Checks if value is negative number. + * + * @param v Value + * @returns true if value is negative number (indicating that no error is present), false otherwise + */ +export const isNegativeNumber = (v: unknown): boolean => isValidNumber(v) && parseFloat(v as string) < 0; + +/** + * Checks if value is non empty array. + * + * @param v Value + * @returns true if value is non empty array (indicating that no error is present), false otherwise + */ +export const isNonEmptyArray = (v: unknown): boolean => Array.isArray(v) && v.length > 0; + +// Source: https://stackoverflow.com/a/201378/563228 +const emailRegex = new RegExp(/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/i); + +/** + * Checks if value is valid email address (RFC 5322). + * + * @param v Value + * @returns true if value is valid email address (RFC 5322), false otherwise + */ +export const isValidEmail = (v: unknown): boolean => isNonEmptyString(v) && emailRegex.test(v as string); + +/** + * Checks if the value is a valid IPv4 or IPv6 address. + * + * @param v Value + * @returns true if the value is a valid IPv4 or IPv6 address, false otherwise + */ +export const isValidIpAddress = (v: unknown): boolean => { + const ipv4RegExp = /^(\d{1,3}\.){3}\d{1,3}$/; + const ipv6RegExp = /^([\da-f]{1,4}:){7}[\da-f]{1,4}$/i; + + if (typeof v !== 'string') return false; + + if (ipv4RegExp.test(v)) { + return v.split('.').every((part) => parseInt(part) <= 255); + } + + if (ipv6RegExp.test(v)) { + return v.split(':').every((part) => part.length <= 4); + } + + return false; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..edb7272 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationDir": "./dist", + "outDir": "./dist", + "rootDir": "./src", + "lib": ["ES2020", "DOM"] + }, + "include": ["src"] +} diff --git a/types/index.d.ts b/types/index.d.ts deleted file mode 100644 index 94a41e2..0000000 --- a/types/index.d.ts +++ /dev/null @@ -1,63 +0,0 @@ -export declare interface FieldConfig { - receiveEvent?: boolean, - reversed?: boolean, - ignoreDirtiness?: boolean -} - -export declare interface Field { - value: any, - error: boolean, - dirty: boolean, - setValue: (v: any) => void, - onChange: (v: any, config?: FieldConfig) => void, - onBlur: (event: any, config?: FieldConfig) => void, - validate: (v: any, config?: FieldConfig) => boolean | Promise, - reset: () => void, - props: { - value: Field['value'], - onChange: Field['onChange'], - onBlur: Field['onBlur'] - } -} - -export declare interface Fields { - [key: string]: Field -} - -export declare function useValidation(initialValue: any, validationFn: ((v: any) => boolean) | ((v: any) => Promise), config?: FieldConfig): Field; - -export declare function extractValues(fields: Fields): object; - -export declare function setValues(fields: Fields, values: object): void; - -export declare function validateFields(fields: Fields): boolean | Promise; - -export declare function resetFields(fields: Fields): void; - -export declare function submitForm(fields: Fields, onSubmit: (values: object) => object | void): Promise | object | undefined; - -export declare function cancelForm(fields: Fields, onCancel: () => void): void; - -export declare function isDirty(fields: Fields): boolean; - -export declare function noError(): true; - -export declare function areEqual(v1: any, v2: any): boolean; - -export declare function isTrue(v: any): boolean; - -export declare function isNotNull(v: any): boolean; - -export declare function isNonEmptyString(v: any): boolean; - -export declare function isValidNumber(v: any): boolean; - -export declare function isPositiveNumber(v: any): boolean; - -export declare function isNegativeNumber(v: any): boolean; - -export declare function isNonEmptyArray(v: any): boolean; - -export declare function isValidEmail(v: any): boolean; - -export declare function isValidIpAddress(v: any): boolean; diff --git a/vite.config.js b/vite.config.js index c7d0119..ca4c64a 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,14 +1,21 @@ import { defineConfig } from 'vite' import { resolve } from 'path' import react from '@vitejs/plugin-react' +import dts from 'vite-plugin-dts' // https://vitejs.dev/config/ /** @type {import('vite').UserConfig} */ export default defineConfig({ - plugins: [react()], + plugins: [ + react(), + dts({ + rollupTypes: true, + tsconfigPath: './tsconfig.json' + }) + ], build: { lib: { - entry: resolve(__dirname, 'src/index.js'), + entry: resolve(__dirname, 'src/index.ts'), formats: ['cjs'], fileName: 'index' }, From 1a887d9f29ddf7c613687b651d590f50caca8dff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Apr 2026 15:10:04 +0000 Subject: [PATCH 3/3] Remove redundant return type annotations that TS can infer Agent-Logs-Url: https://github.com/Enterwell/react-form-validation/sessions/6aa6fff8-c2de-4be5-b7ef-15aa6fe8d981 Co-authored-by: AleksandarDev <643171+AleksandarDev@users.noreply.github.com> --- src/formUtils.ts | 14 +++++++------- src/useValidation.ts | 4 ++-- src/validationFunctions.ts | 22 +++++++++++----------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/formUtils.ts b/src/formUtils.ts index bca1437..986b8ca 100644 --- a/src/formUtils.ts +++ b/src/formUtils.ts @@ -14,7 +14,7 @@ const isFunction = (f: unknown): f is Function => Object.prototype.toString.call * @param fields Form's fields * @returns object containing form fields' values */ -export const extractValues = (fields: Fields): Record => { +export const extractValues = (fields: Fields) => { return Object .entries(fields) .reduce>((acc, [k, v]) => ({ ...acc, [k]: v.value }), {}); @@ -27,7 +27,7 @@ export const extractValues = (fields: Fields): Record => { * @param fields Form's fields * @param values Form's fields new values */ -export const setValues = (fields: Fields, values: Record): void => { +export const setValues = (fields: Fields, values: Record) => { Object .entries(fields) .forEach(([k, v]) => { @@ -44,7 +44,7 @@ export const setValues = (fields: Fields, values: Record): void * @returns true if there is any error in the form, false otherwise. * Promise with same result when at least one validation function resolved to Promise. */ -export const validateFields = (fields: Fields): boolean | Promise => { +export const validateFields = (fields: Fields) => { // Checks whether all fields have correct validation function Object .entries(fields) @@ -77,7 +77,7 @@ export const validateFields = (fields: Fields): boolean | Promise => { * @param fields Form's fields * @returns true if any field is dirty, false otherwise */ -export const isDirty = (fields: Fields): boolean => { +export const isDirty = (fields: Fields) => { return Object.values(fields).some(field => field.dirty); }; @@ -86,7 +86,7 @@ export const isDirty = (fields: Fields): boolean => { * * @param fields Form's fields */ -export const resetFields = (fields: Fields): void => { +export const resetFields = (fields: Fields) => { // Checks whether all fields have correct validation function Object .entries(fields) @@ -111,7 +111,7 @@ export const resetFields = (fields: Fields): void => { * wrapped in Promise if at least one validation function resolved to Promise. * Returns undefined when form is not valid and onSubmit callback is not invoked or onSubmit function returns void. */ -export const submitForm = (fields: Fields, onSubmit: (values: Record) => unknown): Promise | unknown | undefined => { +export const submitForm = (fields: Fields, onSubmit: (values: Record) => unknown) => { const validationResultHasErrors = validateFields(fields); if (typeof validationResultHasErrors === "boolean") { if (validationResultHasErrors) { @@ -135,7 +135,7 @@ export const submitForm = (fields: Fields, onSubmit: (values: Record void): void => { +export const cancelForm = (fields: Fields, onCancel: () => void) => { resetFields(fields); onCancel(); }; diff --git a/src/useValidation.ts b/src/useValidation.ts index a69a552..2dc9b7d 100644 --- a/src/useValidation.ts +++ b/src/useValidation.ts @@ -97,7 +97,7 @@ export const useValidation = ( setValue(v); }; - const _setValidationResult = (isError: boolean, config?: FieldConfig): boolean => { + const _setValidationResult = (isError: boolean, config?: FieldConfig) => { const activeConfig = config ?? _config; // Applies the reverse logic if needed @@ -106,7 +106,7 @@ export const useValidation = ( return _error; }; - const validate = (v: T, config?: FieldConfig): boolean | Promise => { + const validate = (v: T, config?: FieldConfig) => { // Validates the value const validationResult = validationFn(v); if (typeof validationResult === "boolean") { diff --git a/src/validationFunctions.ts b/src/validationFunctions.ts index ba0a411..8a1a486 100644 --- a/src/validationFunctions.ts +++ b/src/validationFunctions.ts @@ -4,7 +4,7 @@ * * @returns true */ -export const noError = (): true => true; +export const noError = () => true as const; /** * Checks whether two value are equal. Should not be used with complex data types @@ -14,7 +14,7 @@ export const noError = (): true => true; * @param v2 Second value * @returns true if values are equal (indicating that no error is present), false otherwise */ -export const areEqual = (v1: unknown, v2: unknown): boolean => v1 === v2; +export const areEqual = (v1: unknown, v2: unknown) => v1 === v2; /** * Checks if value is true. @@ -22,7 +22,7 @@ export const areEqual = (v1: unknown, v2: unknown): boolean => v1 === v2; * @param v Value * @returns true if value is true (indicating that no error is present), false otherwise */ -export const isTrue = (v: unknown): boolean => typeof v === "boolean" && v; +export const isTrue = (v: unknown) => typeof v === "boolean" && v; /** * Checks if value is null. @@ -30,7 +30,7 @@ export const isTrue = (v: unknown): boolean => typeof v === "boolean" && v; * @param v Value * @returns true if value is null (indicating that no error is present), false otherwise */ -export const isNotNull = (v: unknown): boolean => v !== null; +export const isNotNull = (v: unknown) => v !== null; /** * Checks if value is non empty string. @@ -38,7 +38,7 @@ export const isNotNull = (v: unknown): boolean => v !== null; * @param v Value * @returns true if value is non empty string (indicating that no error is present), false otherwise */ -export const isNonEmptyString = (v: unknown): boolean => typeof v === "string" && v.trim() !== ''; +export const isNonEmptyString = (v: unknown) => typeof v === "string" && v.trim() !== ''; /** * Checks if value is valid number. @@ -46,7 +46,7 @@ export const isNonEmptyString = (v: unknown): boolean => typeof v === "string" & * @param v Value * @returns true if value is valid number (indicating that no error is present), false otherwise */ -export const isValidNumber = (v: unknown): boolean => !Number.isNaN(parseFloat(v as string)); +export const isValidNumber = (v: unknown) => !Number.isNaN(parseFloat(v as string)); /** * Checks if value is positive number. @@ -54,7 +54,7 @@ export const isValidNumber = (v: unknown): boolean => !Number.isNaN(parseFloat(v * @param v Value * @returns true if value is positive number (indicating that no error is present), false otherwise */ -export const isPositiveNumber = (v: unknown): boolean => isValidNumber(v) && parseFloat(v as string) >= 0; +export const isPositiveNumber = (v: unknown) => isValidNumber(v) && parseFloat(v as string) >= 0; /** * Checks if value is negative number. @@ -62,7 +62,7 @@ export const isPositiveNumber = (v: unknown): boolean => isValidNumber(v) && par * @param v Value * @returns true if value is negative number (indicating that no error is present), false otherwise */ -export const isNegativeNumber = (v: unknown): boolean => isValidNumber(v) && parseFloat(v as string) < 0; +export const isNegativeNumber = (v: unknown) => isValidNumber(v) && parseFloat(v as string) < 0; /** * Checks if value is non empty array. @@ -70,7 +70,7 @@ export const isNegativeNumber = (v: unknown): boolean => isValidNumber(v) && par * @param v Value * @returns true if value is non empty array (indicating that no error is present), false otherwise */ -export const isNonEmptyArray = (v: unknown): boolean => Array.isArray(v) && v.length > 0; +export const isNonEmptyArray = (v: unknown) => Array.isArray(v) && v.length > 0; // Source: https://stackoverflow.com/a/201378/563228 const emailRegex = new RegExp(/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/i); @@ -81,7 +81,7 @@ const emailRegex = new RegExp(/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&' * @param v Value * @returns true if value is valid email address (RFC 5322), false otherwise */ -export const isValidEmail = (v: unknown): boolean => isNonEmptyString(v) && emailRegex.test(v as string); +export const isValidEmail = (v: unknown) => isNonEmptyString(v) && emailRegex.test(v as string); /** * Checks if the value is a valid IPv4 or IPv6 address. @@ -89,7 +89,7 @@ export const isValidEmail = (v: unknown): boolean => isNonEmptyString(v) && emai * @param v Value * @returns true if the value is a valid IPv4 or IPv6 address, false otherwise */ -export const isValidIpAddress = (v: unknown): boolean => { +export const isValidIpAddress = (v: unknown) => { const ipv4RegExp = /^(\d{1,3}\.){3}\d{1,3}$/; const ipv6RegExp = /^([\da-f]{1,4}:){7}[\da-f]{1,4}$/i;