diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index a4b13c8..381ec66 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: # Без cache: npm — act_runner отменяет шаг на распаковке ~546MB (exit -1). - uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '22' - run: npm ci - run: npm run lint diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..7d41c73 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22.14.0 diff --git a/components.json b/components.json new file mode 100644 index 0000000..6226791 --- /dev/null +++ b/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/index.css", + "baseColor": "slate", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/index.html b/index.html index d28dcbf..fa7f658 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,10 @@ - + - eventhubfrontadmin + EventHub Admin
diff --git a/package-lock.json b/package-lock.json index 5e166cf..977a6de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,19 +8,35 @@ "name": "eventhubfrontadmin", "version": "0.0.0", "dependencies": { - "@ant-design/icons": "^6.2.3", "@hookform/resolvers": "^5.2.2", + "@radix-ui/react-avatar": "^1.2.2", + "@radix-ui/react-dialog": "^1.1.19", + "@radix-ui/react-dropdown-menu": "^2.1.20", + "@radix-ui/react-label": "^2.1.11", + "@radix-ui/react-scroll-area": "^1.2.14", + "@radix-ui/react-select": "^2.3.3", + "@radix-ui/react-separator": "^1.1.11", + "@radix-ui/react-slot": "^1.3.0", + "@radix-ui/react-tabs": "^1.1.17", + "@radix-ui/react-tooltip": "^1.2.12", + "@tailwindcss/vite": "^4.3.2", "@tanstack/react-query": "^5.100.10", - "antd": "^6.4.3", + "@tanstack/react-table": "^8.21.3", "axios": "^1.16.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "dayjs": "^1.11.20", "i18next": "^26.2.0", + "lucide-react": "^1.24.0", "react": "^19.2.6", "react-dom": "^19.2.6", "react-hook-form": "^7.76.0", "react-i18next": "^17.0.8", "react-router-dom": "^7.15.1", "recharts": "^3.8.1", + "sonner": "^2.0.7", + "tailwind-merge": "^3.6.0", + "tailwindcss": "^4.3.2", "zod": "^4.4.3", "zustand": "^5.0.13" }, @@ -37,6 +53,9 @@ "typescript": "~6.0.2", "typescript-eslint": "^8.59.2", "vite": "^8.0.12" + }, + "engines": { + "node": ">=20.19.0" } }, "node_modules/@ant-design/colors": { @@ -385,7 +404,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -397,7 +415,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -408,7 +425,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -555,6 +571,40 @@ "node": "^20.19.0 || ^22.13.0 || >=24" } }, + "node_modules/@floating-ui/core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", + "dependencies": { + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", + "dependencies": { + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz", + "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==", + "dependencies": { + "@floating-ui/dom": "^1.8.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==" + }, "node_modules/@hookform/resolvers": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz", @@ -637,7 +687,6 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -648,7 +697,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -659,7 +707,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -669,14 +716,12 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -687,7 +732,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -706,12 +750,797 @@ "version": "0.130.0", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz", "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" } }, + "node_modules/@radix-ui/number": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.2.tgz", + "integrity": "sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.5.tgz", + "integrity": "sha512-d86WIWFYNtGA0H/d8exstrTRTp7eWJYlYJbtNofxr/3ljupZYn6EFDG/Qgu/0Kc8v7yMUxySagqJsL1+PdYjWg==" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.11.tgz", + "integrity": "sha512-Kdil9BB1rIFC/khmf4hC35bn8701AJcizTU7G7cUbEbk5XqqbjDuHW60uUfKqO5WojjZcbAW51Q7P0hRmMLw8A==", + "dependencies": { + "@radix-ui/react-primitive": "2.1.7" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.2.2.tgz", + "integrity": "sha512-sST0qh8GzOB7besQ3tMLWLyngnRuSk0gc/Hm+667KYKQFCt6Y6ZXv25WlqM7dIDK54ULCh5+CHmk4LIolzfz+A==", + "dependencies": { + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-is-hydrated": "0.1.1", + "@radix-ui/react-use-layout-effect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.12.tgz", + "integrity": "sha512-nb67INpE0IahJKN7EYPp9m9YGwYeKlnzxT3MwXVkgCskaSJia97kG4T0ywpjNUSSnoJk/uvk12V8vbrEHEj+/Q==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.3.tgz", + "integrity": "sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.0.tgz", + "integrity": "sha512-fOE+JtN9rygNZkCnHRBEP0TAvLldlhyOxMsbwFvTP4nAs+nBmfnna+o/Zski2wkmY1YMrFC0aSzsHoLY47iLrg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.19.tgz", + "integrity": "sha512-+HhbN2+YtkRgVirjZ2afMeutQRuGOrdkWR5+EFC58SJojGmtyNQwYzgi6tHBpOxvFHefMtPeHdgtjz0BOGxFQg==", + "dependencies": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-dismissable-layer": "1.1.15", + "@radix-ui/react-focus-guards": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.12", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-controllable-state": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.2.tgz", + "integrity": "sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.15.tgz", + "integrity": "sha512-b0XaRlzn2QKuo10XyNgi2DAJDf5XC9d1nD3FJcuvCjbR7+4Ad28zmZsLsqx+hvDEzMnRuZaZxZm9gYObV6RmRA==", + "dependencies": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-effect-event": "0.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.20.tgz", + "integrity": "sha512-slfm+rRaZRuQBvHq60lXvSVUPhid0IPtjSZzIuUlWZMUs01iYZNlGS3mJgRD3ChLQVBAYlKiL/tFyWGX+dz8Xw==", + "dependencies": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-menu": "2.1.20", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-controllable-state": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.4.tgz", + "integrity": "sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.12.tgz", + "integrity": "sha512-jjk/lqTeNL0azUx5ZYzVrl4NgaDIrdzTNE4mABV9yBFI7FQqN7pIgzV1bTleUezP2QiTGA1BFTqY8MegDgWX9A==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.2.tgz", + "integrity": "sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.11.tgz", + "integrity": "sha512-3PKvDDxOn62k0oV1n4QtNtD2vpu+zYjXR7ojLBPaO6SPvhy53yg0vAmgNeBQeJW5rV3dffoRG+HYfLBZuzw0CQ==", + "dependencies": { + "@radix-ui/react-primitive": "2.1.7" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.20.tgz", + "integrity": "sha512-VsUrXxFe9d2ScbZF0fR/oPR1+qjyeLs5p0jzG8h90puMoA9bq4SirYlXbE+USRg9Q2qTeJSFNqjw2nts8jJe4w==", + "dependencies": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-collection": "1.1.12", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.15", + "@radix-ui/react-focus-guards": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.12", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-popper": "1.3.3", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-roving-focus": "1.1.15", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-callback-ref": "1.1.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.3.tgz", + "integrity": "sha512-mS7dGpyjv6b+gsDjLF7e0ia1W4Im1B1hSCy2yuXlHuvnZxHKagfDaobt/KAKt27EpZMit2pss8eJBVyVjEWM+g==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.11", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.2", + "@radix-ui/react-use-rect": "1.1.2", + "@radix-ui/react-use-size": "1.1.2", + "@radix-ui/rect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.13.tgz", + "integrity": "sha512-z3oXfmaHLJTF1wktbjgD6cn9jiEbq3WSondB10LIuIt2m2Ym4iJlrW04/euMwENDdWDdE7z+OuY7Qyp1YpRSwA==", + "dependencies": { + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-layout-effect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.7.tgz", + "integrity": "sha512-zBZ4QM5XG3JRanDmqXYf3MD6th4AFXFmgU6KNMFzUaV6F3uw9I5/zjMUvFriSEn5ewo1nxuibvyxJdmLlDcslA==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.7.tgz", + "integrity": "sha512-bC3NiwsprbxKjuon9l7X6BUTw7FPVzEYaL92MPEY5SCd/9hUTPXVFtVwRix7778wtRsVao+zE062gL79FZleeQ==", + "dependencies": { + "@radix-ui/react-slot": "1.3.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.15.tgz", + "integrity": "sha512-40svmmugfM3mUN7VUDGVE1tQGOhyi8enlGD0CNJEcMM36C1f71PKM21DFgNHUfem0XnA+d8H8oN3Z9ZpJjSslg==", + "dependencies": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-collection": "1.1.12", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-controllable-state": "1.2.3", + "@radix-ui/react-use-is-hydrated": "0.1.1", + "@radix-ui/react-use-layout-effect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.14.tgz", + "integrity": "sha512-bBODCWZK7JTbQLHs0uIP4f73wIWatakK4OS33UzkR1x897wu0PuO658a3f+6P2GEGyDzGYMuHRatMVoAk9WZTw==", + "dependencies": { + "@radix-ui/number": "1.1.2", + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.3.3.tgz", + "integrity": "sha512-L5RQTXz6Anxsf9CCv+pTgiAsUpyVj7rJxsGtmhFaEOJ++cVfXucv4qWfsIO0AIB4NAhi3yovWGVMKKS1Xf1Wrg==", + "dependencies": { + "@radix-ui/number": "1.1.2", + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-collection": "1.1.12", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.15", + "@radix-ui/react-focus-guards": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.12", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-popper": "1.3.3", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-controllable-state": "1.2.3", + "@radix-ui/react-use-layout-effect": "1.1.2", + "@radix-ui/react-use-previous": "1.1.2", + "@radix-ui/react-visually-hidden": "1.2.7", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.11.tgz", + "integrity": "sha512-jRhe86+8PF7VZ1u14eOWVOuh2BuAhALg/FT1VcMC4OHedMTRUazDnDlKTt+yxo5cRNKHMfmvZ4sSQtWDeMV4CQ==", + "dependencies": { + "@radix-ui/react-primitive": "2.1.7" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.0.tgz", + "integrity": "sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.17.tgz", + "integrity": "sha512-nRyXnrAVCwjeXcHbvEbLS6ndbTeKHG1RqCP4A8Gw5L4cemDzPXdD8rAmr6wet0v57R69wGvuIIsFjHSVkZiMzQ==", + "dependencies": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-roving-focus": "1.1.15", + "@radix-ui/react-use-controllable-state": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.12.tgz", + "integrity": "sha512-U3HoftgWnmla78vzQbLvKKb7bUYJxoiiqYFzp1wu/TBMyDqMZSuCl3aRICsD6EfVEwcJD2mumGDGUXLFVqQHKA==", + "dependencies": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-dismissable-layer": "1.1.15", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-popper": "1.3.3", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-controllable-state": "1.2.3", + "@radix-ui/react-visually-hidden": "1.2.7" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.2.tgz", + "integrity": "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.3.tgz", + "integrity": "sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.3", + "@radix-ui/react-use-layout-effect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.3.tgz", + "integrity": "sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.1.tgz", + "integrity": "sha512-qwOiz4Tjo8CNnrOLAYUMXeZwDzXgXpvK4TKQPmWLECM9XoWvA6+0Z2/7Ag3A4ivjS4ovbLJPbskkxioFyBhr8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.2.tgz", + "integrity": "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.2.tgz", + "integrity": "sha512-IGBQPtRFdhN6MQ8dbegVmBq1LVZluya3F1jWY+puIcQC3MHctRwTDSBWCkL/3ZcnMJLTMJ++Z+ktmvg0F89iCw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.2.tgz", + "integrity": "sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw==", + "dependencies": { + "@radix-ui/rect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.2.tgz", + "integrity": "sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.7.tgz", + "integrity": "sha512-1wNZBggTDK3GRuuQ6nP4k2yi7a6l7I5qbMPbZcRsrGsGVead/f/d5FhEzUvqFs0bcrDLx7n1zKQ3JvLR6whaaw==", + "dependencies": { + "@radix-ui/react-primitive": "2.1.7" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.2.tgz", + "integrity": "sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==" + }, "node_modules/@rc-component/async-validator": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.1.0.tgz", @@ -1452,7 +2281,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1469,7 +2297,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1486,7 +2313,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1503,7 +2329,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1520,7 +2345,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1537,7 +2361,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1554,7 +2377,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1571,7 +2393,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1588,7 +2409,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1605,7 +2425,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1622,7 +2441,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1639,7 +2457,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1656,7 +2473,6 @@ "cpu": [ "wasm32" ], - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1675,7 +2491,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1692,7 +2507,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1706,7 +2520,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", - "dev": true, "license": "MIT" }, "node_modules/@standard-schema/spec": { @@ -1721,6 +2534,308 @@ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", "license": "MIT" }, + "node_modules/@tailwindcss/node": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.2.tgz", + "integrity": "sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "5.21.6", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.2" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.2.tgz", + "integrity": "sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.2", + "@tailwindcss/oxide-darwin-arm64": "4.3.2", + "@tailwindcss/oxide-darwin-x64": "4.3.2", + "@tailwindcss/oxide-freebsd-x64": "4.3.2", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.2", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.2", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.2", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.2", + "@tailwindcss/oxide-linux-x64-musl": "4.3.2", + "@tailwindcss/oxide-wasm32-wasi": "4.3.2", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.2", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.2" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.2.tgz", + "integrity": "sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.2.tgz", + "integrity": "sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.2.tgz", + "integrity": "sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.2.tgz", + "integrity": "sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.2.tgz", + "integrity": "sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.2.tgz", + "integrity": "sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.2.tgz", + "integrity": "sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.2.tgz", + "integrity": "sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.2.tgz", + "integrity": "sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.2.tgz", + "integrity": "sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.11.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "inBundle": true, + "license": "0BSD", + "optional": true + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.2.tgz", + "integrity": "sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.2.tgz", + "integrity": "sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.2.tgz", + "integrity": "sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==", + "dependencies": { + "@tailwindcss/node": "4.3.2", + "@tailwindcss/oxide": "4.3.2", + "tailwindcss": "4.3.2" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7 || ^8" + } + }, "node_modules/@tanstack/query-core": { "version": "5.100.10", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.10.tgz", @@ -1747,11 +2862,41 @@ "react": "^18 || ^19" } }, + "node_modules/@tanstack/react-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", + "dependencies": { + "@tanstack/table-core": "8.21.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1846,7 +2991,7 @@ "version": "24.12.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.4.tgz", "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -1866,7 +3011,7 @@ "version": "19.2.3", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "dev": true, + "devOptional": true, "license": "MIT", "peerDependencies": { "@types/react": "^19.2.0" @@ -2262,6 +3407,17 @@ "react-dom": ">=18.0.0" } }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2384,6 +3540,17 @@ ], "license": "CC-BY-4.0" }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -2622,12 +3789,16 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" } }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -2649,6 +3820,18 @@ "dev": true, "license": "ISC" }, + "node_modules/enhanced-resolve": { + "version": "5.21.6", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", + "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -2940,7 +4123,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -3045,7 +4227,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -3099,6 +4280,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -3150,6 +4339,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -3331,6 +4525,14 @@ "dev": true, "license": "ISC" }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3422,7 +4624,6 @@ "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -3455,7 +4656,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3476,7 +4676,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3497,7 +4696,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3518,7 +4716,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3539,7 +4736,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3560,7 +4756,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3581,7 +4776,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3602,7 +4796,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3623,7 +4816,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3644,7 +4836,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3665,7 +4856,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3705,6 +4895,22 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.24.0.tgz", + "integrity": "sha512-YT6mBD8lGKkg4nM39enlm94/sfJIiW0YKUT60fBy4YK8tai31ylg1VhGNWxkpSKHo9UagfnZqwIff3HTDQwXeA==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -3761,7 +4967,6 @@ "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true, "funding": [ { "type": "github", @@ -3864,14 +5069,12 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3884,7 +5087,6 @@ "version": "8.5.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -4031,6 +5233,51 @@ } } }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-router": { "version": "7.15.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.15.1.tgz", @@ -4069,6 +5316,27 @@ "react-dom": ">=18" } }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/recharts": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.1.tgz", @@ -4124,7 +5392,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz", "integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==", - "dev": true, "license": "MIT", "dependencies": { "@oxc-project/types": "=0.130.0", @@ -4208,11 +5475,19 @@ "node": ">=8" } }, + "node_modules/sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -4230,6 +5505,32 @@ "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", "license": "MIT" }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.2.tgz", + "integrity": "sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/throttle-debounce": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", @@ -4249,7 +5550,6 @@ "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -4279,9 +5579,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", @@ -4338,7 +5636,7 @@ "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/update-browserslist-db": { @@ -4382,6 +5680,47 @@ "punycode": "^2.1.0" } }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/use-sync-external-store": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", @@ -4417,7 +5756,6 @@ "version": "8.0.13", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz", "integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==", - "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", @@ -4636,17 +5974,6 @@ "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-3.0.1.tgz", "integrity": "sha512-esKJegpW4nckh0o6kV3Tkb7NPIZYbPnnFxmQDUmL08ukXZAvV85TZBr70eGuke/CIArLaP6aw8lt9KILjnWuOw==" }, - "@ant-design/icons": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-6.2.3.tgz", - "integrity": "sha512-Pl3aoAtxQeKryYnt6VvDJtOxMOtA8wrRSACe/pTjOAIG3fdHrWm6Ivb4ku9tsFjYroSXBKirvuxG4QkwBXD9gg==", - "requires": { - "@ant-design/colors": "^8.0.1", - "@ant-design/icons-svg": "^4.4.2", - "@rc-component/util": "^1.10.1", - "clsx": "^2.1.1" - } - }, "@ant-design/icons-svg": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", @@ -4838,7 +6165,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, "optional": true, "requires": { "@emnapi/wasi-threads": "1.2.1", @@ -4849,7 +6175,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, "optional": true, "requires": { "tslib": "^2.4.0" @@ -4859,7 +6184,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, "optional": true, "requires": { "tslib": "^2.4.0" @@ -4950,6 +6274,36 @@ "levn": "^0.4.1" } }, + "@floating-ui/core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", + "requires": { + "@floating-ui/utils": "^0.2.12" + } + }, + "@floating-ui/dom": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", + "requires": { + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" + } + }, + "@floating-ui/react-dom": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz", + "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==", + "requires": { + "@floating-ui/dom": "^1.8.0" + } + }, + "@floating-ui/utils": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==" + }, "@hookform/resolvers": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz", @@ -5000,7 +6354,6 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "requires": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" @@ -5010,7 +6363,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -5019,20 +6371,17 @@ "@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" }, "@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" }, "@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -5042,7 +6391,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", - "dev": true, "optional": true, "requires": { "@tybys/wasm-util": "^0.10.1" @@ -5051,8 +6399,395 @@ "@oxc-project/types": { "version": "0.130.0", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz", - "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==", - "dev": true + "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==" + }, + "@radix-ui/number": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.2.tgz", + "integrity": "sha512-ceTwaxc4I5IOi97DgCotl3pqiyRGvffcc0oOsE2dQYaJOFIDsDt4VWG6xEbg1QePv9QWausCEIppud/tJ1wNig==" + }, + "@radix-ui/primitive": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.5.tgz", + "integrity": "sha512-d86WIWFYNtGA0H/d8exstrTRTp7eWJYlYJbtNofxr/3ljupZYn6EFDG/Qgu/0Kc8v7yMUxySagqJsL1+PdYjWg==" + }, + "@radix-ui/react-arrow": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.11.tgz", + "integrity": "sha512-Kdil9BB1rIFC/khmf4hC35bn8701AJcizTU7G7cUbEbk5XqqbjDuHW60uUfKqO5WojjZcbAW51Q7P0hRmMLw8A==", + "requires": { + "@radix-ui/react-primitive": "2.1.7" + } + }, + "@radix-ui/react-avatar": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.2.2.tgz", + "integrity": "sha512-sST0qh8GzOB7besQ3tMLWLyngnRuSk0gc/Hm+667KYKQFCt6Y6ZXv25WlqM7dIDK54ULCh5+CHmk4LIolzfz+A==", + "requires": { + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-is-hydrated": "0.1.1", + "@radix-ui/react-use-layout-effect": "1.1.2" + } + }, + "@radix-ui/react-collection": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.12.tgz", + "integrity": "sha512-nb67INpE0IahJKN7EYPp9m9YGwYeKlnzxT3MwXVkgCskaSJia97kG4T0ywpjNUSSnoJk/uvk12V8vbrEHEj+/Q==", + "requires": { + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0" + } + }, + "@radix-ui/react-compose-refs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.3.tgz", + "integrity": "sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==", + "requires": {} + }, + "@radix-ui/react-context": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.0.tgz", + "integrity": "sha512-fOE+JtN9rygNZkCnHRBEP0TAvLldlhyOxMsbwFvTP4nAs+nBmfnna+o/Zski2wkmY1YMrFC0aSzsHoLY47iLrg==", + "requires": {} + }, + "@radix-ui/react-dialog": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.19.tgz", + "integrity": "sha512-+HhbN2+YtkRgVirjZ2afMeutQRuGOrdkWR5+EFC58SJojGmtyNQwYzgi6tHBpOxvFHefMtPeHdgtjz0BOGxFQg==", + "requires": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-dismissable-layer": "1.1.15", + "@radix-ui/react-focus-guards": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.12", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-controllable-state": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + } + }, + "@radix-ui/react-direction": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.2.tgz", + "integrity": "sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA==", + "requires": {} + }, + "@radix-ui/react-dismissable-layer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.15.tgz", + "integrity": "sha512-b0XaRlzn2QKuo10XyNgi2DAJDf5XC9d1nD3FJcuvCjbR7+4Ad28zmZsLsqx+hvDEzMnRuZaZxZm9gYObV6RmRA==", + "requires": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-effect-event": "0.0.3" + } + }, + "@radix-ui/react-dropdown-menu": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.20.tgz", + "integrity": "sha512-slfm+rRaZRuQBvHq60lXvSVUPhid0IPtjSZzIuUlWZMUs01iYZNlGS3mJgRD3ChLQVBAYlKiL/tFyWGX+dz8Xw==", + "requires": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-menu": "2.1.20", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-controllable-state": "1.2.3" + } + }, + "@radix-ui/react-focus-guards": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.4.tgz", + "integrity": "sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==", + "requires": {} + }, + "@radix-ui/react-focus-scope": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.12.tgz", + "integrity": "sha512-jjk/lqTeNL0azUx5ZYzVrl4NgaDIrdzTNE4mABV9yBFI7FQqN7pIgzV1bTleUezP2QiTGA1BFTqY8MegDgWX9A==", + "requires": { + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2" + } + }, + "@radix-ui/react-id": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.2.tgz", + "integrity": "sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==", + "requires": { + "@radix-ui/react-use-layout-effect": "1.1.2" + } + }, + "@radix-ui/react-label": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.11.tgz", + "integrity": "sha512-3PKvDDxOn62k0oV1n4QtNtD2vpu+zYjXR7ojLBPaO6SPvhy53yg0vAmgNeBQeJW5rV3dffoRG+HYfLBZuzw0CQ==", + "requires": { + "@radix-ui/react-primitive": "2.1.7" + } + }, + "@radix-ui/react-menu": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.20.tgz", + "integrity": "sha512-VsUrXxFe9d2ScbZF0fR/oPR1+qjyeLs5p0jzG8h90puMoA9bq4SirYlXbE+USRg9Q2qTeJSFNqjw2nts8jJe4w==", + "requires": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-collection": "1.1.12", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.15", + "@radix-ui/react-focus-guards": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.12", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-popper": "1.3.3", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-roving-focus": "1.1.15", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-callback-ref": "1.1.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + } + }, + "@radix-ui/react-popper": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.3.tgz", + "integrity": "sha512-mS7dGpyjv6b+gsDjLF7e0ia1W4Im1B1hSCy2yuXlHuvnZxHKagfDaobt/KAKt27EpZMit2pss8eJBVyVjEWM+g==", + "requires": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.11", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.2", + "@radix-ui/react-use-rect": "1.1.2", + "@radix-ui/react-use-size": "1.1.2", + "@radix-ui/rect": "1.1.2" + } + }, + "@radix-ui/react-portal": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.13.tgz", + "integrity": "sha512-z3oXfmaHLJTF1wktbjgD6cn9jiEbq3WSondB10LIuIt2m2Ym4iJlrW04/euMwENDdWDdE7z+OuY7Qyp1YpRSwA==", + "requires": { + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-layout-effect": "1.1.2" + } + }, + "@radix-ui/react-presence": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.7.tgz", + "integrity": "sha512-zBZ4QM5XG3JRanDmqXYf3MD6th4AFXFmgU6KNMFzUaV6F3uw9I5/zjMUvFriSEn5ewo1nxuibvyxJdmLlDcslA==", + "requires": { + "@radix-ui/react-use-layout-effect": "1.1.2" + } + }, + "@radix-ui/react-primitive": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.7.tgz", + "integrity": "sha512-bC3NiwsprbxKjuon9l7X6BUTw7FPVzEYaL92MPEY5SCd/9hUTPXVFtVwRix7778wtRsVao+zE062gL79FZleeQ==", + "requires": { + "@radix-ui/react-slot": "1.3.0" + } + }, + "@radix-ui/react-roving-focus": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.15.tgz", + "integrity": "sha512-40svmmugfM3mUN7VUDGVE1tQGOhyi8enlGD0CNJEcMM36C1f71PKM21DFgNHUfem0XnA+d8H8oN3Z9ZpJjSslg==", + "requires": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-collection": "1.1.12", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-controllable-state": "1.2.3", + "@radix-ui/react-use-is-hydrated": "0.1.1", + "@radix-ui/react-use-layout-effect": "1.1.2" + } + }, + "@radix-ui/react-scroll-area": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.14.tgz", + "integrity": "sha512-bBODCWZK7JTbQLHs0uIP4f73wIWatakK4OS33UzkR1x897wu0PuO658a3f+6P2GEGyDzGYMuHRatMVoAk9WZTw==", + "requires": { + "@radix-ui/number": "1.1.2", + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.2" + } + }, + "@radix-ui/react-select": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.3.3.tgz", + "integrity": "sha512-L5RQTXz6Anxsf9CCv+pTgiAsUpyVj7rJxsGtmhFaEOJ++cVfXucv4qWfsIO0AIB4NAhi3yovWGVMKKS1Xf1Wrg==", + "requires": { + "@radix-ui/number": "1.1.2", + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-collection": "1.1.12", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.15", + "@radix-ui/react-focus-guards": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.12", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-popper": "1.3.3", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-callback-ref": "1.1.2", + "@radix-ui/react-use-controllable-state": "1.2.3", + "@radix-ui/react-use-layout-effect": "1.1.2", + "@radix-ui/react-use-previous": "1.1.2", + "@radix-ui/react-visually-hidden": "1.2.7", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + } + }, + "@radix-ui/react-separator": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.11.tgz", + "integrity": "sha512-jRhe86+8PF7VZ1u14eOWVOuh2BuAhALg/FT1VcMC4OHedMTRUazDnDlKTt+yxo5cRNKHMfmvZ4sSQtWDeMV4CQ==", + "requires": { + "@radix-ui/react-primitive": "2.1.7" + } + }, + "@radix-ui/react-slot": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.0.tgz", + "integrity": "sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA==", + "requires": { + "@radix-ui/react-compose-refs": "1.1.3" + } + }, + "@radix-ui/react-tabs": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.17.tgz", + "integrity": "sha512-nRyXnrAVCwjeXcHbvEbLS6ndbTeKHG1RqCP4A8Gw5L4cemDzPXdD8rAmr6wet0v57R69wGvuIIsFjHSVkZiMzQ==", + "requires": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-direction": "1.1.2", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-roving-focus": "1.1.15", + "@radix-ui/react-use-controllable-state": "1.2.3" + } + }, + "@radix-ui/react-tooltip": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.12.tgz", + "integrity": "sha512-U3HoftgWnmla78vzQbLvKKb7bUYJxoiiqYFzp1wu/TBMyDqMZSuCl3aRICsD6EfVEwcJD2mumGDGUXLFVqQHKA==", + "requires": { + "@radix-ui/primitive": "1.1.5", + "@radix-ui/react-compose-refs": "1.1.3", + "@radix-ui/react-context": "1.2.0", + "@radix-ui/react-dismissable-layer": "1.1.15", + "@radix-ui/react-id": "1.1.2", + "@radix-ui/react-popper": "1.3.3", + "@radix-ui/react-portal": "1.1.13", + "@radix-ui/react-presence": "1.1.7", + "@radix-ui/react-primitive": "2.1.7", + "@radix-ui/react-slot": "1.3.0", + "@radix-ui/react-use-controllable-state": "1.2.3", + "@radix-ui/react-visually-hidden": "1.2.7" + } + }, + "@radix-ui/react-use-callback-ref": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.2.tgz", + "integrity": "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==", + "requires": {} + }, + "@radix-ui/react-use-controllable-state": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.3.tgz", + "integrity": "sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==", + "requires": { + "@radix-ui/react-use-effect-event": "0.0.3", + "@radix-ui/react-use-layout-effect": "1.1.2" + } + }, + "@radix-ui/react-use-effect-event": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.3.tgz", + "integrity": "sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==", + "requires": { + "@radix-ui/react-use-layout-effect": "1.1.2" + } + }, + "@radix-ui/react-use-is-hydrated": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.1.tgz", + "integrity": "sha512-qwOiz4Tjo8CNnrOLAYUMXeZwDzXgXpvK4TKQPmWLECM9XoWvA6+0Z2/7Ag3A4ivjS4ovbLJPbskkxioFyBhr8A==", + "requires": {} + }, + "@radix-ui/react-use-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.2.tgz", + "integrity": "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==", + "requires": {} + }, + "@radix-ui/react-use-previous": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.2.tgz", + "integrity": "sha512-IGBQPtRFdhN6MQ8dbegVmBq1LVZluya3F1jWY+puIcQC3MHctRwTDSBWCkL/3ZcnMJLTMJ++Z+ktmvg0F89iCw==", + "requires": {} + }, + "@radix-ui/react-use-rect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.2.tgz", + "integrity": "sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw==", + "requires": { + "@radix-ui/rect": "1.1.2" + } + }, + "@radix-ui/react-use-size": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.2.tgz", + "integrity": "sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w==", + "requires": { + "@radix-ui/react-use-layout-effect": "1.1.2" + } + }, + "@radix-ui/react-visually-hidden": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.7.tgz", + "integrity": "sha512-1wNZBggTDK3GRuuQ6nP4k2yi7a6l7I5qbMPbZcRsrGsGVead/f/d5FhEzUvqFs0bcrDLx7n1zKQ3JvLR6whaaw==", + "requires": { + "@radix-ui/react-primitive": "2.1.7" + } + }, + "@radix-ui/rect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.2.tgz", + "integrity": "sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==" }, "@rc-component/async-validator": { "version": "5.1.0", @@ -5501,91 +7236,78 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz", "integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==", - "dev": true, "optional": true }, "@rolldown/binding-darwin-arm64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz", "integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==", - "dev": true, "optional": true }, "@rolldown/binding-darwin-x64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz", "integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==", - "dev": true, "optional": true }, "@rolldown/binding-freebsd-x64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz", "integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==", - "dev": true, "optional": true }, "@rolldown/binding-linux-arm-gnueabihf": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz", "integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==", - "dev": true, "optional": true }, "@rolldown/binding-linux-arm64-gnu": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz", "integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==", - "dev": true, "optional": true }, "@rolldown/binding-linux-arm64-musl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz", "integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==", - "dev": true, "optional": true }, "@rolldown/binding-linux-ppc64-gnu": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz", "integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==", - "dev": true, "optional": true }, "@rolldown/binding-linux-s390x-gnu": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz", "integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==", - "dev": true, "optional": true }, "@rolldown/binding-linux-x64-gnu": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz", "integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==", - "dev": true, "optional": true }, "@rolldown/binding-linux-x64-musl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz", "integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==", - "dev": true, "optional": true }, "@rolldown/binding-openharmony-arm64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz", "integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==", - "dev": true, "optional": true }, "@rolldown/binding-wasm32-wasi": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz", "integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==", - "dev": true, "optional": true, "requires": { "@emnapi/core": "1.10.0", @@ -5597,21 +7319,18 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz", "integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==", - "dev": true, "optional": true }, "@rolldown/binding-win32-x64-msvc": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz", "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==", - "dev": true, "optional": true }, "@rolldown/pluginutils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", - "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", - "dev": true + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==" }, "@standard-schema/spec": { "version": "1.1.0", @@ -5623,6 +7342,177 @@ "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==" }, + "@tailwindcss/node": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.2.tgz", + "integrity": "sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==", + "requires": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "5.21.6", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.2" + } + }, + "@tailwindcss/oxide": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.2.tgz", + "integrity": "sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==", + "requires": { + "@tailwindcss/oxide-android-arm64": "4.3.2", + "@tailwindcss/oxide-darwin-arm64": "4.3.2", + "@tailwindcss/oxide-darwin-x64": "4.3.2", + "@tailwindcss/oxide-freebsd-x64": "4.3.2", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.2", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.2", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.2", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.2", + "@tailwindcss/oxide-linux-x64-musl": "4.3.2", + "@tailwindcss/oxide-wasm32-wasi": "4.3.2", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.2", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.2" + } + }, + "@tailwindcss/oxide-android-arm64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.2.tgz", + "integrity": "sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==", + "optional": true + }, + "@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.2.tgz", + "integrity": "sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==", + "optional": true + }, + "@tailwindcss/oxide-darwin-x64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.2.tgz", + "integrity": "sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==", + "optional": true + }, + "@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.2.tgz", + "integrity": "sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==", + "optional": true + }, + "@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.2.tgz", + "integrity": "sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==", + "optional": true + }, + "@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.2.tgz", + "integrity": "sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==", + "optional": true + }, + "@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.2.tgz", + "integrity": "sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==", + "optional": true + }, + "@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.2.tgz", + "integrity": "sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==", + "optional": true + }, + "@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.2.tgz", + "integrity": "sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==", + "optional": true + }, + "@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.2.tgz", + "integrity": "sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==", + "optional": true, + "requires": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "dependencies": { + "@emnapi/core": { + "version": "1.11.1", + "bundled": true, + "optional": true, + "requires": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "@emnapi/runtime": { + "version": "1.11.1", + "bundled": true, + "optional": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@emnapi/wasi-threads": { + "version": "1.2.2", + "bundled": true, + "optional": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "@napi-rs/wasm-runtime": { + "version": "1.1.4", + "bundled": true, + "optional": true, + "requires": { + "@tybys/wasm-util": "^0.10.1" + } + }, + "@tybys/wasm-util": { + "version": "0.10.2", + "bundled": true, + "optional": true, + "requires": { + "tslib": "^2.4.0" + } + }, + "tslib": { + "version": "2.8.1", + "bundled": true, + "optional": true + } + } + }, + "@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.2.tgz", + "integrity": "sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==", + "optional": true + }, + "@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.2.tgz", + "integrity": "sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==", + "optional": true + }, + "@tailwindcss/vite": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.2.tgz", + "integrity": "sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==", + "requires": { + "@tailwindcss/node": "4.3.2", + "@tailwindcss/oxide": "4.3.2", + "tailwindcss": "4.3.2" + } + }, "@tanstack/query-core": { "version": "5.100.10", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.10.tgz", @@ -5636,11 +7526,23 @@ "@tanstack/query-core": "5.100.10" } }, + "@tanstack/react-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", + "requires": { + "@tanstack/table-core": "8.21.3" + } + }, + "@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==" + }, "@tybys/wasm-util": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", - "dev": true, "optional": true, "requires": { "tslib": "^2.4.0" @@ -5722,7 +7624,7 @@ "version": "24.12.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.4.tgz", "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", - "dev": true, + "devOptional": true, "requires": { "undici-types": "~7.16.0" } @@ -5740,7 +7642,7 @@ "version": "19.2.3", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "dev": true, + "devOptional": true, "requires": {} }, "@types/use-sync-external-store": { @@ -5921,58 +7823,12 @@ "uri-js": "^4.2.2" } }, - "antd": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/antd/-/antd-6.4.3.tgz", - "integrity": "sha512-6H2avkxCGfxcF67r3J2mwm9Ck50el1pks/73vfM1wDsPL/tPtj5vHuauMgJFnrqmq7CH3g8aoZ0VBQbt+jpAsw==", + "aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", "requires": { - "@ant-design/colors": "^8.0.1", - "@ant-design/cssinjs": "^2.1.2", - "@ant-design/cssinjs-utils": "^2.1.2", - "@ant-design/fast-color": "^3.0.1", - "@ant-design/icons": "^6.2.3", - "@ant-design/react-slick": "~2.0.0", - "@babel/runtime": "^7.29.2", - "@rc-component/cascader": "~1.15.0", - "@rc-component/checkbox": "~2.0.0", - "@rc-component/collapse": "~1.2.0", - "@rc-component/color-picker": "~3.1.1", - "@rc-component/dialog": "~1.9.0", - "@rc-component/drawer": "~1.4.2", - "@rc-component/dropdown": "~1.0.2", - "@rc-component/form": "~1.8.1", - "@rc-component/image": "~1.9.0", - "@rc-component/input": "~1.3.0", - "@rc-component/input-number": "~1.6.2", - "@rc-component/mentions": "~1.9.0", - "@rc-component/menu": "~1.3.0", - "@rc-component/motion": "^1.3.2", - "@rc-component/mutate-observer": "^2.0.1", - "@rc-component/notification": "~2.0.7", - "@rc-component/pagination": "~1.2.0", - "@rc-component/picker": "~1.10.0", - "@rc-component/progress": "~1.0.2", - "@rc-component/qrcode": "~1.1.1", - "@rc-component/rate": "~1.0.1", - "@rc-component/resize-observer": "^1.1.2", - "@rc-component/segmented": "~1.3.0", - "@rc-component/select": "~1.6.15", - "@rc-component/slider": "~1.0.1", - "@rc-component/steps": "~1.2.2", - "@rc-component/switch": "~1.0.3", - "@rc-component/table": "~1.10.0", - "@rc-component/tabs": "~1.9.0", - "@rc-component/tooltip": "~1.4.0", - "@rc-component/tour": "~2.4.0", - "@rc-component/tree": "~1.3.1", - "@rc-component/tree-select": "~1.9.0", - "@rc-component/trigger": "^3.9.0", - "@rc-component/upload": "~1.1.0", - "@rc-component/util": "^1.11.0", - "clsx": "^2.1.1", - "dayjs": "^1.11.11", - "scroll-into-view-if-needed": "^3.1.0", - "throttle-debounce": "^5.0.2" + "tslib": "^2.0.0" } }, "asynckit": { @@ -6040,6 +7896,14 @@ "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", "dev": true }, + "class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "requires": { + "clsx": "^2.1.1" + } + }, "clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -6194,8 +8058,12 @@ "detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==" + }, + "detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" }, "dunder-proto": { "version": "1.0.1", @@ -6213,6 +8081,15 @@ "integrity": "sha512-NHlTIQDK8fmVwHwuIzmXYEJ1Ewq3D9wDNc0cWXxDGysP6Pb21giwGNkxiTifyKy/4SoPuN5l6GLP1W9Sv7zB2g==", "dev": true }, + "enhanced-resolve": { + "version": "5.21.6", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", + "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + } + }, "es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -6403,7 +8280,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, "requires": {} }, "file-entry-cache": { @@ -6462,7 +8338,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "optional": true }, "function-bind": { @@ -6493,6 +8368,11 @@ "math-intrinsics": "^1.1.0" } }, + "get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==" + }, "get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -6522,6 +8402,11 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, "has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -6629,6 +8514,11 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6696,7 +8586,6 @@ "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, "requires": { "detect-libc": "^2.0.3", "lightningcss-android-arm64": "1.32.0", @@ -6716,77 +8605,66 @@ "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "dev": true, "optional": true }, "lightningcss-darwin-arm64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "dev": true, "optional": true }, "lightningcss-darwin-x64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "dev": true, "optional": true }, "lightningcss-freebsd-x64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "dev": true, "optional": true }, "lightningcss-linux-arm-gnueabihf": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "dev": true, "optional": true }, "lightningcss-linux-arm64-gnu": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "dev": true, "optional": true }, "lightningcss-linux-arm64-musl": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "dev": true, "optional": true }, "lightningcss-linux-x64-gnu": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "dev": true, "optional": true }, "lightningcss-linux-x64-musl": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "dev": true, "optional": true }, "lightningcss-win32-arm64-msvc": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "dev": true, "optional": true }, "lightningcss-win32-x64-msvc": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "dev": true, "optional": true }, "locate-path": { @@ -6807,6 +8685,20 @@ "yallist": "^3.0.2" } }, + "lucide-react": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.24.0.tgz", + "integrity": "sha512-YT6mBD8lGKkg4nM39enlm94/sfJIiW0YKUT60fBy4YK8tai31ylg1VhGNWxkpSKHo9UagfnZqwIff3HTDQwXeA==", + "requires": {} + }, + "magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -6842,8 +8734,7 @@ "nanoid": { "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==" }, "natural-compare": { "version": "1.4.0", @@ -6904,20 +8795,17 @@ "picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==" }, "postcss": { "version": "8.5.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", - "dev": true, "requires": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -6984,6 +8872,27 @@ "use-sync-external-store": "^1.4.0" } }, + "react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "requires": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + } + }, + "react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "requires": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + } + }, "react-router": { "version": "7.15.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.15.1.tgz", @@ -7001,6 +8910,15 @@ "react-router": "7.15.1" } }, + "react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "requires": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + } + }, "recharts": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.1.tgz", @@ -7039,7 +8957,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz", "integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==", - "dev": true, "requires": { "@oxc-project/types": "=0.130.0", "@rolldown/binding-android-arm64": "1.0.1", @@ -7099,11 +9016,16 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "requires": {} + }, "source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" }, "string-convert": { "version": "0.2.1", @@ -7115,6 +9037,21 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==" }, + "tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==" + }, + "tailwindcss": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.2.tgz", + "integrity": "sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==" + }, + "tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==" + }, "throttle-debounce": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", @@ -7129,7 +9066,6 @@ "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, "requires": { "fdir": "^6.5.0", "picomatch": "^4.0.4" @@ -7145,9 +9081,7 @@ "tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "optional": true + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "type-check": { "version": "0.4.0", @@ -7180,7 +9114,7 @@ "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true + "devOptional": true }, "update-browserslist-db": { "version": "1.2.3", @@ -7201,6 +9135,23 @@ "punycode": "^2.1.0" } }, + "use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "requires": { + "tslib": "^2.0.0" + } + }, + "use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "requires": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + } + }, "use-sync-external-store": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", @@ -7232,7 +9183,6 @@ "version": "8.0.13", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz", "integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==", - "dev": true, "requires": { "fsevents": "~2.3.3", "lightningcss": "^1.32.0", diff --git a/package.json b/package.json index 53e418e..f3b15c3 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,9 @@ "private": true, "version": "0.0.0", "type": "module", + "engines": { + "node": ">=20.19.0" + }, "scripts": { "dev": "vite", "build": "tsc -b && vite build", @@ -11,19 +14,35 @@ "preview": "vite preview" }, "dependencies": { - "@ant-design/icons": "^6.2.3", "@hookform/resolvers": "^5.2.2", + "@radix-ui/react-avatar": "^1.2.2", + "@radix-ui/react-dialog": "^1.1.19", + "@radix-ui/react-dropdown-menu": "^2.1.20", + "@radix-ui/react-label": "^2.1.11", + "@radix-ui/react-scroll-area": "^1.2.14", + "@radix-ui/react-select": "^2.3.3", + "@radix-ui/react-separator": "^1.1.11", + "@radix-ui/react-slot": "^1.3.0", + "@radix-ui/react-tabs": "^1.1.17", + "@radix-ui/react-tooltip": "^1.2.12", + "@tailwindcss/vite": "^4.3.2", "@tanstack/react-query": "^5.100.10", - "antd": "^6.4.3", + "@tanstack/react-table": "^8.21.3", "axios": "^1.16.1", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "dayjs": "^1.11.20", "i18next": "^26.2.0", + "lucide-react": "^1.24.0", "react": "^19.2.6", "react-dom": "^19.2.6", "react-hook-form": "^7.76.0", "react-i18next": "^17.0.8", "react-router-dom": "^7.15.1", "recharts": "^3.8.1", + "sonner": "^2.0.7", + "tailwind-merge": "^3.6.0", + "tailwindcss": "^4.3.2", "zod": "^4.4.3", "zustand": "^5.0.13" }, diff --git a/src/App.tsx b/src/App.tsx index c8d2943..3d75e80 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,9 @@ import React, { useEffect } from 'react'; import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { Spin } from 'antd'; import ProtectedRoute from './components/ProtectedRoute'; import RoleGuard from './components/RoleGuard'; -import AdminLayout from './layouts/AdminLayout'; +import ControlCenterLayout from './layouts/ControlCenterLayout'; import LoginPage from './pages/auth/LoginPage'; import ProfilePage from './pages/profile/ProfilePage'; import DashboardPage from './pages/dashboard/DashboardPage'; @@ -26,7 +25,10 @@ import SubscriptionListPage from './pages/subscriptions/SubscriptionListPage'; import AdminListPage from './pages/admins/AdminListPage'; import AdminDetailPage from './pages/admins/AdminDetailPage'; import AuditPage from './pages/audit/AuditPage'; +import ReportInboxPage from './pages/inbox/ReportInboxPage'; +import TicketInboxPage from './pages/inbox/TicketInboxPage'; import { useAuthStore } from './store/authStore'; +import { Skeleton } from '@/components/ui/skeleton'; const queryClient = new QueryClient(); @@ -35,12 +37,13 @@ const App: React.FC = () => { useEffect(() => { checkAuth(); - }, []); + }, [checkAuth]); if (!isInitialized) { return ( -
- +
+ +
); } @@ -51,7 +54,7 @@ const App: React.FC = () => { } /> }> - }> + }> } /> }> @@ -60,6 +63,14 @@ const App: React.FC = () => { } /> + }> + } /> + + + }> + } /> + + }> } /> } /> diff --git a/src/components/Breadcrumbs.tsx b/src/components/Breadcrumbs.tsx new file mode 100644 index 0000000..b320945 --- /dev/null +++ b/src/components/Breadcrumbs.tsx @@ -0,0 +1,37 @@ +import { Link } from 'react-router-dom'; +import { ChevronRight } from 'lucide-react'; +import { cn } from '@/lib/utils'; + +export type BreadcrumbItem = { + label: string; + href?: string; +}; + +interface BreadcrumbsProps { + items: BreadcrumbItem[]; + className?: string; +} + +export function Breadcrumbs({ items, className }: BreadcrumbsProps) { + if (items.length === 0) return null; + + return ( + + ); +} diff --git a/src/components/CommandPalette.tsx b/src/components/CommandPalette.tsx new file mode 100644 index 0000000..8718997 --- /dev/null +++ b/src/components/CommandPalette.tsx @@ -0,0 +1,157 @@ +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { Search } from 'lucide-react'; +import { useAuthStore } from '@/store/authStore'; +import { NAV_GROUPS, filterNavGroupsByRole } from '@/config/adminAccess'; +import { + Dialog, + DialogContent, + DialogTitle, +} from '@/components/ui/dialog'; +import { Input } from '@/components/ui/input'; +import { cn } from '@/lib/utils'; + +type PaletteItem = { + id: string; + label: string; + group: string; + path: string; +}; + +interface CommandPaletteProps { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export function CommandPalette({ open, onOpenChange }: CommandPaletteProps) { + const { t } = useTranslation(); + const navigate = useNavigate(); + const role = useAuthStore((s) => s.user?.role); + const [query, setQuery] = useState(''); + const [activeIndex, setActiveIndex] = useState(0); + + const items = useMemo(() => { + const groups = filterNavGroupsByRole(NAV_GROUPS, role); + const routes = groups.flatMap((g) => + g.items.map((item) => ({ + id: item.key, + label: t(item.label), + group: t(g.label), + path: item.key, + })) + ); + routes.push( + { id: '/profile', label: t('nav.profile'), group: t('navGroup.account'), path: '/profile' }, + { id: '/dashboard', label: t('nav.dashboard'), group: t('navGroup.overview'), path: '/dashboard' } + ); + const seen = new Set(); + return routes.filter((r) => { + if (seen.has(r.path)) return false; + seen.add(r.path); + return true; + }); + }, [role, t]); + + const filtered = useMemo(() => { + const q = query.trim().toLowerCase(); + if (!q) return items; + return items.filter( + (item) => + item.label.toLowerCase().includes(q) || + item.group.toLowerCase().includes(q) || + item.path.toLowerCase().includes(q) + ); + }, [items, query]); + + useEffect(() => { + setActiveIndex(0); + }, [query, open]); + + useEffect(() => { + if (!open) setQuery(''); + }, [open]); + + const go = useCallback( + (path: string) => { + onOpenChange(false); + navigate(path); + }, + [navigate, onOpenChange] + ); + + const onKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'ArrowDown') { + e.preventDefault(); + setActiveIndex((i) => Math.min(i + 1, Math.max(filtered.length - 1, 0))); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + setActiveIndex((i) => Math.max(i - 1, 0)); + } else if (e.key === 'Enter' && filtered[activeIndex]) { + e.preventDefault(); + go(filtered[activeIndex].path); + } + }; + + return ( + + + {t('layout.paletteTitle')} +
+ + setQuery(e.target.value)} + onKeyDown={onKeyDown} + placeholder={t('layout.palettePlaceholder')} + className="h-12 border-0 shadow-none focus-visible:ring-0" + /> +
+
    + {filtered.length === 0 ? ( +
  • + {t('common.nothingFound')} +
  • + ) : ( + filtered.map((item, index) => ( +
  • + +
  • + )) + )} +
+
+ {t('layout.paletteHints')} +
+
+
+ ); +} + +/** Глобальный хоткей Ctrl/⌘+K */ +export function useCommandPaletteHotkey(onOpen: () => void) { + useEffect(() => { + const handler = (e: KeyboardEvent) => { + if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { + e.preventDefault(); + onOpen(); + } + }; + window.addEventListener('keydown', handler); + return () => window.removeEventListener('keydown', handler); + }, [onOpen]); +} diff --git a/src/components/DailyLineChartCard.tsx b/src/components/DailyLineChartCard.tsx index 790faf2..3f8b586 100644 --- a/src/components/DailyLineChartCard.tsx +++ b/src/components/DailyLineChartCard.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Card, Col } from 'antd'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { DayCount } from '../types/api'; import AreaTrendChart from './AreaTrendChart'; @@ -7,10 +7,10 @@ interface Props { title: string; data?: DayCount[]; color: string; - lg?: number; + className?: string; } -const DailyLineChartCard: React.FC = ({ title, data, color, lg = 12 }) => { +const DailyLineChartCard: React.FC = ({ title, data, color, className }) => { const chartData = (data ?? []).map((item) => ({ date: item.date, count: item.count, @@ -21,17 +21,20 @@ const DailyLineChartCard: React.FC = ({ title, data, color, lg = 12 }) => } return ( - - + + + {title} + + - - + + ); }; diff --git a/src/components/EntitySlideOver.tsx b/src/components/EntitySlideOver.tsx new file mode 100644 index 0000000..b74b83d --- /dev/null +++ b/src/components/EntitySlideOver.tsx @@ -0,0 +1,182 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import dayjs from 'dayjs'; +import { useUser } from '@/hooks/useUsers'; +import { useEvent } from '@/hooks/useEvents'; +import { useCalendar } from '@/hooks/useCalendars'; +import { useReport } from '@/hooks/useReports'; +import { formatDisplayValue } from '@/lib/utils'; +import { formatStatusLabel } from '@/utils/statusLabels'; +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { Skeleton } from '@/components/ui/skeleton'; +import { + Sheet, + SheetBody, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, +} from '@/components/ui/sheet'; + +export type ExploreEntityType = 'user' | 'event' | 'calendar' | 'report'; + +export type ExplorePreviewTarget = { + type: ExploreEntityType; + id: string; +} | null; + +interface EntitySlideOverProps { + target: ExplorePreviewTarget; + onOpenChange: (open: boolean) => void; +} + +function Field({ label, children }: { label: string; children: React.ReactNode }) { + return ( +
+
{label}
+
{children}
+
+ ); +} + +function UserPreview({ id }: { id: string }) { + const { t } = useTranslation(); + const { data, isLoading } = useUser(id); + if (isLoading) return ; + if (!data) return

{t('users.notFound')}

; + return ( +
+ {formatDisplayValue(data.email)} + {formatDisplayValue(data.nickname)} + + {data.role} + + + {formatStatusLabel(data.status)} + + + {data.last_login ? dayjs(data.last_login).format('DD.MM.YYYY HH:mm') : t('common.emDash')} + +
+ ); +} + +function EventPreview({ id }: { id: string }) { + const { t } = useTranslation(); + const { data, isLoading } = useEvent(id); + if (isLoading) return ; + if (!data) return

{t('events.notFound')}

; + return ( +
+ {formatDisplayValue(data.title)} + {formatDisplayValue(data.event_type)} + + {formatDisplayValue(data.status)} + + + {data.start_time ? dayjs(data.start_time).format('DD.MM.YYYY HH:mm') : t('common.emDash')} + + + {data.rating_avg} ({data.rating_count}) + +
+ ); +} + +function CalendarPreview({ id }: { id: string }) { + const { t } = useTranslation(); + const { data, isLoading } = useCalendar(id); + if (isLoading) return ; + if (!data) return

{t('calendars.notFound')}

; + return ( +
+ {formatDisplayValue(data.title)} + {formatDisplayValue(data.type)} + + {formatDisplayValue(data.status)} + + {formatDisplayValue(data.owner_id)} +
+ ); +} + +function ReportPreview({ id }: { id: string }) { + const { t } = useTranslation(); + const { data, isLoading } = useReport(id); + if (isLoading) return ; + if (!data) return

{t('reports.notFound')}

; + return ( +
+ {data.reason} + + {data.target_type} · {data.target_id} + + + {formatStatusLabel(data.status)} + + {dayjs(data.created_at).format('DD.MM.YYYY HH:mm')} +
+ ); +} + +function PreviewSkeleton() { + return ( +
+ + + + +
+ ); +} + +const detailPath = (type: ExploreEntityType, id: string) => { + if (type === 'user') return `/users/${id}`; + if (type === 'event') return `/events/${id}`; + if (type === 'calendar') return `/calendars/${id}`; + return `/reports/${id}`; +}; + +export function EntitySlideOver({ target, onOpenChange }: EntitySlideOverProps) { + const { t } = useTranslation(); + const open = Boolean(target); + + const titles: Record = { + user: t('common.user'), + event: t('events.entity'), + calendar: t('calendars.entity'), + report: t('reports.entity'), + }; + + return ( + + + {target && ( + <> + + {titles[target.type]} + {target.id} + + + {target.type === 'user' && } + {target.type === 'event' && } + {target.type === 'calendar' && } + {target.type === 'report' && } + + + + + + + )} + + + ); +} diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..39d6dc8 --- /dev/null +++ b/src/components/ErrorBoundary.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import i18n from '@/i18n'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; + +type Props = { children: React.ReactNode }; +type State = { error: Error | null }; + +export class ErrorBoundary extends React.Component { + state: State = { error: null }; + + static getDerivedStateFromError(error: Error): State { + return { error }; + } + + render() { + if (this.state.error) { + return ( +
+ + + {i18n.t('errors.renderTitle')} + + +

+ {this.state.error.message || i18n.t('errors.renderFallback')} +

+ + +
+
+
+ ); + } + return this.props.children; + } +} diff --git a/src/components/HeaderNodeMetrics.tsx b/src/components/HeaderNodeMetrics.tsx new file mode 100644 index 0000000..e46ff64 --- /dev/null +++ b/src/components/HeaderNodeMetrics.tsx @@ -0,0 +1,127 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import dayjs from 'dayjs'; +import { ChevronLeft, ChevronRight } from 'lucide-react'; +import { useMetricsStore, type NodeMetric } from '@/store/metricsStore'; +import MetricIndicator from '@/components/MetricIndicator'; +import { Button } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; + +const ONLINE_MINUTES = 5; +const RING_SIZE = 36; + +function latestByNode(allHistory: NodeMetric[], current: NodeMetric | null): Map { + const map = new Map(); + if (current) map.set(current.node, current); + allHistory.forEach((m) => { + const prev = map.get(m.node); + if (!prev || dayjs(m.timestamp).isAfter(dayjs(prev.timestamp))) { + map.set(m.node, m); + } + }); + return map; +} + +/** Compact node CPU/RAM rings for the Control Center header. */ +export function HeaderNodeMetrics({ className }: { className?: string }) { + const { t } = useTranslation(); + const navigate = useNavigate(); + const allHistory = useMetricsStore((s) => s.allHistory); + const current = useMetricsStore((s) => s.current); + const scrollerRef = useRef(null); + const [canScroll, setCanScroll] = useState({ left: false, right: false }); + + const nodes = useMemo(() => { + const cutoff = dayjs().subtract(ONLINE_MINUTES, 'minute'); + const latest = latestByNode(allHistory, current); + return Array.from(latest.entries()) + .filter(([, m]) => dayjs(m.timestamp).isAfter(cutoff)) + .sort(([a], [b]) => a.localeCompare(b)); + }, [allHistory, current]); + + const updateScrollState = useCallback(() => { + const el = scrollerRef.current; + if (!el) { + setCanScroll({ left: false, right: false }); + return; + } + setCanScroll({ + left: el.scrollLeft > 2, + right: el.scrollLeft + el.clientWidth < el.scrollWidth - 2, + }); + }, []); + + useEffect(() => { + updateScrollState(); + const el = scrollerRef.current; + if (!el) return; + const ro = new ResizeObserver(updateScrollState); + ro.observe(el); + el.addEventListener('scroll', updateScrollState, { passive: true }); + return () => { + ro.disconnect(); + el.removeEventListener('scroll', updateScrollState); + }; + }, [nodes.length, updateScrollState]); + + const scrollBy = (dir: -1 | 1) => { + scrollerRef.current?.scrollBy({ left: dir * 120, behavior: 'smooth' }); + }; + + if (nodes.length === 0) { + return ( +
+ {t('layout.nodesNoData')} +
+ ); + } + + const showArrows = canScroll.left || canScroll.right; + + return ( +
+ {showArrows && ( + + )} +
+ {nodes.map(([node, stats]) => ( + navigate(`/monitoring?node=${encodeURIComponent(node)}`)} + /> + ))} +
+ {showArrows && ( + + )} +
+ ); +} diff --git a/src/components/ListPageHeader.tsx b/src/components/ListPageHeader.tsx new file mode 100644 index 0000000..0d9c7b4 --- /dev/null +++ b/src/components/ListPageHeader.tsx @@ -0,0 +1,74 @@ +import type { ReactNode } from 'react'; +import { cn } from '@/lib/utils'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; + +export interface KpiItem { + label: string; + value: number | string; + icon?: ReactNode; + hint?: string; +} + +interface ListPageHeaderProps { + title: string; + description?: string; + actions?: ReactNode; + kpis?: KpiItem[]; + className?: string; +} + +export function ListPageHeader({ title, description, actions, kpis, className }: ListPageHeaderProps) { + const visibleKpis = kpis?.slice(0, 4) ?? []; + + return ( +
+
+
+

{title}

+ {description &&

{description}

} +
+ {actions &&
{actions}
} +
+ {visibleKpis.length > 0 && ( +
+ {visibleKpis.map((kpi) => ( + + + {kpi.label} + {kpi.icon &&
{kpi.icon}
} +
+ +
{kpi.value}
+ {kpi.hint &&

{kpi.hint}

} +
+
+ ))} +
+ )} +
+ ); +} + +export function KpiCard({ + label, + value, + icon, + className, +}: { + label: string; + value: number | string; + icon?: ReactNode; + className?: string; +}) { + return ( + + + {label} + {icon &&
{icon}
} +
+ +
{value}
+
+
+ ); +} diff --git a/src/components/LocaleProvider.tsx b/src/components/LocaleProvider.tsx index 2f3969f..03b397f 100644 --- a/src/components/LocaleProvider.tsx +++ b/src/components/LocaleProvider.tsx @@ -1,15 +1,11 @@ import React, { useEffect } from 'react'; -import { ConfigProvider } from 'antd'; -import ruRU from 'antd/locale/ru_RU'; -import enUS from 'antd/locale/en_US'; +import { useTranslation } from 'react-i18next'; import dayjs from 'dayjs'; import 'dayjs/locale/ru'; import 'dayjs/locale/en'; -import { useTranslation } from 'react-i18next'; -import { useAuthStore } from '../store/authStore'; - -const antdLocales = { ru: ruRU, en: enUS } as const; +import { useAuthStore } from '@/store/authStore'; +/** i18n + dayjs locale sync. */ const LocaleProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const { i18n } = useTranslation(); const language = useAuthStore((s) => s.user?.language); @@ -20,11 +16,7 @@ const LocaleProvider: React.FC<{ children: React.ReactNode }> = ({ children }) = dayjs.locale(locale); }, [i18n, locale]); - return ( - - {children} - - ); + return <>{children}; }; export default LocaleProvider; diff --git a/src/components/MetricIndicator.tsx b/src/components/MetricIndicator.tsx index 2a81fe3..9144cd9 100644 --- a/src/components/MetricIndicator.tsx +++ b/src/components/MetricIndicator.tsx @@ -1,14 +1,68 @@ import React from 'react'; -import { Tooltip, Progress } from 'antd'; -import { NodeMetric } from '../store/metricsStore'; +import { NodeMetric } from '@/store/metricsStore'; +import { cn } from '@/lib/utils'; interface Props { node: string; stats: NodeMetric; prevStats?: NodeMetric | null; + /** Outer ring diameter in px (default 48). */ + size?: number; + onClick?: () => void; + className?: string; } -const MetricIndicator: React.FC = ({ node, stats, prevStats }) => { +const CircleProgress: React.FC<{ + percent: number; + size: number; + strokeWidth: number; + color: string; + offset?: number; +}> = ({ percent, size, strokeWidth, color, offset = 0 }) => { + const radius = (size - strokeWidth) / 2; + const circumference = 2 * Math.PI * radius; + const clamped = Math.min(100, Math.max(0, percent)); + const dashOffset = circumference - (clamped / 100) * circumference; + + return ( + + + + + ); +}; + +const MetricIndicator: React.FC = ({ + node, + stats, + prevStats, + size = 48, + onClick, + className, +}) => { const cpu = stats.cpu_utilization ?? 0; const totalMemory = (stats.memory_total ?? 0) + (stats.memory_available ?? 0); const usedMemory = stats.memory_total ?? 0; @@ -19,48 +73,69 @@ const MetricIndicator: React.FC = ({ node, stats, prevStats }) => { const prevUsed = prevStats?.memory_total ?? 0; const prevMemoryPercent = prevTotal > 0 ? (prevUsed / prevTotal) * 100 : null; - const cpuColor = cpu > 80 ? '#ff4d4f' : '#52c41a'; - const memColor = memoryPercent > 80 ? '#ff4d4f' : '#1890ff'; + const cpuColor = cpu > 80 ? '#ef4444' : '#22c55e'; + const memColor = memoryPercent > 80 ? '#ef4444' : '#3b82f6'; - return ( - + + +
+ {cpu.toFixed(0)}% +
+
+
{node}
-
{node}
-
CPU: {cpu.toFixed(1)}% {prevCpu !== undefined ? `(было ${prevCpu.toFixed(1)}%)` : ''}
-
- Память: {(usedMemory / 1048576).toFixed(0)} / {(totalMemory / 1048576).toFixed(0)} МБ ({memoryPercent.toFixed(1)}%) - {prevMemoryPercent !== null ? ` (было ${prevMemoryPercent.toFixed(1)}%)` : ''} -
+ CPU: {cpu.toFixed(1)}%{' '} + {prevCpu !== undefined ? `(было ${prevCpu.toFixed(1)}%)` : ''}
- } - > -
- ''} - size={48} - strokeColor={memColor} - railColor="#f0f0f0" - strokeWidth={6} - style={{ position: 'absolute', top: 0, left: 0 }} - /> - ''} - size={32} - strokeColor={cpuColor} - railColor="#f0f0f0" - strokeWidth={6} - style={{ position: 'absolute', top: 8, left: 8 }} - /> -
- {cpu.toFixed(0)}% +
+ Память: {(usedMemory / 1048576).toFixed(0)} / {(totalMemory / 1048576).toFixed(0)} МБ ( + {memoryPercent.toFixed(1)}%) + {prevMemoryPercent !== null ? ` (было ${prevMemoryPercent.toFixed(1)}%)` : ''}
- + + ); + + if (onClick) { + return ( + + ); + } + + return ( +
+ {body} +
); }; diff --git a/src/components/PageHeader.tsx b/src/components/PageHeader.tsx new file mode 100644 index 0000000..97e5ed0 --- /dev/null +++ b/src/components/PageHeader.tsx @@ -0,0 +1,26 @@ +import type { ReactNode } from 'react'; +import { Breadcrumbs, type BreadcrumbItem } from '@/components/Breadcrumbs'; +import { cn } from '@/lib/utils'; + +interface PageHeaderProps { + title: string; + description?: string; + breadcrumbs?: BreadcrumbItem[]; + actions?: ReactNode; + className?: string; +} + +export function PageHeader({ title, description, breadcrumbs, actions, className }: PageHeaderProps) { + return ( +
+ {breadcrumbs && breadcrumbs.length > 0 && } +
+
+

{title}

+ {description &&

{description}

} +
+ {actions &&
{actions}
} +
+
+ ); +} diff --git a/src/components/ProtectedRoute.tsx b/src/components/ProtectedRoute.tsx index 4d1a8f4..3d166b5 100644 --- a/src/components/ProtectedRoute.tsx +++ b/src/components/ProtectedRoute.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Navigate, Outlet } from 'react-router-dom'; -import { Spin } from 'antd'; -import { useAuthStore } from '../store/authStore'; -import ForbiddenPage from '../pages/errors/ForbiddenPage'; +import { useAuthStore } from '@/store/authStore'; +import ForbiddenPage from '@/pages/errors/ForbiddenPage'; +import { Skeleton } from '@/components/ui/skeleton'; interface Props { allowedRoles?: string[]; @@ -13,8 +13,9 @@ const ProtectedRoute: React.FC = ({ allowedRoles }) => { if (!isInitialized) { return ( -
- +
+ +
); } diff --git a/src/components/StatisticSparklineCard.tsx b/src/components/StatisticSparklineCard.tsx index 200aa7b..20f00da 100644 --- a/src/components/StatisticSparklineCard.tsx +++ b/src/components/StatisticSparklineCard.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Card, Statistic } from 'antd'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { AreaChart, Area, XAxis, Tooltip } from 'recharts'; interface SparklinePoint { @@ -10,7 +10,7 @@ interface SparklinePoint { interface Props { title: string; value: number; - prefix?: React.ReactNode; + icon?: React.ReactNode; data?: SparklinePoint[]; color?: string; gradientId: string; @@ -19,46 +19,42 @@ interface Props { const StatisticSparklineCard: React.FC = ({ title, value, - prefix, + icon, data, - color = '#1890ff', + color = 'hsl(221 83% 53%)', gradientId, }) => ( - -
- - {data && data.length > 0 && ( - - - - - - - - - `Дата: ${label}`} /> - - - )} -
+ + + {title} + {icon &&
{icon}
} +
+ +
+
{value.toLocaleString('ru-RU')}
+ {data && data.length > 0 && ( + + + + + + + + + `Дата: ${label}`} /> + + + )} +
+
); diff --git a/src/components/data-table/DataTable.tsx b/src/components/data-table/DataTable.tsx new file mode 100644 index 0000000..2669b57 --- /dev/null +++ b/src/components/data-table/DataTable.tsx @@ -0,0 +1,158 @@ +import { + ColumnDef, + flexRender, + getCoreRowModel, + SortingState, + useReactTable, +} from '@tanstack/react-table'; +import { useTranslation } from 'react-i18next'; +import { ArrowDown, ArrowUp, ArrowUpDown } from 'lucide-react'; +import { Skeleton } from '@/components/ui/skeleton'; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@/components/ui/table'; +import { TablePaginationBar } from '@/components/explore/TablePaginationBar'; +import { DEFAULT_TABLE_PAGE_SIZE } from '@/utils/tablePagination'; + +export interface ServerTableParams { + offset?: number; + limit?: number; + sort?: string; + order?: 'asc' | 'desc'; +} + +interface DataTableProps { + columns: ColumnDef[]; + data: TData[]; + total?: number; + isLoading?: boolean; + tableKey: string; + params: TParams; + onParamsChange: (params: TParams) => void; + emptyMessage?: string; +} + +export function DataTable({ + columns, + data, + total, + isLoading, + tableKey, + params, + onParamsChange, + emptyMessage, +}: DataTableProps) { + const { t } = useTranslation(); + const empty = emptyMessage ?? t('common.noData'); + const sorting: SortingState = + params.sort && params.order ? [{ id: params.sort, desc: params.order === 'desc' }] : []; + + const table = useReactTable({ + data, + columns, + pageCount: total != null ? Math.ceil(total / (params.limit || DEFAULT_TABLE_PAGE_SIZE)) : -1, + state: { + sorting, + pagination: { + pageIndex: Math.floor((params.offset || 0) / (params.limit || DEFAULT_TABLE_PAGE_SIZE)), + pageSize: params.limit || DEFAULT_TABLE_PAGE_SIZE, + }, + }, + manualPagination: true, + manualSorting: true, + getCoreRowModel: getCoreRowModel(), + onSortingChange: (updater) => { + const next = typeof updater === 'function' ? updater(sorting) : updater; + const first = next[0]; + onParamsChange({ + ...params, + sort: first?.id ?? params.sort, + order: first ? (first.desc ? 'desc' : 'asc') : params.order, + offset: 0, + }); + }, + }); + + return ( +
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + const canSort = header.column.getCanSort(); + const sorted = header.column.getIsSorted(); + return ( + + {header.isPlaceholder ? null : canSort ? ( + + ) : ( + flexRender(header.column.columnDef.header, header.getContext()) + )} + + ); + })} + + ))} + + + {isLoading ? ( + Array.from({ length: 5 }).map((_, i) => ( + + {columns.map((_, j) => ( + + + + ))} + + )) + ) : table.getRowModel().rows.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + )) + ) : ( + + + {empty} + + + )} + +
+
+ + +
+ ); +} diff --git a/src/components/explore/DenseRowList.tsx b/src/components/explore/DenseRowList.tsx new file mode 100644 index 0000000..6035e62 --- /dev/null +++ b/src/components/explore/DenseRowList.tsx @@ -0,0 +1,112 @@ +import type { ReactNode } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Skeleton } from '@/components/ui/skeleton'; +import { cn } from '@/lib/utils'; +import { TablePaginationBar } from '@/components/explore/TablePaginationBar'; +import type { ServerTableParams } from '@/components/data-table/DataTable'; +import type { RowAction } from '@/components/explore/RowActionsMenu'; +import { RowActionsMenu } from '@/components/explore/RowActionsMenu'; + +export interface DenseRowModel { + id: string; + title: ReactNode; + subtitle?: ReactNode; + badges?: ReactNode; + meta?: ReactNode; + onActivate?: () => void; + actions?: RowAction[]; +} + +interface DenseRowListProps { + items: DenseRowModel[]; + isLoading?: boolean; + emptyMessage?: string; + tableKey: string; + params: TParams; + total?: number; + onParamsChange: (params: TParams) => void; + className?: string; +} + +export function DenseRowList({ + items, + isLoading, + emptyMessage, + tableKey, + params, + total, + onParamsChange, + className, +}: DenseRowListProps) { + const { t } = useTranslation(); + const empty = emptyMessage ?? t('common.noData'); + return ( +
+
+ {isLoading ? ( +
+ {Array.from({ length: 6 }).map((_, i) => ( +
+
+ + +
+ +
+ ))} +
+ ) : items.length === 0 ? ( +
{empty}
+ ) : ( +
    + {items.map((item) => ( +
  • +
    + + {item.actions && item.actions.length > 0 && ( +
    e.stopPropagation()}> + +
    + )} +
    +
  • + ))} +
+ )} +
+ +
+ ); +} diff --git a/src/components/explore/ExploreDataView.tsx b/src/components/explore/ExploreDataView.tsx new file mode 100644 index 0000000..8e90095 --- /dev/null +++ b/src/components/explore/ExploreDataView.tsx @@ -0,0 +1,57 @@ +import type { ColumnDef } from '@tanstack/react-table'; +import type { ExploreViewMode } from '@/lib/exploreView'; +import { DataTable, type ServerTableParams } from '@/components/data-table/DataTable'; +import { DenseRowList, type DenseRowModel } from '@/components/explore/DenseRowList'; + +interface ExploreDataViewProps { + viewMode: ExploreViewMode; + columns: ColumnDef[]; + data: TData[]; + total?: number; + isLoading?: boolean; + tableKey: string; + params: TParams; + onParamsChange: (params: TParams) => void; + emptyMessage?: string; + denseRows: DenseRowModel[]; +} + +export function ExploreDataView({ + viewMode, + columns, + data, + total, + isLoading, + tableKey, + params, + onParamsChange, + emptyMessage, + denseRows, +}: ExploreDataViewProps) { + if (viewMode === 'rows') { + return ( + + ); + } + + return ( + + ); +} diff --git a/src/components/explore/ExploreInsightsCollapse.tsx b/src/components/explore/ExploreInsightsCollapse.tsx new file mode 100644 index 0000000..dd3e10d --- /dev/null +++ b/src/components/explore/ExploreInsightsCollapse.tsx @@ -0,0 +1,107 @@ +import { useMemo, useState, type ReactNode } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ChevronRight } from 'lucide-react'; +import { cn } from '@/lib/utils'; + +export interface ExploreInsightRow { + id: string; + primary: ReactNode; + secondary?: ReactNode; + value: ReactNode; +} + +export interface ExploreInsightTab { + id: string; + label: string; + rows: ExploreInsightRow[]; +} + +interface ExploreInsightsCollapseProps { + /** Header label when collapsed */ + title?: string; + tabs: ExploreInsightTab[]; + /** Max rows shown per tab (default 5) */ + limit?: number; + defaultOpen?: boolean; + className?: string; +} + +export function ExploreInsightsCollapse({ + title, + tabs, + limit = 5, + defaultOpen = false, + className, +}: ExploreInsightsCollapseProps) { + const { t } = useTranslation(); + const headerTitle = title ?? t('explore.tops'); + const nonEmpty = useMemo(() => tabs.filter((tab) => tab.rows.length > 0), [tabs]); + const [open, setOpen] = useState(defaultOpen); + const [activeId, setActiveId] = useState(null); + + if (nonEmpty.length === 0) return null; + + const active = nonEmpty.find((tab) => tab.id === activeId) ?? nonEmpty[0]; + const visible = active.rows.slice(0, limit); + const totalRows = nonEmpty.reduce((sum, tab) => sum + tab.rows.length, 0); + + return ( +
+ + {open && ( +
+ {nonEmpty.length > 1 && ( +
+ {nonEmpty.map((tab) => { + const isActive = tab.id === active.id; + return ( + + ); + })} +
+ )} +
    + {visible.map((row) => ( +
  • +
    +
    {row.primary}
    + {row.secondary && ( +
    {row.secondary}
    + )} +
    +
    {row.value}
    +
  • + ))} +
+
+ )} +
+ ); +} diff --git a/src/components/explore/ExploreListShell.tsx b/src/components/explore/ExploreListShell.tsx new file mode 100644 index 0000000..739dba1 --- /dev/null +++ b/src/components/explore/ExploreListShell.tsx @@ -0,0 +1,87 @@ +import type { ReactNode } from 'react'; +import { Link } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { ArrowRight } from 'lucide-react'; +import { cn } from '@/lib/utils'; +import type { ExploreViewMode } from '@/lib/exploreView'; +import { ExploreViewToggle } from '@/components/explore/ExploreViewToggle'; +import { Button } from '@/components/ui/button'; + +export interface ExploreStat { + label: string; + value: number | string; +} + +interface ExploreListShellProps { + title: string; + description?: string; + stats?: ExploreStat[]; + actions?: ReactNode; + toolbar?: ReactNode; + /** Soft CTA strip (e.g. Reports → входящие) */ + banner?: { + text: string; + to: string; + actionLabel?: string; + }; + viewMode: ExploreViewMode; + onViewModeChange: (mode: ExploreViewMode) => void; + children: ReactNode; + className?: string; +} + +export function ExploreListShell({ + title, + description, + stats, + actions, + toolbar, + banner, + viewMode, + onViewModeChange, + children, + className, +}: ExploreListShellProps) { + const { t } = useTranslation(); + return ( +
+
+
+

{title}

+ {description &&

{description}

} + {stats && stats.length > 0 && ( +

+ {stats.map((s, i) => ( + + {i > 0 && ·} + {s.label}{' '} + {s.value} + + ))} +

+ )} +
+ {actions &&
{actions}
} +
+ + {banner && ( +
+

{banner.text}

+ +
+ )} + +
+
{toolbar}
+ +
+ + {children} +
+ ); +} diff --git a/src/components/explore/ExploreSearch.tsx b/src/components/explore/ExploreSearch.tsx new file mode 100644 index 0000000..51a938c --- /dev/null +++ b/src/components/explore/ExploreSearch.tsx @@ -0,0 +1,48 @@ +import { useTranslation } from 'react-i18next'; +import { Search } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { cn } from '@/lib/utils'; + +interface ExploreSearchProps { + value: string; + onChange: (value: string) => void; + onSubmit: () => void; + placeholder?: string; + className?: string; + children?: React.ReactNode; +} + +export function ExploreSearch({ + value, + onChange, + onSubmit, + placeholder, + className, + children, +}: ExploreSearchProps) { + const { t } = useTranslation(); + return ( +
{ + e.preventDefault(); + onSubmit(); + }} + > +
+ + onChange(e.target.value)} + /> +
+ {children} + +
+ ); +} diff --git a/src/components/explore/ExploreViewToggle.tsx b/src/components/explore/ExploreViewToggle.tsx new file mode 100644 index 0000000..40bcf67 --- /dev/null +++ b/src/components/explore/ExploreViewToggle.tsx @@ -0,0 +1,45 @@ +import { useTranslation } from 'react-i18next'; +import { LayoutList, Table2 } from 'lucide-react'; +import type { ExploreViewMode } from '@/lib/exploreView'; +import { cn } from '@/lib/utils'; +import { Button } from '@/components/ui/button'; + +interface ExploreViewToggleProps { + value: ExploreViewMode; + onChange: (mode: ExploreViewMode) => void; + className?: string; +} + +export function ExploreViewToggle({ value, onChange, className }: ExploreViewToggleProps) { + const { t } = useTranslation(); + return ( +
+ + +
+ ); +} diff --git a/src/components/explore/RowActionsMenu.tsx b/src/components/explore/RowActionsMenu.tsx new file mode 100644 index 0000000..596b80b --- /dev/null +++ b/src/components/explore/RowActionsMenu.tsx @@ -0,0 +1,57 @@ +import { Fragment, type ReactNode } from 'react'; +import { useTranslation } from 'react-i18next'; +import { MoreHorizontal } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; +import { cn } from '@/lib/utils'; + +export interface RowAction { + label: string; + onClick: () => void; + disabled?: boolean; + destructive?: boolean; + separatorBefore?: boolean; + icon?: ReactNode; +} + +interface RowActionsMenuProps { + actions: RowAction[]; + label?: string; +} + +export function RowActionsMenu({ actions, label }: RowActionsMenuProps) { + const { t } = useTranslation(); + const menuLabel = label ?? t('common.actions'); + if (actions.length === 0) return null; + + return ( + + + + + + {actions.map((action) => ( + + {action.separatorBefore && } + + {action.icon && {action.icon}} + {action.label} + + + ))} + + + ); +} diff --git a/src/components/explore/TablePaginationBar.tsx b/src/components/explore/TablePaginationBar.tsx new file mode 100644 index 0000000..7ff6a44 --- /dev/null +++ b/src/components/explore/TablePaginationBar.tsx @@ -0,0 +1,103 @@ +import { useTranslation } from 'react-i18next'; +import { ChevronLeft, ChevronRight } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { + DEFAULT_TABLE_PAGE_SIZE, + TABLE_PAGE_SIZE_OPTIONS, + getTablePagination, + mergeTablePagination, +} from '@/utils/tablePagination'; +import type { ServerTableParams } from '@/components/data-table/DataTable'; + +interface TablePaginationBarProps { + tableKey: string; + params: TParams; + total?: number; + dataLength: number; + onParamsChange: (params: TParams) => void; +} + +export function TablePaginationBar({ + tableKey, + params, + total, + dataLength, + onParamsChange, +}: TablePaginationBarProps) { + const { t } = useTranslation(); + const pagination = getTablePagination(params, total); + const pageCount = total != null ? Math.max(1, Math.ceil(total / pagination.pageSize)) : 1; + const canPrev = pagination.current > 1; + const canNext = total != null ? pagination.current < pageCount : dataLength >= pagination.pageSize; + + const handlePageSizeChange = (size: string) => { + const pageSize = Number(size); + onParamsChange( + mergeTablePagination({ ...params, offset: 0 }, { pageSize, current: 1 }, tableKey) + ); + }; + + const handlePageChange = (nextPage: number) => { + onParamsChange( + mergeTablePagination(params, { current: nextPage, pageSize: pagination.pageSize }, tableKey) + ); + }; + + const from = (params.offset ?? 0) + 1; + const to = Math.min((params.offset ?? 0) + (params.limit ?? DEFAULT_TABLE_PAGE_SIZE), total ?? 0); + + return ( +
+
+ {total != null ? ( + t('common.shownRange', { from, to, total }) + ) : ( + t('common.pageLabel', { current: pagination.current }) + )} +
+
+ {t('common.perPage')} + + + + {pagination.current} / {pageCount} + + +
+
+ ); +} diff --git a/src/components/ui/alert.tsx b/src/components/ui/alert.tsx new file mode 100644 index 0000000..253b7d0 --- /dev/null +++ b/src/components/ui/alert.tsx @@ -0,0 +1,43 @@ +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { cn } from '@/lib/utils'; + +const alertVariants = cva( + 'relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7', + { + variants: { + variant: { + default: 'bg-background text-foreground', + destructive: 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive', + info: 'border-primary/30 bg-primary/5 text-foreground [&>svg]:text-primary', + }, + }, + defaultVariants: { + variant: 'default', + }, + } +); + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)); +Alert.displayName = 'Alert'; + +const AlertTitle = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); +AlertTitle.displayName = 'AlertTitle'; + +const AlertDescription = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); +AlertDescription.displayName = 'AlertDescription'; + +export { Alert, AlertTitle, AlertDescription }; diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx new file mode 100644 index 0000000..c26f957 --- /dev/null +++ b/src/components/ui/avatar.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import * as AvatarPrimitive from '@radix-ui/react-avatar'; +import { cn } from '@/lib/utils'; + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +Avatar.displayName = AvatarPrimitive.Root.displayName; + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AvatarImage.displayName = AvatarPrimitive.Image.displayName; + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; + +export { Avatar, AvatarImage, AvatarFallback }; diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx new file mode 100644 index 0000000..6da1b26 --- /dev/null +++ b/src/components/ui/badge.tsx @@ -0,0 +1,30 @@ +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { cn } from '@/lib/utils'; + +const badgeVariants = cva( + 'inline-flex items-center rounded-md border px-2 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring', + { + variants: { + variant: { + default: 'border-transparent bg-primary text-primary-foreground', + secondary: 'border-transparent bg-secondary text-secondary-foreground', + destructive: 'border-transparent bg-destructive text-destructive-foreground', + outline: 'text-foreground', + success: 'border-transparent bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-300', + warning: 'border-transparent bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-300', + }, + }, + defaultVariants: { + variant: 'default', + }, + } +); + +export interface BadgeProps extends React.HTMLAttributes, VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return
; +} + +export { Badge, badgeVariants }; diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..efee10f --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,48 @@ +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { cn } from '@/lib/utils'; + +const buttonVariants = cva( + 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50', + { + variants: { + variant: { + default: 'bg-primary text-primary-foreground hover:bg-primary/90', + destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90', + outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', + secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground', + link: 'text-primary underline-offset-4 hover:underline', + }, + size: { + default: 'h-9 px-4 py-2', + sm: 'h-8 rounded-md px-3 text-xs', + lg: 'h-10 rounded-md px-8', + icon: 'h-9 w-9', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + } +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; + return ( + + ); + } +); +Button.displayName = 'Button'; + +export { Button, buttonVariants }; diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx new file mode 100644 index 0000000..b4a4194 --- /dev/null +++ b/src/components/ui/card.tsx @@ -0,0 +1,50 @@ +import * as React from 'react'; +import { cn } from '@/lib/utils'; + +const Card = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); +Card.displayName = 'Card'; + +const CardHeader = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); +CardHeader.displayName = 'CardHeader'; + +const CardTitle = React.forwardRef>( + ({ className, ...props }, ref) => ( +

+ ) +); +CardTitle.displayName = 'CardTitle'; + +const CardDescription = React.forwardRef>( + ({ className, ...props }, ref) => ( +

+ ) +); +CardDescription.displayName = 'CardDescription'; + +const CardContent = React.forwardRef>( + ({ className, ...props }, ref) => ( +

+ ) +); +CardContent.displayName = 'CardContent'; + +const CardFooter = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); +CardFooter.displayName = 'CardFooter'; + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }; diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx new file mode 100644 index 0000000..95aa168 --- /dev/null +++ b/src/components/ui/dialog.tsx @@ -0,0 +1,82 @@ +import * as React from 'react'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { X } from 'lucide-react'; +import { cn } from '@/lib/utils'; + +const Dialog = DialogPrimitive.Root; +const DialogTrigger = DialogPrimitive.Trigger; +const DialogPortal = DialogPrimitive.Portal; +const DialogClose = DialogPrimitive.Close; + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
+); + +const DialogFooter = ({ className, ...props }: React.HTMLAttributes) => ( +
+); + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +}; diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..40c3ab7 --- /dev/null +++ b/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,73 @@ +import * as React from 'react'; +import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; +import { cn } from '@/lib/utils'; + +const DropdownMenu = DropdownMenuPrimitive.Root; +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; +const DropdownMenuGroup = DropdownMenuPrimitive.Group; +const DropdownMenuPortal = DropdownMenuPrimitive.Portal; + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)); +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { inset?: boolean } +>(({ className, inset, ...props }, ref) => ( + +)); +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { inset?: boolean } +>(({ className, inset, ...props }, ref) => ( + +)); +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuLabel, + DropdownMenuGroup, + DropdownMenuPortal, +}; diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx new file mode 100644 index 0000000..4dbdc5c --- /dev/null +++ b/src/components/ui/input.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +import { cn } from '@/lib/utils'; + +const Input = React.forwardRef>( + ({ className, type, ...props }, ref) => ( + + ) +); +Input.displayName = 'Input'; + +export { Input }; diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx new file mode 100644 index 0000000..1f1f925 --- /dev/null +++ b/src/components/ui/label.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import * as LabelPrimitive from '@radix-ui/react-label'; +import { cn } from '@/lib/utils'; + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; + +export { Label }; diff --git a/src/components/ui/scroll-area.tsx b/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..648e39d --- /dev/null +++ b/src/components/ui/scroll-area.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'; +import { cn } from '@/lib/utils'; + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + + +)); +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName; + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = 'vertical', ...props }, ref) => ( + + + +)); +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName; + +export { ScrollArea, ScrollBar }; diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx new file mode 100644 index 0000000..ecc7ab2 --- /dev/null +++ b/src/components/ui/select.tsx @@ -0,0 +1,139 @@ +import * as React from 'react'; +import * as SelectPrimitive from '@radix-ui/react-select'; +import { Check, ChevronDown, ChevronUp } from 'lucide-react'; +import { cn } from '@/lib/utils'; + +const Select = SelectPrimitive.Root; +const SelectGroup = SelectPrimitive.Group; +const SelectValue = SelectPrimitive.Value; + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1', + className + )} + {...props} + > + {children} + + + + +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName; + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = 'popper', ...props }, ref) => ( + + + + + {children} + + + + +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +}; diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx new file mode 100644 index 0000000..f991503 --- /dev/null +++ b/src/components/ui/separator.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import * as SeparatorPrimitive from '@radix-ui/react-separator'; +import { cn } from '@/lib/utils'; + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => ( + +)); +Separator.displayName = SeparatorPrimitive.Root.displayName; + +export { Separator }; diff --git a/src/components/ui/sheet.tsx b/src/components/ui/sheet.tsx new file mode 100644 index 0000000..9f195ec --- /dev/null +++ b/src/components/ui/sheet.tsx @@ -0,0 +1,87 @@ +import * as React from 'react'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { X } from 'lucide-react'; +import { cn } from '@/lib/utils'; + +const Sheet = DialogPrimitive.Root; +const SheetTrigger = DialogPrimitive.Trigger; +const SheetClose = DialogPrimitive.Close; +const SheetPortal = DialogPrimitive.Portal; + +const SheetOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SheetOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const SheetContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)); +SheetContent.displayName = DialogPrimitive.Content.displayName; + +const SheetHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
+); + +const SheetTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SheetTitle.displayName = DialogPrimitive.Title.displayName; + +const SheetDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SheetDescription.displayName = DialogPrimitive.Description.displayName; + +const SheetBody = ({ className, ...props }: React.HTMLAttributes) => ( +
+); + +const SheetFooter = ({ className, ...props }: React.HTMLAttributes) => ( +
+); + +export { + Sheet, + SheetPortal, + SheetOverlay, + SheetTrigger, + SheetClose, + SheetContent, + SheetHeader, + SheetFooter, + SheetTitle, + SheetDescription, + SheetBody, +}; diff --git a/src/components/ui/skeleton.tsx b/src/components/ui/skeleton.tsx new file mode 100644 index 0000000..6816544 --- /dev/null +++ b/src/components/ui/skeleton.tsx @@ -0,0 +1,7 @@ +import { cn } from '@/lib/utils'; + +function Skeleton({ className, ...props }: React.HTMLAttributes) { + return
; +} + +export { Skeleton }; diff --git a/src/components/ui/table.tsx b/src/components/ui/table.tsx new file mode 100644 index 0000000..0497b06 --- /dev/null +++ b/src/components/ui/table.tsx @@ -0,0 +1,63 @@ +import * as React from 'react'; +import { cn } from '@/lib/utils'; + +const Table = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ + + ) +); +Table.displayName = 'Table'; + +const TableHeader = React.forwardRef>( + ({ className, ...props }, ref) => +); +TableHeader.displayName = 'TableHeader'; + +const TableBody = React.forwardRef>( + ({ className, ...props }, ref) => ( + + ) +); +TableBody.displayName = 'TableBody'; + +const TableRow = React.forwardRef>( + ({ className, ...props }, ref) => ( + + ) +); +TableRow.displayName = 'TableRow'; + +const TableHead = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); +TableHead.displayName = 'TableHead'; + +const TableCell = React.forwardRef>( + ({ className, ...props }, ref) => ( + + ) +); +TableCell.displayName = 'TableCell'; + +export { Table, TableHeader, TableBody, TableRow, TableHead, TableCell }; diff --git a/src/components/ui/textarea.tsx b/src/components/ui/textarea.tsx new file mode 100644 index 0000000..7e145ea --- /dev/null +++ b/src/components/ui/textarea.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import { cn } from '@/lib/utils'; + +const Textarea = React.forwardRef>( + ({ className, ...props }, ref) => ( +