From f23c81373b7666400f9f3edeec33d0e6de403997 Mon Sep 17 00:00:00 2001 From: Matej Marinko Date: Tue, 14 May 2024 15:09:33 +0200 Subject: [PATCH] ci: add validate translations --- package.json | 5 +- pnpm-lock.yaml | 666 +++++++++++++++++++------- scripts/validate-translations.test.ts | 95 ++++ scripts/validate-translations.ts | 266 ++++++++++ 4 files changed, 853 insertions(+), 179 deletions(-) create mode 100644 scripts/validate-translations.test.ts create mode 100644 scripts/validate-translations.ts diff --git a/package.json b/package.json index 3fe2ffe..7ae993b 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "nextjs-template", "version": "0.1.0", "private": true, + "packageManager": "pnpm@9.1.0", "scripts": { "dev": "infisical run -- next dev", "build": "next build", @@ -11,7 +12,8 @@ "format": "prettier --check --ignore-path .prettierignore .", "format:fix": "prettier --write --ignore-path .prettierignore .", "test": "jest", - "test:watch": "jest --watch" + "test:watch": "jest --watch", + "i18n": "tsx ./scripts/validate-translations.ts" }, "dependencies": { "@hookform/resolvers": "^3.3.4", @@ -69,6 +71,7 @@ "prettier-plugin-tailwindcss": "^0.5.14", "tailwindcss": "^3.4.1", "ts-node": "^10.9.2", + "tsx": "^4.10.2", "typescript": "^5.4.5", "typescript-eslint": "^7.8.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad86b89..fc3e794 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,40 +10,40 @@ importers: dependencies: '@hookform/resolvers': specifier: ^3.3.4 - version: 3.3.4(react-hook-form@7.51.4) + version: 3.3.4(react-hook-form@7.51.4(react@18.3.1)) '@radix-ui/react-dialog': specifier: ^1.0.5 - version: 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + version: 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dropdown-menu': specifier: ^2.0.6 - version: 2.0.6(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + version: 2.0.6(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-label': specifier: ^2.0.2 - version: 2.0.2(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + version: 2.0.2(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': specifier: ^1.0.7 - version: 1.0.7(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + version: 1.0.7(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-separator': specifier: ^1.0.3 - version: 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + version: 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': specifier: ^1.0.2 version: 1.0.2(@types/react@18.3.2)(react@18.3.1) '@sentry/nextjs': specifier: ^7.105.0 - version: 7.114.0(next@14.2.3)(react@18.3.1) + version: 7.114.0(next@14.2.3(@babel/core@7.24.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@t3-oss/env-nextjs': specifier: ^0.10.1 version: 0.10.1(typescript@5.4.5)(zod@3.23.8) '@tanstack/react-query': specifier: ^4.36.1 - version: 4.36.1(react-dom@18.3.1)(react@18.3.1) + version: 4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@zodios/core': specifier: ^10.9.6 version: 10.9.6(axios@1.6.8)(zod@3.23.8) '@zodios/react': specifier: ^10.4.5 - version: 10.4.5(@tanstack/react-query@4.36.1)(@zodios/core@10.9.6)(react@18.3.1) + version: 10.4.5(@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@zodios/core@10.9.6(axios@1.6.8)(zod@3.23.8))(react@18.3.1) axios: specifier: ^1.6.8 version: 1.6.8 @@ -55,22 +55,22 @@ importers: version: 2.1.1 cmdk: specifier: ^1.0.0 - version: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + version: 1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) framer-motion: specifier: ^11.1.9 - version: 11.1.9(react-dom@18.3.1)(react@18.3.1) + version: 11.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lucide-react: specifier: ^0.378.0 version: 0.378.0(react@18.3.1) next: specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.5)(react-dom@18.3.1)(react@18.3.1) + version: 14.2.3(@babel/core@7.24.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-international: specifier: ^1.2.4 version: 1.2.4 next-themes: specifier: ^0.3.0 - version: 0.3.0(react-dom@18.3.1)(react@18.3.1) + version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.3.1 version: 18.3.1 @@ -82,13 +82,13 @@ importers: version: 7.51.4(react@18.3.1) sonner: specifier: ^1.4.41 - version: 1.4.41(react-dom@18.3.1)(react@18.3.1) + version: 1.4.41(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tailwind-merge: specifier: ^2.3.0 version: 2.3.0 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.3) + version: 1.0.7(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5))) zod: specifier: ^3.23.8 version: 3.23.8 @@ -98,10 +98,10 @@ importers: version: 9.2.0 '@testing-library/jest-dom': specifier: ^6.4.5 - version: 6.4.5(@types/jest@29.5.12)(jest@29.7.0) + version: 6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5))) '@testing-library/react': specifier: ^15.0.7 - version: 15.0.7(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + version: 15.0.7(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/jest': specifier: ^29.5.12 version: 29.5.12 @@ -128,7 +128,7 @@ importers: version: 2.8.0(eslint@8.57.0) eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5) + version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5) eslint-plugin-react: specifier: ^7.34.1 version: 7.34.1(eslint@8.57.0) @@ -143,7 +143,7 @@ importers: version: 9.0.11 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2) + version: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -161,13 +161,16 @@ importers: version: 3.2.4(prettier@3.2.5)(typescript@5.4.5) prettier-plugin-tailwindcss: specifier: ^0.5.14 - version: 0.5.14(prettier-plugin-organize-imports@3.2.4)(prettier@3.2.5) + version: 0.5.14(prettier-plugin-organize-imports@3.2.4(prettier@3.2.5)(typescript@5.4.5))(prettier@3.2.5) tailwindcss: specifier: ^3.4.1 - version: 3.4.3(ts-node@10.9.2) + version: 3.4.3(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.12.11)(typescript@5.4.5) + tsx: + specifier: ^4.10.2 + version: 4.10.2 typescript: specifier: ^5.4.5 version: 5.4.5 @@ -363,6 +366,144 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@esbuild/aix-ppc64@0.20.2': + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.20.2': + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.20.2': + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.20.2': + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.20.2': + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.20.2': + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.20.2': + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.20.2': + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.20.2': + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.20.2': + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.20.2': + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.20.2': + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.20.2': + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.20.2': + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.20.2': + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.20.2': + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.20.2': + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.20.2': + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.20.2': + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.20.2': + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.20.2': + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.20.2': + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.20.2': + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1808,6 +1949,11 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} + esbuild@0.20.2: + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + engines: {node: '>=12'} + hasBin: true + escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -3612,6 +3758,11 @@ packages: tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + tsx@4.10.2: + resolution: {integrity: sha512-gOfACgv1ElsIjvt7Fp0rMJKGnMGjox0JfGOfX3kmZCV/yZumaNqtHGKBXt1KgaYS9KjDOmqGeI8gHk/W7kWVZg==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -4069,6 +4220,75 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@esbuild/aix-ppc64@0.20.2': + optional: true + + '@esbuild/android-arm64@0.20.2': + optional: true + + '@esbuild/android-arm@0.20.2': + optional: true + + '@esbuild/android-x64@0.20.2': + optional: true + + '@esbuild/darwin-arm64@0.20.2': + optional: true + + '@esbuild/darwin-x64@0.20.2': + optional: true + + '@esbuild/freebsd-arm64@0.20.2': + optional: true + + '@esbuild/freebsd-x64@0.20.2': + optional: true + + '@esbuild/linux-arm64@0.20.2': + optional: true + + '@esbuild/linux-arm@0.20.2': + optional: true + + '@esbuild/linux-ia32@0.20.2': + optional: true + + '@esbuild/linux-loong64@0.20.2': + optional: true + + '@esbuild/linux-mips64el@0.20.2': + optional: true + + '@esbuild/linux-ppc64@0.20.2': + optional: true + + '@esbuild/linux-riscv64@0.20.2': + optional: true + + '@esbuild/linux-s390x@0.20.2': + optional: true + + '@esbuild/linux-x64@0.20.2': + optional: true + + '@esbuild/netbsd-x64@0.20.2': + optional: true + + '@esbuild/openbsd-x64@0.20.2': + optional: true + + '@esbuild/sunos-x64@0.20.2': + optional: true + + '@esbuild/win32-arm64@0.20.2': + optional: true + + '@esbuild/win32-ia32@0.20.2': + optional: true + + '@esbuild/win32-x64@0.20.2': + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 @@ -4103,7 +4323,7 @@ snapshots: '@floating-ui/core': 1.6.1 '@floating-ui/utils': 0.2.2 - '@floating-ui/react-dom@2.0.9(react-dom@18.3.1)(react@18.3.1)': + '@floating-ui/react-dom@2.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@floating-ui/dom': 1.6.5 react: 18.3.1 @@ -4111,7 +4331,7 @@ snapshots: '@floating-ui/utils@0.2.2': {} - '@hookform/resolvers@3.3.4(react-hook-form@7.51.4)': + '@hookform/resolvers@3.3.4(react-hook-form@7.51.4(react@18.3.1))': dependencies: react-hook-form: 7.51.4(react@18.3.1) @@ -4155,7 +4375,7 @@ snapshots: jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2)': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -4169,7 +4389,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2) + jest-config: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -4384,295 +4604,322 @@ snapshots: dependencies: '@babel/runtime': 7.24.5 - '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-arrow@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-collection@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-collection@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.0.2(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 '@radix-ui/react-context@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 - '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-dialog@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-id': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.0.2(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-remove-scroll: 2.5.5(@types/react@18.3.2)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 '@radix-ui/react-direction@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 - '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-id': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-menu': 2.0.6(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-menu': 2.0.6(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 - '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 '@radix-ui/react-id@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 - '@radix-ui/react-label@2.0.2(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-label@2.0.2(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-menu@2.0.6(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-menu@2.0.6(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-direction': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-id': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.0.2(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-remove-scroll: 2.5.5(@types/react@18.3.2)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-popover@1.0.7(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-popover@1.0.7(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/primitive': 1.0.1 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-id': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': 1.0.2(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 aria-hidden: 1.2.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-remove-scroll: 2.5.5(@types/react@18.3.2)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-popper@1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-popper@1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@floating-ui/react-dom': 2.0.9(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@floating-ui/react-dom': 2.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-rect': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-size': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/rect': 1.0.1 - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/react-slot': 1.0.2(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/primitive': 1.0.1 - '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-context': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-direction': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-id': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.2)(react@18.3.1) '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 - '@radix-ui/react-separator@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@radix-ui/react-separator@1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.2 - '@types/react-dom': 18.3.0 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 + '@types/react-dom': 18.3.0 '@radix-ui/react-slot@1.0.2(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 '@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 '@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 '@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 '@radix-ui/react-use-rect@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/rect': 1.0.1 - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 '@radix-ui/react-use-size@1.0.1(@types/react@18.3.2)(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.3.2)(react@18.3.1) - '@types/react': 18.3.2 react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.2 '@radix-ui/rect@1.0.1': dependencies: @@ -4686,6 +4933,7 @@ snapshots: glob: 8.1.0 is-reference: 1.2.1 magic-string: 0.27.0 + optionalDependencies: rollup: 2.78.0 '@rollup/pluginutils@5.1.0(rollup@2.78.0)': @@ -4693,6 +4941,7 @@ snapshots: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 + optionalDependencies: rollup: 2.78.0 '@rushstack/eslint-patch@1.10.2': {} @@ -4751,7 +5000,7 @@ snapshots: '@sentry/utils': 7.114.0 localforage: 1.10.0 - '@sentry/nextjs@7.114.0(next@14.2.3)(react@18.3.1)': + '@sentry/nextjs@7.114.0(next@14.2.3(@babel/core@7.24.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': dependencies: '@rollup/plugin-commonjs': 24.0.0(rollup@2.78.0) '@sentry/core': 7.114.0 @@ -4763,7 +5012,7 @@ snapshots: '@sentry/vercel-edge': 7.114.0 '@sentry/webpack-plugin': 1.21.0 chalk: 3.0.0 - next: 14.2.3(@babel/core@7.24.5)(react-dom@18.3.1)(react@18.3.1) + next: 14.2.3(@babel/core@7.24.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 resolve: 1.22.8 rollup: 2.78.0 @@ -4837,23 +5086,26 @@ snapshots: '@t3-oss/env-core@0.10.1(typescript@5.4.5)(zod@3.23.8)': dependencies: - typescript: 5.4.5 zod: 3.23.8 + optionalDependencies: + typescript: 5.4.5 '@t3-oss/env-nextjs@0.10.1(typescript@5.4.5)(zod@3.23.8)': dependencies: '@t3-oss/env-core': 0.10.1(typescript@5.4.5)(zod@3.23.8) - typescript: 5.4.5 zod: 3.23.8 + optionalDependencies: + typescript: 5.4.5 '@tanstack/query-core@4.36.1': {} - '@tanstack/react-query@4.36.1(react-dom@18.3.1)(react@18.3.1)': + '@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/query-core': 4.36.1 react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) use-sync-external-store: 1.2.2(react@18.3.1) + optionalDependencies: + react-dom: 18.3.1(react@18.3.1) '@testing-library/dom@10.1.0': dependencies: @@ -4866,27 +5118,30 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.5(@types/jest@29.5.12)(jest@29.7.0)': + '@testing-library/jest-dom@6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)))': dependencies: '@adobe/css-tools': 4.3.3 '@babel/runtime': 7.24.5 - '@types/jest': 29.5.12 aria-query: 5.3.0 chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.6.3 - jest: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2) lodash: 4.17.21 redent: 3.0.0 + optionalDependencies: + '@jest/globals': 29.7.0 + '@types/jest': 29.5.12 + jest: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) - '@testing-library/react@15.0.7(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1)': + '@testing-library/react@15.0.7(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.24.5 '@testing-library/dom': 10.1.0 - '@types/react': 18.3.2 '@types/react-dom': 18.3.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 '@tootallnate/once@2.0.0': {} @@ -4979,7 +5234,7 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': dependencies: '@eslint-community/regexpp': 4.10.0 '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) @@ -4994,6 +5249,7 @@ snapshots: natural-compare: 1.4.0 semver: 7.6.2 ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -5006,6 +5262,7 @@ snapshots: '@typescript-eslint/visitor-keys': 7.2.0 debug: 4.3.4 eslint: 8.57.0 + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -5018,6 +5275,7 @@ snapshots: '@typescript-eslint/visitor-keys': 7.8.0 debug: 4.3.4 eslint: 8.57.0 + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -5039,6 +5297,7 @@ snapshots: debug: 4.3.4 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -5057,6 +5316,7 @@ snapshots: minimatch: 9.0.3 semver: 7.6.2 ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -5071,6 +5331,7 @@ snapshots: minimatch: 9.0.4 semver: 7.6.2 ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -5106,9 +5367,9 @@ snapshots: axios: 1.6.8 zod: 3.23.8 - '@zodios/react@10.4.5(@tanstack/react-query@4.36.1)(@zodios/core@10.9.6)(react@18.3.1)': + '@zodios/react@10.4.5(@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@zodios/core@10.9.6(axios@1.6.8)(zod@3.23.8))(react@18.3.1)': dependencies: - '@tanstack/react-query': 4.36.1(react-dom@18.3.1)(react@18.3.1) + '@tanstack/react-query': 4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@zodios/core': 10.9.6(axios@1.6.8)(zod@3.23.8) react: 18.3.1 @@ -5448,10 +5709,10 @@ snapshots: clsx@2.1.1: {} - cmdk@1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1): + cmdk@1.0.0(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) - '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1)(react@18.3.1) + '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -5490,13 +5751,13 @@ snapshots: convert-source-map@2.0.0: {} - create-jest@29.7.0(@types/node@20.12.11)(ts-node@10.9.2): + create-jest@29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2) + jest-config: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -5732,6 +5993,32 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 + esbuild@0.20.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.2 + '@esbuild/android-arm': 0.20.2 + '@esbuild/android-arm64': 0.20.2 + '@esbuild/android-x64': 0.20.2 + '@esbuild/darwin-arm64': 0.20.2 + '@esbuild/darwin-x64': 0.20.2 + '@esbuild/freebsd-arm64': 0.20.2 + '@esbuild/freebsd-x64': 0.20.2 + '@esbuild/linux-arm': 0.20.2 + '@esbuild/linux-arm64': 0.20.2 + '@esbuild/linux-ia32': 0.20.2 + '@esbuild/linux-loong64': 0.20.2 + '@esbuild/linux-mips64el': 0.20.2 + '@esbuild/linux-ppc64': 0.20.2 + '@esbuild/linux-riscv64': 0.20.2 + '@esbuild/linux-s390x': 0.20.2 + '@esbuild/linux-x64': 0.20.2 + '@esbuild/netbsd-x64': 0.20.2 + '@esbuild/openbsd-x64': 0.20.2 + '@esbuild/sunos-x64': 0.20.2 + '@esbuild/win32-arm64': 0.20.2 + '@esbuild/win32-ia32': 0.20.2 + '@esbuild/win32-x64': 0.20.2 + escalade@3.1.2: {} escape-string-regexp@1.0.5: {} @@ -5755,11 +6042,12 @@ snapshots: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-react: 7.34.1(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - eslint-import-resolver-webpack @@ -5777,13 +6065,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0): dependencies: debug: 4.3.4 enhanced-resolve: 5.16.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.13.1 @@ -5794,20 +6082,22 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.5) debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: @@ -5819,9 +6109,8 @@ snapshots: is-glob: 4.0.3 micromatch: 4.0.5 - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0)(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0): dependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 @@ -5830,7 +6119,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -5840,6 +6129,8 @@ snapshots: object.values: 1.2.0 semver: 6.3.1 tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -5865,13 +6156,14 @@ snapshots: object.entries: 1.1.8 object.fromentries: 2.0.8 - eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5): + eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5): dependencies: eslint: 8.57.0 - eslint-config-prettier: 9.1.0(eslint@8.57.0) prettier: 3.2.5 prettier-linter-helpers: 1.0.0 synckit: 0.8.8 + optionalDependencies: + eslint-config-prettier: 9.1.0(eslint@8.57.0) eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): dependencies: @@ -6078,11 +6370,12 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - framer-motion@11.1.9(react-dom@18.3.1)(react@18.3.1): + framer-motion@11.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: + tslib: 2.6.2 + optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - tslib: 2.6.2 fs.realpath@1.0.0: {} @@ -6504,16 +6797,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.12.11)(ts-node@10.9.2): + jest-cli@29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2) + create-jest: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2) + jest-config: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -6523,12 +6816,11 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.12.11)(ts-node@10.9.2): + jest-config@29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)): dependencies: '@babel/core': 7.24.5 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.11 babel-jest: 29.7.0(@babel/core@7.24.5) chalk: 4.1.2 ci-info: 3.9.0 @@ -6548,6 +6840,8 @@ snapshots: pretty-format: 29.7.0 slash: 3.0.0 strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.12.11 ts-node: 10.9.2(@types/node@20.12.11)(typescript@5.4.5) transitivePeerDependencies: - babel-plugin-macros @@ -6645,7 +6939,7 @@ snapshots: jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - dependencies: + optionalDependencies: jest-resolve: 29.7.0 jest-regex-util@29.6.3: {} @@ -6783,12 +7077,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.12.11)(ts-node@10.9.2): + jest@29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2) + jest-cli: 29.7.0(@types/node@20.12.11)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -7038,12 +7332,12 @@ snapshots: international-types: 0.8.1 server-only: 0.0.1 - next-themes@0.3.0(react-dom@18.3.1)(react@18.3.1): + next-themes@0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.2.3(@babel/core@7.24.5)(react-dom@18.3.1)(react@18.3.1): + next@14.2.3(@babel/core@7.24.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.2.3 '@swc/helpers': 0.5.5 @@ -7235,12 +7529,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.4.38 - postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2): + postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)): dependencies: lilconfig: 3.1.1 + yaml: 2.4.2 + optionalDependencies: postcss: 8.4.38 ts-node: 10.9.2(@types/node@20.12.11)(typescript@5.4.5) - yaml: 2.4.2 postcss-nested@6.0.1(postcss@8.4.38): dependencies: @@ -7277,9 +7572,10 @@ snapshots: prettier: 3.2.5 typescript: 5.4.5 - prettier-plugin-tailwindcss@0.5.14(prettier-plugin-organize-imports@3.2.4)(prettier@3.2.5): + prettier-plugin-tailwindcss@0.5.14(prettier-plugin-organize-imports@3.2.4(prettier@3.2.5)(typescript@5.4.5))(prettier@3.2.5): dependencies: prettier: 3.2.5 + optionalDependencies: prettier-plugin-organize-imports: 3.2.4(prettier@3.2.5)(typescript@5.4.5) prettier@3.2.5: {} @@ -7339,28 +7635,31 @@ snapshots: react-remove-scroll-bar@2.3.6(@types/react@18.3.2)(react@18.3.1): dependencies: - '@types/react': 18.3.2 react: 18.3.1 react-style-singleton: 2.2.1(@types/react@18.3.2)(react@18.3.1) tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.2 react-remove-scroll@2.5.5(@types/react@18.3.2)(react@18.3.1): dependencies: - '@types/react': 18.3.2 react: 18.3.1 react-remove-scroll-bar: 2.3.6(@types/react@18.3.2)(react@18.3.1) react-style-singleton: 2.2.1(@types/react@18.3.2)(react@18.3.1) tslib: 2.6.2 use-callback-ref: 1.3.2(@types/react@18.3.2)(react@18.3.1) use-sidecar: 1.1.2(@types/react@18.3.2)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.2 react-style-singleton@2.2.1(@types/react@18.3.2)(react@18.3.1): dependencies: - '@types/react': 18.3.2 get-nonce: 1.0.1 invariant: 2.2.4 react: 18.3.1 tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.2 react@18.3.1: dependencies: @@ -7523,7 +7822,7 @@ snapshots: ansi-styles: 6.2.1 is-fullwidth-code-point: 5.0.0 - sonner@1.4.41(react-dom@18.3.1)(react@18.3.1): + sonner@1.4.41(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -7632,9 +7931,10 @@ snapshots: styled-jsx@5.1.1(@babel/core@7.24.5)(react@18.3.1): dependencies: - '@babel/core': 7.24.5 client-only: 0.0.1 react: 18.3.1 + optionalDependencies: + '@babel/core': 7.24.5 sucrase@3.35.0: dependencies: @@ -7671,11 +7971,11 @@ snapshots: dependencies: '@babel/runtime': 7.24.5 - tailwindcss-animate@1.0.7(tailwindcss@3.4.3): + tailwindcss-animate@1.0.7(tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5))): dependencies: - tailwindcss: 3.4.3(ts-node@10.9.2) + tailwindcss: 3.4.3(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) - tailwindcss@3.4.3(ts-node@10.9.2): + tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -7694,7 +7994,7 @@ snapshots: postcss: 8.4.38 postcss-import: 15.1.0(postcss@8.4.38) postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2) + postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.12.11)(typescript@5.4.5)) postcss-nested: 6.0.1(postcss@8.4.38) postcss-selector-parser: 6.0.16 resolve: 1.22.8 @@ -7774,6 +8074,13 @@ snapshots: tslib@2.6.2: {} + tsx@4.10.2: + dependencies: + esbuild: 0.20.2 + get-tsconfig: 4.7.5 + optionalDependencies: + fsevents: 2.3.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -7820,10 +8127,11 @@ snapshots: typescript-eslint@7.8.0(eslint@8.57.0)(typescript@5.4.5): dependencies: - '@typescript-eslint/eslint-plugin': 7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 7.8.0(@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 + optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -7858,16 +8166,18 @@ snapshots: use-callback-ref@1.3.2(@types/react@18.3.2)(react@18.3.1): dependencies: - '@types/react': 18.3.2 react: 18.3.1 tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.2 use-sidecar@1.1.2(@types/react@18.3.2)(react@18.3.1): dependencies: - '@types/react': 18.3.2 detect-node-es: 1.1.0 react: 18.3.1 tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.3.2 use-sync-external-store@1.2.2(react@18.3.1): dependencies: diff --git a/scripts/validate-translations.test.ts b/scripts/validate-translations.test.ts new file mode 100644 index 0000000..c7287d9 --- /dev/null +++ b/scripts/validate-translations.test.ts @@ -0,0 +1,95 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable sonarjs/no-duplicate-string */ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const { deepKeysDiff } = require('./validate-translations'); + +// Mocking modules +jest.mock('fs'); + +describe('Translation Validator', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + describe('deepKeysDiff', () => { + it('should return correct diff of keys', () => { + const obj1 = { a: '1', b: { c: '2', d: '3' } }; + const obj2 = { a: '1', b: { c: '2' } }; + const diff = deepKeysDiff(obj1, obj2); + + expect(diff.missingKeys).toEqual(['b.d']); + expect(diff.extraKeys).toEqual([]); + expect(diff.invalidTypes).toEqual([]); + }); + + it('should detect invalid types', () => { + const obj1 = { a: '1', b: { c: '2', d: '3' } }; + const obj2 = { a: 1, b: { c: '2' } }; + const diff = deepKeysDiff(obj1, obj2); + + expect(diff.missingKeys).toEqual(['b.d']); + expect(diff.extraKeys).toEqual([]); + expect(diff.invalidTypes).toEqual(['a']); + }); + }); + + describe('plural check', () => { + it('should remove number suffixes from keys', () => { + const obj1 = { + a: '1', + b: { 'c#one': '2', 'c#other': '3', 'd#zero': '3', 'd#other': '3' }, + e: { f: { 'g#one': '4', 'g#other': '5' } }, + }; + const obj2 = { + a: '1', + b: { c: '2', d: '3' }, + e: { f: { 'g#zero': '4', 'g#other': '5', 'g#two': '32' } }, + }; + + const diff = deepKeysDiff(obj1, obj2); + expect(diff.missingKeys).toEqual([]); + expect(diff.extraKeys).toEqual([]); + expect(diff.invalidTypes).toEqual([]); + }); + + it('should return correct diff of keys', () => { + const obj1 = { + a: '1', + b: { 'c#one': '2', 'c#other': '3', 'd#zero': '3', 'd#other': '3' }, + e: { f: { h: 'asdf' } }, + }; + const obj2 = { + a: '1', + b: { c: '2' }, + e: { f: { 'g#zero': '4', 'g#other': '5', 'g#two': '32' } }, + }; + + const diff = deepKeysDiff(obj1, obj2); + expect(diff.missingKeys).toEqual(['b.d', 'e.f.h']); + expect(diff.extraKeys).toEqual(['e.f.g']); + expect(diff.invalidTypes).toEqual([]); + }); + + it('should keep object suffixes', () => { + const obj1 = { + 'a#one': { + e: '1', + }, + 'a#other': { + e: '1', + }, + b: { 'c#one': '2', 'c#other': '3', 'd#zero': '3', 'd#other': '3' }, + }; + const obj2 = { + a: { e: '1' }, + b: { c: '2' }, + }; + + const diff = deepKeysDiff(obj1, obj2); + expect(diff.missingKeys).toEqual(['a#one', 'a#other', 'b.d']); + expect(diff.extraKeys).toEqual(['a']); + expect(diff.invalidTypes).toEqual([]); + }); + }); +}); diff --git a/scripts/validate-translations.ts b/scripts/validate-translations.ts new file mode 100644 index 0000000..05ec63a --- /dev/null +++ b/scripts/validate-translations.ts @@ -0,0 +1,266 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +// Simple script to validate translations +// Usage: pnpm i18n + +import { readdirSync } from 'fs'; +import path from 'path'; + +import { defaultLocale, LOCALES } from '../src/i18n/i18n'; + +const localesFolder = './src/i18n'; +// 'require' imports work relative to the file, not the cwd +const localesFolderRelative = '../src/i18n'; + +const getLocalePath = (locale: string) => path.join(localesFolder, locale); + +const getLocaleFile = (locale: string, file: string) => + path.join(path.join(localesFolderRelative, locale), file); + +/** + * Deep diff between keys of two objects. + * @param {Object} obj1 Object compared + * @param {Object} obj2 Object to compare with + * @return Return a three element array with: + * - the keys present in obj1 but not in obj2 + * - the keys present in obj2 but not in obj1 + * - keys where the type of value is invalid (different from obj1 to obj2 or not string or object) + */ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const deepKeysDiff = ( + /* eslint-disable @typescript-eslint/no-explicit-any */ + obj1: any, + obj2: any, +): { missingKeys: string[]; extraKeys: string[]; invalidTypes: string[] } => { + if (typeof obj1 !== 'object' || typeof obj2 !== 'object') { + console.error( + `Both arguments must be objects, got ${typeof obj1} and ${typeof obj2}`, + ); + process.exit(1); + } + + const missingKeys: string[] = []; + const extraKeys: string[] = []; + const invalidTypes: string[] = []; + + const pairs1 = pairsWithoutPlural(obj1); + const pairs2 = pairsWithoutPlural(obj2); + + for (const pair of pairs1) { + const key = pair.key; + + // Check if key is present in obj2 + const otherPair = pairs2.find((pair2) => pair2.key === key); + if (!otherPair) { + missingKeys.push(key); + continue; + } + + // Check type of value + if (typeof pair.value !== typeof otherPair.value) { + invalidTypes.push(key); + continue; + } + + const type = typeof pair.value; + + if (type === 'string') { + // If value is a string, we're done + } else if (type === 'object') { + // If value is an object, recurse + const { + missingKeys: missingKeys2, + extraKeys: extraKeys2, + invalidTypes: invalidTypes2, + } = deepKeysDiff(obj1[key], obj2[key]); + + // Prepend key to keys + missingKeys.push(...missingKeys2.map((key2: string) => `${key}.${key2}`)); + extraKeys.push(...extraKeys2.map((key2: string) => `${key}.${key2}`)); + invalidTypes.push( + ...invalidTypes2.map((key2: string) => `${key}.${key2}`), + ); + } else { + // If value is neither a string nor an object, this is invalid translation. + invalidTypes.push(key); + } + } + + // Check if there are extra keys in obj2 + for (const pair of pairs2) { + if (!pairs1.find((pair1) => pair1.key === pair.key)) { + extraKeys.push(pair.key); + } + + // No need to recurse here, we already checked all keys in obj1. + } + + return { + missingKeys, + extraKeys, + invalidTypes, + }; +}; + +// See docs here for supported suffixes: +// https://www.i18next.com/translation-function/plurals#languages-with-multiple-plurals +const plural_suffixes = ['zero', 'one', 'two', 'few', 'many', 'other']; + +function stripPluralSuffix(key: string): string { + for (const suffix of plural_suffixes) { + if (key.endsWith(`#${suffix}`)) { + return key.slice(0, -suffix.length - 1); + } + } + + return key; +} + +function pairsWithoutPlural(obj: any) { + const keys: { key: string; value: any }[] = []; + for (const key in obj) { + const isString = typeof obj[key] === 'string'; + + if (isString) { + keys.push({ key: stripPluralSuffix(key), value: obj[key] }); + } else { + keys.push({ key, value: obj[key] }); + } + } + // Remove duplicates + return keys.filter( + (pair, index, self) => self.findIndex((p) => p.key === pair.key) === index, + ); +} + +const validateDefaultLocale = () => { + if (!LOCALES.includes(defaultLocale)) { + console.error(`Default locale '${defaultLocale}' is invalid.`); + process.exit(1); + } +}; + +const validateFiles = (locale: string, defaultLocaleFiles: any[]) => { + for (const file of defaultLocaleFiles) { + // Open js text files + const defaultLocaleFile = getLocaleFile(defaultLocale, file); + const localeFile = getLocaleFile(locale, file); + + const defaultLocaleData = require(defaultLocaleFile); + const localeData = require(localeFile); + + // Check if all keys in default locale are present in locale + const { missingKeys, extraKeys, invalidTypes } = deepKeysDiff( + defaultLocaleData, + localeData, + ); + + if (missingKeys.length > 0) { + console.error( + `Missing keys in ${getLocaleFile(locale, file)}:`, + missingKeys, + ); + } + + if (extraKeys.length > 0) { + console.error(`Extra keys in ${getLocaleFile(locale, file)}:`, extraKeys); + } + + if (invalidTypes.length > 0) { + console.error( + `Invalid types in ${getLocaleFile(locale, file)}:`, + invalidTypes, + ); + } + + if ( + missingKeys.length > 0 || + extraKeys.length > 0 || + invalidTypes.length > 0 + ) { + process.exit(1); + } + } +}; + +const isNotTsFile = (file: string) => + !(file.endsWith('.ts') || file.endsWith('.tsx')); + +const validate = () => { + // 1. + // Check if all locales in config are present in i18n folder and vice versa + const locales = readdirSync(localesFolder).filter(isNotTsFile); + + const missingLocales = LOCALES.filter( + (locale: string) => !locales.includes(locale), + ); + + if (missingLocales.length > 0) { + console.error(`Missing locales in ${localesFolder}:`, missingLocales); + process.exit(1); + } + + const extraLocales = locales.filter( + (locale: string) => !LOCALES.includes(locale as any), + ); + + if (extraLocales.length > 0) { + console.error('Extra locales in public/locales:', extraLocales); + process.exit(1); + } + + // 2. + // Check if default locale is valid + validateDefaultLocale(); + + const defaultLocaleFiles = readdirSync(getLocalePath(defaultLocale)); + + for (const locale of locales) { + // Skip default locale + if (locale === defaultLocale) { + continue; + } + + // 3. + // Check if namespaces match + const localeFiles = readdirSync(getLocalePath(locale)); + + const missingNamespaces = defaultLocaleFiles.filter( + (file: string) => !localeFiles.includes(file), + ); + + if (missingNamespaces.length > 0) { + console.error( + `Missing namespaces in ${getLocalePath(locale)}:`, + missingNamespaces, + ); + process.exit(1); + } + + const extraNamespaces = localeFiles.filter( + (file: string) => !defaultLocaleFiles.includes(file), + ); + + if (extraNamespaces.length > 0) { + console.error( + `Extra namespaces in ${getLocalePath(locale)}:`, + extraNamespaces, + ); + process.exit(1); + } + + // 4. + // Check if keys match + validateFiles(locale, defaultLocaleFiles); + } + console.log('All good! 🎉'); +}; + +// Run validation only if script is called directly +if (require.main === module) { + validate(); +} + +module.exports = { + deepKeysDiff, +};