diff --git a/package-lock.json b/package-lock.json index 9da83c2..c5b1006 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "eslint-plugin-tailwindcss": "^3.13.0", "eslint-plugin-unused-imports": "^2.0.0", "fast-deep-equal": "^3.1.3", + "glob": "^11.0.0", "lucide-react": "^0.262.0", "prettier": "^3.0.0", "react": "^18.2.0", @@ -41,7 +42,7 @@ "react-hook-form": "^7.45.2", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.6", - "zod": "^3.21.4" + "zod": "^3.23.8" }, "devDependencies": { "@types/node": "^20.4.2", @@ -461,6 +462,30 @@ "node": ">=0.1.90" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "optional": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "optional": true, + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@cypress/request": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", @@ -990,6 +1015,90 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -1070,6 +1179,15 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@radix-ui/number": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", @@ -2061,6 +2179,34 @@ "@babel/runtime": "^7.13.10" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "optional": true, + "peer": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "optional": true, + "peer": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "optional": true, + "peer": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "optional": true, + "peer": true + }, "node_modules/@types/json-schema": { "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", @@ -2076,7 +2222,7 @@ "version": "20.4.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz", "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==", - "dev": true + "devOptional": true }, "node_modules/@types/prop-types": { "version": "15.7.5", @@ -2345,9 +2491,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "bin": { "acorn": "bin/acorn" }, @@ -2363,6 +2509,19 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "optional": true, + "peer": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -3183,6 +3342,13 @@ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "optional": true, + "peer": true + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -3472,6 +3638,16 @@ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -3500,6 +3676,11 @@ "node": ">=6.0.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -4457,6 +4638,32 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -4636,19 +4843,22 @@ } }, "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4665,6 +4875,28 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -5057,7 +5289,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -5255,6 +5486,23 @@ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, + "node_modules/jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jiti": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", @@ -5673,6 +5921,13 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "optional": true, + "peer": true + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -5748,6 +6003,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -6031,6 +6294,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6071,6 +6339,29 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", + "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -6639,6 +6930,26 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "3.26.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.3.tgz", @@ -6920,7 +7231,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6930,11 +7240,29 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/string.prototype.matchall": { "version": "4.0.8", @@ -7007,6 +7335,18 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -7248,6 +7588,57 @@ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "optional": true, + "peer": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "optional": true, + "peer": true + }, "node_modules/tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -7550,6 +7941,13 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "optional": true, + "peer": true + }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -7683,6 +8081,53 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -7745,6 +8190,16 @@ "fd-slicer": "~1.1.0" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -7757,9 +8212,9 @@ } }, "node_modules/zod": { - "version": "3.21.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", - "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index a48ff6b..6671814 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives", "fix": "eslint src --ext ts,tsx --report-unused-disable-directives --fix && prettier --write .", "preview": "vite preview", + "build-registry": "npx tsx scripts/build.ts", + "host-registry": "npx http-server registry", "test": "cypress open" }, "dependencies": { @@ -37,6 +39,7 @@ "eslint-plugin-tailwindcss": "^3.13.0", "eslint-plugin-unused-imports": "^2.0.0", "fast-deep-equal": "^3.1.3", + "glob": "^11.0.0", "lucide-react": "^0.262.0", "prettier": "^3.0.0", "react": "^18.2.0", @@ -45,7 +48,7 @@ "react-hook-form": "^7.45.2", "tailwind-merge": "^1.14.0", "tailwindcss-animate": "^1.0.6", - "zod": "^3.21.4" + "zod": "^3.23.8" }, "devDependencies": { "@types/node": "^20.4.2", diff --git a/registry/auto-form-src.json b/registry/auto-form-src.json new file mode 100644 index 0000000..f01ca77 --- /dev/null +++ b/registry/auto-form-src.json @@ -0,0 +1,144 @@ +{ + "name": "AutoForm", + "type": "registry:ui", + "registryDependencies": [ + "accordion", + "button", + "calendar", + "card", + "checkbox", + "form", + "input", + "label", + "popover", + "radio-group", + "select", + "separator", + "switch", + "textarea", + "tooltip", + "toggle" + ], + "dependencies": [], + "devDependencies": [], + "tailwind": { + "config": {} + }, + "cssVars": {}, + "files": [ + { + "path": "utils.ts", + "target": "src/components/ui/auto-form/utils.ts", + "content": "import React from \"react\";\nimport { DefaultValues } from \"react-hook-form\";\nimport { z } from \"zod\";\nimport { FieldConfig } from \"./types\";\n\n// TODO: This should support recursive ZodEffects but TypeScript doesn't allow circular type definitions.\nexport type ZodObjectOrWrapped =\n | z.ZodObject\n | z.ZodEffects>;\n\n/**\n * Beautify a camelCase string.\n * e.g. \"myString\" -> \"My String\"\n */\nexport function beautifyObjectName(string: string) {\n // if numbers only return the string\n let output = string.replace(/([A-Z])/g, \" $1\");\n output = output.charAt(0).toUpperCase() + output.slice(1);\n return output;\n}\n\n/**\n * Get the lowest level Zod type.\n * This will unpack optionals, refinements, etc.\n */\nexport function getBaseSchema<\n ChildType extends z.ZodAny | z.AnyZodObject = z.ZodAny,\n>(schema: ChildType | z.ZodEffects): ChildType | null {\n if (!schema) return null;\n if (\"innerType\" in schema._def) {\n return getBaseSchema(schema._def.innerType as ChildType);\n }\n if (\"schema\" in schema._def) {\n return getBaseSchema(schema._def.schema as ChildType);\n }\n\n return schema as ChildType;\n}\n\n/**\n * Get the type name of the lowest level Zod type.\n * This will unpack optionals, refinements, etc.\n */\nexport function getBaseType(schema: z.ZodAny): string {\n const baseSchema = getBaseSchema(schema);\n return baseSchema ? baseSchema._def.typeName : \"\";\n}\n\n/**\n * Search for a \"ZodDefult\" in the Zod stack and return its value.\n */\nexport function getDefaultValueInZodStack(schema: z.ZodAny): any {\n const typedSchema = schema as unknown as z.ZodDefault<\n z.ZodNumber | z.ZodString\n >;\n\n if (typedSchema._def.typeName === \"ZodDefault\") {\n return typedSchema._def.defaultValue();\n }\n\n if (\"innerType\" in typedSchema._def) {\n return getDefaultValueInZodStack(\n typedSchema._def.innerType as unknown as z.ZodAny,\n );\n }\n if (\"schema\" in typedSchema._def) {\n return getDefaultValueInZodStack(\n (typedSchema._def as any).schema as z.ZodAny,\n );\n }\n\n return undefined;\n}\n\n/**\n * Get all default values from a Zod schema.\n */\nexport function getDefaultValues>(\n schema: Schema,\n fieldConfig?: FieldConfig>,\n) {\n if (!schema) return null;\n const { shape } = schema;\n type DefaultValuesType = DefaultValues>>;\n const defaultValues = {} as DefaultValuesType;\n if (!shape) return defaultValues;\n\n for (const key of Object.keys(shape)) {\n const item = shape[key] as z.ZodAny;\n\n if (getBaseType(item) === \"ZodObject\") {\n const defaultItems = getDefaultValues(\n getBaseSchema(item) as unknown as z.ZodObject,\n fieldConfig?.[key] as FieldConfig>,\n );\n\n if (defaultItems !== null) {\n for (const defaultItemKey of Object.keys(defaultItems)) {\n const pathKey = `${key}.${defaultItemKey}` as keyof DefaultValuesType;\n defaultValues[pathKey] = defaultItems[defaultItemKey];\n }\n }\n } else {\n let defaultValue = getDefaultValueInZodStack(item);\n if (\n (defaultValue === null || defaultValue === \"\") &&\n fieldConfig?.[key]?.inputProps\n ) {\n defaultValue = (fieldConfig?.[key]?.inputProps as unknown as any)\n .defaultValue;\n }\n if (defaultValue !== undefined) {\n defaultValues[key as keyof DefaultValuesType] = defaultValue;\n }\n }\n }\n\n return defaultValues;\n}\n\nexport function getObjectFormSchema(\n schema: ZodObjectOrWrapped,\n): z.ZodObject {\n if (schema?._def.typeName === \"ZodEffects\") {\n const typedSchema = schema as z.ZodEffects>;\n return getObjectFormSchema(typedSchema._def.schema);\n }\n return schema as z.ZodObject;\n}\n\n/**\n * Convert a Zod schema to HTML input props to give direct feedback to the user.\n * Once submitted, the schema will be validated completely.\n */\nexport function zodToHtmlInputProps(\n schema:\n | z.ZodNumber\n | z.ZodString\n | z.ZodOptional\n | any,\n): React.InputHTMLAttributes {\n if ([\"ZodOptional\", \"ZodNullable\"].includes(schema._def.typeName)) {\n const typedSchema = schema as z.ZodOptional;\n return {\n ...zodToHtmlInputProps(typedSchema._def.innerType),\n required: false,\n };\n }\n const typedSchema = schema as z.ZodNumber | z.ZodString;\n\n if (!(\"checks\" in typedSchema._def))\n return {\n required: true,\n };\n\n const { checks } = typedSchema._def;\n const inputProps: React.InputHTMLAttributes = {\n required: true,\n };\n const type = getBaseType(schema);\n\n for (const check of checks) {\n if (check.kind === \"min\") {\n if (type === \"ZodString\") {\n inputProps.minLength = check.value;\n } else {\n inputProps.min = check.value;\n }\n }\n if (check.kind === \"max\") {\n if (type === \"ZodString\") {\n inputProps.maxLength = check.value;\n } else {\n inputProps.max = check.value;\n }\n }\n }\n\n return inputProps;\n}\n", + "type": "registry:ui" + }, + { + "path": "types.ts", + "target": "src/components/ui/auto-form/types.ts", + "content": "import { ControllerRenderProps, FieldValues } from \"react-hook-form\";\nimport * as z from \"zod\";\nimport { INPUT_COMPONENTS } from \"./config\";\n\nexport type FieldConfigItem = {\n description?: React.ReactNode;\n inputProps?: React.InputHTMLAttributes & {\n showLabel?: boolean;\n };\n label?: string;\n fieldType?:\n | keyof typeof INPUT_COMPONENTS\n | React.FC;\n\n renderParent?: (props: {\n children: React.ReactNode;\n }) => React.ReactElement | null;\n};\n\nexport type FieldConfig>> = {\n // If SchemaType.key is an object, create a nested FieldConfig, otherwise FieldConfigItem\n [Key in keyof SchemaType]?: SchemaType[Key] extends object\n ? FieldConfig>\n : FieldConfigItem;\n};\n\nexport enum DependencyType {\n DISABLES,\n REQUIRES,\n HIDES,\n SETS_OPTIONS,\n}\n\ntype BaseDependency>> = {\n sourceField: keyof SchemaType;\n type: DependencyType;\n targetField: keyof SchemaType;\n when: (sourceFieldValue: any, targetFieldValue: any) => boolean;\n};\n\nexport type ValueDependency>> =\n BaseDependency & {\n type:\n | DependencyType.DISABLES\n | DependencyType.REQUIRES\n | DependencyType.HIDES;\n };\n\nexport type EnumValues = readonly [string, ...string[]];\n\nexport type OptionsDependency<\n SchemaType extends z.infer>,\n> = BaseDependency & {\n type: DependencyType.SETS_OPTIONS;\n\n // Partial array of values from sourceField that will trigger the dependency\n options: EnumValues;\n};\n\nexport type Dependency>> =\n | ValueDependency\n | OptionsDependency;\n\n/**\n * A FormInput component can handle a specific Zod type (e.g. \"ZodBoolean\")\n */\nexport type AutoFormInputComponentProps = {\n zodInputProps: React.InputHTMLAttributes;\n field: ControllerRenderProps;\n fieldConfigItem: FieldConfigItem;\n label: string;\n isRequired: boolean;\n fieldProps: any;\n zodItem: z.ZodAny;\n className?: string;\n};\n", + "type": "registry:ui" + }, + { + "path": "index.tsx", + "target": "src/components/ui/auto-form/index.tsx", + "content": "\"use client\";\nimport { Form } from \"@/components/ui/form\";\nimport React from \"react\";\nimport { DefaultValues, FormState, useForm } from \"react-hook-form\";\nimport { z } from \"zod\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport { zodResolver } from \"@hookform/resolvers/zod\";\n\nimport AutoFormObject from \"./fields/object\";\nimport { Dependency, FieldConfig } from \"./types\";\nimport {\n ZodObjectOrWrapped,\n getDefaultValues,\n getObjectFormSchema,\n} from \"./utils\";\n\nexport function AutoFormSubmit({\n children,\n className,\n disabled,\n}: {\n children?: React.ReactNode;\n className?: string;\n disabled?: boolean;\n}) {\n return (\n \n );\n}\n\nfunction AutoForm({\n formSchema,\n values: valuesProp,\n onValuesChange: onValuesChangeProp,\n onParsedValuesChange,\n onSubmit: onSubmitProp,\n fieldConfig,\n children,\n className,\n dependencies,\n}: {\n formSchema: SchemaType;\n values?: Partial>;\n onValuesChange?: (values: Partial>) => void;\n onParsedValuesChange?: (values: Partial>) => void;\n onSubmit?: (values: z.infer) => void;\n fieldConfig?: FieldConfig>;\n children?:\n | React.ReactNode\n | ((formState: FormState>) => React.ReactNode);\n className?: string;\n dependencies?: Dependency>[];\n}) {\n const objectFormSchema = getObjectFormSchema(formSchema);\n const defaultValues: DefaultValues> | null =\n getDefaultValues(objectFormSchema, fieldConfig);\n\n const form = useForm>({\n resolver: zodResolver(formSchema),\n defaultValues: defaultValues ?? undefined,\n values: valuesProp,\n });\n\n function onSubmit(values: z.infer) {\n const parsedValues = formSchema.safeParse(values);\n if (parsedValues.success) {\n onSubmitProp?.(parsedValues.data);\n }\n }\n\n const values = form.watch();\n // valuesString is needed because form.watch() returns a new object every time\n const valuesString = JSON.stringify(values);\n\n React.useEffect(() => {\n onValuesChangeProp?.(values);\n const parsedValues = formSchema.safeParse(values);\n if (parsedValues.success) {\n onParsedValuesChange?.(parsedValues.data);\n }\n }, [valuesString]);\n\n const renderChildren =\n typeof children === \"function\"\n ? children(form.formState as FormState>)\n : children;\n\n return (\n
\n
\n {\n form.handleSubmit(onSubmit)(e);\n }}\n className={cn(\"space-y-5\", className)}\n >\n \n\n {renderChildren}\n \n \n
\n );\n}\n\nexport default AutoForm;\n", + "type": "registry:ui" + }, + { + "path": "dependencies.ts", + "target": "src/components/ui/auto-form/dependencies.ts", + "content": "import { FieldValues, UseFormWatch } from \"react-hook-form\";\nimport { Dependency, DependencyType, EnumValues } from \"./types\";\nimport * as z from \"zod\";\n\nexport default function resolveDependencies<\n SchemaType extends z.infer>,\n>(\n dependencies: Dependency[],\n currentFieldName: keyof SchemaType,\n watch: UseFormWatch,\n) {\n let isDisabled = false;\n let isHidden = false;\n let isRequired = false;\n let overrideOptions: EnumValues | undefined;\n\n const currentFieldValue = watch(currentFieldName as string);\n\n const currentFieldDependencies = dependencies.filter(\n (dependency) => dependency.targetField === currentFieldName,\n );\n for (const dependency of currentFieldDependencies) {\n const watchedValue = watch(dependency.sourceField as string);\n\n const conditionMet = dependency.when(watchedValue, currentFieldValue);\n\n switch (dependency.type) {\n case DependencyType.DISABLES:\n if (conditionMet) {\n isDisabled = true;\n }\n break;\n case DependencyType.REQUIRES:\n if (conditionMet) {\n isRequired = true;\n }\n break;\n case DependencyType.HIDES:\n if (conditionMet) {\n isHidden = true;\n }\n break;\n case DependencyType.SETS_OPTIONS:\n if (conditionMet) {\n overrideOptions = dependency.options;\n }\n break;\n }\n }\n\n return {\n isDisabled,\n isHidden,\n isRequired,\n overrideOptions,\n };\n}\n", + "type": "registry:ui" + }, + { + "path": "config.ts", + "target": "src/components/ui/auto-form/config.ts", + "content": "import AutoFormCheckbox from \"./fields/checkbox\";\nimport AutoFormDate from \"./fields/date\";\nimport AutoFormEnum from \"./fields/enum\";\nimport AutoFormFile from \"./fields/file\";\nimport AutoFormInput from \"./fields/input\";\nimport AutoFormNumber from \"./fields/number\";\nimport AutoFormRadioGroup from \"./fields/radio-group\";\nimport AutoFormSwitch from \"./fields/switch\";\nimport AutoFormTextarea from \"./fields/textarea\";\n\nexport const INPUT_COMPONENTS = {\n checkbox: AutoFormCheckbox,\n date: AutoFormDate,\n select: AutoFormEnum,\n radio: AutoFormRadioGroup,\n switch: AutoFormSwitch,\n textarea: AutoFormTextarea,\n number: AutoFormNumber,\n file: AutoFormFile,\n fallback: AutoFormInput,\n};\n\n/**\n * Define handlers for specific Zod types.\n * You can expand this object to support more types.\n */\nexport const DEFAULT_ZOD_HANDLERS: {\n [key: string]: keyof typeof INPUT_COMPONENTS;\n} = {\n ZodBoolean: \"checkbox\",\n ZodDate: \"date\",\n ZodEnum: \"select\",\n ZodNativeEnum: \"select\",\n ZodNumber: \"number\",\n};\n", + "type": "registry:ui" + }, + { + "path": "tests/basics.cy.tsx", + "target": "src/components/ui/auto-form/tests/basics.cy.tsx", + "content": "import { z } from \"zod\";\nimport AutoForm from \"../index\";\n\ndescribe(\"\", () => {\n it(\"renders fields\", () => {\n const formSchema = z.object({\n username: z.string().min(2, {\n message: \"Username must be at least 2 characters.\",\n }),\n\n password: z.string().describe(\"Your secure password\").min(8, {\n message: \"Password must be at least 8 characters.\",\n }),\n });\n\n cy.mount();\n cy.get(\"input[name=username]\").should(\"exist\");\n cy.get(\"input[name=password]\").should(\"exist\");\n });\n\n it(\"renders fields with custom labels\", () => {\n const formSchema = z.object({\n username: z.string().describe(\"Your username\"),\n });\n\n cy.mount();\n\n cy.get(\"label\").contains(\"Your username\");\n });\n\n it(\"generates default labels\", () => {\n const formSchema = z.object({\n someFieldName: z.string(),\n });\n\n cy.mount();\n\n cy.get(\"label\").contains(\"Some Field Name\");\n });\n\n it(\"allows setting custom field labels\", () => {\n const formSchema = z.object({\n someFieldName: z.string(),\n });\n\n cy.mount(\n ,\n );\n\n cy.get(\"label\").contains(\"My field name\");\n });\n\n it(\"allows setting custom field props\", () => {\n const formSchema = z.object({\n username: z.string(),\n });\n\n cy.mount(\n ,\n );\n\n cy.get(\"input[name=username]\").should(\n \"have.attr\",\n \"placeholder\",\n \"Enter your username\",\n );\n });\n\n it(\"allows setting custom field type\", () => {\n const formSchema = z.object({\n username: z.string(),\n });\n\n cy.mount(\n ,\n );\n\n cy.get(\"input\").should(\"have.attr\", \"type\", \"number\");\n });\n\n it(\"can submit valid forms\", () => {\n const formSchema = z.object({\n username: z.string(),\n });\n\n cy.mount(\n {\n expect(values).to.deep.equal({\n username: \"john\",\n });\n }}\n >\n \n ,\n );\n\n cy.get(\"input[name=username]\").type(\"john\");\n cy.get(\"button[type=submit]\").click();\n });\n\n it(\"shows error for invalid forms\", () => {\n const formSchema = z.object({\n username: z.string(),\n });\n\n cy.mount(\n {\n expect.fail(\"Should not be called.\");\n }}\n >\n \n ,\n );\n\n cy.get(\"button[type=submit]\").click();\n });\n\n it(\"can set default values\", () => {\n const formSchema = z.object({\n username: z.string().default(\"john\"),\n });\n\n cy.mount();\n\n cy.get(\"input[name=username]\").should(\"have.value\", \"john\");\n });\n\n it(\"can submit with default values\", () => {\n const formSchema = z.object({\n username: z.string().default(\"john\"),\n });\n\n cy.mount(\n {\n expect(values).to.deep.equal({\n username: \"john\",\n });\n }}\n >\n \n ,\n );\n\n cy.get(\"button[type=submit]\").click();\n });\n\n it(\"can set and submit optional values\", () => {\n const formSchema = z.object({\n username: z.string().optional(),\n });\n\n cy.mount(\n {\n expect(values).to.deep.equal({\n username: undefined,\n });\n }}\n >\n \n ,\n );\n\n cy.get(\"input[name=username]\").should(\"have.value\", \"\");\n cy.get(\"button[type=submit]\").click();\n });\n\n it(\"can add description\", () => {\n const formSchema = z.object({\n username: z.string(),\n });\n\n cy.mount(\n ,\n );\n\n cy.get(\"p\").contains(\"Your username here\");\n });\n\n it(\"can set default values on array\", () => {\n const formSchema = z.object({\n arr: z.array(z.object({ name: z.string(), age: z.number() })).default([\n { name: \"Haykal\", age: 21 },\n { name: \"John\", age: 20 },\n ]),\n });\n\n cy.mount();\n\n //get button with text Arr\n cy.get(\"button\").contains(\"Arr\").click();\n cy.get(\"input[name='arr.0.name']\").should(\"have.value\", \"Haykal\");\n cy.get(\"input[name='arr.0.age']\").should(\"have.value\", \"21\");\n cy.get(\"input[name='arr.1.name']\").should(\"have.value\", \"John\");\n cy.get(\"input[name='arr.1.age']\").should(\"have.value\", \"20\");\n });\n\n it(\"can set default value of number to 0\", () => {\n const formSchema = z.object({\n number: z.number().default(0),\n });\n\n cy.mount();\n\n cy.get(\"input[name='number']\").should(\"have.value\", \"0\");\n });\n});\n", + "type": "registry:ui" + }, + { + "path": "fields/textarea.tsx", + "target": "src/components/ui/auto-form/fields/textarea.tsx", + "content": "import { FormControl, FormItem, FormMessage } from \"@/components/ui/form\";\nimport { Textarea } from \"@/components/ui/textarea\";\nimport AutoFormLabel from \"../common/label\";\nimport AutoFormTooltip from \"../common/tooltip\";\nimport { AutoFormInputComponentProps } from \"../types\";\n\nexport default function AutoFormTextarea({\n label,\n isRequired,\n fieldConfigItem,\n fieldProps,\n}: AutoFormInputComponentProps) {\n const { showLabel: _showLabel, ...fieldPropsWithoutShowLabel } = fieldProps;\n const showLabel = _showLabel === undefined ? true : _showLabel;\n return (\n \n {showLabel && (\n \n )}\n \n