From 87c6b55e812eed9bccac0330e971125986f93200 Mon Sep 17 00:00:00 2001 From: Aleksey Sabilin Date: Tue, 14 Jul 2026 22:18:34 +0300 Subject: [PATCH] =?UTF-8?q?feat(admin):=20Playwright=20E2E=20=D0=BA=D0=B0?= =?UTF-8?q?=D1=80=D0=BA=D0=B0=D1=81=20=E2=80=94=20TESTIDS,=20login/shell/r?= =?UTF-8?q?oles,=20CI=20mock.=20Refs=20EventHub/EventHubFrontAdmin#33=20#3?= =?UTF-8?q?4=20#35?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/ci.yml | 14 + .gitignore | 4 + e2e/TESTIDS.md | 26 + e2e/helpers/auth.ts | 10 + e2e/helpers/session.ts | 18 + e2e/mocks/adminApi.ts | 116 ++ e2e/tests/auth.spec.ts | 29 + e2e/tests/ift/smoke.spec.ts | 10 + e2e/tests/shell.spec.ts | 68 ++ eslint.config.js | 3 +- package-lock.json | 1551 ++----------------------- package.json | 5 +- playwright.config.ts | 45 + src/components/CommandPalette.tsx | 7 +- src/layouts/ControlCenterLayout.tsx | 24 +- src/lib/testid.ts | 7 + src/pages/auth/LoginPage.tsx | 4 +- src/pages/dashboard/DashboardPage.tsx | 8 +- src/pages/errors/ForbiddenPage.tsx | 6 +- 19 files changed, 493 insertions(+), 1462 deletions(-) create mode 100644 e2e/TESTIDS.md create mode 100644 e2e/helpers/auth.ts create mode 100644 e2e/helpers/session.ts create mode 100644 e2e/mocks/adminApi.ts create mode 100644 e2e/tests/auth.spec.ts create mode 100644 e2e/tests/ift/smoke.spec.ts create mode 100644 e2e/tests/shell.spec.ts create mode 100644 playwright.config.ts create mode 100644 src/lib/testid.ts diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index b87e270..91b4252 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -47,6 +47,12 @@ jobs: - run: npm run lint - run: npm run build + - name: Install Playwright browser + run: npx playwright install --with-deps chromium + + - name: E2E mock suite + run: npm run test:e2e + - name: Upload dist for docker job if: github.event_name == 'push' uses: actions/upload-artifact@v3 @@ -55,6 +61,14 @@ jobs: path: dist/ retention-days: 1 + - name: Upload Playwright report + if: failure() + uses: actions/upload-artifact@v3 + with: + name: playwright-report + path: playwright-report/ + retention-days: 7 + - name: Mark test complete id: mark_test if: success() diff --git a/.gitignore b/.gitignore index a547bf3..d1a3d07 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,10 @@ node_modules dist dist-ssr *.local +playwright-report +test-results +blob-report +.playwright # Editor directories and files .vscode/* diff --git a/e2e/TESTIDS.md b/e2e/TESTIDS.md new file mode 100644 index 0000000..ed09114 --- /dev/null +++ b/e2e/TESTIDS.md @@ -0,0 +1,26 @@ +# E2E testid contract (EventHubFrontAdmin) + +Селекторы: **`data-testid`** + a11y (`getByRole` / `getByLabel`) где имя стабильно. + +## Naming + +| Pattern | Example | +|---------|---------| +| `page-{name}` | `page-login`, `page-users` | +| `nav-{slug}` | `nav-users` (slug = path without `/`) | +| `{entity}-row-{id}` | `user-row-{uuid}` | +| `{entity}-detail` | `user-detail` | +| `{entity}-filter-{field}` | `event-filter-status` | +| `btn-{action}` | `btn-login`, `btn-save`, `btn-delete-confirm` | +| `dialog-{name}` | `dialog-edit-user` | +| `menu-user` | avatar dropdown | +| `palette-input` | command palette | + +Helper in app: `src/lib/testid.ts` → `testid(['user-row', id])`. + +## Rules + +- kebab-case only +- Dynamic id segment = real API entity id +- Prefer roles/labels for login email/password and primary submit when i18n fixed to `ru` in mock suite +- Do not decorate every layout div — only interaction anchors diff --git a/e2e/helpers/auth.ts b/e2e/helpers/auth.ts new file mode 100644 index 0000000..994fab0 --- /dev/null +++ b/e2e/helpers/auth.ts @@ -0,0 +1,10 @@ +import type { Page } from '@playwright/test'; +import { MOCK_ADMIN } from '../mocks/adminApi'; + +export async function loginAsE2EAdmin(page: Page) { + await page.goto('/login'); + await page.getByLabel(/email/i).fill(MOCK_ADMIN.email); + await page.getByLabel(/пароль|password/i).fill('e2e-pass'); + await page.getByTestId('btn-login').click(); + await page.waitForURL(/\/(dashboard|inbox)/); +} diff --git a/e2e/helpers/session.ts b/e2e/helpers/session.ts new file mode 100644 index 0000000..ac22a19 --- /dev/null +++ b/e2e/helpers/session.ts @@ -0,0 +1,18 @@ +import type { Page } from '@playwright/test'; +import { ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY } from '../../src/utils/constants'; +import { installAdminApiMocks, MOCK_ADMIN, type MockAdmin } from '../mocks/adminApi'; + +export async function seedAuthenticatedSession(page: Page, admin: Partial = {}) { + const user: MockAdmin = { ...MOCK_ADMIN, ...admin }; + await installAdminApiMocks(page, { user }); + // Origin + localStorage before app boot (addInitScript alone races under load). + await page.goto('/login'); + await page.evaluate( + ([accessKey, refreshKey]) => { + localStorage.setItem(accessKey, 'e2e-access-token'); + localStorage.setItem(refreshKey, 'e2e-refresh-token'); + }, + [ACCESS_TOKEN_KEY, REFRESH_TOKEN_KEY] as [string, string] + ); + return user; +} diff --git a/e2e/mocks/adminApi.ts b/e2e/mocks/adminApi.ts new file mode 100644 index 0000000..5052da2 --- /dev/null +++ b/e2e/mocks/adminApi.ts @@ -0,0 +1,116 @@ +import type { Page, Route } from '@playwright/test'; + +export type MockAdmin = { + id: string; + email: string; + nickname: string; + role: string; + language: string; + avatar_url: string | null; +}; + +export const MOCK_ADMIN: MockAdmin = { + id: 'admin-e2e-1', + email: 'e2e@eventhub.local', + nickname: 'E2E Admin', + role: 'superadmin', + language: 'ru', + avatar_url: null, +}; + +async function json(route: Route, status: number, body: unknown, headers: Record = {}) { + await route.fulfill({ + status, + contentType: 'application/json', + headers, + body: JSON.stringify(body), + }); +} + +type MockOptions = { + user?: MockAdmin; +}; + +/** Default admin API mocks for Control Center shell / login. */ +export async function installAdminApiMocks(page: Page, options: MockOptions = {}) { + let currentUser: MockAdmin = { ...MOCK_ADMIN, ...options.user }; + + await page.route('**/v1/admin/**', async (route) => { + const req = route.request(); + const method = req.method(); + const url = new URL(req.url()); + const path = url.pathname; + + if (method === 'POST' && path.endsWith('/v1/admin/login')) { + const payload = req.postDataJSON() as { email?: string; password?: string }; + if (payload?.email === MOCK_ADMIN.email && payload?.password === 'e2e-pass') { + await json(route, 200, { + token: 'e2e-access-token', + refresh_token: 'e2e-refresh-token', + user: currentUser, + }); + return; + } + await json(route, 401, { error: 'invalid_credentials' }); + return; + } + + if (method === 'GET' && path.endsWith('/v1/admin/me')) { + await json(route, 200, currentUser); + return; + } + + if (method === 'PUT' && path.endsWith('/v1/admin/me')) { + const payload = (req.postDataJSON() || {}) as Partial; + currentUser = { ...currentUser, ...payload }; + await json(route, 200, currentUser); + return; + } + + if (method === 'GET' && path.endsWith('/v1/admin/health')) { + await json(route, 200, { + status: 'ok', + service: 'eventhub', + version: '0.1', + git_sha: 'e2etestsha000', + built_at: '2026-07-14T00:00:00Z', + }); + return; + } + + if (method === 'GET' && path.endsWith('/v1/admin/stats')) { + await json(route, 200, { + users_total: 10, + events_total: 5, + reviews_total: 2, + calendars_total: 3, + tickets_total: 1, + tickets_open: 1, + reports_total: 2, + reports_pending: 1, + reports_reviewed: 1, + avg_report_resolution_h: 1.5, + avg_ticket_resolution_h: 2, + events_by_day: [], + registrations_by_day: [], + reviews_by_day: [], + reports_by_day: [], + tickets_by_day: [], + subscriptions_by_day: [], + }); + return; + } + + if (method === 'GET' && path.includes('/v1/admin/nodes/metrics')) { + await json(route, 200, { nodes: [] }); + return; + } + + if (method === 'GET') { + await json(route, 200, [], { 'X-Total-Count': '0' }); + return; + } + + await json(route, 200, { ok: true }); + }); +} diff --git a/e2e/tests/auth.spec.ts b/e2e/tests/auth.spec.ts new file mode 100644 index 0000000..27f5293 --- /dev/null +++ b/e2e/tests/auth.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from '@playwright/test'; +import { installAdminApiMocks, MOCK_ADMIN } from '../mocks/adminApi'; + +test.describe('auth / login (mock)', () => { + test.beforeEach(async ({ page }) => { + await installAdminApiMocks(page); + }); + + test('успешный вход ведёт на dashboard', async ({ page }) => { + await page.goto('/login'); + await expect(page.getByTestId('page-login')).toBeVisible(); + + await page.getByLabel(/email/i).fill(MOCK_ADMIN.email); + await page.getByLabel(/пароль|password/i).fill('e2e-pass'); + await page.getByRole('button', { name: /войти|log in|sign in/i }).click(); + + await expect(page).toHaveURL(/\/dashboard/); + await expect(page.getByTestId('page-dashboard')).toBeVisible(); + }); + + test('неверный пароль показывает ошибку', async ({ page }) => { + await page.goto('/login'); + await page.getByLabel(/email/i).fill(MOCK_ADMIN.email); + await page.getByLabel(/пароль|password/i).fill('wrong'); + await page.getByTestId('btn-login').click(); + await expect(page.getByText(/неверный email или пароль|invalid/i)).toBeVisible(); + await expect(page).toHaveURL(/\/login/); + }); +}); diff --git a/e2e/tests/ift/smoke.spec.ts b/e2e/tests/ift/smoke.spec.ts new file mode 100644 index 0000000..4a7af05 --- /dev/null +++ b/e2e/tests/ift/smoke.spec.ts @@ -0,0 +1,10 @@ +import { test } from '@playwright/test'; + +/** IFT smoke project placeholder — filled in phase 6. */ +test.describe('IFT smoke', () => { + test.skip(!process.env.E2E_ADMIN_EMAIL, 'Set E2E_ADMIN_EMAIL / E2E_ADMIN_PASSWORD for IFT'); + + test('placeholder', async () => { + // Implemented in E2E phase 6 + }); +}); diff --git a/e2e/tests/shell.spec.ts b/e2e/tests/shell.spec.ts new file mode 100644 index 0000000..e2d729c --- /dev/null +++ b/e2e/tests/shell.spec.ts @@ -0,0 +1,68 @@ +import { test, expect } from '@playwright/test'; +import { seedAuthenticatedSession } from '../helpers/session'; +import { loginAsE2EAdmin } from '../helpers/auth'; +import { installAdminApiMocks } from '../mocks/adminApi'; + +test.describe('shell / layout (mock)', () => { + test('после логина видны sidebar, nav dashboard и user menu', async ({ page }) => { + await installAdminApiMocks(page); + await loginAsE2EAdmin(page); + + await expect(page.getByTestId('layout-shell')).toBeVisible(); + await expect(page.getByTestId('layout-sidebar')).toBeVisible(); + await expect(page.getByTestId('nav-dashboard')).toBeVisible(); + await expect(page.getByTestId('nav-users')).toBeVisible(); + await expect(page.getByTestId('nav-admins')).toBeVisible(); + + await page.getByTestId('menu-user').click(); + await expect(page.getByTestId('menu-user-content')).toBeVisible(); + await expect(page.getByTestId('menu-profile')).toBeVisible(); + await expect(page.getByTestId('btn-logout')).toBeVisible(); + }); + + test('command palette открывается и навигирует', async ({ page }) => { + await seedAuthenticatedSession(page); + await page.goto('/dashboard'); + await expect(page.getByTestId('layout-shell')).toBeVisible(); + + await page.getByTestId('btn-open-palette').click(); + await expect(page.getByTestId('command-palette')).toBeVisible(); + await page.getByTestId('palette-input').fill('Пользователи'); + await page.keyboard.press('Enter'); + await expect(page).toHaveURL(/\/users/); + }); + + test('logout возвращает на login', async ({ page }) => { + await seedAuthenticatedSession(page); + await page.goto('/dashboard'); + await page.getByTestId('menu-user').click(); + await page.getByTestId('btn-logout').click(); + await expect(page).toHaveURL(/\/login/); + await expect(page.getByTestId('page-login')).toBeVisible(); + }); +}); + +test.describe('shell / roles (mock)', () => { + test('moderator: нет nav users, admins запрещён', async ({ page }) => { + await seedAuthenticatedSession(page, { role: 'moderator', nickname: 'Mod' }); + await page.goto('/dashboard'); + await expect(page.getByTestId('nav-inbox-reports')).toBeVisible(); + await expect(page.getByTestId('nav-users')).toHaveCount(0); + await expect(page.getByTestId('nav-admins')).toHaveCount(0); + + await page.goto('/admins'); + await expect(page.getByTestId('page-forbidden')).toBeVisible(); + await page.getByTestId('btn-to-dashboard').click(); + await expect(page).toHaveURL(/\/dashboard/); + }); + + test('support: tickets inbox есть, reports inbox нет', async ({ page }) => { + await seedAuthenticatedSession(page, { role: 'support', nickname: 'Support' }); + await page.goto('/dashboard'); + await expect(page.getByTestId('nav-inbox-tickets')).toBeVisible(); + await expect(page.getByTestId('nav-inbox-reports')).toHaveCount(0); + + await page.goto('/inbox/reports'); + await expect(page.getByTestId('page-forbidden')).toBeVisible(); + }); +}); diff --git a/eslint.config.js b/eslint.config.js index 085f927..be1aaa6 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -6,9 +6,10 @@ import tseslint from 'typescript-eslint' import { defineConfig, globalIgnores } from 'eslint/config' export default defineConfig([ - globalIgnores(['dist']), + globalIgnores(['dist', 'playwright-report', 'test-results', 'e2e']), { files: ['**/*.{ts,tsx}'], + ignores: ['playwright.config.ts'], extends: [ js.configs.recommended, tseslint.configs.recommended, diff --git a/package-lock.json b/package-lock.json index 977a6de..6f2f6f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ }, "devDependencies": { "@eslint/js": "^10.0.1", + "@playwright/test": "^1.61.1", "@types/node": "^24.12.4", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", @@ -58,99 +59,6 @@ "node": ">=20.19.0" } }, - "node_modules/@ant-design/colors": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-8.0.1.tgz", - "integrity": "sha512-foPVl0+SWIslGUtD/xBr1p9U4AKzPhNYEseXYRRo5QSzGACYZrQbe11AYJbYfAWnWSpGBx6JjBmSeugUsD9vqQ==", - "license": "MIT", - "dependencies": { - "@ant-design/fast-color": "^3.0.0" - } - }, - "node_modules/@ant-design/cssinjs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-2.1.2.tgz", - "integrity": "sha512-2Hy8BnCEH31xPeSLbhhB2ctCPXE2ZnASdi+KbSeS79BNbUhL9hAEe20SkUk+BR8aKTmqb6+FKFruk7w8z0VoRQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.1", - "@emotion/hash": "^0.8.0", - "@emotion/unitless": "^0.7.5", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1", - "csstype": "^3.1.3", - "stylis": "^4.3.4" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/@ant-design/cssinjs-utils": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-2.1.2.tgz", - "integrity": "sha512-5fTHQ158jJJ5dC/ECeyIdZUzKxE/mpEMRZxthyG1sw/AKRHKgJBg00Yi6ACVXgycdje7KahRNvNET/uBccwCnA==", - "license": "MIT", - "dependencies": { - "@ant-design/cssinjs": "^2.1.2", - "@babel/runtime": "^7.23.2", - "@rc-component/util": "^1.4.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - } - }, - "node_modules/@ant-design/fast-color": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-3.0.1.tgz", - "integrity": "sha512-esKJegpW4nckh0o6kV3Tkb7NPIZYbPnnFxmQDUmL08ukXZAvV85TZBr70eGuke/CIArLaP6aw8lt9KILjnWuOw==", - "license": "MIT", - "engines": { - "node": ">=8.x" - } - }, - "node_modules/@ant-design/icons": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-6.2.3.tgz", - "integrity": "sha512-Pl3aoAtxQeKryYnt6VvDJtOxMOtA8wrRSACe/pTjOAIG3fdHrWm6Ivb4ku9tsFjYroSXBKirvuxG4QkwBXD9gg==", - "license": "MIT", - "dependencies": { - "@ant-design/colors": "^8.0.1", - "@ant-design/icons-svg": "^4.4.2", - "@rc-component/util": "^1.10.1", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/@ant-design/icons-svg": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", - "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", - "license": "MIT" - }, - "node_modules/@ant-design/react-slick": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-2.0.0.tgz", - "integrity": "sha512-HMS9sRoEmZey8LsE/Yo6+klhlzU12PisjrVcydW3So7RdklyEd2qehyU6a7Yp+OYN72mgsYs3NFCyP2lCPFVqg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.28.4", - "clsx": "^2.1.1", - "json2mq": "^0.2.0", - "throttle-debounce": "^5.0.0" - }, - "peerDependencies": { - "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -431,18 +339,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", - "license": "MIT" - }, - "node_modules/@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", - "license": "MIT" - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", @@ -755,6 +651,22 @@ "url": "https://github.com/sponsors/Boshen" } }, + "node_modules/@playwright/test": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.1.tgz", + "integrity": "sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.2.tgz", @@ -1541,703 +1453,6 @@ "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", - "integrity": "sha512-n4HcR5siNUXRX23nDizbZBQPO0ZM/5oTtmKZ6/eqL0L2bo747cklFdZGRN2f+c9qWGICwDzrhW0H7tE9PptdcA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.24.4" - }, - "engines": { - "node": ">=14.x" - } - }, - "node_modules/@rc-component/cascader": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@rc-component/cascader/-/cascader-1.15.0.tgz", - "integrity": "sha512-ZzpMtwFCRo3fbXHuDnncARJMZQjdqA2w7aDuPofNQt+aDx39st1hgfIpEwTBLhe2Hqsvs/zOr8RTtgxTkCPySw==", - "license": "MIT", - "dependencies": { - "@rc-component/select": "~1.6.0", - "@rc-component/tree": "~1.3.0", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/checkbox": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@rc-component/checkbox/-/checkbox-2.0.0.tgz", - "integrity": "sha512-3CXGPpAR9gsPKeO2N78HAPOzU30UdemD6HGJoWVJOpa6WleaGB5kzZj3v6bdTZab31YuWgY/RxV3VKPctn0DwQ==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/collapse": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rc-component/collapse/-/collapse-1.2.0.tgz", - "integrity": "sha512-ZRYSKSS39qsFx93p26bde7JUZJshsUBEQRlRXPuJYlAiNX0vyYlF5TsAm8JZN3LcF8XvKikdzPbgAtXSbkLUkw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/motion": "^1.1.4", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/color-picker": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-3.1.1.tgz", - "integrity": "sha512-OHaCHLHszCegdXmIq2ZRIZBN/EtpT6Wm8SG/gpzLATHbVKc/avvuKi+zlOuk05FTWvgaMmpxAko44uRJ3M+2pg==", - "license": "MIT", - "dependencies": { - "@ant-design/fast-color": "^3.0.1", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/context": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-2.0.1.tgz", - "integrity": "sha512-HyZbYm47s/YqtP6pKXNMjPEMaukyg7P0qVfgMLzr7YiFNMHbK2fKTAGzms9ykfGHSfyf75nBbgWw+hHkp+VImw==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.3.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/dialog": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/dialog/-/dialog-1.9.0.tgz", - "integrity": "sha512-zbAAogkg4kkKum79sLE6M+vq1jSAW25zdkafrahgcTP9t9S//SD634Znd1A4c8F2Gc12ZKnehGLsVaaOvZzD2A==", - "license": "MIT", - "dependencies": { - "@rc-component/motion": "^1.1.3", - "@rc-component/portal": "^2.1.0", - "@rc-component/util": "^1.9.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/drawer": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@rc-component/drawer/-/drawer-1.4.2.tgz", - "integrity": "sha512-1ib+fZEp6FBu+YvcIktm+nCQ+Q+qIpwpoaJH6opGr4ofh2QMq+qdr5DLC4oCf5qf3pcWX9lUWPYX652k4ini8Q==", - "license": "MIT", - "dependencies": { - "@rc-component/motion": "^1.1.4", - "@rc-component/portal": "^2.1.3", - "@rc-component/util": "^1.9.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/dropdown": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rc-component/dropdown/-/dropdown-1.0.2.tgz", - "integrity": "sha512-6PY2ecUSYhDPhkNHHb4wfeAya04WhpmUSKzdR60G+kMNVUCX2vjT/AgTS0Lz0I/K6xrPMJ3enQbwVpeN3sHCgg==", - "license": "MIT", - "dependencies": { - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.11.0", - "react-dom": ">=16.11.0" - } - }, - "node_modules/@rc-component/form": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@rc-component/form/-/form-1.8.1.tgz", - "integrity": "sha512-8O7TB55Fi2mWIGvSnwZjk8jFqVNYyKDAswglwGShcbndxqzKz4cHwNtNaLjZlAeRge9wcB0LL8IWsC/Bl18raQ==", - "license": "MIT", - "dependencies": { - "@rc-component/async-validator": "^5.1.0", - "@rc-component/util": "^1.6.2", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/image": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/image/-/image-1.9.0.tgz", - "integrity": "sha512-khF7w7xkBH5B1bsBcI1FSUZdkyd1aqpl2eYyILCqCzzQH3XdfehGUaZTnptyaJJfs09/R5hv9jXWyazOMFIClQ==", - "license": "MIT", - "dependencies": { - "@rc-component/motion": "^1.0.0", - "@rc-component/portal": "^2.1.2", - "@rc-component/util": "^1.10.1", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/input": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@rc-component/input/-/input-1.3.0.tgz", - "integrity": "sha512-IUUNOdAuWuEvDEFFgfmwQl818tiDbvXwLgon4HL1q2hJeYkqrRrYwYhJN0zfPHGTDxs3gvyVC/C02D4hWFoIcA==", - "license": "MIT", - "dependencies": { - "@rc-component/resize-observer": "^1.1.1", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/@rc-component/input-number": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@rc-component/input-number/-/input-number-1.6.2.tgz", - "integrity": "sha512-Gjcq7meZlCOiWN1t1xCC+7/s85humHVokTBI7PJgTfoyw5OWF74y3e6P8PHX104g9+b54jsodFIzyaj6p8LI9w==", - "license": "MIT", - "dependencies": { - "@rc-component/mini-decimal": "^1.0.1", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/mentions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/mentions/-/mentions-1.9.0.tgz", - "integrity": "sha512-WUwfFKDSOF5S9UPsNsXcLYtzjTxBGsftTXWRbZuxX6BYrsySISTnujfJNgaaQ6qVzaCDJ35QUkZKvsYxip1C5g==", - "license": "MIT", - "dependencies": { - "@rc-component/input": "~1.3.0", - "@rc-component/menu": "~1.3.0", - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/menu": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@rc-component/menu/-/menu-1.3.0.tgz", - "integrity": "sha512-u3NfiwpiEgT177qa5Yxm5QsI8i/93EBGpWj8HYZQDnh2pCZ2xtQCe/+w3pSR2NlwKOZDTCKzEhEyD09mGphssA==", - "license": "MIT", - "dependencies": { - "@rc-component/motion": "^1.1.4", - "@rc-component/overflow": "^1.0.0", - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/mini-decimal": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.3.tgz", - "integrity": "sha512-bk/FJ09fLf+NLODMAFll6CfYrHPBioTedhW6lxDBuuWucJEqFUd4l/D/5JgIi3dina6sYahB8iuPAZTNz2pMxw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.0" - }, - "engines": { - "node": ">=8.x" - } - }, - "node_modules/@rc-component/motion": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@rc-component/motion/-/motion-1.3.2.tgz", - "integrity": "sha512-itfd+GztzJYAb04Z4RkEub1TbJAfZc2Iuy8p44U44xD1F5+fNYFKI3897ijlbIyfvXkTmMm+KGcjkQQGMHywEQ==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.2.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/mutate-observer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-2.0.1.tgz", - "integrity": "sha512-AyarjoLU5YlxuValRi+w8JRH2Z84TBbFO2RoGWz9d8bSu0FqT8DtugH3xC3BV7mUwlmROFauyWuXFuq4IFbH+w==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.2.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/notification": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rc-component/notification/-/notification-2.0.7.tgz", - "integrity": "sha512-nqZzpf6BPdaj+3ILx7si79LLmqPKyUmQoXa+/9gg0SkH0v1DbD66oJgRMSBEVnd/zUT3D4gwxWIHUKebYf2ZXQ==", - "license": "MIT", - "dependencies": { - "@rc-component/motion": "^1.1.4", - "@rc-component/util": "^1.11.0", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/overflow": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/overflow/-/overflow-1.0.1.tgz", - "integrity": "sha512-syfmgAABaHCnCDzPwHZ/2tuvIcpOO3jefYZMmfkN+pmo8HKTzsfhS57vxo4ksPdN0By+uWVJhJWNFozNBxi2eA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.1", - "@rc-component/resize-observer": "^1.0.1", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/pagination": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rc-component/pagination/-/pagination-1.2.0.tgz", - "integrity": "sha512-YcpUFE8dMLfSo6OARJlK6DbHHvrxz7pMGPGmC/caZSJJz6HRKHC1RPP001PRHCvG9Z/veD039uOQmazVuLJzlw==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/picker": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@rc-component/picker/-/picker-1.10.0.tgz", - "integrity": "sha512-vVOXP2RVWozwpERGUFAehVH1Jz6o/uRrAb9qSZm1LC+iJs8rvEwFo1bzz2jlOYV+uWwu0dIuG86tnDui14Ea0w==", - "license": "MIT", - "dependencies": { - "@rc-component/overflow": "^1.0.0", - "@rc-component/resize-observer": "^1.0.0", - "@rc-component/trigger": "^3.6.15", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=12.x" - }, - "peerDependencies": { - "date-fns": ">= 2.x", - "dayjs": ">= 1.x", - "luxon": ">= 3.x", - "moment": ">= 2.x", - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - }, - "peerDependenciesMeta": { - "date-fns": { - "optional": true - }, - "dayjs": { - "optional": true - }, - "luxon": { - "optional": true - }, - "moment": { - "optional": true - } - } - }, - "node_modules/@rc-component/portal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-2.2.0.tgz", - "integrity": "sha512-oc6FlA+uXCMiwArHsJyHcIkX4q6uKyndrPol2eWX8YPkAnztHOPsFIRtmWG4BMlGE5h7YIRE3NiaJ5VS8Lb1QQ==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=12.x" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/progress": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rc-component/progress/-/progress-1.0.2.tgz", - "integrity": "sha512-WZUnH9eGxH1+xodZKqdrHke59uyGZSWgj5HBM5Kwk5BrTMuAORO7VJ2IP5Qbm9aH3n9x3IcesqHHR0NWPBC7fQ==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/qrcode": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.1.1.tgz", - "integrity": "sha512-LfLGNymzKdUPjXUbRP+xOhIWY4jQ+YMj5MmWAcgcAq1Ij8XP7tRmAXqyuv96XvLUBE/5cA8hLFl9eO1JQMujrA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.24.7" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/rate": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/rate/-/rate-1.0.1.tgz", - "integrity": "sha512-bkXxeBqDpl5IOC7yL7GcSYjQx9G8H+6kLYQnNZWeBYq2OYIv1MONd6mqKTjnnJYpV0cQIU2z3atdW0j1kttpTw==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/resize-observer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@rc-component/resize-observer/-/resize-observer-1.1.2.tgz", - "integrity": "sha512-t/Bb0W8uvL4PYKAB3YcChC+DlHh0Wt5kM7q/J+0qpVEUMLe7Hk5zuvc9km0hMnTFPSx5Z7Wu/fzCLN6erVLE8Q==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.2.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/segmented": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@rc-component/segmented/-/segmented-1.3.0.tgz", - "integrity": "sha512-5J/bJ01mbDnoA6P/FW8SxUvKn+OgUSTZJPzCNnTBntG50tzoP7DydGhqxp7ggZXZls7me3mc2EQDXakU3iTVFg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.1", - "@rc-component/motion": "^1.1.4", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/@rc-component/select": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@rc-component/select/-/select-1.6.15.tgz", - "integrity": "sha512-SyVCWnqxCQZZcQvQJ/CxSjx2bGma6ds/HtnpkIfZVnt6RoEgbqUmHgD6vrzNarNXwbLXerwVzWwq8F3d1sst7g==", - "license": "MIT", - "dependencies": { - "@rc-component/overflow": "^1.0.0", - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.3.0", - "@rc-component/virtual-list": "^1.0.1", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/@rc-component/slider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/slider/-/slider-1.0.1.tgz", - "integrity": "sha512-uDhEPU1z3WDfCJhaL9jfd2ha/Eqpdfxsn0Zb0Xcq1NGQAman0TWaR37OWp2vVXEOdV2y0njSILTMpTfPV1454g==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/steps": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rc-component/steps/-/steps-1.2.2.tgz", - "integrity": "sha512-/yVIZ00gDYYPHSY0JP+M+s3ZvuXLu2f9rEjQqiUDs7EcYsUYrpJ/1bLj9aI9R7MBR3fu/NGh6RM9u2qGfqp+Nw==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/switch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rc-component/switch/-/switch-1.0.3.tgz", - "integrity": "sha512-Jgi+EbOBquje/XNdofr7xbJQZPYJP+BlPfR0h+WN4zFkdtB2EWqEfvkXJWeipflwjWip0/17rNbxEAqs8hVHfw==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/table": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@rc-component/table/-/table-1.10.0.tgz", - "integrity": "sha512-SjtpcCf+rL7dDc62GKT3rXTdERjVuJvRiqjpU7g0Jc/ewCifXynHc7Nm3Em1XsD+WhGrgQtxNDScI/0+Lpfr0w==", - "license": "MIT", - "dependencies": { - "@rc-component/context": "^2.0.1", - "@rc-component/resize-observer": "^1.0.0", - "@rc-component/util": "^1.1.0", - "@rc-component/virtual-list": "^1.0.1", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/tabs": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/tabs/-/tabs-1.9.0.tgz", - "integrity": "sha512-tn1slmbbaTyt8mgwyWJcT8jo/qNiYUs6u1H7OgGQt9faYO06BJIkU5cTmMqORzIrNmSEeeUY6pD5i+JlqSHYhg==", - "license": "MIT", - "dependencies": { - "@rc-component/dropdown": "~1.0.0", - "@rc-component/menu": "~1.3.0", - "@rc-component/motion": "^1.1.3", - "@rc-component/resize-observer": "^1.0.0", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/tooltip": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@rc-component/tooltip/-/tooltip-1.4.0.tgz", - "integrity": "sha512-8Rx5DCctIlLI4raR0I0xHjVTf1aF48+gKCNeAAo5bmF5VoR5YED+A/XEqzXv9KKqrJDRcd3Wndpxh2hyzrTtSg==", - "license": "MIT", - "dependencies": { - "@rc-component/trigger": "^3.7.1", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/tour": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-2.4.0.tgz", - "integrity": "sha512-aui4r4TqmTzwaBgcQxHYep8kM8PTjZFufjokObpy35KfFeZ0k9ArquWFZqegQlH24P14t+F0qO0mGTgzlav1yg==", - "license": "MIT", - "dependencies": { - "@rc-component/portal": "^2.2.0", - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.7.0", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/tree": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@rc-component/tree/-/tree-1.3.1.tgz", - "integrity": "sha512-zlL0PW0bTFlveTtLcA01VD/yMWKK73EywItFMgIZUY5sb6tMOAw7zV6qGzqldufqrV93ZWQB4H3NBNoTMCueJA==", - "license": "MIT", - "dependencies": { - "@rc-component/motion": "^1.0.0", - "@rc-component/util": "^1.8.1", - "@rc-component/virtual-list": "^1.0.1", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=10.x" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/@rc-component/tree-select": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/tree-select/-/tree-select-1.9.0.tgz", - "integrity": "sha512-GXcFe15a+trUl1/J3OHWQhsVWFpwFpGFK2cqYWZ1sK22Zs3KZTvMwDpzr75PIo1s6QVioVxpE/pRwRopkeDQ6w==", - "license": "MIT", - "dependencies": { - "@rc-component/select": "~1.6.0", - "@rc-component/tree": "~1.3.0", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/@rc-component/trigger": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-3.9.0.tgz", - "integrity": "sha512-X8btpwfrT27AgrZVOz4swclhEHTZcqaHeQMXXBgveagOiakTa36uObXbdwerXffgV8G9dH1fAAE0DHtVQs8EHg==", - "license": "MIT", - "dependencies": { - "@rc-component/motion": "^1.1.4", - "@rc-component/portal": "^2.2.0", - "@rc-component/resize-observer": "^1.1.1", - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/upload": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/upload/-/upload-1.1.0.tgz", - "integrity": "sha512-LIBV90mAnUE6VK5N4QvForoxZc4XqEYZimcp7fk+lkE4XwHHyJWxpIXQQwMU8hJM+YwBbsoZkGksL1sISWHQxw==", - "license": "MIT", - "dependencies": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/util": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@rc-component/util/-/util-1.11.1.tgz", - "integrity": "sha512-awVlI3ub2vqfqkYxOBc/uQ0efm3jw0wcrhtO/YWLyZfxiKXczKwNbVuhlnyxytDt7H9pbbVQiqr+O6MLATtRYg==", - "license": "MIT", - "dependencies": { - "is-mobile": "^5.0.0", - "react-is": "^18.2.0" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, - "node_modules/@rc-component/virtual-list": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/virtual-list/-/virtual-list-1.1.0.tgz", - "integrity": "sha512-fSzVg8xFDCK+xKJJ9lljBpaGDmur4REZwXHJjsNFRi4UbfOXuH/FSbGC2oliCE5krFqM3lSZqB4Ly4vc3xQHOQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.20.0", - "@rc-component/resize-observer": "^1.0.1", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, "node_modules/@reduxjs/toolkit": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz", @@ -3344,69 +2559,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/antd": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/antd/-/antd-6.4.3.tgz", - "integrity": "sha512-6H2avkxCGfxcF67r3J2mwm9Ck50el1pks/73vfM1wDsPL/tPtj5vHuauMgJFnrqmq7CH3g8aoZ0VBQbt+jpAsw==", - "license": "MIT", - "dependencies": { - "@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" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ant-design" - }, - "peerDependencies": { - "react": ">=18.0.0", - "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", @@ -3572,12 +2724,6 @@ "node": ">= 0.8" } }, - "node_modules/compute-scroll-into-view": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", - "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", - "license": "MIT" - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -3617,6 +2763,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, "license": "MIT" }, "node_modules/d3-array": { @@ -4512,12 +3659,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-mobile": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-5.0.0.tgz", - "integrity": "sha512-Tz/yndySvLAEXh+Uk8liFCxOwVH6YutuR74utvOcu7I9Di+DwM0mtdPVZNaVvvBUM2OXxne/NhOs1zAO7riusQ==", - "license": "MIT" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4574,15 +3715,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json2mq": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", - "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", - "license": "MIT", - "dependencies": { - "string-convert": "^0.2.0" - } - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -5083,6 +4215,53 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", + "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.61.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", + "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/postcss": { "version": "8.5.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", @@ -5208,7 +4387,8 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-redux": { "version": "9.3.0", @@ -5427,15 +4607,6 @@ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, - "node_modules/scroll-into-view-if-needed": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", - "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", - "license": "MIT", - "dependencies": { - "compute-scroll-into-view": "^3.0.2" - } - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -5493,18 +4664,6 @@ "node": ">=0.10.0" } }, - "node_modules/string-convert": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", - "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", - "license": "MIT" - }, - "node_modules/stylis": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", - "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", @@ -5531,15 +4690,6 @@ "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", - "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", - "license": "MIT", - "engines": { - "node": ">=12.22" - } - }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -5937,59 +5087,6 @@ } }, "dependencies": { - "@ant-design/colors": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-8.0.1.tgz", - "integrity": "sha512-foPVl0+SWIslGUtD/xBr1p9U4AKzPhNYEseXYRRo5QSzGACYZrQbe11AYJbYfAWnWSpGBx6JjBmSeugUsD9vqQ==", - "requires": { - "@ant-design/fast-color": "^3.0.0" - } - }, - "@ant-design/cssinjs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-2.1.2.tgz", - "integrity": "sha512-2Hy8BnCEH31xPeSLbhhB2ctCPXE2ZnASdi+KbSeS79BNbUhL9hAEe20SkUk+BR8aKTmqb6+FKFruk7w8z0VoRQ==", - "requires": { - "@babel/runtime": "^7.11.1", - "@emotion/hash": "^0.8.0", - "@emotion/unitless": "^0.7.5", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1", - "csstype": "^3.1.3", - "stylis": "^4.3.4" - } - }, - "@ant-design/cssinjs-utils": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-2.1.2.tgz", - "integrity": "sha512-5fTHQ158jJJ5dC/ECeyIdZUzKxE/mpEMRZxthyG1sw/AKRHKgJBg00Yi6ACVXgycdje7KahRNvNET/uBccwCnA==", - "requires": { - "@ant-design/cssinjs": "^2.1.2", - "@babel/runtime": "^7.23.2", - "@rc-component/util": "^1.4.0" - } - }, - "@ant-design/fast-color": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-3.0.1.tgz", - "integrity": "sha512-esKJegpW4nckh0o6kV3Tkb7NPIZYbPnnFxmQDUmL08ukXZAvV85TZBr70eGuke/CIArLaP6aw8lt9KILjnWuOw==" - }, - "@ant-design/icons-svg": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", - "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==" - }, - "@ant-design/react-slick": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-2.0.0.tgz", - "integrity": "sha512-HMS9sRoEmZey8LsE/Yo6+klhlzU12PisjrVcydW3So7RdklyEd2qehyU6a7Yp+OYN72mgsYs3NFCyP2lCPFVqg==", - "requires": { - "@babel/runtime": "^7.28.4", - "clsx": "^2.1.1", - "json2mq": "^0.2.0", - "throttle-debounce": "^5.0.0" - } - }, "@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -6189,16 +5286,6 @@ "tslib": "^2.4.0" } }, - "@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" - }, - "@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" - }, "@eslint-community/eslint-utils": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", @@ -6401,6 +5488,15 @@ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz", "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==" }, + "@playwright/test": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.1.tgz", + "integrity": "sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==", + "dev": true, + "requires": { + "playwright": "1.61.1" + } + }, "@radix-ui/number": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.2.tgz", @@ -6789,429 +5885,6 @@ "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", - "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.1.0.tgz", - "integrity": "sha512-n4HcR5siNUXRX23nDizbZBQPO0ZM/5oTtmKZ6/eqL0L2bo747cklFdZGRN2f+c9qWGICwDzrhW0H7tE9PptdcA==", - "requires": { - "@babel/runtime": "^7.24.4" - } - }, - "@rc-component/cascader": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@rc-component/cascader/-/cascader-1.15.0.tgz", - "integrity": "sha512-ZzpMtwFCRo3fbXHuDnncARJMZQjdqA2w7aDuPofNQt+aDx39st1hgfIpEwTBLhe2Hqsvs/zOr8RTtgxTkCPySw==", - "requires": { - "@rc-component/select": "~1.6.0", - "@rc-component/tree": "~1.3.0", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/checkbox": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@rc-component/checkbox/-/checkbox-2.0.0.tgz", - "integrity": "sha512-3CXGPpAR9gsPKeO2N78HAPOzU30UdemD6HGJoWVJOpa6WleaGB5kzZj3v6bdTZab31YuWgY/RxV3VKPctn0DwQ==", - "requires": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/collapse": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rc-component/collapse/-/collapse-1.2.0.tgz", - "integrity": "sha512-ZRYSKSS39qsFx93p26bde7JUZJshsUBEQRlRXPuJYlAiNX0vyYlF5TsAm8JZN3LcF8XvKikdzPbgAtXSbkLUkw==", - "requires": { - "@babel/runtime": "^7.10.1", - "@rc-component/motion": "^1.1.4", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/color-picker": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-3.1.1.tgz", - "integrity": "sha512-OHaCHLHszCegdXmIq2ZRIZBN/EtpT6Wm8SG/gpzLATHbVKc/avvuKi+zlOuk05FTWvgaMmpxAko44uRJ3M+2pg==", - "requires": { - "@ant-design/fast-color": "^3.0.1", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/context": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-2.0.1.tgz", - "integrity": "sha512-HyZbYm47s/YqtP6pKXNMjPEMaukyg7P0qVfgMLzr7YiFNMHbK2fKTAGzms9ykfGHSfyf75nBbgWw+hHkp+VImw==", - "requires": { - "@rc-component/util": "^1.3.0" - } - }, - "@rc-component/dialog": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/dialog/-/dialog-1.9.0.tgz", - "integrity": "sha512-zbAAogkg4kkKum79sLE6M+vq1jSAW25zdkafrahgcTP9t9S//SD634Znd1A4c8F2Gc12ZKnehGLsVaaOvZzD2A==", - "requires": { - "@rc-component/motion": "^1.1.3", - "@rc-component/portal": "^2.1.0", - "@rc-component/util": "^1.9.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/drawer": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@rc-component/drawer/-/drawer-1.4.2.tgz", - "integrity": "sha512-1ib+fZEp6FBu+YvcIktm+nCQ+Q+qIpwpoaJH6opGr4ofh2QMq+qdr5DLC4oCf5qf3pcWX9lUWPYX652k4ini8Q==", - "requires": { - "@rc-component/motion": "^1.1.4", - "@rc-component/portal": "^2.1.3", - "@rc-component/util": "^1.9.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/dropdown": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rc-component/dropdown/-/dropdown-1.0.2.tgz", - "integrity": "sha512-6PY2ecUSYhDPhkNHHb4wfeAya04WhpmUSKzdR60G+kMNVUCX2vjT/AgTS0Lz0I/K6xrPMJ3enQbwVpeN3sHCgg==", - "requires": { - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - } - }, - "@rc-component/form": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@rc-component/form/-/form-1.8.1.tgz", - "integrity": "sha512-8O7TB55Fi2mWIGvSnwZjk8jFqVNYyKDAswglwGShcbndxqzKz4cHwNtNaLjZlAeRge9wcB0LL8IWsC/Bl18raQ==", - "requires": { - "@rc-component/async-validator": "^5.1.0", - "@rc-component/util": "^1.6.2", - "clsx": "^2.1.1" - } - }, - "@rc-component/image": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/image/-/image-1.9.0.tgz", - "integrity": "sha512-khF7w7xkBH5B1bsBcI1FSUZdkyd1aqpl2eYyILCqCzzQH3XdfehGUaZTnptyaJJfs09/R5hv9jXWyazOMFIClQ==", - "requires": { - "@rc-component/motion": "^1.0.0", - "@rc-component/portal": "^2.1.2", - "@rc-component/util": "^1.10.1", - "clsx": "^2.1.1" - } - }, - "@rc-component/input": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@rc-component/input/-/input-1.3.0.tgz", - "integrity": "sha512-IUUNOdAuWuEvDEFFgfmwQl818tiDbvXwLgon4HL1q2hJeYkqrRrYwYhJN0zfPHGTDxs3gvyVC/C02D4hWFoIcA==", - "requires": { - "@rc-component/resize-observer": "^1.1.1", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/input-number": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@rc-component/input-number/-/input-number-1.6.2.tgz", - "integrity": "sha512-Gjcq7meZlCOiWN1t1xCC+7/s85humHVokTBI7PJgTfoyw5OWF74y3e6P8PHX104g9+b54jsodFIzyaj6p8LI9w==", - "requires": { - "@rc-component/mini-decimal": "^1.0.1", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/mentions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/mentions/-/mentions-1.9.0.tgz", - "integrity": "sha512-WUwfFKDSOF5S9UPsNsXcLYtzjTxBGsftTXWRbZuxX6BYrsySISTnujfJNgaaQ6qVzaCDJ35QUkZKvsYxip1C5g==", - "requires": { - "@rc-component/input": "~1.3.0", - "@rc-component/menu": "~1.3.0", - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/menu": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@rc-component/menu/-/menu-1.3.0.tgz", - "integrity": "sha512-u3NfiwpiEgT177qa5Yxm5QsI8i/93EBGpWj8HYZQDnh2pCZ2xtQCe/+w3pSR2NlwKOZDTCKzEhEyD09mGphssA==", - "requires": { - "@rc-component/motion": "^1.1.4", - "@rc-component/overflow": "^1.0.0", - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/mini-decimal": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.3.tgz", - "integrity": "sha512-bk/FJ09fLf+NLODMAFll6CfYrHPBioTedhW6lxDBuuWucJEqFUd4l/D/5JgIi3dina6sYahB8iuPAZTNz2pMxw==", - "requires": { - "@babel/runtime": "^7.18.0" - } - }, - "@rc-component/motion": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@rc-component/motion/-/motion-1.3.2.tgz", - "integrity": "sha512-itfd+GztzJYAb04Z4RkEub1TbJAfZc2Iuy8p44U44xD1F5+fNYFKI3897ijlbIyfvXkTmMm+KGcjkQQGMHywEQ==", - "requires": { - "@rc-component/util": "^1.2.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/mutate-observer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-2.0.1.tgz", - "integrity": "sha512-AyarjoLU5YlxuValRi+w8JRH2Z84TBbFO2RoGWz9d8bSu0FqT8DtugH3xC3BV7mUwlmROFauyWuXFuq4IFbH+w==", - "requires": { - "@rc-component/util": "^1.2.0" - } - }, - "@rc-component/notification": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rc-component/notification/-/notification-2.0.7.tgz", - "integrity": "sha512-nqZzpf6BPdaj+3ILx7si79LLmqPKyUmQoXa+/9gg0SkH0v1DbD66oJgRMSBEVnd/zUT3D4gwxWIHUKebYf2ZXQ==", - "requires": { - "@rc-component/motion": "^1.1.4", - "@rc-component/util": "^1.11.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/overflow": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/overflow/-/overflow-1.0.1.tgz", - "integrity": "sha512-syfmgAABaHCnCDzPwHZ/2tuvIcpOO3jefYZMmfkN+pmo8HKTzsfhS57vxo4ksPdN0By+uWVJhJWNFozNBxi2eA==", - "requires": { - "@babel/runtime": "^7.11.1", - "@rc-component/resize-observer": "^1.0.1", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/pagination": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rc-component/pagination/-/pagination-1.2.0.tgz", - "integrity": "sha512-YcpUFE8dMLfSo6OARJlK6DbHHvrxz7pMGPGmC/caZSJJz6HRKHC1RPP001PRHCvG9Z/veD039uOQmazVuLJzlw==", - "requires": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/picker": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@rc-component/picker/-/picker-1.10.0.tgz", - "integrity": "sha512-vVOXP2RVWozwpERGUFAehVH1Jz6o/uRrAb9qSZm1LC+iJs8rvEwFo1bzz2jlOYV+uWwu0dIuG86tnDui14Ea0w==", - "requires": { - "@rc-component/overflow": "^1.0.0", - "@rc-component/resize-observer": "^1.0.0", - "@rc-component/trigger": "^3.6.15", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/portal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-2.2.0.tgz", - "integrity": "sha512-oc6FlA+uXCMiwArHsJyHcIkX4q6uKyndrPol2eWX8YPkAnztHOPsFIRtmWG4BMlGE5h7YIRE3NiaJ5VS8Lb1QQ==", - "requires": { - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - } - }, - "@rc-component/progress": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rc-component/progress/-/progress-1.0.2.tgz", - "integrity": "sha512-WZUnH9eGxH1+xodZKqdrHke59uyGZSWgj5HBM5Kwk5BrTMuAORO7VJ2IP5Qbm9aH3n9x3IcesqHHR0NWPBC7fQ==", - "requires": { - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - } - }, - "@rc-component/qrcode": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.1.1.tgz", - "integrity": "sha512-LfLGNymzKdUPjXUbRP+xOhIWY4jQ+YMj5MmWAcgcAq1Ij8XP7tRmAXqyuv96XvLUBE/5cA8hLFl9eO1JQMujrA==", - "requires": { - "@babel/runtime": "^7.24.7" - } - }, - "@rc-component/rate": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/rate/-/rate-1.0.1.tgz", - "integrity": "sha512-bkXxeBqDpl5IOC7yL7GcSYjQx9G8H+6kLYQnNZWeBYq2OYIv1MONd6mqKTjnnJYpV0cQIU2z3atdW0j1kttpTw==", - "requires": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/resize-observer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@rc-component/resize-observer/-/resize-observer-1.1.2.tgz", - "integrity": "sha512-t/Bb0W8uvL4PYKAB3YcChC+DlHh0Wt5kM7q/J+0qpVEUMLe7Hk5zuvc9km0hMnTFPSx5Z7Wu/fzCLN6erVLE8Q==", - "requires": { - "@rc-component/util": "^1.2.0" - } - }, - "@rc-component/segmented": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@rc-component/segmented/-/segmented-1.3.0.tgz", - "integrity": "sha512-5J/bJ01mbDnoA6P/FW8SxUvKn+OgUSTZJPzCNnTBntG50tzoP7DydGhqxp7ggZXZls7me3mc2EQDXakU3iTVFg==", - "requires": { - "@babel/runtime": "^7.11.1", - "@rc-component/motion": "^1.1.4", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/select": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@rc-component/select/-/select-1.6.15.tgz", - "integrity": "sha512-SyVCWnqxCQZZcQvQJ/CxSjx2bGma6ds/HtnpkIfZVnt6RoEgbqUmHgD6vrzNarNXwbLXerwVzWwq8F3d1sst7g==", - "requires": { - "@rc-component/overflow": "^1.0.0", - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.3.0", - "@rc-component/virtual-list": "^1.0.1", - "clsx": "^2.1.1" - } - }, - "@rc-component/slider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/slider/-/slider-1.0.1.tgz", - "integrity": "sha512-uDhEPU1z3WDfCJhaL9jfd2ha/Eqpdfxsn0Zb0Xcq1NGQAman0TWaR37OWp2vVXEOdV2y0njSILTMpTfPV1454g==", - "requires": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/steps": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rc-component/steps/-/steps-1.2.2.tgz", - "integrity": "sha512-/yVIZ00gDYYPHSY0JP+M+s3ZvuXLu2f9rEjQqiUDs7EcYsUYrpJ/1bLj9aI9R7MBR3fu/NGh6RM9u2qGfqp+Nw==", - "requires": { - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - } - }, - "@rc-component/switch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rc-component/switch/-/switch-1.0.3.tgz", - "integrity": "sha512-Jgi+EbOBquje/XNdofr7xbJQZPYJP+BlPfR0h+WN4zFkdtB2EWqEfvkXJWeipflwjWip0/17rNbxEAqs8hVHfw==", - "requires": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/table": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@rc-component/table/-/table-1.10.0.tgz", - "integrity": "sha512-SjtpcCf+rL7dDc62GKT3rXTdERjVuJvRiqjpU7g0Jc/ewCifXynHc7Nm3Em1XsD+WhGrgQtxNDScI/0+Lpfr0w==", - "requires": { - "@rc-component/context": "^2.0.1", - "@rc-component/resize-observer": "^1.0.0", - "@rc-component/util": "^1.1.0", - "@rc-component/virtual-list": "^1.0.1", - "clsx": "^2.1.1" - } - }, - "@rc-component/tabs": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/tabs/-/tabs-1.9.0.tgz", - "integrity": "sha512-tn1slmbbaTyt8mgwyWJcT8jo/qNiYUs6u1H7OgGQt9faYO06BJIkU5cTmMqORzIrNmSEeeUY6pD5i+JlqSHYhg==", - "requires": { - "@rc-component/dropdown": "~1.0.0", - "@rc-component/menu": "~1.3.0", - "@rc-component/motion": "^1.1.3", - "@rc-component/resize-observer": "^1.0.0", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/tooltip": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@rc-component/tooltip/-/tooltip-1.4.0.tgz", - "integrity": "sha512-8Rx5DCctIlLI4raR0I0xHjVTf1aF48+gKCNeAAo5bmF5VoR5YED+A/XEqzXv9KKqrJDRcd3Wndpxh2hyzrTtSg==", - "requires": { - "@rc-component/trigger": "^3.7.1", - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/tour": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-2.4.0.tgz", - "integrity": "sha512-aui4r4TqmTzwaBgcQxHYep8kM8PTjZFufjokObpy35KfFeZ0k9ArquWFZqegQlH24P14t+F0qO0mGTgzlav1yg==", - "requires": { - "@rc-component/portal": "^2.2.0", - "@rc-component/trigger": "^3.0.0", - "@rc-component/util": "^1.7.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/tree": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@rc-component/tree/-/tree-1.3.1.tgz", - "integrity": "sha512-zlL0PW0bTFlveTtLcA01VD/yMWKK73EywItFMgIZUY5sb6tMOAw7zV6qGzqldufqrV93ZWQB4H3NBNoTMCueJA==", - "requires": { - "@rc-component/motion": "^1.0.0", - "@rc-component/util": "^1.8.1", - "@rc-component/virtual-list": "^1.0.1", - "clsx": "^2.1.1" - } - }, - "@rc-component/tree-select": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/tree-select/-/tree-select-1.9.0.tgz", - "integrity": "sha512-GXcFe15a+trUl1/J3OHWQhsVWFpwFpGFK2cqYWZ1sK22Zs3KZTvMwDpzr75PIo1s6QVioVxpE/pRwRopkeDQ6w==", - "requires": { - "@rc-component/select": "~1.6.0", - "@rc-component/tree": "~1.3.0", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/trigger": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-3.9.0.tgz", - "integrity": "sha512-X8btpwfrT27AgrZVOz4swclhEHTZcqaHeQMXXBgveagOiakTa36uObXbdwerXffgV8G9dH1fAAE0DHtVQs8EHg==", - "requires": { - "@rc-component/motion": "^1.1.4", - "@rc-component/portal": "^2.2.0", - "@rc-component/resize-observer": "^1.1.1", - "@rc-component/util": "^1.2.1", - "clsx": "^2.1.1" - } - }, - "@rc-component/upload": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/upload/-/upload-1.1.0.tgz", - "integrity": "sha512-LIBV90mAnUE6VK5N4QvForoxZc4XqEYZimcp7fk+lkE4XwHHyJWxpIXQQwMU8hJM+YwBbsoZkGksL1sISWHQxw==", - "requires": { - "@rc-component/util": "^1.3.0", - "clsx": "^2.1.1" - } - }, - "@rc-component/util": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@rc-component/util/-/util-1.11.1.tgz", - "integrity": "sha512-awVlI3ub2vqfqkYxOBc/uQ0efm3jw0wcrhtO/YWLyZfxiKXczKwNbVuhlnyxytDt7H9pbbVQiqr+O6MLATtRYg==", - "requires": { - "is-mobile": "^5.0.0", - "react-is": "^18.2.0" - } - }, - "@rc-component/virtual-list": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/virtual-list/-/virtual-list-1.1.0.tgz", - "integrity": "sha512-fSzVg8xFDCK+xKJJ9lljBpaGDmur4REZwXHJjsNFRi4UbfOXuH/FSbGC2oliCE5krFqM3lSZqB4Ly4vc3xQHOQ==", - "requires": { - "@babel/runtime": "^7.20.0", - "@rc-component/resize-observer": "^1.0.1", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1" - } - }, "@reduxjs/toolkit": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz", @@ -7917,11 +6590,6 @@ "delayed-stream": "~1.0.0" } }, - "compute-scroll-into-view": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", - "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==" - }, "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -7947,7 +6615,8 @@ "csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true }, "d3-array": { "version": "3.2.4", @@ -8503,11 +7172,6 @@ "is-extglob": "^2.1.1" } }, - "is-mobile": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-5.0.0.tgz", - "integrity": "sha512-Tz/yndySvLAEXh+Uk8liFCxOwVH6YutuR74utvOcu7I9Di+DwM0mtdPVZNaVvvBUM2OXxne/NhOs1zAO7riusQ==" - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -8549,14 +7213,6 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "json2mq": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", - "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", - "requires": { - "string-convert": "^0.2.0" - } - }, "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -8802,6 +7458,31 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==" }, + "playwright": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", + "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.61.1" + }, + "dependencies": { + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + } + } + }, + "playwright-core": { + "version": "1.61.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", + "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", + "dev": true + }, "postcss": { "version": "8.5.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", @@ -8861,7 +7542,8 @@ "react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "peer": true }, "react-redux": { "version": "9.3.0", @@ -8982,14 +7664,6 @@ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==" }, - "scroll-into-view-if-needed": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", - "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", - "requires": { - "compute-scroll-into-view": "^3.0.2" - } - }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -9027,16 +7701,6 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" }, - "string-convert": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", - "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" - }, - "stylis": { - "version": "4.4.0", - "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", @@ -9052,11 +7716,6 @@ "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", - "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==" - }, "tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", diff --git a/package.json b/package.json index f3b15c3..5be9b4e 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,9 @@ "build": "tsc -b && vite build", "build:ift": "npm run build", "lint": "eslint .", - "preview": "vite preview" + "preview": "vite preview", + "test:e2e": "playwright test --project=mock", + "test:e2e:ift": "E2E_TARGET=ift playwright test --project=ift-smoke" }, "dependencies": { "@hookform/resolvers": "^5.2.2", @@ -48,6 +50,7 @@ }, "devDependencies": { "@eslint/js": "^10.0.1", + "@playwright/test": "^1.61.1", "@types/node": "^24.12.4", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..19eeb74 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,45 @@ +import { defineConfig, devices } from '@playwright/test'; + +const port = Number(process.env.E2E_PORT || 4173); +const baseURL = process.env.E2E_BASE_URL || `http://127.0.0.1:${port}`; + +export default defineConfig({ + testDir: './e2e/tests', + fullyParallel: false, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 1 : 0, + workers: 1, + reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list', + timeout: 90_000, + expect: { timeout: 10_000 }, + use: { + baseURL, + trace: 'on-first-retry', + locale: 'ru-RU', + }, + projects: [ + { + name: 'mock', + use: { ...devices['Desktop Chrome'] }, + testIgnore: /ift\//, + }, + { + name: 'ift-smoke', + use: { + ...devices['Desktop Chrome'], + baseURL: process.env.E2E_IFT_BASE_URL || 'https://admin-ui.ift.eventhub.local', + ignoreHTTPSErrors: true, + }, + testMatch: /ift\//, + }, + ], + webServer: + process.env.E2E_TARGET === 'ift' + ? undefined + : { + command: `npm run preview -- --host 127.0.0.1 --port ${port}`, + url: baseURL, + reuseExistingServer: !process.env.CI, + timeout: 120_000, + }, +}); diff --git a/src/components/CommandPalette.tsx b/src/components/CommandPalette.tsx index a1a1d44..83a5483 100644 --- a/src/components/CommandPalette.tsx +++ b/src/components/CommandPalette.tsx @@ -121,11 +121,16 @@ export function CommandPalette({ open, onOpenChange }: CommandPaletteProps) { return ( - + {t('layout.paletteTitle')}
setQuery(e.target.value)} diff --git a/src/layouts/ControlCenterLayout.tsx b/src/layouts/ControlCenterLayout.tsx index d0be9ce..3ab0e48 100644 --- a/src/layouts/ControlCenterLayout.tsx +++ b/src/layouts/ControlCenterLayout.tsx @@ -36,6 +36,7 @@ import { } from '@/config/adminAccess'; import { notify } from '@/lib/notify'; import { cn } from '@/lib/utils'; +import { testid } from '@/lib/testid'; import { getTableDensity, toggleTableDensity, type TableDensity } from '@/lib/density'; import { Button } from '@/components/ui/button'; import { ScrollArea } from '@/components/ui/scroll-area'; @@ -76,6 +77,10 @@ const navIconByKey: Record> '/monitoring': Activity, }; +function navTestId(path: string): string { + return testid(['nav', ...path.split('/').filter(Boolean)]); +} + function NavLinkItem({ item, active, collapsed }: { item: NavItem; active: boolean; collapsed: boolean }) { const { t } = useTranslation(); const Icon = navIconByKey[item.key] ?? LayoutDashboard; @@ -83,6 +88,7 @@ function NavLinkItem({ item, active, collapsed }: { item: NavItem; active: boole return ( { const initials = displayName.slice(0, 2).toUpperCase(); return ( -
+
- + {t('layout.logout')} diff --git a/src/lib/testid.ts b/src/lib/testid.ts new file mode 100644 index 0000000..a7d80e7 --- /dev/null +++ b/src/lib/testid.ts @@ -0,0 +1,7 @@ +/** Build stable data-testid values for E2E. */ +export function testid(parts: Array): string { + return parts + .filter((p) => p !== undefined && p !== null && `${p}`.length > 0) + .map((p) => String(p).replace(/\s+/g, '-')) + .join('-'); +} diff --git a/src/pages/auth/LoginPage.tsx b/src/pages/auth/LoginPage.tsx index 4feb143..3cfd70b 100644 --- a/src/pages/auth/LoginPage.tsx +++ b/src/pages/auth/LoginPage.tsx @@ -44,7 +44,7 @@ const LoginPage: React.FC = () => { }; return ( -
+
{

{errors.password.message}

)}
- diff --git a/src/pages/dashboard/DashboardPage.tsx b/src/pages/dashboard/DashboardPage.tsx index 39f2390..f6e802a 100644 --- a/src/pages/dashboard/DashboardPage.tsx +++ b/src/pages/dashboard/DashboardPage.tsx @@ -66,7 +66,7 @@ const DashboardPage: React.FC = () => { if (isLoading) { return ( -
+
{Array.from({ length: 4 }).map((_, i) => ( @@ -90,7 +90,7 @@ const DashboardPage: React.FC = () => { if (role === 'moderator') { return ( -
+

{t('dashboard.moderation')}

{t('dashboard.subtitleModeration')}

@@ -121,7 +121,7 @@ const DashboardPage: React.FC = () => { if (role === 'support') { return ( -
+

{t('dashboard.support')}

{t('dashboard.subtitleSupport')}

@@ -155,7 +155,7 @@ const DashboardPage: React.FC = () => { const eventsSparkline = data.events_by_day?.map((item) => ({ date: item.date, value: item.count })) ?? []; return ( -
+

{t('dashboard.controlCenter')}

{t('dashboard.subtitleAdmin')}

diff --git a/src/pages/errors/ForbiddenPage.tsx b/src/pages/errors/ForbiddenPage.tsx index df667a2..2f7de0a 100644 --- a/src/pages/errors/ForbiddenPage.tsx +++ b/src/pages/errors/ForbiddenPage.tsx @@ -14,7 +14,7 @@ const ForbiddenPage: React.FC = () => { const sectionLabel = sectionItem ? t(sectionItem.label) : t('common.notFound'); return ( -
+
{t('errors.forbiddenTitle')} @@ -23,7 +23,9 @@ const ForbiddenPage: React.FC = () => { - +