From 131ecdbbe62c531cb6693a212ba08b9da77538de Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Wed, 27 May 2026 21:34:12 +0330 Subject: [PATCH] feat(dashboard): Next.js 16 merchant panel with offline POS and PWA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complete merchant dashboard upgrade: Next.js 16 compatibility: - Fix params/searchParams typed as Promise<{}> throughout App Router - Replace middleware.ts with proxy.ts (Next.js 16 convention) - Remove unused @ts-expect-error directives caught by stricter TS - Cast dynamic next-intl t() keys to fix TranslateArgs type errors Offline POS: - IndexedDB queue (meezi_pos_offline) for orders created while offline - Zustand sync store tracking queueCount, isSyncing, isOnline - useOfflineSync hook: auto-syncs on reconnect/visibility-change - SyncStatusIndicator chip in topbar (amber=offline, blue=syncing) - submitOrderToApi falls back to local order on network failure - Local orders skip payment flow; sync on reconnect PWA (installable): - @ducanh2912/next-pwa with Workbox runtime caching rules - Web App Manifest (manifest.ts) — RTL/Farsi, theme #0F6E56 - PWA icons: 192px, 512px, maskable 512px - next.config.ts replaces next.config.mjs Co-Authored-By: Claude Sonnet 4.5 --- web/dashboard/.env.example | 8 + web/dashboard/.eslintrc.json | 3 + web/dashboard/.gitignore | 7 + web/dashboard/README.md | 29 + web/dashboard/e2e/api-health.spec.ts | 28 + web/dashboard/e2e/discover-public.spec.ts | 10 + web/dashboard/messages/ar.json | 1392 +++ web/dashboard/messages/en.json | 1519 +++ web/dashboard/messages/fa.json | 1520 +++ web/dashboard/next.config.ts | 72 + web/dashboard/package-lock.json | 9265 +++++++++++++++++ web/dashboard/package.json | 50 + web/dashboard/playwright.config.ts | 29 + web/dashboard/postcss.config.mjs | 9 + web/dashboard/public/.gitkeep | 1 + web/dashboard/public/icons/icon-192.png | Bin 0 -> 547 bytes web/dashboard/public/icons/icon-512.png | Bin 0 -> 1881 bytes .../public/icons/icon-maskable-512.png | Bin 0 -> 1881 bytes .../[locale]/(dashboard)/branches/page.tsx | 5 + .../app/[locale]/(dashboard)/coupons/page.tsx | 5 + .../src/app/[locale]/(dashboard)/crm/page.tsx | 5 + .../[locale]/(dashboard)/expenses/page.tsx | 5 + .../src/app/[locale]/(dashboard)/hr/page.tsx | 5 + .../[locale]/(dashboard)/inventory/page.tsx | 7 + .../src/app/[locale]/(dashboard)/kds/page.tsx | 5 + .../src/app/[locale]/(dashboard)/layout.tsx | 59 + .../app/[locale]/(dashboard)/menu/page.tsx | 5 + .../(dashboard)/notifications/page.tsx | 5 + .../src/app/[locale]/(dashboard)/page.tsx | 5 + .../src/app/[locale]/(dashboard)/pos/page.tsx | 13 + .../app/[locale]/(dashboard)/queue/page.tsx | 5 + .../app/[locale]/(dashboard)/reports/page.tsx | 5 + .../(dashboard)/reservations/page.tsx | 5 + .../app/[locale]/(dashboard)/reviews/page.tsx | 5 + .../[locale]/(dashboard)/settings/page.tsx | 10 + .../app/[locale]/(dashboard)/shifts/page.tsx | 5 + .../src/app/[locale]/(dashboard)/sms/page.tsx | 5 + .../(dashboard)/subscription/page.tsx | 10 + .../(dashboard)/support/[ticketId]/page.tsx | 5 + .../app/[locale]/(dashboard)/support/page.tsx | 5 + .../app/[locale]/(dashboard)/tables/page.tsx | 5 + .../app/[locale]/(dashboard)/taxes/page.tsx | 5 + .../src/app/[locale]/(fullscreen)/layout.tsx | 25 + .../(fullscreen)/queue/display/page.tsx | 10 + .../(public)/discover/[slug]/page.tsx | 10 + .../app/[locale]/(public)/discover/page.tsx | 5 + .../src/app/[locale]/(public)/layout.tsx | 6 + web/dashboard/src/app/[locale]/layout.tsx | 61 + web/dashboard/src/app/[locale]/login/page.tsx | 144 + web/dashboard/src/app/[locale]/page.tsx | 10 + web/dashboard/src/app/globals.css | 253 + web/dashboard/src/app/layout.tsx | 7 + web/dashboard/src/app/manifest.ts | 46 + web/dashboard/src/app/q/[code]/page.tsx | 11 + web/dashboard/src/app/q/error.tsx | 29 + web/dashboard/src/app/q/layout.tsx | 27 + .../components/branches/branches-screen.tsx | 420 + .../src/components/coupons/coupons-screen.tsx | 142 + .../src/components/crm/crm-screen.tsx | 132 + .../src/components/crm/customer-wizard.tsx | 363 + .../discover/cafe-discover-profile-editor.tsx | 187 + .../discover/cafe-discover-profile-panel.tsx | 144 + .../discover/cafe-public-profile-panel.tsx | 347 + .../discover/coffee-advisor-panel.tsx | 108 + .../discover/public-cafe-detail-screen.tsx | 337 + .../discover/public-discover-screen.tsx | 521 + .../components/expenses/expenses-screen.tsx | 358 + web/dashboard/src/components/hr/hr-screen.tsx | 228 + .../components/inventory/inventory-screen.tsx | 655 ++ .../inventory/inventory-unit-field.tsx | 55 + .../src/components/kds/kds-screen.tsx | 209 + .../layout/branch-filter-select.tsx | 52 + .../src/components/layout/branch-select.tsx | 46 + .../layout/header-center-cluster.tsx | 111 + .../src/components/layout/page-header.tsx | 32 + .../src/components/layout/sidebar.tsx | 277 + .../layout/sync-status-indicator.tsx | 102 + .../src/components/layout/topbar.tsx | 105 + .../layout/trial-countdown-banner.tsx | 146 + .../components/media/media-pair-upload.tsx | 115 + .../src/components/media/menu-3d-upload.tsx | 80 + .../components/media/menu-ai-3d-generate.tsx | 128 + .../components/menu/branch-menu-overrides.tsx | 235 + .../components/menu/category-emoji-picker.tsx | 48 + .../components/menu/category-media-fields.tsx | 180 + .../components/menu/category-preset-icon.tsx | 167 + .../menu/category-preset-picker.tsx | 126 + .../src/components/menu/category-visual.tsx | 91 + .../src/components/menu/menu-admin-screen.tsx | 571 + .../src/components/menu/menu-item-labels.tsx | 54 + .../src/components/menu/menu-item-media.tsx | 76 + .../menu/menu-item-model-viewer.tsx | 41 + .../notifications/notification-center.tsx | 111 + .../notifications/notification-ui.tsx | 124 + .../notifications/notifications-screen.tsx | 108 + .../overview/overview-mini-chart.tsx | 76 + .../components/overview/overview-screen.tsx | 408 + .../src/components/placeholder-page.tsx | 15 + .../components/pos/pos-customer-picker.tsx | 314 + .../src/components/pos/pos-pay-panel.tsx | 632 ++ .../src/components/pos/pos-queue-bar.tsx | 72 + .../src/components/pos/pos-receipt-modal.tsx | 2 + .../src/components/pos/pos-receipt-print.css | 44 + .../src/components/pos/pos-screen.tsx | 1211 +++ .../src/components/pos/pos-slip-modal.tsx | 167 + .../src/components/pos/pos-table-board.tsx | 290 + web/dashboard/src/components/providers.tsx | 26 + .../components/providers/confirm-provider.tsx | 114 + .../src/components/qr/qr-guest-menu-body.tsx | 880 ++ .../src/components/qr/qr-guest-menu.tsx | 723 ++ .../src/components/qr/qr-menu-3d-sheet.tsx | 73 + .../src/components/qr/qr-order-track.tsx | 141 + .../src/components/qr/qr-turnstile.tsx | 94 + .../components/queue/queue-display-screen.tsx | 90 + .../src/components/queue/queue-screen.tsx | 177 + .../reports/reports-charts-fallback.tsx | 52 + .../src/components/reports/reports-charts.tsx | 212 + .../reports/reports-charts.types.ts | 22 + .../src/components/reports/reports-screen.tsx | 444 + .../reservations/reservations-screen.tsx | 257 + .../src/components/reviews/reviews-screen.tsx | 161 + .../settings/guest-menu-template-preview.tsx | 173 + .../components/settings/plan-comparison.tsx | 474 + .../settings/settings-appearance-panel.tsx | 439 + .../src/components/settings/settings-nav.tsx | 89 + .../settings/settings-print-test-panel.tsx | 183 + .../settings/settings-printer-panel.tsx | 270 + .../components/settings/settings-screen.tsx | 105 + .../settings/settings-shop-panel.tsx | 208 + .../settings/settings-terminals-panel.tsx | 78 + .../src/components/settings/settings-types.ts | 40 + .../src/components/shifts/shifts-screen.tsx | 189 + .../src/components/sms/sms-screen.tsx | 106 + .../subscription/subscription-screen.tsx | 228 + .../src/components/support/support-screen.tsx | 253 + .../support/ticket-status-badge.tsx | 67 + .../src/components/tables/tables-screen.tsx | 538 + .../src/components/taxes/taxes-screen.tsx | 173 + .../components/theme/cafe-theme-provider.tsx | 18 + .../src/components/ui/alert-dialog.tsx | 116 + web/dashboard/src/components/ui/alert.tsx | 75 + web/dashboard/src/components/ui/badge.tsx | 25 + web/dashboard/src/components/ui/button.tsx | 48 + web/dashboard/src/components/ui/card.tsx | 33 + .../src/components/ui/dropdown-menu.tsx | 48 + web/dashboard/src/components/ui/input.tsx | 19 + web/dashboard/src/components/ui/label.tsx | 22 + .../src/components/ui/labeled-field.tsx | 23 + .../src/components/ui/meezi-toaster.tsx | 116 + web/dashboard/src/components/ui/skeleton.tsx | 11 + web/dashboard/src/fonts/Inter-Variable.woff2 | Bin 0 -> 352240 bytes .../src/fonts/Vazirmatn-Variable.woff2 | Bin 0 -> 111152 bytes web/dashboard/src/i18n/request.ts | 14 + web/dashboard/src/i18n/routing.ts | 10 + web/dashboard/src/lib/api/admin-client.ts | 87 + web/dashboard/src/lib/api/admin-types.ts | 143 + web/dashboard/src/lib/api/branch-menu.ts | 57 + web/dashboard/src/lib/api/branch-tables.ts | 134 + .../src/lib/api/cafe-public-profile.ts | 57 + web/dashboard/src/lib/api/client.ts | 183 + web/dashboard/src/lib/api/download.ts | 2 + web/dashboard/src/lib/api/notifications.ts | 41 + web/dashboard/src/lib/api/pos-device.ts | 33 + web/dashboard/src/lib/api/print.ts | 26 + web/dashboard/src/lib/api/public-discover.ts | 153 + web/dashboard/src/lib/api/qr-public.ts | 176 + web/dashboard/src/lib/api/types.ts | 202 + web/dashboard/src/lib/auth-permissions.ts | 38 + .../src/lib/cafe-discover-profile.ts | 65 + web/dashboard/src/lib/cafe-theme.ts | 548 + .../src/lib/category-emoji-presets.ts | 56 + .../src/lib/category-icon-presets.ts | 247 + web/dashboard/src/lib/format-datetime.ts | 30 + web/dashboard/src/lib/format.ts | 7 + web/dashboard/src/lib/guest-order-storage.ts | 57 + .../src/lib/hooks/use-cafe-settings.ts | 39 + web/dashboard/src/lib/hooks/use-live-clock.ts | 14 + .../src/lib/hooks/use-notifications-feed.ts | 107 + .../src/lib/hooks/use-online-status.ts | 23 + web/dashboard/src/lib/inventory-units.ts | 20 + web/dashboard/src/lib/menu-3d.ts | 10 + web/dashboard/src/lib/menu-display.ts | 58 + web/dashboard/src/lib/menu-item-image.ts | 52 + web/dashboard/src/lib/notify.ts | 56 + web/dashboard/src/lib/offline/offline-db.ts | 111 + .../src/lib/offline/use-offline-sync.ts | 111 + web/dashboard/src/lib/order-number.ts | 16 + web/dashboard/src/lib/phone.ts | 28 + .../src/lib/pos-confirm-pay-label.ts | 23 + web/dashboard/src/lib/pos-order-label.ts | 17 + web/dashboard/src/lib/pos/submit-order.ts | 191 + web/dashboard/src/lib/qr-menu-constants.ts | 2 + web/dashboard/src/lib/qr-menu-texture.ts | 34 + web/dashboard/src/lib/reports/analytics.ts | 258 + web/dashboard/src/lib/sidebar-nav.ts | 134 + .../src/lib/stores/admin-auth.store.ts | 34 + web/dashboard/src/lib/stores/auth.store.ts | 44 + web/dashboard/src/lib/stores/branch.store.ts | 17 + web/dashboard/src/lib/stores/cart.store.ts | 209 + .../src/lib/stores/sync-queue.store.ts | 28 + web/dashboard/src/lib/terminal.ts | 11 + web/dashboard/src/lib/use-is-rtl.ts | 8 + web/dashboard/src/lib/utils.ts | 6 + web/dashboard/src/lib/utils/otp.ts | 19 + web/dashboard/src/proxy.ts | 8 + web/dashboard/tailwind.config.ts | 49 + web/dashboard/tsconfig.json | 39 + web/dashboard/tsconfig.typecheck.json | 5 + 208 files changed, 37123 insertions(+) create mode 100644 web/dashboard/.env.example create mode 100644 web/dashboard/.eslintrc.json create mode 100644 web/dashboard/.gitignore create mode 100644 web/dashboard/README.md create mode 100644 web/dashboard/e2e/api-health.spec.ts create mode 100644 web/dashboard/e2e/discover-public.spec.ts create mode 100644 web/dashboard/messages/ar.json create mode 100644 web/dashboard/messages/en.json create mode 100644 web/dashboard/messages/fa.json create mode 100644 web/dashboard/next.config.ts create mode 100644 web/dashboard/package-lock.json create mode 100644 web/dashboard/package.json create mode 100644 web/dashboard/playwright.config.ts create mode 100644 web/dashboard/postcss.config.mjs create mode 100644 web/dashboard/public/.gitkeep create mode 100644 web/dashboard/public/icons/icon-192.png create mode 100644 web/dashboard/public/icons/icon-512.png create mode 100644 web/dashboard/public/icons/icon-maskable-512.png create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/branches/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/coupons/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/crm/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/expenses/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/hr/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/inventory/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/kds/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/layout.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/menu/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/notifications/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/pos/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/queue/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/reports/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/reservations/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/reviews/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/settings/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/shifts/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/sms/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/subscription/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/support/[ticketId]/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/support/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/tables/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(dashboard)/taxes/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(fullscreen)/layout.tsx create mode 100644 web/dashboard/src/app/[locale]/(fullscreen)/queue/display/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(public)/discover/[slug]/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(public)/discover/page.tsx create mode 100644 web/dashboard/src/app/[locale]/(public)/layout.tsx create mode 100644 web/dashboard/src/app/[locale]/layout.tsx create mode 100644 web/dashboard/src/app/[locale]/login/page.tsx create mode 100644 web/dashboard/src/app/[locale]/page.tsx create mode 100644 web/dashboard/src/app/globals.css create mode 100644 web/dashboard/src/app/layout.tsx create mode 100644 web/dashboard/src/app/manifest.ts create mode 100644 web/dashboard/src/app/q/[code]/page.tsx create mode 100644 web/dashboard/src/app/q/error.tsx create mode 100644 web/dashboard/src/app/q/layout.tsx create mode 100644 web/dashboard/src/components/branches/branches-screen.tsx create mode 100644 web/dashboard/src/components/coupons/coupons-screen.tsx create mode 100644 web/dashboard/src/components/crm/crm-screen.tsx create mode 100644 web/dashboard/src/components/crm/customer-wizard.tsx create mode 100644 web/dashboard/src/components/discover/cafe-discover-profile-editor.tsx create mode 100644 web/dashboard/src/components/discover/cafe-discover-profile-panel.tsx create mode 100644 web/dashboard/src/components/discover/cafe-public-profile-panel.tsx create mode 100644 web/dashboard/src/components/discover/coffee-advisor-panel.tsx create mode 100644 web/dashboard/src/components/discover/public-cafe-detail-screen.tsx create mode 100644 web/dashboard/src/components/discover/public-discover-screen.tsx create mode 100644 web/dashboard/src/components/expenses/expenses-screen.tsx create mode 100644 web/dashboard/src/components/hr/hr-screen.tsx create mode 100644 web/dashboard/src/components/inventory/inventory-screen.tsx create mode 100644 web/dashboard/src/components/inventory/inventory-unit-field.tsx create mode 100644 web/dashboard/src/components/kds/kds-screen.tsx create mode 100644 web/dashboard/src/components/layout/branch-filter-select.tsx create mode 100644 web/dashboard/src/components/layout/branch-select.tsx create mode 100644 web/dashboard/src/components/layout/header-center-cluster.tsx create mode 100644 web/dashboard/src/components/layout/page-header.tsx create mode 100644 web/dashboard/src/components/layout/sidebar.tsx create mode 100644 web/dashboard/src/components/layout/sync-status-indicator.tsx create mode 100644 web/dashboard/src/components/layout/topbar.tsx create mode 100644 web/dashboard/src/components/layout/trial-countdown-banner.tsx create mode 100644 web/dashboard/src/components/media/media-pair-upload.tsx create mode 100644 web/dashboard/src/components/media/menu-3d-upload.tsx create mode 100644 web/dashboard/src/components/media/menu-ai-3d-generate.tsx create mode 100644 web/dashboard/src/components/menu/branch-menu-overrides.tsx create mode 100644 web/dashboard/src/components/menu/category-emoji-picker.tsx create mode 100644 web/dashboard/src/components/menu/category-media-fields.tsx create mode 100644 web/dashboard/src/components/menu/category-preset-icon.tsx create mode 100644 web/dashboard/src/components/menu/category-preset-picker.tsx create mode 100644 web/dashboard/src/components/menu/category-visual.tsx create mode 100644 web/dashboard/src/components/menu/menu-admin-screen.tsx create mode 100644 web/dashboard/src/components/menu/menu-item-labels.tsx create mode 100644 web/dashboard/src/components/menu/menu-item-media.tsx create mode 100644 web/dashboard/src/components/menu/menu-item-model-viewer.tsx create mode 100644 web/dashboard/src/components/notifications/notification-center.tsx create mode 100644 web/dashboard/src/components/notifications/notification-ui.tsx create mode 100644 web/dashboard/src/components/notifications/notifications-screen.tsx create mode 100644 web/dashboard/src/components/overview/overview-mini-chart.tsx create mode 100644 web/dashboard/src/components/overview/overview-screen.tsx create mode 100644 web/dashboard/src/components/placeholder-page.tsx create mode 100644 web/dashboard/src/components/pos/pos-customer-picker.tsx create mode 100644 web/dashboard/src/components/pos/pos-pay-panel.tsx create mode 100644 web/dashboard/src/components/pos/pos-queue-bar.tsx create mode 100644 web/dashboard/src/components/pos/pos-receipt-modal.tsx create mode 100644 web/dashboard/src/components/pos/pos-receipt-print.css create mode 100644 web/dashboard/src/components/pos/pos-screen.tsx create mode 100644 web/dashboard/src/components/pos/pos-slip-modal.tsx create mode 100644 web/dashboard/src/components/pos/pos-table-board.tsx create mode 100644 web/dashboard/src/components/providers.tsx create mode 100644 web/dashboard/src/components/providers/confirm-provider.tsx create mode 100644 web/dashboard/src/components/qr/qr-guest-menu-body.tsx create mode 100644 web/dashboard/src/components/qr/qr-guest-menu.tsx create mode 100644 web/dashboard/src/components/qr/qr-menu-3d-sheet.tsx create mode 100644 web/dashboard/src/components/qr/qr-order-track.tsx create mode 100644 web/dashboard/src/components/qr/qr-turnstile.tsx create mode 100644 web/dashboard/src/components/queue/queue-display-screen.tsx create mode 100644 web/dashboard/src/components/queue/queue-screen.tsx create mode 100644 web/dashboard/src/components/reports/reports-charts-fallback.tsx create mode 100644 web/dashboard/src/components/reports/reports-charts.tsx create mode 100644 web/dashboard/src/components/reports/reports-charts.types.ts create mode 100644 web/dashboard/src/components/reports/reports-screen.tsx create mode 100644 web/dashboard/src/components/reservations/reservations-screen.tsx create mode 100644 web/dashboard/src/components/reviews/reviews-screen.tsx create mode 100644 web/dashboard/src/components/settings/guest-menu-template-preview.tsx create mode 100644 web/dashboard/src/components/settings/plan-comparison.tsx create mode 100644 web/dashboard/src/components/settings/settings-appearance-panel.tsx create mode 100644 web/dashboard/src/components/settings/settings-nav.tsx create mode 100644 web/dashboard/src/components/settings/settings-print-test-panel.tsx create mode 100644 web/dashboard/src/components/settings/settings-printer-panel.tsx create mode 100644 web/dashboard/src/components/settings/settings-screen.tsx create mode 100644 web/dashboard/src/components/settings/settings-shop-panel.tsx create mode 100644 web/dashboard/src/components/settings/settings-terminals-panel.tsx create mode 100644 web/dashboard/src/components/settings/settings-types.ts create mode 100644 web/dashboard/src/components/shifts/shifts-screen.tsx create mode 100644 web/dashboard/src/components/sms/sms-screen.tsx create mode 100644 web/dashboard/src/components/subscription/subscription-screen.tsx create mode 100644 web/dashboard/src/components/support/support-screen.tsx create mode 100644 web/dashboard/src/components/support/ticket-status-badge.tsx create mode 100644 web/dashboard/src/components/tables/tables-screen.tsx create mode 100644 web/dashboard/src/components/taxes/taxes-screen.tsx create mode 100644 web/dashboard/src/components/theme/cafe-theme-provider.tsx create mode 100644 web/dashboard/src/components/ui/alert-dialog.tsx create mode 100644 web/dashboard/src/components/ui/alert.tsx create mode 100644 web/dashboard/src/components/ui/badge.tsx create mode 100644 web/dashboard/src/components/ui/button.tsx create mode 100644 web/dashboard/src/components/ui/card.tsx create mode 100644 web/dashboard/src/components/ui/dropdown-menu.tsx create mode 100644 web/dashboard/src/components/ui/input.tsx create mode 100644 web/dashboard/src/components/ui/label.tsx create mode 100644 web/dashboard/src/components/ui/labeled-field.tsx create mode 100644 web/dashboard/src/components/ui/meezi-toaster.tsx create mode 100644 web/dashboard/src/components/ui/skeleton.tsx create mode 100644 web/dashboard/src/fonts/Inter-Variable.woff2 create mode 100644 web/dashboard/src/fonts/Vazirmatn-Variable.woff2 create mode 100644 web/dashboard/src/i18n/request.ts create mode 100644 web/dashboard/src/i18n/routing.ts create mode 100644 web/dashboard/src/lib/api/admin-client.ts create mode 100644 web/dashboard/src/lib/api/admin-types.ts create mode 100644 web/dashboard/src/lib/api/branch-menu.ts create mode 100644 web/dashboard/src/lib/api/branch-tables.ts create mode 100644 web/dashboard/src/lib/api/cafe-public-profile.ts create mode 100644 web/dashboard/src/lib/api/client.ts create mode 100644 web/dashboard/src/lib/api/download.ts create mode 100644 web/dashboard/src/lib/api/notifications.ts create mode 100644 web/dashboard/src/lib/api/pos-device.ts create mode 100644 web/dashboard/src/lib/api/print.ts create mode 100644 web/dashboard/src/lib/api/public-discover.ts create mode 100644 web/dashboard/src/lib/api/qr-public.ts create mode 100644 web/dashboard/src/lib/api/types.ts create mode 100644 web/dashboard/src/lib/auth-permissions.ts create mode 100644 web/dashboard/src/lib/cafe-discover-profile.ts create mode 100644 web/dashboard/src/lib/cafe-theme.ts create mode 100644 web/dashboard/src/lib/category-emoji-presets.ts create mode 100644 web/dashboard/src/lib/category-icon-presets.ts create mode 100644 web/dashboard/src/lib/format-datetime.ts create mode 100644 web/dashboard/src/lib/format.ts create mode 100644 web/dashboard/src/lib/guest-order-storage.ts create mode 100644 web/dashboard/src/lib/hooks/use-cafe-settings.ts create mode 100644 web/dashboard/src/lib/hooks/use-live-clock.ts create mode 100644 web/dashboard/src/lib/hooks/use-notifications-feed.ts create mode 100644 web/dashboard/src/lib/hooks/use-online-status.ts create mode 100644 web/dashboard/src/lib/inventory-units.ts create mode 100644 web/dashboard/src/lib/menu-3d.ts create mode 100644 web/dashboard/src/lib/menu-display.ts create mode 100644 web/dashboard/src/lib/menu-item-image.ts create mode 100644 web/dashboard/src/lib/notify.ts create mode 100644 web/dashboard/src/lib/offline/offline-db.ts create mode 100644 web/dashboard/src/lib/offline/use-offline-sync.ts create mode 100644 web/dashboard/src/lib/order-number.ts create mode 100644 web/dashboard/src/lib/phone.ts create mode 100644 web/dashboard/src/lib/pos-confirm-pay-label.ts create mode 100644 web/dashboard/src/lib/pos-order-label.ts create mode 100644 web/dashboard/src/lib/pos/submit-order.ts create mode 100644 web/dashboard/src/lib/qr-menu-constants.ts create mode 100644 web/dashboard/src/lib/qr-menu-texture.ts create mode 100644 web/dashboard/src/lib/reports/analytics.ts create mode 100644 web/dashboard/src/lib/sidebar-nav.ts create mode 100644 web/dashboard/src/lib/stores/admin-auth.store.ts create mode 100644 web/dashboard/src/lib/stores/auth.store.ts create mode 100644 web/dashboard/src/lib/stores/branch.store.ts create mode 100644 web/dashboard/src/lib/stores/cart.store.ts create mode 100644 web/dashboard/src/lib/stores/sync-queue.store.ts create mode 100644 web/dashboard/src/lib/terminal.ts create mode 100644 web/dashboard/src/lib/use-is-rtl.ts create mode 100644 web/dashboard/src/lib/utils.ts create mode 100644 web/dashboard/src/lib/utils/otp.ts create mode 100644 web/dashboard/src/proxy.ts create mode 100644 web/dashboard/tailwind.config.ts create mode 100644 web/dashboard/tsconfig.json create mode 100644 web/dashboard/tsconfig.typecheck.json diff --git a/web/dashboard/.env.example b/web/dashboard/.env.example new file mode 100644 index 0000000..806cdef --- /dev/null +++ b/web/dashboard/.env.example @@ -0,0 +1,8 @@ +# Local dotnet run (HTTPS) +# Merchant API (POS / dashboard café features) +# NEXT_PUBLIC_API_URL=https://localhost:7208 +# Platform admin API (run Meezi.Admin.API — default https://localhost:7210) +# NEXT_PUBLIC_ADMIN_API_URL=https://localhost:7210 + +# Docker Compose (HTTP, default API_PORT=5080) +NEXT_PUBLIC_API_URL=http://localhost:5080 diff --git a/web/dashboard/.eslintrc.json b/web/dashboard/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/web/dashboard/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/web/dashboard/.gitignore b/web/dashboard/.gitignore new file mode 100644 index 0000000..2467142 --- /dev/null +++ b/web/dashboard/.gitignore @@ -0,0 +1,7 @@ +node_modules +.next +out +.env +.env.local +*.tsbuildinfo +next-env.d.ts diff --git a/web/dashboard/README.md b/web/dashboard/README.md new file mode 100644 index 0000000..ed15252 --- /dev/null +++ b/web/dashboard/README.md @@ -0,0 +1,29 @@ +# Meezi Dashboard + +Next.js 14 POS dashboard for Meezi (میزی). + +## Setup + +```bash +cd web/dashboard +npm install +cp .env.example .env.local +npm run dev +``` + +Open [http://localhost:3000/fa/login](http://localhost:3000/fa/login) + +Ensure the API is running at `NEXT_PUBLIC_API_URL` (default `https://localhost:7208`). + +## Demo login + +- Phone: `09121234567` +- OTP: check API console log (`DEV OTP for ...`) when Kavenegar is not configured + +## Features (Sprint 4) + +- i18n: `fa` (default, RTL), `ar` (RTL), `en` (LTR) +- Dashboard layout with RTL-aware sidebar +- POS screen: menu grid + cart + order submit +- KDS screen: live orders + SignalR + status advance +- Placeholder pages for upcoming modules diff --git a/web/dashboard/e2e/api-health.spec.ts b/web/dashboard/e2e/api-health.spec.ts new file mode 100644 index 0000000..9b53448 --- /dev/null +++ b/web/dashboard/e2e/api-health.spec.ts @@ -0,0 +1,28 @@ +import { test, expect } from "@playwright/test"; + +const apiURL = process.env.PLAYWRIGHT_API_URL ?? "http://localhost:5080"; + +test.describe("API health", () => { + test("GET /health returns 200", async ({ request }) => { + const res = await request.get(`${apiURL}/health`); + expect(res.ok()).toBeTruthy(); + const body = await res.json(); + expect(body.status).toBe("healthy"); + }); + + test("GET /api/public/security-config", async ({ request }) => { + const res = await request.get(`${apiURL}/api/public/security-config`); + expect(res.ok()).toBeTruthy(); + const json = await res.json(); + expect(json.success).toBe(true); + expect(json.data).toBeDefined(); + }); + + test("GET /api/public/discover returns list", async ({ request }) => { + const res = await request.get(`${apiURL}/api/public/discover?city=تهران`); + expect(res.ok()).toBeTruthy(); + const json = await res.json(); + expect(json.success).toBe(true); + expect(Array.isArray(json.data)).toBe(true); + }); +}); diff --git a/web/dashboard/e2e/discover-public.spec.ts b/web/dashboard/e2e/discover-public.spec.ts new file mode 100644 index 0000000..68ae796 --- /dev/null +++ b/web/dashboard/e2e/discover-public.spec.ts @@ -0,0 +1,10 @@ +import { test, expect } from "@playwright/test"; + +test.describe("Public discover", () => { + test("discover page loads", async ({ page }) => { + await page.goto("/fa/discover"); + await expect(page.getByRole("heading", { name: /کافه‌یاب|Discover cafés/i })).toBeVisible({ + timeout: 15_000, + }); + }); +}); diff --git a/web/dashboard/messages/ar.json b/web/dashboard/messages/ar.json new file mode 100644 index 0000000..621a063 --- /dev/null +++ b/web/dashboard/messages/ar.json @@ -0,0 +1,1392 @@ +{ + "common": { + "save": "حفظ", + "cancel": "إلغاء", + "confirm": "تأكيد", + "delete": "حذف", + "search": "بحث", + "loading": "جاري التحميل...", + "logout": "تسجيل الخروج", + "language": "اللغة", + "comingSoon": "قريباً", + "edit": "تعديل" + }, + "confirm": { + "title": "تأكيد الإجراء", + "confirm": "تأكيد", + "cancel": "إلغاء" + }, + "notify": { + "saved": "تم الحفظ", + "errorGeneric": "حدث خطأ. حاول مرة أخرى." + }, + "brand": { + "name": "ميزي" + }, + "languages": { + "fa": "فارسی", + "ar": "العربية", + "en": "English" + }, + "auth": { + "title": "تسجيل الدخول إلى ميزي", + "subtitle": "سيتم إرسال رمز التحقق إلى هاتفك", + "phone": "رقم الجوال", + "phonePlaceholder": "٠٩١٢١٢٣٤٥٦٧", + "sendOtp": "إرسال الرمز", + "otp": "رمز التحقق", + "otpPlaceholder": "٦ أرقام", + "verify": "دخول", + "resend": "إعادة الإرسال", + "rateLimited": "طلبات الرمز كثيرة جداً. انتظر ساعة كحد أقصى أو تواصل مع الدعم.", + "notFound": "لا يوجد حساب بهذا الرقم.", + "smsFailed": "فشل إرسال الرسالة. حاول مرة أخرى.", + "invalidOtp": "رمز التحقق غير صحيح أو منتهٍ." + }, + "nav": { + "aria": "القائمة الرئيسية", + "groups": { + "operations": "العمليات اليومية", + "menuSales": "القائمة والمبيعات", + "customers": "العملاء", + "finance": "التقارير والمالية", + "management": "إدارة المقهى" + }, + "pos": "نقطة البيع", + "tables": "الطاولات", + "menu": "القائمة", + "crm": "العملاء", + "coupons": "القسائم", + "inventory": "المخزون", + "hr": "الموارد البشرية", + "reports": "التقارير", + "expenses": "المصروفات", + "reviews": "التقييمات", + "reservations": "الحجوزات", + "sms": "رسائل", + "taxes": "الضرائب", + "branches": "الفروع", + "subscription": "الاشتراك والخطة", + "support": "الدعم", + "settings": "الإعدادات", + "kds": "المطبخ", + "notifications": "الإشعارات", + "queue": "الدور اليومي", + "discover": "اكتشف المقاهي" + }, + "dashboard": { + "cafeName": "مقهى تجريبي", + "planPro": "برو", + "online": "متصل", + "offline": "غير متصل", + "activePlan": "الخطة النشطة", + "editCafeSettings": "إعدادات المقهى", + "viewSubscription": "الاشتراك والخطة" + }, + "overview": { + "title": "الرئيسية", + "greeting": "أهلاً بك", + "todayRevenue": "مبيعات اليوم", + "todayOrders": "طلبات اليوم", + "netIncome": "صافي الدخل", + "avgOrder": "متوسط الطلب", + "revenueChart": "اتجاه المبيعات ٧ أيام", + "tableStatus": "حالة الطاولات", + "tableFree": "فارغة", + "tableBusy": "مشغولة", + "tableCleaning": "تنظيف", + "tableTotal": "إجمالي الطاولات", + "topProducts": "الأكثر مبيعاً", + "vsYesterday": "مقارنة بالأمس", + "noData": "لا توجد بيانات", + "quickLinks": "وصول سريع", + "unit": "قطعة" + }, + "pos": { + "order": "طلب", + "table": "طاولة", + "total": "المجموع", + "subtotal": "المجموع الفرعي", + "tax": "الضريبة", + "discount": "خصم", + "confirmOrder": "تأكيد ودفع", + "modeOrder": "أخذ الطلب", + "modePay": "الدفع", + "takeOrder": "تسجيل الطلب", + "submitOrder": "حفظ الطلب", + "submitOrderAndPay": "حفظ الطلب والدفع", + "orderPaidNew": "تم حفظ الطلب والدفع", + "orderPaidAdd": "تمت إضافة الأصناف والدفع", + "posDeviceSent": "تم إرسال المبلغ إلى جهاز نقطة البيع", + "posDeviceError": "فشل الإرسال إلى جهاز نقطة البيع", + "posDeviceNotConfigured": "جهاز نقطة البيع غير مُعد — سُجّل الدفع في النظام فقط", + "posDeviceConnectionFailed": "تعذّر الاتصال بجهاز نقطة البيع", + "posDeviceTimeout": "انتهت مهلة جهاز نقطة البيع", + "posDeviceRejected": "رفض جهاز نقطة البيع الدفع", + "posDeviceNoBranch": "لم يُحدد فرع لإرسال الدفع إلى نقطة البيع", + "kitchenSlip": "تذكرة المطبخ (معاينة وطباعة)", + "orderPlaced": "تم حفظ الطلب — انتقل إلى الدفع لتحصيل المبلغ", + "guestName": "اسم الضيف", + "guestNamePlaceholder": "مثلاً علي", + "needTableOrName": "اختر طاولة أو عميلاً أو اسم ضيف", + "openOrders": "طلبات مفتوحة", + "openOrdersHint": "طلبات لم تُدفع بعد", + "noOpenOrders": "لا توجد طلبات بانتظار الدفع", + "payOrder": "الدفع", + "payFor": "الدفع لـ", + "selectOrderToPay": "اختر طلباً من القائمة", + "confirmPay": "تحصيل", + "confirmPayCash": "تحصيل (نقداً)", + "confirmPayCard": "تحصيل (بطاقة)", + "confirmPayCredit": "تحصيل (آجل)", + "confirmPaySplit": "تحصيل (مختلط)", + "previewBill": "معاينة وطباعة الفاتورة", + "paySuccess": "تم تسجيل الدفع", + "payError": "فشل الدفع", + "payNeedsOpenShift": "افتح وردية الصندوق لهذا الفرع قبل التحصيل", + "cancelOrder": "إلغاء الطلب (بدون دفع)", + "cancelOrderConfirm": "غادر العميل دون دفع؟ سيُلغى الطلب ويُحرَّر الطاولة.", + "cancelOrderSuccess": "تم إلغاء الطلب", + "cancelOrderError": "تعذّر إلغاء الطلب", + "itemsCount": "صنف", + "applyCoupon": "تطبيق القسيمة", + "couponPlaceholder": "رمز القسيمة", + "couponCode": "رمز القسيمة", + "selectTable": "الطاولة", + "emptyCart": "السلة فارغة", + "cash": "نقد", + "card": "بطاقة", + "clearCart": "مسح", + "allCategories": "الكل", + "searchItems": "بحث عن صنف", + "searchItemsPlaceholder": "ابحث باسم الصنف…", + "searchNoResults": "لا توجد أصناف مطابقة", + "reservationBanner": "حجز: {name} — أضف الأصناف ثم اضغط تأكيد ودفع", + "orderSuccess": "تم تسجيل الطلب", + "orderError": "فشل تسجيل الطلب", + "orderInvalid": "طلب غير صالح (تحقق من القائمة أو الطاولة)", + "orderNotOpen": "هذا الطلب لم يعد مفتوحاً", + "orderValidation": "بيانات الطلب غير صالحة", + "nothingPending": "لا توجد أصناف جديدة للمطبخ", + "couponApplied": "تم تطبيق القسيمة «{code}» — خصم {amount}", + "couponActive": "قسيمة {code}", + "couponRemoved": "تمت إزالة القسيمة", + "removeCoupon": "إزالة", + "couponInvalid": "رمز القسيمة غير صالح", + "couponExpired": "انتهت صلاحية هذه القسيمة", + "couponNotStarted": "هذه القسيمة غير مفعّلة بعد", + "couponLimitReached": "وصلت القسيمة إلى حد الاستخدام", + "couponMinOrder": "الحد الأدنى للطلب غير مستوفى", + "couponCartEmpty": "أضف عناصر إلى السلة أولاً", + "couponRequired": "أدخل رمز القسيمة", + "guestPhone": "هاتف الضيف", + "guestPhonePlaceholder": "09121234567", + "selectTableBoard": "اختر الطاولة", + "loadingTables": "جاري تحميل الطاولات...", + "selectBranchForTables": "اختر الفرع أولاً", + "noTablesOnBoard": "لا توجد طاولات لهذا الفرع. أضف طاولات من شاشة الطاولات.", + "tablesLoadError": "تعذّر تحميل الطاولات", + "retryTables": "إعادة المحاولة", + "manageTablesLink": "الذهاب إلى الطاولات", + "sessionActive": "جلسة طاولة نشطة", + "addToOrder": "أُضيف إلى طلب الطاولة", + "void": "إلغاء", + "voidItem": "إلغاء الصنف", + "voided": "ملغى", + "confirmVoid": "هل أنت متأكد أنك تريد إلغاء هذا الصنف؟", + "voidError": "تعذر إلغاء الصنف", + "transferTable": "نقل الطاولة", + "selectTargetTable": "اختر الطاولة المستهدفة", + "transferSuccess": "تم نقل الطلب بنجاح", + "transferError": "تعذر نقل الطاولة", + "tableNotAvailable": "الطاولة قيد التنظيف", + "tableOccupied": "الطاولة مشغولة", + "searchOpenOrder": "طاولة، اسم، هاتف، أو معرف الطلب...", + "paidSoFar": "المدفوع", + "remaining": "المتبقي", + "loyaltyBalance": "نقاط العميل: {points}", + "loyaltyUseMax": "الحد الأقصى", + "loyaltyRedeemHint": "كل نقطة = ١٠٠ ت خصم على هذا الدفع", + "loyaltyRedeemApplied": "خصم النقاط", + "loyaltyNoCustomer": "اربط عميلاً بالطلب لاستخدام النقاط", + "loyaltyInsufficient": "نقاط غير كافية", + "splitPayments": "دفع مقسّم", + "addPaymentRow": "إضافة دفعة", + "credit": "ائتمان", + "paySelectTable": "اختر طاولة (مشغولة)", + "payPickByName": "أو من الاسم / قائمة الطلبات المفتوحة", + "payOpenOrdersHint": "اضغط طاولة مشغولة، أو من القائمة، أو ابحث بالاسم/الهاتف", + "allTables": "كل الطاولات", + "noOrderOnTable": "لا يوجد طلب مفتوح على هذه الطاولة", + "noOpenOrdersOnTable": "لا طلبات مفتوحة لهذه الطاولة", + "customerSection": "العميل", + "existingCustomer": "عميل مسجّل", + "newCustomer": "ضيف جديد", + "customerSearchPlaceholder": "الاسم، الهاتف، أو الرقم الوطني...", + "customerSearchHint": "اكتب حرفين على الأقل للبحث", + "customerNotFound": "لم يُعثر على عميل — أضف كضيف جديد", + "customerSaved": "تم حفظ العميل في CRM", + "customerSaveError": "تعذّر حفظ العميل", + "customerPhoneExists": "الهاتف مسجّل مسبقاً — ابحث واختر", + "newCustomerHint": "للطلب الحالي فقط، أو احفظ في CRM عبر «إضافة عميل»", + "offlineQueueNotice": "غير متصل — تم حفظ الطلب في الطابور وسيتم إرساله عند الاتصال" + }, + "print": { + "printReceipt": "طباعة الإيصال", + "printKitchen": "إرسال للمطبخ", + "success": "تمت طباعة الإيصال بنجاح", + "notConfigured": "لم يتم ضبط عنوان الطابعة", + "connectionFailed": "تعذر الاتصال بالطابعة", + "testPrint": "اختبار الطباعة", + "printerSettings": "إعدادات الطابعة", + "receiptPrinter": "طابعة الإيصال", + "kitchenPrinter": "طابعة المطبخ", + "paperWidth": "عرض الورق", + "autoCut": "قطع تلقائي", + "port": "المنفذ", + "receiptHeader": "ترويسة الإيصال", + "receiptFooter": "تذييل الإيصال", + "wifiOnReceipt": "كلمة WiFi على الإيصال", + "saveSettings": "حفظ الإعدادات", + "settingsSaved": "تم حفظ إعدادات الطابعة", + "noBranchForPrinter": "أضف فرعاً قبل إعداد الطابعات.", + "testPageHint": "يرسل إيصالاً تجريبياً إلى الطابعات المحفوظة. عيّن IP والمنفذ في إعدادات الطابعة أولاً.", + "testPrintReceipt": "اختبار طابعة الإيصال", + "testPrintKitchen": "اختبار طابعة المطبخ", + "configurePrinters": "فتح إعدادات الطابعة", + "posDeviceSection": "جهاز نقطة البيع (بطاقة)", + "posDeviceHint": "عند الدفع بالبطاقة، يُرسل المبلغ عبر HTTP (POST /pay) إلى الجهاز على الشبكة المحلية.", + "posDeviceIp": "عنوان IP لجهاز نقطة البيع" + }, + "receipt": { + "table": "الطاولة", + "order": "الطلب", + "guest": "الضيف", + "total": "الإجمالي", + "print": "طباعة", + "close": "إغلاق", + "thankYou": "شكراً على زيارتكم", + "kitchenTitle": "تذكرة المطبخ / البار", + "billTitle": "فاتورة العميل", + "kitchenFooter": "— للمطبخ —", + "payment": { + "cash": "نقداً", + "card": "بطاقة", + "credit": "رصيد" + } + }, + "crm": { + "title": "العملاء", + "searchPlaceholder": "الاسم، الجوال، أو الرقم الوطني...", + "addCustomer": "عميل جديد", + "name": "الاسم", + "phone": "الجوال", + "nationalId": "الرقم الوطني", + "birthDate": "تاريخ الميلاد (شمسي)", + "group": "المجموعة", + "loyaltyPoints": "النقاط", + "noCustomers": "لا يوجد عملاء", + "groups": { + "Regular": "عادي", + "Vip": "مميز", + "New": "جديد", + "Employee": "موظف" + }, + "wizard": { + "titleCreate": "إضافة عميل", + "titleEdit": "تعديل العميل", + "stepOf": "الخطوة {current} من {total}", + "steps": { + "contact": "التواصل", + "profile": "بيانات إضافية", + "loyalty": "المجموعة والنقاط", + "confirm": "مراجعة" + }, + "back": "السابق", + "next": "التالي", + "birthHint": "تنسيق شمسي، مثال 1400/01/01", + "referredBy": "المُحيل (اختياري)", + "loyaltyCreateHint": "يمكن تعديل نقاط الولاء بعد إنشاء العميل.", + "errors": { + "duplicatePhone": "رقم الجوال مسجل مسبقاً.", + "generic": "تعذر الحفظ. حاول مرة أخرى." + } + } + }, + "coupons": { + "title": "القسائم", + "addCoupon": "قسيمة جديدة", + "code": "الرمز", + "type": "النوع", + "value": "القيمة", + "usage": "الاستخدام", + "active": "نشط", + "inactive": "غير نشط", + "types": { + "Percentage": "نسبة", + "FixedAmount": "مبلغ ثابت", + "FreeItem": "عنصر مجاني" + }, + "noCoupons": "لا توجد قسائم" + }, + "hr": { + "title": "الموارد البشرية", + "tabs": { + "attendance": "الحضور", + "leave": "الإجازة", + "payroll": "الرواتب" + }, + "myAttendance": "حضوري", + "clockIn": "تسجيل دخول", + "clockOut": "تسجيل خروج", + "approve": "موافقة", + "noLeave": "لا توجد طلبات إجازة", + "paid": "مدفوع", + "markPaid": "تسجيل الدفع", + "employeeCount": "الموظفون", + "monthYear": "شهر الرواتب" + }, + "reviews": { + "title": "تقييمات العملاء", + "summary": "متوسط التقييم", + "reviewCount": "{count} تقييم", + "empty": "لا توجد تقييمات بعد.", + "ownerReply": "رد المقهى", + "reply": "رد", + "replyPlaceholder": "اكتب ردك..." + }, + "sms": { + "title": "التسويق عبر SMS", + "message": "الرسالة", + "messagePlaceholder": "اكتب نص الرسالة...", + "targetGroup": "المجموعة المستهدفة", + "allCustomers": "كل العملاء", + "send": "إرسال", + "usage": "الاستخدام هذا الشهر", + "unlimited": "غير محدود", + "sent": "تم الإرسال", + "failed": "فشل" + }, + "reports": { + "title": "التقارير والتحليلات", + "subtitle": "ملخص المبيعات من اللقطات اليومية", + "exportCsv": "تنزيل CSV", + "fromDate": "من تاريخ", + "toDate": "إلى تاريخ", + "branch": "الفرع", + "allBranches": "كل الفروع", + "preset": { + "7d": "٧ أيام", + "30d": "٣٠ يوماً", + "90d": "٩٠ يوماً" + }, + "kpiTotalRevenue": "إجمالي المبيعات", + "kpiTotalOrders": "عدد الطلبات", + "kpiAvgOrder": "متوسط الطلب", + "kpiNetIncome": "صافي الدخل", + "kpiTotalExpenses": "إجمالي المصروفات", + "vsPrevious": "مقارنة بالفترة السابقة", + "revenueChartTitle": "اتجاه الإيراد اليومي", + "paymentMixTitle": "طرق الدفع", + "branchCompareTitle": "مقارنة الفروع", + "topProductsTitle": "المنتجات الأكثر مبيعاً", + "colProduct": "المنتج", + "colQuantity": "الكمية", + "colRevenue": "الإيراد", + "revenue": "الإيراد", + "cash": "نقد", + "card": "بطاقة", + "credit": "ائتمان", + "noData": "لا توجد بيانات", + "loading": "جاري التحميل...", + "csvDate": "التاريخ", + "csvBranch": "الفرع", + "csvTotalRevenue": "إجمالي المبيعات", + "csvTotalOrders": "عدد الطلبات", + "csvAvgOrder": "متوسط الطلب", + "csvCash": "نقد", + "csvCard": "بطاقة", + "csvCredit": "ائتمان", + "csvNetIncome": "صافي الدخل", + "csvVoids": "الإلغاءات", + "csvVoidAmount": "مبلغ الإلغاء", + "csvExpenses": "المصروفات" + }, + "expenses": { + "title": "المصروفات", + "subtitle": "تسجيل ومتابعة مصروفات الفرع", + "addExpense": "تسجيل مصروف", + "listTitle": "سجل المصروفات", + "branch": "الفرع", + "fromDate": "من تاريخ", + "toDate": "إلى تاريخ", + "periodTotal": "مجموع الفترة", + "category": "الفئة", + "amount": "المبلغ", + "note": "ملاحظة", + "notePlaceholder": "اختياري", + "linkOpenShift": "خصم من الصندوق المفتوح (سحب نقدي)", + "noOpenShift": "لا يوجد صندوق مفتوح — يُسجَّل المصروف دون ربط بوردية", + "colDate": "التاريخ", + "colCategory": "الفئة", + "colNote": "ملاحظة", + "colAmount": "المبلغ", + "loading": "جاري التحميل...", + "empty": "لا توجد مصروفات", + "rowCount": "{count} صف", + "categories": { + "Supplies": "مستلزمات", + "Utilities": "مرافق", + "Salary": "رواتب", + "Rent": "إيجار", + "Maintenance": "صيانة", + "Other": "أخرى" + } + }, + "queue": { + "title": "نظام الدور اليومي", + "subtitle": "يبدأ الترقيم من ١ كل يوم (توقيت إيران)", + "nowServing": "الدور الحالي", + "lastIssued": "آخر رقم", + "waitingCount": "{count} في الانتظار", + "issueNext": "رقم جديد", + "callNext": "استدعاء التالي", + "customerLabelPlaceholder": "اسم الضيف (اختياري)", + "dailyResetHint": "تُصفَّر الأرقام عند منتصف الليل بتوقيت إيران.", + "empty": "لم يُصدر أي دور اليوم بعد.", + "issuedOnOrder": "الدور {number}", + "openDisplay": "شاشة TV", + "displayMode": "ملء الشاشة", + "exitDisplay": "العودة للوحة", + "displayWaitingLabel": "في الانتظار", + "displayUpNext": "التالي", + "status": { + "Waiting": "انتظار", + "Called": "مُستدعى", + "Done": "تم", + "Cancelled": "ملغى" + } + }, + "kds": { + "title": "شاشة المطبخ", + "pending": "قيد الانتظار", + "preparing": "قيد التحضير", + "ready": "جاهز", + "table": "طاولة", + "noOrders": "لا توجد طلبات", + "loading": "جاري التحميل...", + "live": "مباشر", + "polling": "تحديث دوري", + "advance": "المرحلة التالية", + "status": { + "Pending": "قيد الانتظار", + "Confirmed": "مؤكد", + "Preparing": "قيد التحضير", + "Ready": "جاهز", + "Delivered": "تم التسليم", + "Cancelled": "ملغى" + }, + "advanceTo": { + "Confirmed": "تأكيد الطلب", + "Preparing": "بدء التحضير", + "Ready": "جاهز", + "Delivered": "تم التسليم" + } + }, + "tables": { + "title": "إدارة الطاولات", + "addTable": "إضافة طاولة", + "number": "رقم الطاولة", + "capacity": "السعة", + "floor": "الطابق", + "floorPlan": "مخطط الصالة", + "empty": "لا توجد طاولات.", + "emptyBranch": "لا توجد طاولات لهذا الفرع.", + "allBranches": "كل الفروع", + "branchFilter": "تصفية الفرع", + "branch": "الفرع", + "branchUnassigned": "بدون فرع", + "branchHint": "الطاولات تخص المقهى؛ الفرع اختياري لنقطة البيع والتقارير.", + "tableLabel": "طاولة {number}", + "meta": "سعة {capacity} · طابق {floor}", + "status": { + "Free": "فارغ", + "Busy": "مشغول", + "Reserved": "محجوز", + "Cleaning": "تنظيف", + "free": "متاح", + "occupied": "مشغول", + "reserved": "محجوز", + "cleaning": "تنظيف" + }, + "markCleaning": "يحتاج تنظيف", + "markReady": "جاهز للضيوف", + "activeOrder": "طلب نشط", + "reserved": "محجوز", + "printQr": "طباعة QR", + "qrMenuUrl": "رابط قائمة الضيف", + "openQrUrl": "فتح", + "copyQrUrl": "نسخ الرابط", + "qrUrlCopied": "تم نسخ الرابط", + "qrUrlCopyFailed": "تعذر نسخ الرابط", + "reprintHint": "فقدت QR؟ نفس الزر — الكود ثابت.", + "deactivate": "تعطيل", + "inactive": "غير نشط", + "edit": "تعديل", + "editTable": "تعديل الطاولة", + "reactivate": "إعادة التفعيل", + "saveTable": "حفظ الطاولة", + "media": "صورة وفيديو الطاولة", + "section": "قسم", + "sections": "الأقسام", + "addSection": "إضافة قسم", + "noSection": "بدون قسم", + "noSectionsYet": "لم يتم تعريف أقسام بعد.", + "sectionTableCount": "{count} طاولة", + "sectionHasTables": "هذا القسم يحتوي على طاولات ولا يمكن حذفه", + "tableHasOpenOrder": "هذه الطاولة لديها طلب مفتوح", + "deleteTable": "حذف الطاولة", + "deleteTableConfirm": "حذف هذه الطاولة نهائياً؟ (فقط عندما لا يوجد طلب مفتوح)", + "deleteError": "تعذّر حذف الطاولة", + "createError": "تعذّر إضافة الطاولة", + "cleaningError": "تعذّر تحديث حالة التنظيف" + }, + "menuAdmin": { + "title": "إدارة القائمة", + "subtitle": "الصور والأسعار والخصومات لكل صنف", + "categories": "الفئات", + "items": "الأصناف", + "addCategory": "فئة جديدة", + "addItem": "إضافة", + "name": "الاسم", + "nameEn": "الاسم بالإنجليزية (للضيوف الدوليين)", + "price": "السعر", + "category": "الفئة", + "available": "متوفر", + "unavailable": "غير متوفر", + "discountPercent": "خصم (٪)", + "discountBadge": "خصم", + "uploadImage": "رفع صورة", + "imageReady": "الصورة جاهزة", + "empty": "لا أصناف بعد.", + "editItem": "تعديل", + "editCategory": "تعديل الفئة", + "categoryIcon": "أيقونة (إيموجي)", + "categoryImage": "صورة الفئة", + "iconTabPreset": "أيقونات جاهزة", + "iconTabEmoji": "إيموجي", + "iconTabImage": "رفع صورة", + "iconStyleLabel": "نمط التصميم", + "iconPreview": "معاينة:", + "clearIconPreset": "إزالة الأيقونة", + "clearIconEmoji": "إزالة الإيموجي", + "categoryIconCustom": "أو إيموجي مخصص", + "iconPresetGroupDrinks": "مشروبات", + "iconPresetGroupFood": "طعام", + "iconStyles": { + "flat": "مسطح", + "modern": "عصري", + "real": "واقعي", + "minimal": "بسيط", + "outline": "خطي", + "soft": "ناعم", + "bold": "غامق", + "gradient": "تدرج", + "pastel": "باستيل", + "duotone": "ثنائي اللون" + }, + "iconEmojiGroups": { + "hotDrinks": "مشروبات ساخنة", + "coldDrinks": "مشروبات باردة", + "breakfast": "فطور", + "mains": "أطباق رئيسية", + "pastaPizza": "معكرونة وبيتزا", + "desserts": "حلويات", + "salads": "سلطات", + "seafoodGrill": "مشويات وبحرية", + "snacks": "وجبات خفيفة", + "vegan": "نباتي", + "specials": "عروض خاصة", + "general": "عام" + }, + "iconPresets": { + "drinks-hot": "قهوة ساخنة", + "drinks-cold": "مشروبات باردة", + "drinks-tea": "شاي", + "drinks-juice": "عصير", + "drinks-milkshake": "حليب وسموذي", + "drinks-alcohol": "نبيذ", + "drinks-beer": "بيرة", + "breakfast": "فطور", + "food-mains": "أطباق رئيسية", + "food-fastfood": "وجبات سريعة", + "food-rice": "أرز", + "pasta-pizza": "معكرونة وبيتزا", + "dessert": "حلويات", + "ice-cream": "آيس كريم", + "bakery": "مخبوزات", + "salad": "سلطة", + "grill": "شواء", + "seafood": "مأكولات بحرية", + "snacks": "ساندويتش", + "snacks-sweet": "معجنات", + "appetizers": "مقبلات", + "vegan": "نباتي", + "fruits": "فواكه", + "specials": "خاص", + "chef-special": "اختيار الشيف", + "generic": "عام" + }, + "media": "صورة وفيديو", + "tabCatalog": "الكتالوج", + "tabBranch": "إعدادات الفرع", + "selectBranchForOverrides": "اختر فرعاً من الأعلى لإدارة قائمة الفرع." + }, + "branchMenu": { + "title": "قائمة الفرع", + "name": "الاسم", + "masterPrice": "السعر الأساسي", + "branchPrice": "سعر الفرع", + "availability": "الحالة", + "available": "نشط", + "unavailable": "مخفي", + "resetOverride": "إعادة تعيين", + "savePrice": "حفظ", + "actions": "إجراءات", + "priceOverridePro": "تخصيص الأسعار يتطلب خطة Pro", + "overrideActive": "إعداد فرع نشط", + "confirmReset": "إعادة هذا الصنف إلى الإعدادات الافتراضية؟", + "loading": "جاري التحميل..." + }, + "media": { + "uploadImage": "رفع صورة", + "uploadVideo": "رفع فيديو", + "removeImage": "إزالة الصورة", + "removeVideo": "إزالة الفيديو", + "upload3dTitle": "عرض ثلاثي الأبعاد (اختياري)", + "upload3dHint": "ملف GLB حتى {maxMb} ميجابايت — يمكن للضيف تدوير العنصر باللمس", + "upload3dPhotoCount": "بالإضافة إلى صورة الغلاف: ملف GLB واحد يكفي. للدوران 360° بالصور (لاحقاً): {min} إلى {ideal} صورة من زوايا مختلفة", + "upload3d": "رفع نموذج 3D", + "remove3d": "إزالة النموذج", + "upload3dReady": "النموذج ثلاثي الأبعاد جاهز لقائمة QR" + }, + "taxes": { + "title": "الضرائب", + "subtitle": "معدلات تطبق على فئات القائمة", + "addTax": "إضافة ضريبة", + "name": "الاسم", + "rate": "المعدل (٪)", + "hint": "الضريبة الافتراضية للفئات الجديدة. إرسال تاراز من الإعدادات.", + "empty": "لا ضرائب.", + "default": "افتراضي", + "setDefault": "تعيين افتراضي", + "delete": "حذف", + "deleteConfirm": "حذف «{name}» من القائمة؟ الفئات المرتبطة ستنتقل إلى الضريبة الافتراضية التالية (أو بدون ضريبة).", + "required": "إلزامي", + "optional": "اختياري", + "ownerOnly": "تعديل الضرائب للمالك فقط." + }, + "branches": { + "label": "الفرع" + }, + "inventory": { + "title": "المخزون", + "subtitle": "المواد ووصفات القائمة والخصم التلقائي", + "description": "تتبع كميات المواد وحد إعادة الطلب.", + "tabMaterials": "المواد", + "tabRecipes": "وصفات القائمة", + "addIngredient": "مكون جديد", + "name": "الاسم", + "unit": "الوحدة", + "unitHint": "غرام، مل، قطعة...", + "quantity": "المتوفر", + "parLevel": "مستوى الملء الكامل", + "unitCost": "تكلفة الوحدة", + "warningPercent": "نسبة التنبيه", + "reorderLevel": "حد إعادة الطلب", + "reorder": "حد التنبيه", + "warningAt": "تنبيه عند", + "stockValue": "قيمة المخزون", + "lowStock": "منخفض", + "lowStockAlert": "مواد تحت حد التنبيه — أعد التعبئة", + "adjust": "تطبيق", + "adjustDelta": "+/- الكمية", + "adjustNote": "تعديل يدوي", + "adjusted": "تم التحديث", + "created": "تمت الإضافة", + "empty": "لا توجد مواد.", + "defaultUnit": "قطعة", + "selectMenuItem": "صنف القائمة", + "selectMenuItemPlaceholder": "اختر...", + "recipeLines": "مواد لكل وحدة مباعة", + "perUnit": "الكمية", + "pickIngredient": "المادة", + "addLine": "إضافة", + "saveRecipe": "حفظ الوصفة", + "recipeSaved": "تم الحفظ", + "materialCostPerUnit": "تكلفة المواد / وحدة", + "recipeHint": "مثال: ١٠ غرام قهوة لكل إسبريسو.", + "totalPaid": "المبلغ المدفوع (تومان)", + "impliedUnitCost": "تكلفة الوحدة المحسوبة", + "purchaseNote": "شراء / إدخال مخزون", + "purchaseHint": "لزيادة المخزون (+) أدخل المبلغ المدفوع — يُسجّل في المصروفات والتقارير.", + "purchaseRequired": "المبلغ المدفوع والفرع مطلوبان لزيادة المخزون.", + "purchasesThisMonth": "مشتريات المواد هذا الشهر", + "purchaseCount": "{count} عملية شراء", + "viewInExpenses": "عرض في المصروفات", + "selectBranchForPurchases": "اختر الفرع من الشريط العلوي لتسجيل مشتريات المستودع." + }, + "qr": { + "brand": "ميزي", + "notFound": "الطاولة غير موجودة", + "loadError": "فشل التحميل", + "tableLabel": "طاولة {number}", + "hint": "افتح تطبيق ميزي للطلب أو راجع الكاونتر.", + "discoverCta": "اكتشف المقاهي على ميزي" + }, + "qrMenu": { + "loading": "جاري التحميل...", + "welcome": "مرحباً", + "tableLabel": "طاولة", + "tableNotFound": "الطاولة غير موجودة أو القائمة غير متاحة", + "tableCleaning": "الطاولة قيد التنظيف — يرجى إبلاغ الموظفين", + "loadError": "تعذر تحميل القائمة", + "scanAgain": "يرجى مسح رمز QR مرة أخرى", + "addToCart": "إضافة", + "viewCart": "عرض السلة", + "cartTitle": "سلة الطلب", + "placeOrder": "تأكيد الطلب", + "orderPlaced": "تم تسجيل الطلب!", + "orderNumber": "رقم الطلب: {number}", + "orderHint": "سيقوم الموظفون بتحضير طلبك قريباً", + "guestName": "اسمك (اختياري)", + "guestPhone": "الجوال (اختياري)", + "addMoreItems": "إضافة المزيد", + "orderError": "تعذر تسجيل الطلب. حاول مرة أخرى.", + "rateLimited": "طلبات كثيرة — انتظر بضع دقائق", + "captchaRequired": "أكمل التحقق الأمني", + "cafeUnavailable": "المقهى غير متاح مؤقتاً", + "subtotal": "المجموع", + "searchPlaceholder": "البحث في القائمة...", + "allCategories": "الكل", + "searchNoResults": "لا توجد أصناف مطابقة", + "clearSearch": "مسح البحث", + "emptyCategory": "لا أصناف في هذا القسم", + "view3d": "3D", + "view3dHint": "اسحب للتدوير — النموذج يدور مباشرة", + "close3d": "إغلاق", + "emptyMenu": "قائمة هذا الفرع فارغة أو غير متاحة", + "guestQrBadge": "طلب QR", + "tabMenu": "القائمة", + "tabOrders": "طلباتي", + "callWaiter": "استدعاء النادل", + "callWaiterSent": "النادل في الطريق!", + "callWaiterCooldown": "انتظر ٦٠ ثانية", + "callWaiterError": "خطأ — حاول مرة أخرى", + "myOrders": "طلبات هذا الطاولة", + "noOrders": "لا توجد طلبات بعد", + "tracking": { + "back": "العودة للقائمة", + "orderNumber": "رقم الطلب", + "table": "طاولة", + "loadError": "تعذر تحميل التتبع", + "currentStep": "قيد التنفيذ", + "readyHint": "طلبك جاهز — استلمه من الطاولة أو الكاونتر", + "status": { + "pending": "بانتظار المقهى", + "seen": "شوهد من الموظفين", + "preparing": "المطبخ يحضّر", + "ready": "جاهز للاستلام", + "done": "تم التسليم", + "cancelled": "ملغى" + }, + "steps": { + "submitted": "تم إرسال الطلب", + "seen": "شوهد من المطعم", + "preparing": "قيد التحضير", + "ready": "جاهز", + "done": "مكتمل", + "cancelled": "ملغى" + } + } + }, + "notifications": { + "title": "الإشعارات", + "pageTitle": "الإشعارات", + "empty": "لا إشعارات", + "emptyUnread": "لا إشعارات غير مقروءة", + "markAllRead": "قراءة الكل", + "unreadCount": "{count} غير مقروء", + "filterLabel": "تصفية الإشعارات", + "filterAll": "الكل", + "filterUnread": "غير مقروء", + "loading": "جاري التحميل...", + "refreshing": "جاري التحديث..." + }, + "reservations": { + "title": "الحجوزات", + "guest": "الضيف", + "phone": "الهاتف", + "date": "التاريخ", + "time": "الوقت", + "party": "أشخاص", + "table": "طاولة", + "tableOptional": "بدون طاولة محددة", + "tableNumber": "طاولة {number}", + "notes": "ملاحظات", + "confirm": "تأكيد", + "cancel": "إلغاء", + "create": "إنشاء حجز", + "newReservation": "حجز يدوي", + "newReservationHint": "حدد الطاولة والوقت. عند حضور الضيف استخدم «طلب ودفع» في نقطة البيع.", + "openPos": "طلب ودفع", + "markCompleted": "إنهاء الزيارة", + "empty": "لا حجوزات", + "status": { + "Pending": "قيد الانتظار", + "Confirmed": "مؤكد", + "Cancelled": "ملغى", + "Seated": "جالس", + "Completed": "مكتمل" + } + }, + "branchesPage": { + "title": "الفروع", + "subtitle": "كل فرع له جوال دخول منفصل ضمن خطة المقهى الرئيسية", + "listTitle": "قائمة الفروع", + "newName": "اسم الفرع", + "loginPhone": "جوال دخول الفرع", + "managerName": "اسم مسؤول الفرع", + "managerNamePlaceholder": "اختياري — يُستخدم اسم الفرع", + "addSection": "فرع جديد", + "add": "إضافة فرع", + "empty": "لا توجد فروع بعد.", + "created": "تم إنشاء الفرع وحساب الدخول.", + "createError": "تعذر الإضافة (جوال مكرر أو حد الخطة)", + "branchSelectHint": "اختر الفرع النشط في الصندوق والدور.", + "masterPlanHint": "الاشتراك والضرائب من حساب المالك فقط.", + "ownerOnly": "إدارة الفروع للمالك فقط.", + "delete": "حذف الفرع", + "deleteTitle": "حذف هذا الفرع؟", + "deleteWarning": "سيتم حذف الطاولات والموظفين وإعدادات قائمة الفرع والبيانات المرتبطة. يمكنك الاستعادة خلال ٧ أيام؛ بعدها يُحذف نهائياً.", + "deleteConfirm": "نعم، احذف الفرع", + "deleteScheduled": "تم جدولة حذف الفرع. يمكنك استعادته خلال ٧ أيام.", + "deleteError": "تعذر الحذف (ربما هو آخر فرع نشط).", + "restore": "استعادة", + "restored": "تمت استعادة الفرع.", + "restoreError": "تعذرت الاستعادة.", + "pendingTitle": "في انتظار الحذف النهائي", + "pendingHint": "هذه الفروع غير نشطة وستُحذف نهائياً بعد انتهاء المؤقت.", + "purgeInDays": "حذف نهائي خلال {days} يوم", + "purgeInOneDay": "حذف نهائي غداً", + "purgeToday": "حذف نهائي اليوم", + "review": "مراجعة", + "reviewTitle": "تفاصيل الفرع", + "location": "الموقع" + }, + "subscription": { + "title": "الاشتراك والخطة", + "subtitle": "الخطة الحالية والاستخدام والترقية", + "currentPlan": "الخطة الحالية", + "expires": "ينتهي", + "noExpiry": "—", + "refresh": "تحديث", + "ordersToday": "طلبات اليوم", + "customers": "العملاء", + "smsUsage": "SMS هذا الشهر", + "paymentSuccess": "تم الدفع بنجاح.", + "paymentFailed": "فشل الدفع.", + "loading": "جاري التحميل...", + "ownerOnly": "إدارة الاشتراك للمالك فقط. الفروع تحت خطة المقهى الرئيسية.", + "paymentMethod": "طريقة الدفع", + "planExpired": "انتهى الاشتراك", + "featureMenu3d": "قائمة ثلاثية الأبعاد", + "featureDiscover": "ملف الاكتشاف (ذكاء اصطناعي)", + "featureOn": "مفعّل", + "featureOff": "غير متاح — ترقية", + "featureMenu3dUpgrade": "القائمة 3D متاحة في برو وما فوق." + }, + "settings": { + "title": "الإعدادات", + "subtitle": "المتجر والطابعات والتكاملات", + "nav": { + "aria": "قائمة الإعدادات", + "shop": "المقهى والمتجر", + "shopGeneral": "الملف والتكاملات", + "shopAppearance": "المظهر والألوان", + "printer": "الطابعة", + "printerSettings": "إعدادات الطابعة", + "printTest": "صفحة اختبار الطباعة", + "shopDiscover": "اكتشاف و AI" + }, + "appearance": { + "paletteSection": "لوحة الألوان", + "paletteTitle": "اختر لوحة جاهزة", + "paletteHint": "تُطبَّق ألوان اللوحة على لوحة التحكم وقائمة QR للضيف.", + "dashboardSection": "لوحة التحكم", + "dashboardTitle": "مظهر لوحة التحكم", + "dashboardDesc": "شكل صفحات الإدارة (نقطة البيع، المخزون، التقارير) — منفصل عن قائمة QR على الطاولة.", + "dashboardPreviewSection": "معاينة", + "dashboardPreviewTitle": "عينة لوحة التحكم", + "dashboardPreviewHint": "عينة الشريط الجانبي وبطاقة العنصر؛ تتحدث مع نمط اللوحة والكثافة والزوايا.", + "panelStyle": "نمط لوحة التحكم", + "guestMenuStyle": "تخطيط قائمة QR", + "menuTexture": "نسيج خلفية قائمة QR", + "guestMenuSection": "قائمة QR للطاولة", + "guestMenuTitle": "قالب قائمة الضيف", + "guestMenuDesc": "ما يراه الضيوف عند مسح QR — منفصل عن مظهر لوحة التحكم.", + "guestMenuPreviewSection": "معاينة", + "guestMenuPreviewHint": "معاينة الجوال (قائمة QR)", + "density": "الكثافة", + "radius": "زوايا العناصر", + "customSection": "ألوان مخصصة", + "customTitle": "ألوان المقهى", + "customHint": "اترك الحقل فارغاً لاستخدام اللوحة المختارة.", + "resetCustom": "إعادة تعيين الألوان", + "previewSection": "معاينة", + "previewTitle": "عينة اللوحة والقائمة", + "previewNav": "القائمة", + "previewItem": "لاتيه", + "previewCta": "إضافة", + "saved": "تم حفظ المظهر.", + "palettes": { + "meezi-green": "ميزي أخضر", + "ocean-blue": "أزرق محيطي", + "royal-purple": "بنفسجي ملكي", + "sunset-orange": "برتقالي غروب", + "rose-blush": "وردي", + "charcoal-gold": "فحمي ذهبي", + "espresso": "إسبريسو", + "forest": "غابة", + "midnight": "منتصف الليل", + "coral": "مرجاني", + "gold-luxury": "ذهبي فاخر", + "mint-fresh": "نعناع", + "wine-bar": "بار نبيذ", + "slate-modern": "أردوازي", + "cherry": "كرز", + "teal-wave": "تركواز", + "sand-cafe": "رملي" + }, + "panelStyles": { + "flat": "مسطح", + "modern": "عصري", + "glass": "زجاجي", + "minimal": "بسيط", + "bold": "غامق", + "soft": "ناعم", + "elevated": "بارز", + "outline": "خطي" + }, + "menuStyles": { + "cards": "بطاقات", + "compact": "مضغوط", + "grid": "شبكة", + "list": "قائمة", + "magazine": "مجلة", + "classic": "كلاسيكي" + }, + "menuTextures": { + "none": "عادي", + "paper": "ورقي", + "linen": "كتان", + "dots": "نقاط", + "grid": "شبكة", + "marble": "رخام", + "wood": "خشب", + "warm": "دافئ" + }, + "densities": { + "compact": "مضغوط", + "comfortable": "مريح", + "spacious": "واسع" + }, + "radiusOptions": { + "none": "حاد", + "sm": "صغير", + "md": "متوسط", + "lg": "كبير", + "full": "دائري" + }, + "colors": { + "primary": "أساسي", + "secondary": "ثانوي", + "accent": "تمييز", + "background": "خلفية", + "surface": "بطاقة", + "text": "نص", + "textMuted": "نص باهت", + "destructive": "حذف / خطأ", + "success": "نجاح" + } + }, + "snappfoodVendor": "معرف Snappfood", + "saveProfile": "حفظ الملف", + "profile": { + "title": "ملف المقهى", + "name": "اسم المقهى", + "city": "المدينة", + "phone": "الهاتف", + "address": "العنوان", + "description": "الوصف", + "logo": "الشعار", + "uploadLogo": "رفع الشعار", + "uploadCover": "رفع الغلاف", + "saved": "تم حفظ الملف.", + "reloginHint": "تم تحديث الخطة؛ سجّل الخروج والدخول إن لزم." + }, + "taraz": "تاراز (الضرائب)", + "tarazHint": "إرسال فواتير الأمس إلى تاراز (وضع تجريبي).", + "tarazSubmit": "إرسال إلى تاراز", + "tarazQueued": "تم تسجيل الطلب.", + "plans": { + "compareLabel": "مقارنة الخطط", + "compareHint": "قارن الميزات واختر الخطة المناسبة لمقهاك.", + "featureColumn": "الميزات", + "popular": "الأكثر شعبية", + "current": "الحالية", + "perMonth": "/ شهر", + "freePrice": "مجاني", + "customPrice": "اتصل بنا", + "unlimited": "غير محدود", + "included": "مفعّل", + "currentPlanBtn": "خطتك", + "contactSales": "اتصل بالمبيعات", + "subscribe": "اشترك {plan}", + "names": { + "Free": "مجاني", + "Pro": "برو", + "Business": "أعمال", + "Enterprise": "مؤسسات" + }, + "features": { + "ordersPerDay": "طلبات يومياً", + "terminals": "أجهزة نقطة البيع", + "crmCustomers": "عملاء CRM", + "smsPerMonth": "رسائل تسويقية", + "branches": "فروع", + "posKds": "نقطة البيع والمطبخ", + "tablesQr": "طاولات و QR", + "menuReservations": "قائمة وحجوزات", + "reports": "تقارير", + "hrModule": "الموارد البشرية", + "snappfoodDelivery": "توصيل / سناب‌فود", + "tarazTax": "تكامل تاراز", + "badges": "شارات الثقة", + "whiteLabel": "علامة بيضاء", + "apiAccess": "API عام" + }, + "levels": { + "basic": "أساسي", + "full": "كامل" + } + }, + "discoverProfile": { + "title": "ملف الاكتشاف والذكاء", + "subtitle": "وسوم لمطابقة الضيوف", + "save": "حفظ", + "saved": "تم الحفظ", + "loading": "جاري التحميل..." + } + }, + "support": { + "title": "دعم ميزي", + "subtitle": "افتح تذكرة للتواصل مع فريق المنصة", + "newTicket": "تذكرة جديدة", + "subject": "الموضوع", + "message": "رسالتك", + "submit": "إرسال", + "myTickets": "تذاكري", + "messages": "رسالة", + "created": "تم إنشاء التذكرة", + "createFailed": "فشل إنشاء التذكرة", + "empty": "لا توجد تذاكر بعد", + "loadFailed": "تعذّر تحميل التذاكر.", + "retry": "إعادة المحاولة", + "loading": "جاري التحميل...", + "notFound": "التذكرة غير موجودة", + "back": "رجوع", + "reply": "ردك", + "send": "إرسال", + "replySent": "تم إرسال الرد", + "replyFailed": "فشل إرسال الرد", + "fromAdmin": "دعم ميزي", + "fromYou": "أنت", + "closedHint": "هذه التذكرة مغلقة — لا يمكن إضافة ردود.", + "status": { + "open": "مفتوحة", + "inProgress": "قيد المعالجة", + "waitingMerchant": "بانتظار ردك", + "resolved": "محلولة", + "closed": "مغلقة" + } + }, + "admin": { + "nav": { + "title": "إدارة المنصة", + "dashboard": "لوحة التحكم", + "plans": "الخطط والأسعار", + "integrations": "الدفع والرسائل", + "notifications": "الإشعارات", + "settings": "إعدادات التطبيق", + "features": "الميزات", + "cafes": "المقاهي", + "tickets": "التذاكر", + "logout": "خروج" + }, + "auth": { + "title": "دخول مدير النظام", + "subtitle": "حسابات ميزي المصرح بها فقط", + "phone": "الجوال", + "sendOtp": "إرسال الرمز", + "otp": "رمز التحقق", + "login": "دخول", + "error": "فشل تسجيل الدخول", + "devHint": "في التطوير يُطبع الرمز في سجل Admin API." + }, + "dashboard": { + "title": "نظرة عامة", + "totalCafes": "إجمالي المقاهي", + "activeCafes": "نشط", + "openTickets": "تذاكر مفتوحة", + "plans": "خطط مُعرّفة" + }, + "plans": { + "title": "خطط الاشتراك", + "monthlyPrice": "السعر الشهري (تومان)", + "maxOrders": "حد الطلبات اليومي", + "saved": "تم الحفظ" + }, + "settings": { + "title": "إعدادات التطبيق", + "saved": "تم الحفظ" + }, + "features": { + "title": "تفعيل الميزات", + "enabled": "مفعّل", + "disabled": "معطّل" + }, + "cafes": { + "title": "المقاهي المسجلة", + "suspended": "موقوف", + "suspend": "إيقاف", + "activate": "تفعيل", + "discoverProfile": { + "edit": "ملف الاكتشاف", + "title": "ملف الاكتشاف والذكاء", + "subtitle": "وسوم لمطابقة الضيوف", + "save": "حفظ", + "saved": "تم الحفظ", + "loading": "جاري التحميل..." + } + }, + "integrations": { + "title": "بوابات الدفع وكاوه‌نگار", + "save": "حفظ الإعدادات", + "saved": "تم الحفظ", + "paymentTitle": "بوابات الدفع", + "kavenegarTitle": "كاوه‌نگار (SMS)", + "active": "نشط للفوترة", + "enabled": "مفعّل", + "sandbox": "وضع الاختبار", + "merchantId": "معرّف التاجر", + "apiKey": "رمز API", + "username": "اسم المستخدم", + "password": "كلمة المرور", + "branchCode": "رمز الفرع", + "terminalCode": "رمز المحطة (اختياري)", + "clientId": "Client ID", + "clientSecret": "Client Secret", + "baseUrl": "عنوان API (اختياري)", + "taraHint": "تارا — شراء بالائتمان. API: api.tara-club.ir/club/api/v1", + "snappPayHint": "سناب‌بي — تقسيط BNPL. OAuth و payment token من لوحة التاجر", + "otpTemplate": "قالب OTP" + }, + "notifications": { + "title": "مركز الإشعارات", + "broadcastTitle": "بث لجميع المقاهي", + "broadcastTitlePlaceholder": "عنوان الإشعار", + "broadcastBodyPlaceholder": "النص (اختياري)", + "sendBroadcast": "إرسال للجميع", + "broadcastSent": "أُرسل إلى {count} مقهى", + "allNotifications": "كل الإشعارات", + "empty": "لا توجد إشعارات" + }, + "tickets": { + "title": "تذاكر الدعم", + "messages": "رسالة", + "loading": "تحميل...", + "empty": "لا توجد تذاكر", + "notFound": "التذكرة غير موجودة", + "back": "كل التذاكر", + "replyPlaceholder": "الرد على المقهى...", + "sendReply": "إرسال الرد", + "replySent": "تم إرسال الرد", + "replyFailed": "فشل الإرسال", + "resolve": "تعليم كمحلولة", + "close": "إغلاق التذكرة", + "statusUpdated": "تم تحديث الحالة", + "closedHint": "التذكرة مغلقة — الردود معطلة.", + "fromAdmin": "دعم ميزي", + "fromCafe": "المقهى", + "filter": { + "all": "الكل", + "open": "مفتوحة", + "closed": "مغلقة" + } + } + }, + "errors": { + "planLimit": "وصلت إلى حد الخطة", + "notFound": "غير موجود", + "unauthorized": "غير مصرح", + "network": "خطأ في الاتصال" + }, + "discoverPublic": { + "brand": "ميزي", + "title": "اكتشاف المقاهي", + "subtitle": "اعثر على المقهى المناسب في طهران وكرج", + "searchPlaceholder": "اسم المقهى، الحي، قهوة، حلوى، مطعم…", + "searchHint": "مثلاً: وليعصر، كرج، محمصة، مقهى كتب، تشيز كيك", + "loading": "جاري التحميل…", + "empty": "لا توجد مقاهي بهذه الفلاتر", + "resultCount": "{count} مقهى", + "applyFilters": "تطبيق", + "clearFilters": "مسح", + "viewCafe": "عرض المقهى", + "backToList": "العودة للقائمة", + "notFound": "المقهى غير موجود", + "exploreMore": "المزيد من المقاهي", + "reviewCount": "{count} مراجعة", + "mapTitle": "الموقع على الخريطة", + "openInNeshan": "فتح في نشان", + "reviewsTitle": "مراجعات الضيوف", + "ownerReply": "رد المقهى", + "coffeeAdvisor": { + "title": "مستشار المشروبات", + "subtitle": "اذكر غرض زيارتك للحصول على اقتراحات", + "placeholder": "مثلاً: عمل جماعي، موعد، طاقة للامتحان…", + "submit": "اقترح", + "loading": "جاري التفكير…", + "notConfigured": "المستشار الذكي غير مفعّل لهذا المقهى", + "failed": "الاقتراحات غير متاحة. حاول لاحقاً" + }, + "cities": { + "tehran": "طهران", + "karaj": "كرج" + }, + "sort": { + "rating": "الأعلى تقييماً", + "reviews": "الأكثر مراجعات", + "name": "الاسم" + }, + "filters": { + "themes": "الطراز", + "vibes": "الأجواء", + "occasions": "مناسب لـ", + "spaceFeatures": "المساحة", + "noise": "الضوضاء", + "priceTier": "السعر" + } + }, + "discoverProfile": { + "sections": { + "themes": "تم و سبک فضا", + "occasions": "مناسب برای (چند انتخابی)", + "spaceFeatures": "امکانات فضا", + "vibes": "حس و حال", + "size": "اندازه", + "floors": "طبقات", + "noiseLevel": "سطح صدا", + "priceTier": "رده قیمت" + }, + "hints": { + "themes": "برای پیشنهاد هوشمند به مهمان — مثلاً مدرن، سنتی، پر گیاه", + "occasions": "قرار، خانواده، دوستان، پیدا کردن نفر جدید و …", + "spaceFeatures": "فضای باز، بسته، تراس، گیاه و …", + "vibes": "آرام، شلوغ، رمانتیک و …" + }, + "themes": { + "modern": "مدرن", + "minimal": "مینیمال", + "vintage": "رترو", + "industrial": "صنعتی", + "scandi": "اسکاندیناوی", + "persian_traditional": "سنتی ایرانی", + "book_cafe": "کتاب‌کافه", + "roastery": "رستری", + "dessert_focus": "دسرمحور", + "brunch": "برانچ", + "late_night": "شب‌گاه", + "plants_heavy": "پر گیاه", + "instagrammable": "عکاسی", + "heritage": "میراث", + "luxury": "لوکس" + }, + "occasions": { + "date": "قرار عاشقانه", + "family": "با خانواده", + "friends": "با دوستان", + "finding_someone": "پیدا کردن نفر جدید", + "solo": "تنهایی", + "business_meeting": "جلسه کاری", + "study_work": "درس و کار", + "celebration": "جشن", + "quick_coffee": "قهوه سریع", + "breakfast": "صبحانه", + "brunch": "برانچ" + }, + "spaceFeatures": { + "indoor": "فضای بسته", + "outdoor": "فضای باز", + "terrace": "تراس", + "rooftop": "پشت‌بام", + "garden": "باغ", + "plants": "گیاه", + "wifi": "وای‌فای", + "parking": "پارکینگ", + "wheelchair": "ویلچر", + "kids_friendly": "مناسب کودک", + "pet_friendly": "حیوان خانگی", + "smoking_area": "سیگار", + "live_music": "موسیقی زنده", + "private_room": "اتاق خصوصی", + "counter_only": "فقط پیشخوان" + }, + "vibes": { + "quiet": "آرام", + "lively": "شلوغ و پرانرژی", + "romantic": "رمانتیک", + "cozy": "دنج", + "trendy": "ترندی", + "traditional": "سنتی", + "artistic": "هنری", + "luxury": "لوکس", + "casual": "راحت", + "study_friendly": "مناسب درس" + }, + "sizes": { + "tiny": "خیلی کوچک", + "cozy": "دنج", + "medium": "متوسط", + "large": "بزرگ", + "spacious": "فراخ" + }, + "floors": { + "one": "یک طبقه", + "two": "دو طبقه", + "three": "سه طبقه", + "multi": "چند طبقه" + }, + "noiseLevels": { + "quiet": "آرام", + "moderate": "متوسط", + "lively": "پرصدا" + }, + "priceTiers": { + "budget": "اقتصادی", + "mid": "میانه", + "premium": "پریمیوم" + } + } +} \ No newline at end of file diff --git a/web/dashboard/messages/en.json b/web/dashboard/messages/en.json new file mode 100644 index 0000000..d22f84e --- /dev/null +++ b/web/dashboard/messages/en.json @@ -0,0 +1,1519 @@ +{ + "common": { + "save": "Save", + "cancel": "Cancel", + "confirm": "Confirm", + "delete": "Delete", + "search": "Search", + "loading": "Loading...", + "logout": "Log out", + "language": "Language", + "comingSoon": "Coming soon", + "edit": "Edit" + }, + "confirm": { + "title": "Confirm action", + "confirm": "Confirm", + "cancel": "Cancel" + }, + "notify": { + "saved": "Saved", + "errorGeneric": "Something went wrong. Please try again." + }, + "brand": { + "name": "Meezi" + }, + "languages": { + "fa": "فارسی", + "ar": "العربية", + "en": "English" + }, + "auth": { + "title": "Sign in to Meezi", + "subtitle": "We will send a verification code to your phone", + "phone": "Mobile number", + "phonePlaceholder": "09121234567", + "sendOtp": "Send code", + "otp": "Verification code", + "otpPlaceholder": "6 digits", + "verify": "Sign in", + "resend": "Resend", + "rateLimited": "Too many code requests. Wait up to one hour or contact support.", + "notFound": "No account found for this mobile number.", + "smsFailed": "Could not send SMS. Please try again.", + "invalidOtp": "Invalid or expired verification code." + }, + "nav": { + "aria": "Main navigation", + "groups": { + "operations": "Daily operations", + "menuSales": "Menu & sales", + "customers": "Customers", + "finance": "Reports & finance", + "management": "Café management" + }, + "pos": "POS", + "tables": "Tables", + "crm": "CRM", + "coupons": "Coupons", + "menu": "Menu", + "inventory": "Inventory", + "hr": "HR", + "reports": "Reports", + "expenses": "Expenses", + "shifts": "Shift close", + "reviews": "Reviews", + "reservations": "Reservations", + "sms": "SMS", + "taxes": "Taxes", + "branches": "Branches", + "subscription": "Plan & billing", + "support": "Support", + "settings": "Settings", + "kds": "Kitchen", + "notifications": "Notifications", + "queue": "Daily queue", + "discover": "Discover cafés" + }, + "dashboard": { + "cafeName": "Demo Cafe", + "planPro": "Pro", + "online": "Online", + "offline": "Offline", + "activePlan": "Active plan", + "editCafeSettings": "Café settings", + "viewSubscription": "Plan & billing" + }, + "overview": { + "title": "Home", + "greeting": "Welcome back", + "todayRevenue": "Today's revenue", + "todayOrders": "Today's orders", + "netIncome": "Net income", + "avgOrder": "Avg. order value", + "revenueChart": "7-day revenue trend", + "tableStatus": "Table status", + "tableFree": "Free", + "tableBusy": "Busy", + "tableCleaning": "Cleaning", + "tableTotal": "Total tables", + "topProducts": "Top sellers", + "vsYesterday": "vs yesterday", + "noData": "No data available", + "quickLinks": "Quick access", + "unit": "items" + }, + "pos": { + "order": "Order", + "table": "Table", + "total": "Total", + "subtotal": "Subtotal", + "tax": "Tax", + "discount": "Discount", + "confirmOrder": "Confirm & pay", + "modeOrder": "Take order", + "modePay": "Pay", + "takeOrder": "Order taking", + "submitOrder": "Submit order", + "submitOrderAndPay": "Submit order & pay", + "orderPaidNew": "Order submitted and paid", + "orderPaidAdd": "Items added and paid", + "posDeviceSent": "Amount sent to POS terminal", + "posDeviceError": "Could not send amount to POS terminal", + "posDeviceNotConfigured": "POS terminal not configured — payment recorded in Meezi only", + "posDeviceConnectionFailed": "Could not connect to POS terminal", + "posDeviceTimeout": "POS terminal timed out", + "posDeviceRejected": "POS terminal rejected the payment", + "posDeviceNoBranch": "No branch selected for POS payment", + "kitchenSlip": "Kitchen ticket (preview & print)", + "queueNumber": "Queue #{number}", + "orderPlaced": "Order saved — go to Pay to collect payment", + "guestName": "Guest name", + "guestNamePlaceholder": "e.g. Ali", + "needTableOrName": "Select a table, customer, or guest name", + "openOrders": "Open orders", + "openOrdersHint": "Orders not paid yet", + "noOpenOrders": "No orders waiting for payment", + "payOrder": "Payment", + "payFor": "Pay for", + "selectOrderToPay": "Select an order from the list", + "confirmPay": "Collect payment", + "confirmPayCash": "Collect payment (cash)", + "confirmPayCard": "Collect payment (card)", + "confirmPayCredit": "Collect payment (credit)", + "confirmPaySplit": "Collect payment (split)", + "previewBill": "Preview & print bill", + "paySuccess": "Payment recorded", + "payError": "Payment failed", + "payNeedsOpenShift": "Open the register shift for this branch before taking payment", + "cancelOrder": "Cancel order (no payment)", + "cancelOrderConfirm": "Customer left without paying? The order will be cancelled and the table freed.", + "cancelOrderSuccess": "Order cancelled", + "cancelOrderError": "Could not cancel order", + "itemsCount": "items", + "applyCoupon": "Apply coupon", + "couponPlaceholder": "Coupon code", + "couponCode": "Coupon code", + "selectTable": "Table", + "emptyCart": "Cart is empty", + "cash": "Cash", + "card": "Card", + "clearCart": "Clear", + "allCategories": "All", + "searchItems": "Search items", + "searchItemsPlaceholder": "Search by item name…", + "searchNoResults": "No items match your search", + "reservationBanner": "Reservation: {name} — add items and tap Confirm & pay", + "orderSuccess": "Order placed", + "orderError": "Failed to place order", + "orderInvalid": "Invalid order (check menu items or table)", + "orderNotOpen": "This order is no longer open", + "orderValidation": "Invalid order details", + "nothingPending": "No new items to send to the kitchen", + "couponApplied": "Coupon «{code}» applied — {amount} off", + "couponActive": "Coupon {code}", + "couponRemoved": "Coupon removed", + "removeCoupon": "Remove", + "couponInvalid": "Invalid coupon code", + "couponExpired": "This coupon has expired", + "couponNotStarted": "This coupon is not active yet", + "couponLimitReached": "This coupon has reached its usage limit", + "couponMinOrder": "Minimum order amount not met", + "couponCartEmpty": "Add items to the cart first", + "couponRequired": "Enter a coupon code", + "guestPhone": "Guest phone", + "guestPhonePlaceholder": "09121234567", + "selectTableBoard": "Select table", + "loadingTables": "Loading tables...", + "selectBranchForTables": "Select a branch first", + "noTablesOnBoard": "No tables for this branch. Add tables in the Tables screen.", + "tablesLoadError": "Could not load tables", + "retryTables": "Try again", + "manageTablesLink": "Go to Tables", + "sessionActive": "Active table session", + "addToOrder": "Added to table order", + "void": "Void", + "voidItem": "Void item", + "voided": "Voided", + "confirmVoid": "Are you sure you want to void this item?", + "voidError": "Could not void item", + "transferTable": "Transfer table", + "selectTargetTable": "Select destination table", + "transferSuccess": "Order transferred successfully", + "transferError": "Could not transfer table", + "tableNotAvailable": "Table is being cleaned", + "tableOccupied": "Table is already occupied", + "searchOpenOrder": "Table, name, phone, or order ID...", + "paidSoFar": "Paid", + "remaining": "Remaining", + "loyaltyBalance": "Customer points: {points}", + "loyaltyUseMax": "Max", + "loyaltyRedeemHint": "1 point = 100 T discount on this payment", + "loyaltyRedeemApplied": "Points discount", + "loyaltyNoCustomer": "Attach a customer to the order to redeem points", + "loyaltyInsufficient": "Not enough points", + "splitPayments": "Split payment", + "addPaymentRow": "Add payment row", + "credit": "Credit", + "paySelectTable": "Pick table (occupied)", + "payPickByName": "Or pick by name / open order list", + "payOpenOrdersHint": "Tap an occupied table, use the table dropdown, or search by name/phone", + "allTables": "All tables", + "noOrderOnTable": "No open order on this table", + "noOpenOrdersOnTable": "No open orders for this table", + "customerSection": "Customer", + "existingCustomer": "Existing", + "newCustomer": "New guest", + "customerSearchPlaceholder": "Name, phone, or national ID...", + "customerSearchHint": "Type at least 2 characters to search", + "customerNotFound": "No customer found — add as new guest", + "customerSaved": "Customer saved to CRM", + "customerSaveError": "Could not save customer", + "customerPhoneExists": "Phone already registered — search and select", + "newCustomerHint": "Use for this order only, or tap Add customer to save to CRM", + "offlineQueueNotice": "Offline — order saved in queue and will sync when connected" + }, + "print": { + "printReceipt": "Print receipt", + "printKitchen": "Send to kitchen", + "success": "Receipt printed successfully", + "notConfigured": "Printer IP is not configured", + "connectionFailed": "Could not connect to printer", + "testPrint": "Test print", + "printerSettings": "Printer settings", + "receiptPrinter": "Receipt printer", + "kitchenPrinter": "Kitchen printer", + "paperWidth": "Paper width", + "autoCut": "Auto cut", + "port": "Port", + "receiptHeader": "Receipt header", + "receiptFooter": "Receipt footer", + "wifiOnReceipt": "WiFi password on receipt", + "saveSettings": "Save settings", + "settingsSaved": "Printer settings saved", + "noBranchForPrinter": "Add a branch before configuring printers.", + "testPageHint": "Sends a test ticket to your saved printers. Configure IP and port under Printer settings first.", + "testPrintReceipt": "Test receipt printer", + "testPrintKitchen": "Test kitchen printer", + "configurePrinters": "Open printer settings", + "posDeviceSection": "Card POS terminal", + "posDeviceHint": "On card payment, the amount is sent via HTTP (POST /pay) to the device on your LAN.", + "posDeviceIp": "POS device IP address" + }, + "receipt": { + "table": "Table", + "order": "Order", + "guest": "Guest", + "total": "Total", + "print": "Print", + "close": "Close", + "thankYou": "Thank you for your visit", + "kitchenTitle": "Kitchen / bar ticket", + "billTitle": "Customer bill", + "kitchenFooter": "— For kitchen —", + "payment": { + "cash": "Cash", + "card": "Card", + "credit": "Credit" + } + }, + "crm": { + "title": "Customers", + "searchPlaceholder": "Name, phone, or national ID...", + "addCustomer": "Add customer", + "name": "Name", + "phone": "Phone", + "nationalId": "National ID", + "birthDate": "Birth date (Jalali)", + "group": "Group", + "loyaltyPoints": "Points", + "noCustomers": "No customers found", + "groups": { + "Regular": "Regular", + "Vip": "VIP", + "New": "New", + "Employee": "Employee" + }, + "wizard": { + "titleCreate": "Add customer", + "titleEdit": "Edit customer", + "stepOf": "Step {current} of {total}", + "steps": { + "contact": "Contact", + "profile": "Profile", + "loyalty": "Group & points", + "confirm": "Review" + }, + "back": "Back", + "next": "Next", + "birthHint": "Jalali format, e.g. 1400/01/01", + "referredBy": "Referred by (optional)", + "loyaltyCreateHint": "Loyalty points can be adjusted after the customer is created.", + "errors": { + "duplicatePhone": "This phone number is already registered.", + "generic": "Could not save. Please try again." + } + } + }, + "coupons": { + "title": "Coupons", + "addCoupon": "New coupon", + "code": "Code", + "type": "Type", + "value": "Value", + "usage": "Usage", + "active": "Active", + "inactive": "Inactive", + "types": { + "Percentage": "Percentage", + "FixedAmount": "Fixed amount", + "FreeItem": "Free item" + }, + "noCoupons": "No coupons yet" + }, + "hr": { + "title": "Human resources", + "tabs": { + "attendance": "Attendance", + "leave": "Leave", + "payroll": "Payroll" + }, + "myAttendance": "My attendance", + "clockIn": "Clock in", + "clockOut": "Clock out", + "approve": "Approve", + "noLeave": "No pending leave requests", + "paid": "Paid", + "markPaid": "Mark paid", + "employeeCount": "Employees", + "monthYear": "Payroll month" + }, + "reviews": { + "title": "Customer reviews", + "summary": "Average rating", + "reviewCount": "{count} reviews", + "empty": "No reviews yet.", + "ownerReply": "Cafe reply", + "reply": "Reply", + "replyPlaceholder": "Write your reply..." + }, + "sms": { + "title": "SMS marketing", + "message": "Message", + "messagePlaceholder": "Write your SMS text...", + "targetGroup": "Target group", + "allCustomers": "All customers", + "send": "Send", + "usage": "Usage this month", + "unlimited": "Unlimited", + "sent": "Sent", + "failed": "Failed" + }, + "reports": { + "title": "Reports & analytics", + "subtitle": "Sales summary from daily snapshots", + "exportCsv": "Download CSV", + "fromDate": "From", + "toDate": "To", + "branch": "Branch", + "allBranches": "All branches", + "preset": { + "7d": "7 days", + "30d": "30 days", + "90d": "90 days" + }, + "kpiTotalRevenue": "Total revenue", + "kpiTotalOrders": "Orders", + "kpiAvgOrder": "Avg. order value", + "kpiNetIncome": "Net income", + "kpiTotalExpenses": "Total expenses", + "vsPrevious": "vs previous period", + "revenueChartTitle": "Daily revenue trend", + "paymentMixTitle": "Payment methods", + "branchCompareTitle": "Branch comparison", + "topProductsTitle": "Top products", + "colProduct": "Product", + "colQuantity": "Qty", + "colRevenue": "Revenue", + "revenue": "Revenue", + "cash": "Cash", + "card": "Card", + "credit": "Credit", + "noData": "No data", + "loading": "Loading...", + "csvDate": "Date", + "csvBranch": "Branch", + "csvTotalRevenue": "Total revenue", + "csvTotalOrders": "Orders", + "csvAvgOrder": "Avg order", + "csvCash": "Cash", + "csvCard": "Card", + "csvCredit": "Credit", + "csvNetIncome": "Net income", + "csvVoids": "Voids", + "csvVoidAmount": "Void amount", + "csvExpenses": "Expenses" + }, + "shifts": { + "title": "Cash shift", + "subtitle": "Open and close the register daily", + "branch": "Branch", + "openShift": "Open shift", + "shiftOpen": "Shift is open", + "startShift": "Start shift", + "closeShift": "Close shift", + "confirmClose": "Confirm close", + "openingCash": "Opening float", + "expectedCash": "Expected cash", + "countedCash": "Counted cash", + "opened": "Shift opened", + "closed": "Shift closed" + }, + "expenses": { + "title": "Expenses", + "subtitle": "Log and track branch expenses", + "addExpense": "Log expense", + "listTitle": "Expense log", + "branch": "Branch", + "fromDate": "From", + "toDate": "To", + "periodTotal": "Period total", + "category": "Category", + "amount": "Amount", + "note": "Note", + "notePlaceholder": "Optional", + "linkOpenShift": "Deduct from open register (cash withdrawal)", + "noOpenShift": "No open shift — expense will not link to a register", + "colDate": "Date", + "colCategory": "Category", + "colNote": "Note", + "colAmount": "Amount", + "loading": "Loading...", + "empty": "No expenses logged", + "rowCount": "{count} rows", + "categories": { + "Supplies": "Supplies", + "Utilities": "Utilities", + "Salary": "Salary", + "Rent": "Rent", + "Maintenance": "Maintenance", + "Other": "Other" + } + }, + "queue": { + "title": "Daily queue", + "subtitle": "Ticket numbers restart at 1 each day (Iran calendar)", + "nowServing": "Now serving", + "lastIssued": "Last issued", + "waitingCount": "{count} waiting", + "issueNext": "New number", + "callNext": "Call next", + "customerLabelPlaceholder": "Guest name (optional)", + "dailyResetHint": "Numbers reset at midnight Iran time.", + "empty": "No tickets issued today yet.", + "issuedOnOrder": "Queue #{number}", + "openDisplay": "TV display", + "displayMode": "Fullscreen", + "exitDisplay": "Back to panel", + "displayWaitingLabel": "In queue", + "displayUpNext": "Up next", + "status": { + "Waiting": "Waiting", + "Called": "Called", + "Done": "Done", + "Cancelled": "Cancelled" + } + }, + "kds": { + "title": "Kitchen display", + "pending": "Pending", + "preparing": "Preparing", + "ready": "Ready", + "table": "Table", + "noOrders": "No orders", + "loading": "Loading...", + "live": "Live", + "polling": "Polling", + "advance": "Next step", + "status": { + "Pending": "Pending", + "Confirmed": "Confirmed", + "Preparing": "Preparing", + "Ready": "Ready", + "Delivered": "Delivered", + "Cancelled": "Cancelled" + }, + "advanceTo": { + "Confirmed": "Confirm order", + "Preparing": "Start preparing", + "Ready": "Mark ready", + "Delivered": "Mark delivered" + } + }, + "tables": { + "title": "Table management", + "addTable": "Add table", + "number": "Table number", + "capacity": "Capacity", + "floor": "Floor", + "floorPlan": "Floor plan", + "empty": "No tables yet.", + "emptyBranch": "No tables for this branch.", + "allBranches": "All branches", + "branchFilter": "Branch filter", + "branch": "Branch", + "branchUnassigned": "No branch", + "branchHint": "Tables belong to your café; branch is optional for POS and reports.", + "tableLabel": "Table {number}", + "meta": "Cap. {capacity} · Floor {floor}", + "status": { + "Free": "Free", + "Busy": "Occupied", + "Reserved": "Reserved", + "Cleaning": "Cleaning", + "free": "Available", + "occupied": "Occupied", + "reserved": "Reserved", + "cleaning": "Cleaning" + }, + "markCleaning": "Needs cleaning", + "markReady": "Ready for guests", + "activeOrder": "Active order", + "reserved": "Reserved", + "printQr": "Print QR", + "qrMenuUrl": "Guest menu link", + "openQrUrl": "Open", + "copyQrUrl": "Copy link", + "qrUrlCopied": "Link copied", + "qrUrlCopyFailed": "Could not copy link", + "reprintHint": "Lost QR? Same button — code never changes.", + "deactivate": "Deactivate", + "inactive": "Inactive", + "edit": "Edit", + "editTable": "Edit table", + "reactivate": "Reactivate", + "saveTable": "Save table", + "media": "Table image & video", + "section": "Section", + "sections": "Sections", + "addSection": "Add section", + "noSection": "No section", + "noSectionsYet": "No sections defined yet.", + "sectionTableCount": "{count} tables", + "sectionHasTables": "This section has tables and cannot be deleted", + "tableHasOpenOrder": "This table has an open order", + "deleteTable": "Delete table", + "deleteTableConfirm": "Permanently delete this table? (Only when it has no open order)", + "deleteError": "Could not delete table", + "createError": "Could not add table", + "cleaningError": "Could not update cleaning status" + }, + "menuAdmin": { + "title": "Menu management", + "subtitle": "Images, prices, and per-item discounts", + "categories": "Categories", + "items": "Items", + "addCategory": "New category", + "addItem": "Add item", + "name": "Name", + "nameEn": "English name (for international guests)", + "price": "Price (T)", + "category": "Category", + "available": "Available", + "unavailable": "Unavailable", + "discountPercent": "Discount (%)", + "discountBadge": "off", + "uploadImage": "Upload image", + "imageReady": "Image ready", + "empty": "No menu items yet.", + "editItem": "Edit", + "editCategory": "Edit category", + "categoryIcon": "Icon (emoji)", + "categoryImage": "Category image", + "iconTabPreset": "Preset icons", + "iconTabEmoji": "Emoji", + "iconTabImage": "Upload image", + "iconStyleLabel": "Design style", + "iconPreview": "Preview:", + "clearIconPreset": "Clear icon", + "clearIconEmoji": "Clear emoji", + "categoryIconCustom": "Or custom emoji", + "iconPresetGroupDrinks": "Drinks", + "iconPresetGroupFood": "Food", + "iconStyles": { + "flat": "Flat", + "modern": "Modern", + "real": "Real", + "minimal": "Minimal", + "outline": "Outline", + "soft": "Soft", + "bold": "Bold", + "gradient": "Gradient", + "pastel": "Pastel", + "duotone": "Duotone" + }, + "iconEmojiGroups": { + "hotDrinks": "Hot drinks", + "coldDrinks": "Cold drinks", + "breakfast": "Breakfast", + "mains": "Main dishes", + "pastaPizza": "Pasta & pizza", + "desserts": "Desserts", + "salads": "Salads", + "seafoodGrill": "Grill & seafood", + "snacks": "Snacks & fast food", + "vegan": "Plant-based", + "specials": "Specials", + "general": "General" + }, + "iconPresets": { + "drinks-hot": "Hot coffee", + "drinks-cold": "Cold drinks", + "drinks-tea": "Tea", + "drinks-juice": "Juice", + "drinks-milkshake": "Milk & smoothies", + "drinks-alcohol": "Wine", + "drinks-beer": "Beer", + "breakfast": "Breakfast", + "food-mains": "Main dishes", + "food-fastfood": "Fast food", + "food-rice": "Rice dishes", + "pasta-pizza": "Pasta & pizza", + "dessert": "Dessert", + "ice-cream": "Ice cream", + "bakery": "Bakery", + "salad": "Salad", + "grill": "Grill", + "seafood": "Seafood", + "snacks": "Sandwich", + "snacks-sweet": "Pastries", + "appetizers": "Appetizers", + "vegan": "Plant-based", + "fruits": "Fruits", + "specials": "Specials", + "chef-special": "Chef's pick", + "generic": "General" + }, + "media": "Image & video", + "tabCatalog": "Catalog", + "tabBranch": "Branch settings", + "selectBranchForOverrides": "Select a branch above to manage its menu overrides." + }, + "branchMenu": { + "title": "Branch Menu", + "name": "Name", + "masterPrice": "Master Price", + "branchPrice": "Branch Price", + "availability": "Status", + "available": "Active", + "unavailable": "Hidden", + "resetOverride": "Reset", + "savePrice": "Save", + "actions": "Actions", + "priceOverridePro": "Price overrides require Pro plan", + "overrideActive": "Branch override active", + "confirmReset": "Reset this item to catalog defaults?", + "loading": "Loading..." + }, + "media": { + "uploadImage": "Upload image", + "uploadVideo": "Upload video", + "removeImage": "Remove image", + "removeVideo": "Remove video", + "upload3dTitle": "3D view (optional)", + "upload3dHint": "GLB file up to {maxMb} MB — guests can rotate the item on touch", + "upload3dPhotoCount": "Besides cover photo: one GLB is enough. For photo-based 360° (future): {min}–{ideal} photos from different angles", + "upload3d": "Upload 3D model", + "remove3d": "Remove model", + "upload3dReady": "3D model will show on the QR menu", + "ai3dTitle": "AI 3D generation", + "ai3dHint": "Build a GLB from the product photo for the QR menu (Business plan and above).", + "ai3dGenerate": "Generate 3D with AI", + "ai3dGenerating": "Generating…", + "ai3dUsage": "Monthly quota: {used} of {limit}", + "ai3dSuccess": "3D model generated.", + "ai3dFailed": "3D generation failed.", + "ai3dLimitReached": "Monthly AI quota (100) is used up.", + "ai3dNoImage": "Upload a product photo first." + }, + "taxes": { + "title": "Taxes", + "subtitle": "Rates applied to menu categories", + "addTax": "Add tax", + "name": "Name (e.g. VAT)", + "rate": "Rate (%)", + "hint": "Default tax applies to new categories. Taraz submission is in Settings.", + "empty": "No taxes defined.", + "default": "Default", + "setDefault": "Set default", + "delete": "Remove", + "deleteConfirm": "Remove \"{name}\" from the list? Menu categories using this tax will switch to the next default tax (or no tax).", + "required": "Required", + "optional": "Optional", + "ownerOnly": "Only the café owner can change taxes." + }, + "branches": { + "label": "Branch" + }, + "inventory": { + "title": "Inventory", + "subtitle": "Materials, menu recipes, and auto-deduction on orders", + "description": "Track ingredient quantities and reorder levels.", + "tabMaterials": "Materials", + "tabRecipes": "Menu recipes", + "addIngredient": "New ingredient", + "name": "Name", + "unit": "Unit", + "unitHint": "g, ml, pcs...", + "unitCustom": "Other (custom)", + "unitCustomPlaceholder": "e.g. cup, shot", + "unitsHelp": "Unit for stock and recipes: pcs, g, ml, etc. Change on-hand qty with +/- on each card.", + "units": { + "piece": "Piece (pcs)", + "gram": "Gram (g)", + "kilogram": "Kilogram (kg)", + "milliliter": "Milliliter (ml)", + "liter": "Liter (l)", + "cc": "cc", + "pack": "Pack", + "can": "Can", + "bag": "Bag" + }, + "editIngredient": "Edit material", + "updated": "Material updated", + "quantityEditHint": "on-hand qty changes via +/- on this card only", + "quantity": "On hand", + "parLevel": "Full stock (e.g. 500 g)", + "unitCost": "Unit cost (Toman)", + "warningPercent": "Warning %", + "reorderLevel": "Reorder level", + "reorder": "Reorder at", + "warningAt": "Warn below", + "stockValue": "Stock value", + "lowStock": "Low", + "lowStockAlert": "Below warning level — refill these materials", + "adjust": "Apply", + "adjustDelta": "+/- qty", + "adjustNote": "Manual adjustment", + "adjusted": "Stock updated", + "created": "Ingredient added", + "empty": "No ingredients yet.", + "defaultUnit": "pcs", + "selectMenuItem": "Menu item", + "selectMenuItemPlaceholder": "Select...", + "recipeLines": "Per sold unit", + "perUnit": "Qty", + "pickIngredient": "Ingredient", + "addLine": "Add", + "saveRecipe": "Save recipe", + "recipeSaved": "Recipe saved", + "materialCostPerUnit": "Material cost / unit", + "recipeHint": "Example: 10 g coffee per espresso — 10 orders use 100 g.", + "totalPaid": "Amount paid (Toman)", + "impliedUnitCost": "Calculated unit cost", + "purchaseNote": "Stock purchase", + "purchaseHint": "For stock in (+), enter amount paid — recorded in expenses and reports.", + "purchaseRequired": "Amount paid and branch are required to add stock.", + "purchasesThisMonth": "Material purchases this month", + "purchaseCount": "{count} purchases", + "viewInExpenses": "View in expenses", + "selectBranchForPurchases": "Select a branch in the top bar to record warehouse purchases." + }, + "qr": { + "brand": "Meezi", + "notFound": "Table not found", + "loadError": "Failed to load", + "tableLabel": "Table {number}", + "hint": "Open the Meezi app to order, or ask at the counter.", + "discoverCta": "Discover cafés on Meezi" + }, + "qrMenu": { + "loading": "Loading...", + "welcome": "Welcome", + "tableLabel": "Table", + "tableNotFound": "Table not found or menu unavailable", + "tableCleaning": "This table is being cleaned — please ask staff", + "loadError": "Could not load menu", + "scanAgain": "Please scan the QR code again", + "addToCart": "Add", + "viewCart": "View cart", + "cartTitle": "Your cart", + "placeOrder": "Place order", + "orderPlaced": "Order placed!", + "orderNumber": "Order #: {number}", + "orderHint": "Staff will prepare your order shortly", + "guestName": "Your name (optional)", + "guestPhone": "Mobile (optional)", + "addMoreItems": "Add more items", + "orderError": "Could not place order. Try again.", + "rateLimited": "Too many requests — please wait a few minutes", + "captchaRequired": "Please complete the security check", + "cafeUnavailable": "This café is temporarily unavailable", + "subtotal": "Total", + "searchPlaceholder": "Search menu...", + "allCategories": "All", + "searchNoResults": "No items match your search", + "clearSearch": "Clear search", + "emptyCategory": "No items in this category", + "view3d": "3D", + "view3dHint": "Drag to rotate — model spins live", + "close3d": "Close", + "emptyMenu": "This branch menu is empty or unavailable", + "guestQrBadge": "QR guest", + "tabMenu": "Menu", + "tabOrders": "My orders", + "callWaiter": "Call waiter", + "callWaiterSent": "Waiter is on the way!", + "callWaiterCooldown": "Please wait 60 seconds", + "callWaiterError": "Error — please try again", + "myOrders": "Orders at this table", + "noOrders": "No orders yet", + "tracking": { + "back": "Back to menu", + "orderNumber": "Order number", + "table": "Table", + "loadError": "Could not load tracking", + "currentStep": "In progress", + "readyHint": "Your order is ready — pick it up at the counter or table", + "status": { + "pending": "Waiting for the café", + "seen": "Seen by staff", + "preparing": "Kitchen is preparing", + "ready": "Ready for pickup", + "done": "Delivered", + "cancelled": "Cancelled" + }, + "steps": { + "submitted": "Order submitted", + "seen": "Seen by restaurant", + "preparing": "Preparing", + "ready": "Ready", + "done": "Completed", + "cancelled": "Cancelled" + } + } + }, + "notifications": { + "title": "Notifications", + "pageTitle": "Notifications", + "empty": "No notifications", + "emptyUnread": "No unread notifications", + "markAllRead": "Mark all read", + "unreadCount": "{count} unread", + "filterLabel": "Filter notifications", + "filterAll": "All", + "filterUnread": "Unread", + "loading": "Loading...", + "refreshing": "Updating...", + "backToList": "Back to list" + }, + "reservations": { + "title": "Reservations", + "guest": "Guest", + "phone": "Phone", + "date": "Date", + "time": "Time", + "party": "Guests", + "table": "Table", + "tableOptional": "No specific table", + "tableNumber": "Table {number}", + "notes": "Notes", + "confirm": "Confirm", + "cancel": "Cancel", + "create": "Create reservation", + "newReservation": "Manual reservation", + "newReservationHint": "Pick table and time. When the guest arrives, use “Order & pay” at POS.", + "openPos": "Order & pay", + "markCompleted": "Mark completed", + "empty": "No reservations", + "status": { + "Pending": "Pending", + "Confirmed": "Confirmed", + "Cancelled": "Cancelled", + "Seated": "Seated", + "Completed": "Completed" + } + }, + "branchesPage": { + "title": "Branches", + "subtitle": "Each branch has its own login mobile under the café master plan", + "listTitle": "Branch list", + "newName": "Branch name", + "loginPhone": "Branch login mobile", + "managerName": "Branch manager name", + "managerNamePlaceholder": "Optional — defaults to branch name", + "addSection": "New branch", + "add": "Add branch", + "empty": "No branches yet.", + "created": "Branch and login account created.", + "createError": "Could not add branch (duplicate phone or plan limit)", + "branchSelectHint": "Pick the active branch on POS and queue.", + "masterPlanHint": "Billing and taxes are managed only by the café owner.", + "ownerOnly": "Only the café owner can manage branches.", + "delete": "Delete branch", + "deleteTitle": "Delete this branch?", + "deleteWarning": "Tables, staff, branch menu overrides, and related data will be removed. You can restore within 7 days; after that the branch is permanently deleted.", + "deleteConfirm": "Yes, delete branch", + "deleteScheduled": "Branch scheduled for deletion. You can restore it within 7 days.", + "deleteError": "Could not delete branch (maybe it is the last active branch).", + "restore": "Restore", + "restored": "Branch restored.", + "restoreError": "Could not restore branch.", + "pendingTitle": "Pending permanent deletion", + "pendingHint": "These branches are inactive. They will be permanently removed when the timer ends.", + "purgeInDays": "Permanent delete in {days} days", + "purgeInOneDay": "Permanent delete tomorrow", + "purgeToday": "Permanent delete today", + "review": "Review", + "reviewTitle": "Branch details", + "location": "Location" + }, + "subscription": { + "title": "Plan & billing", + "subtitle": "Current plan, usage, and upgrades", + "currentPlan": "Current plan", + "expires": "Expires", + "noExpiry": "—", + "refresh": "Refresh", + "ordersToday": "Orders today", + "customers": "Customers", + "smsUsage": "SMS this month", + "paymentSuccess": "Payment successful. Your plan was updated.", + "paymentFailed": "Payment failed.", + "loading": "Loading...", + "ownerOnly": "Only the café owner can manage billing. Branches use the master café plan.", + "paymentMethod": "Payment method", + "planExpired": "Subscription expired", + "featureMenu3d": "3D menu", + "featureDiscover": "Discover profile (AI)", + "featureOn": "Enabled", + "featureOff": "Not included — upgrade", + "featureMenu3dUpgrade": "3D menu is available on Pro and higher plans.", + "featureMenuAi3d": "AI 3D generation", + "featureMenuAi3dUpgrade": "AI 3D generation is on Business and Enterprise (100 per month)." + }, + "settings": { + "title": "Settings", + "subtitle": "Shop profile, printers, and integrations", + "terminals": { + "title": "Active terminals", + "hint": "Your plan allows up to {max} concurrent terminals.", + "thisDevice": "This device", + "empty": "No terminals registered", + "revoke": "Remove", + "revoked": "Terminal removed", + "loading": "Loading…" + }, + "nav": { + "aria": "Settings menu", + "shop": "Shop & café", + "shopGeneral": "Profile & integrations", + "shopAppearance": "Appearance & colors", + "printer": "Printer", + "printerSettings": "Printer settings", + "printTest": "Print test page", + "shopDiscover": "Discover & AI" + }, + "appearance": { + "paletteSection": "Color palette", + "paletteTitle": "Choose a preset palette", + "paletteHint": "Palette colors apply to the dashboard and the guest QR menu.", + "dashboardSection": "Dashboard", + "dashboardTitle": "Dashboard look", + "dashboardDesc": "How admin pages look (POS, inventory, reports) — separate from the table QR menu.", + "dashboardPreviewSection": "Preview", + "dashboardPreviewTitle": "Dashboard sample", + "dashboardPreviewHint": "Sample sidebar and item card in this panel; updates with panel style, density, and corners.", + "panelStyle": "Dashboard panel style", + "guestMenuStyle": "QR menu layout", + "menuTexture": "QR menu background texture", + "guestMenuSection": "Table QR menu", + "guestMenuTitle": "Guest menu template", + "guestMenuDesc": "What guests see when scanning the table QR — separate from your dashboard.", + "guestMenuPreviewSection": "Preview", + "guestMenuPreviewHint": "Mobile preview (QR menu)", + "density": "Density", + "radius": "Corner radius", + "customSection": "Custom colors", + "customTitle": "Your café brand colors", + "customHint": "Leave empty to use the selected palette. Opacity applies to custom or palette colors.", + "colorOpacity": "Opacity", + "resetCustom": "Reset custom colors", + "previewSection": "Preview", + "previewTitle": "Panel & menu sample", + "previewNav": "Menu", + "previewItem": "Latte", + "previewCta": "Add", + "saved": "Appearance saved.", + "palettes": { + "meezi-green": "Meezi green", + "ocean-blue": "Ocean blue", + "royal-purple": "Royal purple", + "sunset-orange": "Sunset orange", + "rose-blush": "Rose blush", + "charcoal-gold": "Charcoal gold", + "espresso": "Espresso", + "forest": "Forest", + "midnight": "Midnight", + "coral": "Coral", + "gold-luxury": "Gold luxury", + "mint-fresh": "Mint fresh", + "wine-bar": "Wine bar", + "slate-modern": "Slate modern", + "cherry": "Cherry", + "teal-wave": "Teal wave", + "sand-cafe": "Sand café" + }, + "panelStyles": { + "flat": "Flat", + "modern": "Modern", + "glass": "Glass", + "minimal": "Minimal", + "bold": "Bold", + "soft": "Soft", + "elevated": "Elevated", + "outline": "Outline" + }, + "menuStyles": { + "cards": "Cards", + "compact": "Compact", + "grid": "Grid", + "list": "List", + "magazine": "Magazine", + "classic": "Classic" + }, + "menuTextures": { + "none": "Plain", + "paper": "Paper", + "linen": "Linen", + "dots": "Dots", + "grid": "Grid", + "marble": "Marble", + "wood": "Wood", + "warm": "Warm café" + }, + "densities": { + "compact": "Compact", + "comfortable": "Comfortable", + "spacious": "Spacious" + }, + "radiusOptions": { + "none": "Sharp", + "sm": "Small", + "md": "Medium", + "lg": "Large", + "full": "Round" + }, + "colors": { + "primary": "Primary", + "secondary": "Secondary", + "accent": "Accent / promo", + "background": "Background", + "surface": "Card / surface", + "text": "Text", + "textMuted": "Muted text", + "destructive": "Error / delete", + "success": "Success" + } + }, + "snappfoodVendor": "Snappfood vendor ID", + "saveProfile": "Save profile", + "profile": { + "title": "Café profile", + "name": "Café name", + "city": "City", + "phone": "Phone", + "address": "Address", + "description": "Description", + "logo": "Logo", + "uploadLogo": "Upload logo", + "uploadCover": "Upload cover", + "saved": "Profile saved.", + "reloginHint": "Plan updated; sign out and in again if the badge looks wrong." + }, + "taraz": "Taraz (tax system)", + "tarazHint": "Submit yesterday's invoices to Taraz (demo mode logs only).", + "tarazSubmit": "Submit to Taraz", + "tarazQueued": "Submission queued.", + "plans": { + "compareLabel": "Compare plans", + "compareHint": "Compare features and pick the right plan for your café.", + "featureColumn": "Features", + "popular": "Popular", + "current": "Current", + "perMonth": "/ month", + "freePrice": "Free", + "customPrice": "Contact us", + "unlimited": "Unlimited", + "included": "Included", + "currentPlanBtn": "Your plan", + "contactSales": "Contact sales", + "subscribe": "Get {plan}", + "names": { + "Free": "Free", + "Pro": "Pro", + "Business": "Business", + "Enterprise": "Enterprise" + }, + "features": { + "ordersPerDay": "Orders per day", + "terminals": "POS terminals", + "crmCustomers": "CRM customers", + "smsPerMonth": "Marketing SMS", + "branches": "Branches", + "posKds": "POS & kitchen display", + "tablesQr": "Tables & QR ordering", + "menuReservations": "Menu & reservations", + "reports": "Reports", + "hrModule": "HR module", + "snappfoodDelivery": "Snappfood / delivery", + "tarazTax": "Taraz tax integration", + "badges": "Trust badges", + "whiteLabel": "White label", + "apiAccess": "Public API" + }, + "levels": { + "basic": "Basic", + "full": "Full" + } + }, + "discoverProfile": { + "title": "Discover & AI profile", + "subtitle": "Tags for matching guests to cafés", + "save": "Save", + "saved": "Saved", + "loading": "Loading..." + } + }, + "support": { + "title": "Meezi support", + "subtitle": "Open a ticket for platform help", + "newTicket": "New ticket", + "subject": "Subject", + "message": "Your message", + "submit": "Submit ticket", + "myTickets": "My tickets", + "messages": "messages", + "created": "Ticket created", + "createFailed": "Could not create ticket", + "empty": "No tickets yet", + "loadFailed": "Could not load tickets.", + "retry": "Try again", + "loading": "Loading...", + "notFound": "Ticket not found", + "back": "Back", + "reply": "Your reply", + "send": "Send", + "replySent": "Reply sent", + "replyFailed": "Could not send reply", + "fromAdmin": "Meezi support", + "fromYou": "You", + "closedHint": "This ticket is closed — no new replies.", + "status": { + "open": "Open", + "inProgress": "In progress", + "waitingMerchant": "Awaiting your reply", + "resolved": "Resolved", + "closed": "Closed" + } + }, + "admin": { + "nav": { + "title": "Platform admin", + "dashboard": "Dashboard", + "plans": "Plans & pricing", + "integrations": "Payments & SMS", + "notifications": "Notifications", + "settings": "App settings", + "features": "Features", + "cafes": "Cafes", + "tickets": "Tickets", + "logout": "Log out" + }, + "auth": { + "title": "System admin login", + "subtitle": "Authorized Meezi staff only", + "phone": "Phone", + "sendOtp": "Send code", + "otp": "Verification code", + "login": "Sign in", + "error": "Login failed", + "devHint": "In development the OTP is logged by Admin API (DEV admin OTP)." + }, + "dashboard": { + "title": "Platform overview", + "totalCafes": "Total cafes", + "activeCafes": "Active", + "openTickets": "Open tickets", + "plans": "Plans configured" + }, + "plans": { + "title": "Subscription plans", + "monthlyPrice": "Monthly price (Toman)", + "maxOrders": "Max orders per day", + "saved": "Plan saved" + }, + "settings": { + "title": "Application settings", + "saved": "Saved" + }, + "features": { + "title": "Feature flags", + "enabled": "On", + "disabled": "Off" + }, + "cafes": { + "title": "Registered cafes", + "suspended": "Suspended", + "suspend": "Suspend", + "activate": "Activate", + "discoverProfile": { + "edit": "Discover profile", + "title": "Discover & AI profile", + "subtitle": "Tags for matching guests to cafés", + "save": "Save", + "saved": "Saved", + "loading": "Loading..." + } + }, + "integrations": { + "title": "Payment gateways & Kavenegar", + "save": "Save settings", + "saved": "Settings saved", + "paymentTitle": "Payment gateways", + "kavenegarTitle": "Kavenegar (SMS)", + "active": "Active for billing", + "enabled": "Enabled", + "sandbox": "Sandbox mode", + "merchantId": "Merchant ID", + "apiKey": "API token", + "username": "Username", + "password": "Password", + "branchCode": "Branch code", + "terminalCode": "Terminal code (optional)", + "clientId": "Client ID", + "clientSecret": "Client Secret", + "baseUrl": "API base URL (optional)", + "taraHint": "Tara credit pay — API: api.tara-club.ir/club/api/v1 (login, trace, request, verify)", + "snappPayHint": "Snapp Pay BNPL — OAuth + payment token from Snapp Pay merchant panel", + "otpTemplate": "OTP template name (Kavenegar panel)" + }, + "notifications": { + "title": "Notification center", + "broadcastTitle": "Broadcast to all cafes", + "broadcastTitlePlaceholder": "Notification title", + "broadcastBodyPlaceholder": "Body (optional)", + "sendBroadcast": "Send to all", + "broadcastSent": "Sent to {count} cafes", + "allNotifications": "All notifications", + "empty": "No notifications yet" + }, + "tickets": { + "title": "Support tickets", + "messages": "messages", + "loading": "Loading...", + "empty": "No tickets", + "notFound": "Ticket not found", + "back": "All tickets", + "replyPlaceholder": "Reply to merchant...", + "sendReply": "Send reply", + "replySent": "Reply sent", + "replyFailed": "Could not send reply", + "resolve": "Mark resolved", + "close": "Close ticket", + "statusUpdated": "Ticket status updated", + "closedHint": "Ticket is closed — replies disabled.", + "fromAdmin": "Meezi support", + "fromCafe": "Cafe", + "filter": { + "all": "All", + "open": "Open", + "closed": "Closed" + } + } + }, + "errors": { + "planLimit": "Plan limit reached. Please upgrade.", + "notFound": "Not found", + "unauthorized": "Unauthorized", + "network": "Network error" + }, + "discoverPublic": { + "brand": "Meezi", + "title": "Discover cafés", + "subtitle": "Find the right café in Tehran and Karaj", + "searchPlaceholder": "Type: quiet, date night, Wi-Fi, roastery, book café…", + "searchHint": "Smart search — filters are auto-detected from your text", + "aiDetectedLabel": "Detected filters:", + "aiDetectedClear": "Clear", + "loading": "Loading…", + "empty": "No cafés match these filters", + "resultCount": "{count} cafés", + "applyFilters": "Apply filters", + "clearFilters": "Clear", + "viewCafe": "View café", + "backToList": "Back to list", + "notFound": "Café not found", + "exploreMore": "Explore more cafés", + "reviewCount": "{count} reviews", + "mapTitle": "Map", + "openInNeshan": "Open in Neshan", + "reviewsTitle": "Guest reviews", + "ownerReply": "Cafe reply", + "coffeeAdvisor": { + "title": "Drink advisor", + "subtitle": "Tell us your purpose and get tailored suggestions", + "placeholder": "e.g. group work, date night, exam energy…", + "submit": "Suggest", + "loading": "Thinking…", + "notConfigured": "Smart advisor is not enabled for this café yet", + "failed": "Suggestions unavailable. Try again later" + }, + "cities": { + "tehran": "Tehran", + "karaj": "Karaj" + }, + "sort": { + "rating": "Top rated", + "reviews": "Most reviews", + "name": "Name" + }, + "openNow": "Open now", + "openNowLabel": "Open now", + "closedLabel": "Closed", + "galleryTitle": "Gallery", + "workingHoursTitle": "Working hours", + "instagramLabel": "Instagram", + "websiteLabel": "Website", + "days": { + "sat": "Sat", + "sun": "Sun", + "mon": "Mon", + "tue": "Tue", + "wed": "Wed", + "thu": "Thu", + "fri": "Fri" + }, + "filters": { + "themes": "Theme", + "vibes": "Vibe", + "occasions": "Good for", + "spaceFeatures": "Space", + "noise": "Noise", + "priceTier": "Price", + "size": "Size" + } + }, + "cafePublicProfile": { + "title": "Public profile", + "subtitle": "Information shown to guests on the discovery page", + "tabs": { + "info": "Info", + "gallery": "Gallery", + "hours": "Hours", + "social": "Social" + }, + "description": "About your café", + "descriptionPlaceholder": "Describe your café, its ambiance, specialty drinks, and the experience you offer…", + "instagram": "Instagram handle (without @)", + "instagramPlaceholder": "mycafe.tehran", + "website": "Website URL", + "websitePlaceholder": "https://mycafe.ir", + "gallery": "Photo gallery (max 8)", + "galleryHint": "Upload quality photos of your space — JPEG, PNG or WebP up to 5 MB", + "uploadPhoto": "Upload photo", + "uploading": "Uploading…", + "uploadFailed": "Upload failed", + "galleryFull": "Gallery is full. Remove a photo first", + "removePhoto": "Remove", + "workingHours": "Daily working hours", + "isOpen": "Open", + "openTime": "Opens at", + "closeTime": "Closes at", + "days": { + "sat": "Saturday", + "sun": "Sunday", + "mon": "Monday", + "tue": "Tuesday", + "wed": "Wednesday", + "thu": "Thursday", + "fri": "Friday" + }, + "save": "Save", + "saved": "Saved", + "saveFailed": "Save failed", + "loading": "Loading…" + }, + "discoverProfile": { + "sections": { + "themes": "Theme & style", + "occasions": "Good for (multi)", + "spaceFeatures": "Space features", + "vibes": "Vibe", + "size": "Size", + "floors": "Floors", + "noiseLevel": "Noise", + "priceTier": "Price tier" + }, + "hints": { + "themes": "For AI recommendations", + "occasions": "Dates, family, friends, meeting someone new…", + "spaceFeatures": "Indoor, outdoor, terrace, plants…", + "vibes": "Quiet, lively, romantic…" + }, + "themes": { + "modern": "Modern", + "minimal": "Minimal", + "vintage": "Vintage", + "industrial": "Industrial", + "scandi": "Scandi", + "persian_traditional": "Persian traditional", + "book_cafe": "Book café", + "roastery": "Roastery", + "dessert_focus": "Dessert focus", + "brunch": "Brunch", + "late_night": "Late night", + "plants_heavy": "Plant-heavy", + "instagrammable": "Instagrammable", + "heritage": "Heritage", + "luxury": "Luxury", + "specialty_coffee": "Specialty coffee", + "tea_house": "Tea house", + "art_gallery": "Art gallery", + "sport_cafe": "Sport café", + "gaming_cafe": "Gaming café" + }, + "occasions": { + "date": "Date", + "family": "Family", + "friends": "Friends", + "finding_someone": "Meeting someone new", + "solo": "Solo", + "business_meeting": "Business", + "study_work": "Study & work", + "celebration": "Celebration", + "quick_coffee": "Quick coffee", + "breakfast": "Breakfast", + "brunch": "Brunch", + "after_dinner": "After dinner", + "group_large": "Large group" + }, + "spaceFeatures": { + "indoor": "Indoor", + "outdoor": "Outdoor", + "terrace": "Terrace", + "rooftop": "Rooftop", + "garden": "Garden", + "plants": "Plants", + "wifi": "Wi‑Fi", + "parking": "Parking", + "wheelchair": "Wheelchair access", + "kids_friendly": "Kid-friendly", + "pet_friendly": "Pet-friendly", + "smoking_area": "Smoking area", + "live_music": "Live music", + "private_room": "Private room", + "counter_only": "Counter only", + "takeaway": "Takeaway", + "hookah": "Hookah", + "board_games": "Board games", + "no_smoking": "Non-smoking", + "prayer_room": "Prayer room" + }, + "vibes": { + "quiet": "Quiet", + "lively": "Lively", + "romantic": "Romantic", + "cozy": "Cozy", + "trendy": "Trendy", + "traditional": "Traditional", + "artistic": "Artistic", + "luxury": "Luxury", + "casual": "Casual", + "study_friendly": "Study-friendly" + }, + "sizes": { + "tiny": "Tiny", + "cozy": "Cozy", + "medium": "Medium", + "large": "Large", + "spacious": "Spacious" + }, + "floors": { + "one": "1 floor", + "two": "2 floors", + "three": "3 floors", + "multi": "Multi-floor" + }, + "noiseLevels": { + "quiet": "Quiet", + "moderate": "Moderate", + "lively": "Lively" + }, + "priceTiers": { + "budget": "Budget", + "mid": "Mid", + "premium": "Premium" + } + } +} \ No newline at end of file diff --git a/web/dashboard/messages/fa.json b/web/dashboard/messages/fa.json new file mode 100644 index 0000000..ad3d682 --- /dev/null +++ b/web/dashboard/messages/fa.json @@ -0,0 +1,1520 @@ +{ + "common": { + "save": "ذخیره", + "cancel": "انصراف", + "confirm": "تأیید", + "delete": "حذف", + "search": "جستجو", + "loading": "در حال بارگذاری...", + "logout": "خروج", + "language": "زبان", + "comingSoon": "به‌زودی", + "edit": "ویرایش" + }, + "confirm": { + "title": "تأیید عملیات", + "confirm": "تأیید", + "cancel": "انصراف" + }, + "notify": { + "saved": "ذخیره شد", + "errorGeneric": "خطایی رخ داد. دوباره تلاش کنید." + }, + "brand": { + "name": "میزی" + }, + "languages": { + "fa": "فارسی", + "ar": "العربية", + "en": "English" + }, + "auth": { + "title": "ورود به میزی", + "subtitle": "کد تأیید به موبایل شما ارسال می‌شود", + "phone": "شماره موبایل", + "phonePlaceholder": "۰۹۱۲۱۲۳۴۵۶۷", + "sendOtp": "ارسال کد", + "otp": "کد تأیید", + "otpPlaceholder": "۶ رقم", + "verify": "ورود", + "resend": "ارسال مجدد", + "rateLimited": "تعداد درخواست کد بیش از حد است. حداکثر یک ساعت صبر کنید یا با پشتیبانی تماس بگیرید.", + "notFound": "حسابی با این شماره موبایل یافت نشد.", + "smsFailed": "ارسال پیامک ناموفق بود. دوباره تلاش کنید.", + "invalidOtp": "کد تأیید نادرست یا منقضی شده است." + }, + "nav": { + "aria": "منوی اصلی", + "groups": { + "operations": "عملیات روزانه", + "menuSales": "منو و فروش", + "customers": "مشتریان", + "finance": "گزارش و مالی", + "management": "مدیریت کافه" + }, + "pos": "صندوق", + "tables": "میزها", + "crm": "مشتریان", + "coupons": "کوپن‌ها", + "menu": "منو", + "inventory": "انبار", + "hr": "منابع انسانی", + "reports": "گزارش‌ها", + "expenses": "هزینه‌ها", + "shifts": "بستن شیفت", + "reviews": "نظرات", + "reservations": "رزرو", + "sms": "پیامک", + "taxes": "مالیات", + "branches": "شعب", + "subscription": "اشتراک و پلن", + "support": "پشتیبانی", + "settings": "تنظیمات", + "kds": "آشپزخانه", + "notifications": "اعلان‌ها", + "queue": "نوبت‌دهی", + "discover": "کشف کافه‌ها" + }, + "dashboard": { + "cafeName": "کافه دمو", + "planPro": "پرو", + "online": "متصل", + "offline": "آفلاین", + "activePlan": "پلن فعال", + "editCafeSettings": "تنظیمات کافه", + "viewSubscription": "اشتراک و پلن" + }, + "overview": { + "title": "خانه", + "greeting": "خوش‌آمدید", + "todayRevenue": "فروش امروز", + "todayOrders": "سفارش‌های امروز", + "netIncome": "درآمد خالص", + "avgOrder": "میانگین سفارش", + "revenueChart": "روند فروش ۷ روز", + "tableStatus": "وضعیت میزها", + "tableFree": "آزاد", + "tableBusy": "اشغال", + "tableCleaning": "نظافت", + "tableTotal": "کل میزها", + "topProducts": "پرفروش‌ترین آیتم‌ها", + "vsYesterday": "نسبت به دیروز", + "noData": "داده‌ای موجود نیست", + "quickLinks": "دسترسی سریع", + "unit": "قلم" + }, + "pos": { + "order": "سفارش", + "table": "میز", + "total": "مبلغ نهایی", + "subtotal": "جمع جزء", + "tax": "مالیات", + "discount": "تخفیف", + "confirmOrder": "ثبت و پرداخت", + "modeOrder": "ثبت سفارش", + "modePay": "پرداخت", + "takeOrder": "سفارش‌گیری", + "submitOrder": "ثبت سفارش", + "submitOrderAndPay": "ثبت سفارش و پرداخت", + "orderPaidNew": "سفارش ثبت و پرداخت شد", + "orderPaidAdd": "آیتم‌ها ثبت و پرداخت شد", + "posDeviceSent": "مبلغ به دستگاه پوز ارسال شد", + "posDeviceError": "ارسال به دستگاه پوز ناموفق بود", + "posDeviceNotConfigured": "دستگاه پوز تنظیم نشده — فقط پرداخت در سیستم ثبت شد", + "posDeviceConnectionFailed": "اتصال به دستگاه پوز برقرار نشد", + "posDeviceTimeout": "زمان انتظار دستگاه پوز تمام شد", + "posDeviceRejected": "دستگاه پوز پرداخت را رد کرد", + "posDeviceNoBranch": "شعبه برای ارسال به پوز مشخص نیست", + "kitchenSlip": "فیش آشپزخانه (پیش‌نمایش و چاپ)", + "queueNumber": "نوبت {number}", + "orderPlaced": "سفارش ثبت شد — برای دریافت وجه به «پرداخت» بروید", + "guestName": "نام مهمان", + "guestNamePlaceholder": "مثلاً علی", + "needTableOrName": "میز، مشتری، یا نام مهمان را وارد کنید", + "openOrders": "سفارش‌های باز", + "openOrdersHint": "سفارش‌هایی که هنوز پرداخت نشده‌اند", + "noOpenOrders": "سفارش بازی برای پرداخت نیست", + "payOrder": "پرداخت", + "payFor": "پرداخت برای", + "selectOrderToPay": "یک سفارش از لیست انتخاب کنید", + "confirmPay": "دریافت وجه", + "confirmPayCash": "دریافت وجه (نقد)", + "confirmPayCard": "دریافت وجه (کارت)", + "confirmPayCredit": "دریافت وجه (اعتبار)", + "confirmPaySplit": "دریافت وجه (ترکیبی)", + "previewBill": "پیش‌نمایش و چاپ صورتحساب", + "paySuccess": "پرداخت ثبت شد", + "payError": "خطا در ثبت پرداخت", + "payNeedsOpenShift": "ابتدا صندوق این شعبه را باز کنید (شیفت)", + "cancelOrder": "لغو سفارش (بدون پرداخت)", + "cancelOrderConfirm": "مشتری بدون پرداخت رفته است؟ سفارش لغو می‌شود و میز آزاد می‌شود.", + "cancelOrderSuccess": "سفارش لغو شد", + "cancelOrderError": "لغو سفارش ناموفق بود", + "itemsCount": "قلم", + "applyCoupon": "اعمال کوپن", + "couponPlaceholder": "کد کوپن", + "couponCode": "کد کوپن", + "selectTable": "میز", + "emptyCart": "سبد خالی است", + "cash": "نقد", + "card": "کارت", + "clearCart": "پاک کردن", + "allCategories": "همه", + "searchItems": "جستجوی آیتم", + "searchItemsPlaceholder": "نام آیتم را جستجو کنید…", + "searchNoResults": "آیتمی با این عبارت یافت نشد", + "reservationBanner": "رزرو: {name} — آیتم‌ها را اضافه کنید و «ثبت و پرداخت» بزنید", + "orderSuccess": "سفارش ثبت شد", + "orderError": "خطا در ثبت سفارش", + "orderInvalid": "سفارش نامعتبر است (منو یا میز را بررسی کنید)", + "orderNotOpen": "این سفارش دیگر باز نیست", + "orderValidation": "اطلاعات سفارش نامعتبر است", + "nothingPending": "آیتم جدیدی برای ارسال به آشپزخانه نیست", + "couponApplied": "کوپن «{code}» اعمال شد — {amount} تخفیف", + "couponActive": "کوپن {code}", + "couponRemoved": "کوپن حذف شد", + "removeCoupon": "حذف", + "couponInvalid": "کد کوپن نامعتبر است", + "couponExpired": "این کوپن منقضی شده است", + "couponNotStarted": "این کوپن هنوز فعال نیست", + "couponLimitReached": "سقف استفاده از این کوپن پر شده", + "couponMinOrder": "حداقل مبلغ سفارش برای این کوپن رعایت نشده", + "couponCartEmpty": "ابتدا آیتم به سبد اضافه کنید", + "couponRequired": "کد کوپن را وارد کنید", + "guestPhone": "موبایل مهمان", + "guestPhonePlaceholder": "09121234567", + "selectTableBoard": "انتخاب میز", + "loadingTables": "بارگذاری میزها...", + "selectBranchForTables": "ابتدا شعبه را انتخاب کنید", + "noTablesOnBoard": "میزی برای این شعبه ثبت نشده. از بخش میزها میز اضافه کنید.", + "tablesLoadError": "بارگذاری میزها ناموفق بود", + "retryTables": "تلاش مجدد", + "manageTablesLink": "رفتن به مدیریت میزها", + "sessionActive": "سفارش فعال روی میز", + "addToOrder": "به سفارش میز اضافه شد", + "void": "ابطال", + "voidItem": "ابطال آیتم", + "voided": "ابطال شده", + "confirmVoid": "آیا مطمئن هستید که می‌خواهید این آیتم را ابطال کنید؟", + "voidError": "خطا در ابطال آیتم", + "transferTable": "انتقال میز", + "selectTargetTable": "میز مقصد را انتخاب کنید", + "transferSuccess": "سفارش با موفقیت منتقل شد", + "transferError": "خطا در انتقال میز", + "tableNotAvailable": "میز در حال نظافت است", + "tableOccupied": "میز مشغول است", + "searchOpenOrder": "میز، نام، موبایل یا شناسه سفارش...", + "paidSoFar": "پرداخت‌شده", + "remaining": "مانده", + "loyaltyBalance": "امتیاز مشتری: {points}", + "loyaltyUseMax": "حداکثر", + "loyaltyRedeemHint": "هر ۱ امتیاز = ۱۰۰ ت تخفیف روی همین پرداخت", + "loyaltyRedeemApplied": "تخفیف امتیاز", + "loyaltyNoCustomer": "برای استفاده از امتیاز، مشتری را به سفارش وصل کنید", + "loyaltyInsufficient": "امتیاز کافی نیست", + "splitPayments": "پرداخت ترکیبی", + "addPaymentRow": "ردیف پرداخت", + "credit": "اعتبار", + "paySelectTable": "انتخاب میز (اشغال)", + "payPickByName": "یا از نام / لیست سفارش‌های باز", + "payOpenOrdersHint": "میز اشغال را بزنید، از منوی میز انتخاب کنید، یا نام/موبایل را جستجو کنید", + "allTables": "همه میزها", + "noOrderOnTable": "سفارش بازی روی این میز نیست", + "noOpenOrdersOnTable": "سفارش بازی برای این میز نیست", + "customerSection": "مشتری", + "existingCustomer": "مشتری موجود", + "newCustomer": "مهمان جدید", + "customerSearchPlaceholder": "نام، موبایل یا کد ملی...", + "customerSearchHint": "حداقل ۲ حرف برای جستجو", + "customerNotFound": "مشتری یافت نشد — مهمان جدید ثبت کنید", + "customerSaved": "مشتری در CRM ذخیره شد", + "customerSaveError": "خطا در ذخیره مشتری", + "customerPhoneExists": "این موبایل قبلاً ثبت شده — از جستجو انتخاب کنید", + "newCustomerHint": "می‌توانید فقط برای این سفارش نام بزنید یا با «افزودن مشتری» در CRM ذخیره کنید", + "offlineQueueNotice": "آفلاین ‐ سفارش در صف ذخیره شد و پس از اتصال ارسال می‌شود" + }, + "print": { + "printReceipt": "چاپ رسید", + "printKitchen": "ارسال به آشپزخانه", + "success": "رسید با موفقیت چاپ شد", + "notConfigured": "آدرس پرینتر تنظیم نشده است", + "connectionFailed": "خطا در اتصال به پرینتر", + "testPrint": "تست پرینت", + "printerSettings": "تنظیمات پرینتر", + "receiptPrinter": "پرینتر رسید", + "kitchenPrinter": "پرینتر آشپزخانه", + "paperWidth": "عرض کاغذ", + "autoCut": "برش خودکار", + "port": "پورت", + "receiptHeader": "سرتیتر رسید", + "receiptFooter": "پاورقی رسید", + "wifiOnReceipt": "رمز WiFi روی رسید", + "saveSettings": "ذخیره تنظیمات", + "settingsSaved": "تنظیمات پرینتر ذخیره شد", + "noBranchForPrinter": "برای تنظیم پرینتر ابتدا یک شعبه در سیستم ثبت کنید.", + "testPageHint": "یک رسید تست به پرینترهای ذخیره‌شده ارسال می‌شود. ابتدا IP و پورت را در تنظیمات پرینتر وارد کنید.", + "testPrintReceipt": "چاپ تست رسید", + "testPrintKitchen": "چاپ تست آشپزخانه", + "configurePrinters": "رفتن به تنظیمات پرینتر", + "posDeviceSection": "دستگاه پوز (کارتخوان)", + "posDeviceHint": "هنگام پرداخت کارتی، مبلغ به آدرس HTTP دستگاه ارسال می‌شود (POST /pay).", + "posDeviceIp": "آدرس IP دستگاه پوز" + }, + "receipt": { + "table": "میز", + "order": "سفارش", + "guest": "مهمان", + "total": "مجموع", + "print": "چاپ", + "close": "بستن", + "thankYou": "ممنون از انتخاب شما", + "kitchenTitle": "فیش آشپزخانه / بار", + "billTitle": "صورتحساب مشتری", + "kitchenFooter": "— برای آشپزخانه —", + "payment": { + "cash": "نقد", + "card": "کارت", + "credit": "اعتبار" + } + }, + "crm": { + "title": "مشتریان", + "searchPlaceholder": "نام، موبایل یا کد ملی...", + "addCustomer": "مشتری جدید", + "name": "نام", + "phone": "موبایل", + "nationalId": "کد ملی", + "birthDate": "تاریخ تولد (شمسی)", + "group": "گروه", + "loyaltyPoints": "امتیاز", + "noCustomers": "مشتری‌ای یافت نشد", + "groups": { + "Regular": "عادی", + "Vip": "ویژه", + "New": "جدید", + "Employee": "کارمند" + }, + "wizard": { + "titleCreate": "ثبت مشتری جدید", + "titleEdit": "ویرایش مشتری", + "stepOf": "مرحله {current} از {total}", + "steps": { + "contact": "تماس", + "profile": "اطلاعات تکمیلی", + "loyalty": "گروه و امتیاز", + "confirm": "بازبینی" + }, + "back": "قبلی", + "next": "بعدی", + "birthHint": "فرمت شمسی، مثلاً 1400/01/01", + "referredBy": "معرف (اختیاری)", + "loyaltyCreateHint": "امتیاز وفاداری پس از ثبت، از طریق سفارش‌ها قابل تنظیم است.", + "errors": { + "duplicatePhone": "این شماره موبایل قبلاً ثبت شده است.", + "generic": "ذخیره انجام نشد. دوباره تلاش کنید." + } + } + }, + "coupons": { + "title": "کوپن‌ها", + "addCoupon": "کوپن جدید", + "code": "کد", + "type": "نوع", + "value": "مقدار", + "usage": "استفاده", + "active": "فعال", + "inactive": "غیرفعال", + "types": { + "Percentage": "درصد", + "FixedAmount": "مبلغ ثابت", + "FreeItem": "آیتم رایگان" + }, + "noCoupons": "کوپنی ثبت نشده" + }, + "hr": { + "title": "منابع انسانی", + "tabs": { + "attendance": "حضور و غیاب", + "leave": "مرخصی", + "payroll": "حقوق" + }, + "myAttendance": "حضور من", + "clockIn": "ورود", + "clockOut": "خروج", + "approve": "تأیید", + "noLeave": "درخواست مرخصی در انتظار نیست", + "paid": "پرداخت شده", + "markPaid": "ثبت پرداخت", + "employeeCount": "تعداد کارمندان", + "monthYear": "ماه حقوق" + }, + "reviews": { + "title": "نظرات مشتریان", + "summary": "میانگین امتیاز", + "reviewCount": "{count} نظر", + "empty": "هنوز نظری ثبت نشده است.", + "ownerReply": "پاسخ کافه", + "reply": "پاسخ دادن", + "replyPlaceholder": "پاسخ خود را بنویسید..." + }, + "sms": { + "title": "پیامک بازاریابی", + "message": "متن پیام", + "messagePlaceholder": "متن پیامک را بنویسید...", + "targetGroup": "گروه هدف", + "allCustomers": "همه مشتریان", + "send": "ارسال", + "usage": "مصرف این ماه", + "unlimited": "نامحدود", + "sent": "ارسال شد", + "failed": "ناموفق" + }, + "reports": { + "title": "گزارش‌ها و تحلیل", + "subtitle": "خلاصه فروش بر اساس گزارش روزانه", + "exportCsv": "دانلود CSV", + "fromDate": "از تاریخ", + "toDate": "تا تاریخ", + "branch": "شعبه", + "allBranches": "همه شعبه‌ها", + "preset": { + "7d": "۷ روز", + "30d": "۳۰ روز", + "90d": "۹۰ روز" + }, + "kpiTotalRevenue": "کل فروش", + "kpiTotalOrders": "تعداد سفارش", + "kpiAvgOrder": "میانگین سفارش", + "kpiNetIncome": "درآمد خالص", + "kpiTotalExpenses": "جمع هزینه‌ها", + "vsPrevious": "نسبت به دوره قبل", + "revenueChartTitle": "روند فروش روزانه", + "paymentMixTitle": "روش پرداخت", + "branchCompareTitle": "مقایسه شعب", + "topProductsTitle": "پرفروش‌ترین محصولات", + "colProduct": "نام محصول", + "colQuantity": "تعداد", + "colRevenue": "درآمد", + "revenue": "درآمد", + "cash": "نقد", + "card": "کارت", + "credit": "اعتبار", + "noData": "داده‌ای نیست", + "loading": "در حال بارگذاری...", + "csvDate": "تاریخ", + "csvBranch": "شعبه", + "csvTotalRevenue": "کل فروش", + "csvTotalOrders": "تعداد سفارش", + "csvAvgOrder": "میانگین سفارش", + "csvCash": "نقد", + "csvCard": "کارت", + "csvCredit": "اعتبار", + "csvNetIncome": "درآمد خالص", + "csvVoids": "ابطال‌ها", + "csvVoidAmount": "مبلغ ابطال", + "csvExpenses": "هزینه‌ها" + }, + "shifts": { + "title": "شیفت صندوق", + "subtitle": "باز و بستن صندوق روزانه", + "branch": "شعبه", + "openShift": "باز کردن شیفت", + "shiftOpen": "شیفت باز است", + "startShift": "شروع شیفت", + "closeShift": "بستن شیفت", + "confirmClose": "تأیید بستن", + "openingCash": "موجودی اول صندوق", + "expectedCash": "مبلغ مورد انتظار", + "countedCash": "نقد شمارش‌شده", + "opened": "شیفت باز شد", + "closed": "شیفت بسته شد" + }, + "expenses": { + "title": "هزینه‌ها", + "subtitle": "ثبت و پیگیری هزینه‌های شعبه", + "addExpense": "ثبت هزینه", + "listTitle": "لیست هزینه‌ها", + "branch": "شعبه", + "fromDate": "از تاریخ", + "toDate": "تا تاریخ", + "periodTotal": "جمع دوره", + "category": "دسته", + "amount": "مبلغ", + "note": "توضیح", + "notePlaceholder": "اختیاری", + "linkOpenShift": "کسر از صندوق باز (برداشت نقدی)", + "noOpenShift": "صندوق باز نیست — هزینه بدون ارتباط با شیفت ثبت می‌شود", + "colDate": "تاریخ", + "colCategory": "دسته", + "colNote": "توضیح", + "colAmount": "مبلغ", + "loading": "در حال بارگذاری...", + "empty": "هزینه‌ای ثبت نشده", + "rowCount": "{count} ردیف", + "categories": { + "Supplies": "ملزومات", + "Utilities": "آب و برق و گاز", + "Salary": "حقوق", + "Rent": "اجاره", + "Maintenance": "تعمیرات", + "Other": "سایر" + } + }, + "queue": { + "title": "نوبت‌دهی روزانه", + "subtitle": "شماره نوبت هر روز از ۱ شروع می‌شود (بر اساس تاریخ ایران)", + "nowServing": "نوبت فعلی", + "lastIssued": "آخرین شماره", + "waitingCount": "{count} نفر در صف", + "issueNext": "شماره جدید", + "callNext": "فراخوانی نوبت بعدی", + "customerLabelPlaceholder": "نام مهمان (اختیاری)", + "dailyResetHint": "هر شب نیمه‌شب به‌وقت ایران شماره‌ها صفر می‌شوند.", + "empty": "امروز هنوز نوبتی صادر نشده.", + "issuedOnOrder": "نوبت {number}", + "openDisplay": "نمایشگر TV", + "displayMode": "نمایش تمام‌صفحه", + "exitDisplay": "بازگشت به پنل", + "displayWaitingLabel": "در صف", + "displayUpNext": "نوبت‌های بعدی", + "status": { + "Waiting": "در انتظار", + "Called": "فراخوانده", + "Done": "انجام شد", + "Cancelled": "لغو" + } + }, + "kds": { + "title": "نمایشگر آشپزخانه", + "pending": "در انتظار", + "preparing": "در حال آماده‌سازی", + "ready": "آماده", + "table": "میز", + "noOrders": "سفارشی نیست", + "loading": "در حال بارگذاری...", + "live": "زنده", + "polling": "به‌روزرسانی دوره‌ای", + "advance": "مرحله بعد", + "status": { + "Pending": "در انتظار", + "Confirmed": "تأیید شده", + "Preparing": "در حال آماده‌سازی", + "Ready": "آماده", + "Delivered": "تحویل شده", + "Cancelled": "لغو شده" + }, + "advanceTo": { + "Confirmed": "تأیید سفارش", + "Preparing": "شروع آماده‌سازی", + "Ready": "آماده شد", + "Delivered": "تحویل شد" + } + }, + "tables": { + "title": "مدیریت میزها", + "addTable": "افزودن میز", + "number": "شماره میز", + "capacity": "ظرفیت", + "floor": "طبقه", + "floorPlan": "نقشه سالن", + "empty": "میزی ثبت نشده است.", + "emptyBranch": "برای این شعبه میزی ثبت نشده است.", + "allBranches": "همه شعب", + "branchFilter": "فیلتر شعبه", + "branch": "شعبه", + "branchUnassigned": "بدون شعبه", + "branchHint": "میزها متعلق به کافه شماست؛ شعبه فقط برای صندوق و گزارش است.", + "tableLabel": "میز {number}", + "meta": "ظرفیت {capacity} · طبقه {floor}", + "status": { + "Free": "آزاد", + "Busy": "مشغول", + "Reserved": "رزرو", + "Cleaning": "نظافت", + "free": "آزاد", + "occupied": "مشغول", + "reserved": "رزرو", + "cleaning": "نظافت" + }, + "markCleaning": "نیاز به نظافت", + "markReady": "آماده پذیرش", + "activeOrder": "سفارش فعال", + "reserved": "رزرو شده", + "printQr": "چاپ QR", + "qrMenuUrl": "لینک منوی مهمان", + "openQrUrl": "باز کردن", + "copyQrUrl": "کپی لینک", + "qrUrlCopied": "لینک کپی شد", + "qrUrlCopyFailed": "کپی لینک ناموفق بود", + "reprintHint": "QR گم شده؟ همان دکمه — کد ثابت است.", + "deactivate": "غیرفعال", + "inactive": "غیرفعال", + "edit": "ویرایش", + "editTable": "ویرایش میز", + "reactivate": "فعال‌سازی مجدد", + "saveTable": "ذخیره میز", + "media": "تصویر و ویدیو میز", + "section": "بخش", + "sections": "بخش‌ها", + "addSection": "افزودن بخش", + "noSection": "بدون بخش", + "noSectionsYet": "هنوز بخشی تعریف نشده است.", + "sectionTableCount": "{count} میز", + "sectionHasTables": "این بخش دارای میز است و قابل حذف نیست", + "tableHasOpenOrder": "این میز دارای سفارش باز است", + "deleteTable": "حذف میز", + "deleteTableConfirm": "این میز برای همیشه حذف شود؟ (فقط وقتی سفارش باز ندارد)", + "deleteError": "حذف میز ناموفق بود", + "createError": "افزودن میز ناموفق بود", + "cleaningError": "تغییر وضعیت نظافت ناموفق بود" + }, + "menuAdmin": { + "title": "مدیریت منو", + "subtitle": "تصویر، قیمت و تخفیف هر آیتم", + "categories": "دسته‌ها", + "items": "آیتم‌ها", + "addCategory": "دسته جدید", + "addItem": "افزودن", + "name": "نام", + "nameEn": "نام انگلیسی (برای مهمان خارجی)", + "price": "قیمت (ت)", + "category": "دسته", + "available": "موجود", + "unavailable": "ناموجود", + "discountPercent": "تخفیف (٪)", + "discountBadge": "تخفیف", + "uploadImage": "آپلود تصویر", + "imageReady": "تصویر آماده است", + "empty": "هنوز آیتمی نیست.", + "editItem": "ویرایش", + "editCategory": "ویرایش دسته", + "categoryIcon": "آیکون (ایموجی)", + "categoryImage": "تصویر دسته", + "iconTabPreset": "آیکون آماده", + "iconTabEmoji": "ایموجی", + "iconTabImage": "تصویر آپلود", + "iconStyleLabel": "سبک طراحی", + "iconPreview": "پیش‌نمایش:", + "clearIconPreset": "حذف آیکون", + "clearIconEmoji": "حذف ایموجی", + "categoryIconCustom": "یا ایموجی دلخواه", + "iconPresetGroupDrinks": "نوشیدنی", + "iconPresetGroupFood": "غذا", + "iconStyles": { + "flat": "فلت", + "modern": "مدرن", + "real": "واقعی", + "minimal": "مینیمال", + "outline": "خطی", + "soft": "نرم", + "bold": "پررنگ", + "gradient": "گرادیان", + "pastel": "پاستلی", + "duotone": "دو رنگ" + }, + "iconEmojiGroups": { + "hotDrinks": "نوشیدنی گرم", + "coldDrinks": "نوشیدنی سرد", + "breakfast": "صبحانه", + "mains": "غذای اصلی", + "pastaPizza": "پاستا و پیتزا", + "desserts": "دسر و شیرینی", + "salads": "سالاد و سبزی", + "seafoodGrill": "گریل و دریایی", + "snacks": "اسنک و فست‌فود", + "vegan": "گیاهی", + "specials": "ویژه و پرومو", + "general": "عمومی" + }, + "iconPresets": { + "drinks-hot": "قهوه گرم", + "drinks-cold": "نوشیدنی سرد", + "drinks-tea": "چای", + "drinks-juice": "آبمیوه", + "drinks-milkshake": "شیر و اسموتی", + "drinks-alcohol": "شراب", + "drinks-beer": "آبجو", + "breakfast": "صبحانه", + "food-mains": "غذای اصلی", + "food-fastfood": "فست‌فود", + "food-rice": "برنج و پلو", + "pasta-pizza": "پاستا و پیتزا", + "dessert": "دسر", + "ice-cream": "بستنی", + "bakery": "نان و شیرینی", + "salad": "سالاد", + "grill": "گریل", + "seafood": "دریایی", + "snacks": "ساندویچ", + "snacks-sweet": "شیرینی خشک", + "appetizers": "پیش‌غذا", + "vegan": "گیاهی", + "fruits": "میوه", + "specials": "ویژه", + "chef-special": "پیشنهاد سرآشپز", + "generic": "عمومی" + }, + "media": "تصویر و ویدیو", + "tabCatalog": "کاتالوگ", + "tabBranch": "تنظیمات شعبه", + "selectBranchForOverrides": "برای تنظیم منوی شعبه، یک شعبه از بالا انتخاب کنید." + }, + "branchMenu": { + "title": "منوی شعبه", + "name": "نام", + "masterPrice": "قیمت اصلی", + "branchPrice": "قیمت شعبه", + "availability": "وضعیت", + "available": "فعال", + "unavailable": "غیرفعال", + "resetOverride": "بازنشانی", + "savePrice": "ذخیره", + "actions": "عملیات", + "priceOverridePro": "قیمت‌گذاری اختصاصی برای پلن Pro", + "overrideActive": "تنظیمات شعبه فعال", + "confirmReset": "آیا می‌خواهید تنظیمات این آیتم را به حالت پیش‌فرض برگردانید؟", + "loading": "در حال بارگذاری..." + }, + "media": { + "uploadImage": "آپلود تصویر", + "uploadVideo": "آپلود ویدیو", + "removeImage": "حذف تصویر", + "removeVideo": "حذف ویدیو", + "upload3dTitle": "نمای سه‌بعدی (اختیاری)", + "upload3dHint": "فایل GLB تا {maxMb} مگابایت — با لمس، مهمان می‌تواند آیتم را بچرخاند", + "upload3dPhotoCount": "علاوه بر عکس کاور: یک مدل GLB کافی است. برای چرخش ۳۶۰° با عکس (آینده): {min} تا {ideal} عکس از زوایای مختلف", + "upload3d": "آپلود مدل ۳D", + "remove3d": "حذف مدل", + "upload3dReady": "مدل ۳D آماده نمایش در منوی QR است", + "ai3dTitle": "تولید مدل ۳D با هوش مصنوعی", + "ai3dHint": "از عکس محصول، مدل GLB برای منوی QR ساخته می‌شود (پلن کسب‌وکار و بالاتر).", + "ai3dGenerate": "ساخت ۳D با AI", + "ai3dGenerating": "در حال ساخت…", + "ai3dUsage": "سهمیه ماهانه: {used} از {limit}", + "ai3dSuccess": "مدل ۳D ساخته شد.", + "ai3dFailed": "ساخت مدل ۳D ناموفق بود.", + "ai3dLimitReached": "سهمیه ماهانه AI (۱۰۰ بار) تمام شده است.", + "ai3dNoImage": "ابتدا عکس محصول را آپلود کنید." + }, + "taxes": { + "title": "مالیات و عوارض", + "subtitle": "نرخ مالیات برای دسته‌های منو", + "addTax": "افزودن مالیات", + "name": "نام (مثلاً مالیات بر ارزش افزوده)", + "rate": "نرخ (٪)", + "hint": "مالیات پیش‌فرض روی دسته‌های جدید اعمال می‌شود. ارسال به تاراز از تنظیمات.", + "empty": "مالیاتی تعریف نشده.", + "default": "پیش‌فرض", + "setDefault": "پیش‌فرض کن", + "delete": "حذف", + "deleteConfirm": "«{name}» از لیست حذف شود؟ دسته‌های منو که به این مالیات وصل بودند به مالیات پیش‌فرض بعدی (یا بدون مالیات) منتقل می‌شوند.", + "required": "اجباری", + "optional": "اختیاری", + "ownerOnly": "فقط مالک کافه می‌تواند مالیات را تغییر دهد." + }, + "branches": { + "label": "شعبه" + }, + "inventory": { + "title": "انبار", + "subtitle": "مواد اولیه، رسپی هر آیتم منو و کسر خودکار پس از سفارش", + "description": "موجودی مواد را ثبت و تنظیم کنید.", + "tabMaterials": "مواد", + "tabRecipes": "رسپی منو", + "addIngredient": "ماده جدید", + "name": "نام", + "unit": "واحد", + "unitHint": "گرم، میلی‌لیتر، عدد...", + "unitCustom": "واحد دیگر (دستی)", + "unitCustomPlaceholder": "مثلاً فنجان، شات", + "unitsHelp": "واحد برای موجودی و رسپی: عدد (لیوان)، گرم، میلی‌لیتر و... — مقدار فعلی با +/- زیر هر کارت تغییر می‌کند.", + "units": { + "piece": "عدد (شمارشی)", + "gram": "گرم", + "kilogram": "کیلوگرم", + "milliliter": "میلی‌لیتر", + "liter": "لیتر", + "cc": "سی‌سی", + "pack": "بسته", + "can": "قوطی", + "bag": "کیسه" + }, + "editIngredient": "ویرایش ماده", + "updated": "ماده به‌روز شد", + "quantityEditHint": "موجودی فقط با فیلد +/- در همین کارت", + "quantity": "موجودی فعلی", + "parLevel": "سطح پر (مثلاً ۵۰۰ گرم)", + "unitCost": "قیمت واحد (تومان)", + "warningPercent": "درصد هشدار کمبود", + "reorderLevel": "حد مطلق هشدار", + "reorder": "حد هشدار", + "warningAt": "هشدار زیر", + "stockValue": "ارزش موجودی", + "lowStock": "کمبود", + "lowStockAlert": "مواد زیر سطح هشدار — موجودی را شارژ کنید", + "adjust": "اعمال", + "adjustDelta": "+/- مقدار", + "adjustNote": "تنظیم دستی", + "adjusted": "موجودی به‌روز شد", + "created": "ماده ثبت شد", + "empty": "ماده‌ای ثبت نشده.", + "defaultUnit": "عدد", + "selectMenuItem": "آیتم منو", + "selectMenuItemPlaceholder": "انتخاب کنید...", + "recipeLines": "مواد مصرفی برای هر واحد فروش", + "perUnit": "مقدار", + "pickIngredient": "ماده", + "addLine": "افزودن", + "saveRecipe": "ذخیره رسپی", + "recipeSaved": "رسپی ذخیره شد", + "materialCostPerUnit": "هزینه مواد هر واحد", + "recipeHint": "مثال: اسپرسو = ۱۰ گرم پودر قهوه برای هر فنجان؛ با ۱۰ سفارش، ۱۰۰ گرم کم می‌شود.", + "totalPaid": "مبلغ پرداختی (تومان)", + "impliedUnitCost": "قیمت واحد محاسبه‌شده", + "purchaseNote": "خرید / ورود به انبار", + "purchaseHint": "برای ورود موجودی (+) مبلغ پرداختی را وارد کنید — در هزینه‌ها و گزارش ثبت می‌شود.", + "purchaseRequired": "برای افزایش موجودی، مبلغ پرداختی و شعبه لازم است.", + "purchasesThisMonth": "خرید مواد این ماه", + "purchaseCount": "{count} خرید", + "viewInExpenses": "مشاهده در هزینه‌ها", + "selectBranchForPurchases": "برای ثبت خرید انبار، ابتدا شعبه را از نوار بالا انتخاب کنید." + }, + "qr": { + "brand": "میزی", + "notFound": "میز یافت نشد", + "loadError": "خطا در بارگذاری", + "tableLabel": "میز {number}", + "hint": "برای سفارش، اپلیکیشن میزی را باز کنید یا به صندوق مراجعه کنید.", + "discoverCta": "کافه‌یاب میزی" + }, + "qrMenu": { + "loading": "در حال بارگذاری...", + "welcome": "خوش آمدید", + "tableLabel": "میز", + "tableNotFound": "میز یافت نشد یا منو در دسترس نیست", + "tableCleaning": "میز در حال نظافت است — لطفاً کارکنان را مطلع کنید", + "loadError": "خطا در بارگذاری منو", + "scanAgain": "لطفاً دوباره کد QR را اسکن کنید", + "addToCart": "افزودن", + "viewCart": "مشاهده سبد خرید", + "cartTitle": "سبد خرید", + "placeOrder": "ثبت سفارش", + "orderPlaced": "سفارش ثبت شد!", + "orderNumber": "شماره سفارش: {number}", + "orderHint": "کارکنان به زودی سفارش شما را آماده می‌کنند", + "guestName": "نام شما (اختیاری)", + "guestPhone": "شماره موبایل (اختیاری)", + "addMoreItems": "افزودن آیتم دیگر", + "orderError": "خطا در ثبت سفارش. دوباره امتحان کنید", + "orderSaveError": "سفارش ثبت شد اما ذخیره محلی ناموفق بود. صفحه را رفرش نکنید.", + "rateLimited": "درخواست‌های زیاد — لطفاً چند دقیقه صبر کنید", + "captchaRequired": "لطفاً تأیید امنیتی را تکمیل کنید", + "cafeUnavailable": "این کافه موقتاً در دسترس نیست", + "subtotal": "جمع کل", + "searchPlaceholder": "جستجو در منو...", + "allCategories": "همه", + "searchNoResults": "آیتمی با این عبارت پیدا نشد", + "clearSearch": "پاک کردن جستجو", + "emptyCategory": "آیتمی در این دسته نیست", + "view3d": "۳D", + "view3dHint": "با انگشت بچرخانید — مدل به‌صورت زنده می‌چرخد", + "close3d": "بستن", + "emptyMenu": "منوی این شعبه خالی است یا در دسترس نیست", + "guestQrBadge": "سفارش QR مهمان", + "tabMenu": "منو", + "tabOrders": "سفارش‌های من", + "callWaiter": "صدا کردن گارسون", + "callWaiterSent": "گارسون در راه است!", + "callWaiterCooldown": "لطفاً ۶۰ ثانیه صبر کنید", + "callWaiterError": "خطا — دوباره امتحان کنید", + "myOrders": "سفارش‌های این میز", + "noOrders": "هنوز سفارشی ثبت نکرده‌اید", + "tracking": { + "back": "بازگشت به منو", + "orderNumber": "شماره سفارش", + "table": "میز", + "loadError": "پیگیری سفارش ممکن نیست", + "currentStep": "در حال انجام", + "readyHint": "سفارش شما آماده است — از میز یا پیشخوان تحویل بگیرید", + "status": { + "pending": "در انتظار تأیید کافه", + "seen": "کافه سفارش را دید", + "preparing": "آشپزخانه شروع به آماده‌سازی کرد", + "ready": "آماده تحویل", + "done": "تحویل شد", + "cancelled": "لغو شد" + }, + "steps": { + "submitted": "ثبت سفارش", + "seen": "دیده شد توسط رستوران", + "preparing": "در حال آماده‌سازی", + "ready": "آماده", + "done": "تحویل شده", + "cancelled": "لغو شده" + } + } + }, + "notifications": { + "title": "اعلان‌ها", + "pageTitle": "اعلان‌ها", + "empty": "اعلانی نیست", + "emptyUnread": "اعلان خوانده‌نشده‌ای نیست", + "markAllRead": "خواندن همه", + "unreadCount": "{count} اعلان خوانده‌نشده", + "filterLabel": "فیلتر اعلان‌ها", + "filterAll": "همه", + "filterUnread": "خوانده‌نشده", + "loading": "در حال بارگذاری...", + "refreshing": "به‌روزرسانی...", + "backToList": "بازگشت به لیست" + }, + "reservations": { + "title": "رزرو میز", + "guest": "مهمان", + "phone": "موبایل", + "date": "تاریخ", + "time": "ساعت", + "party": "نفر", + "table": "میز", + "tableOptional": "بدون میز مشخص", + "tableNumber": "میز {number}", + "notes": "یادداشت", + "confirm": "تأیید", + "cancel": "لغو", + "create": "ثبت رزرو", + "newReservation": "رزرو دستی", + "newReservationHint": "میز و زمان را مشخص کنید. هنگام حضور مهمان از «ثبت سفارش و پرداخت» در صندوق استفاده کنید.", + "openPos": "ثبت سفارش و پرداخت", + "markCompleted": "پایان ویزیت", + "empty": "رزروی نیست", + "status": { + "Pending": "در انتظار", + "Confirmed": "تأیید شده", + "Cancelled": "لغو شده", + "Seated": "نشسته", + "Completed": "انجام شده" + } + }, + "branchesPage": { + "title": "شعب", + "subtitle": "مدیریت شعب کافه؛ هر شعبه با موبایل ورود جدا و زیر اشتراک کافه اصلی", + "listTitle": "لیست شعب", + "newName": "نام شعبه", + "loginPhone": "موبایل ورود شعبه", + "managerName": "نام مسئول شعبه", + "managerNamePlaceholder": "اختیاری — پیش‌فرض نام شعبه", + "addSection": "شعبه جدید", + "add": "افزودن شعبه", + "empty": "هنوز شعبه‌ای ثبت نشده.", + "created": "شعبه و حساب ورود اضافه شد.", + "createError": "خطا در افزودن شعبه (موبایل تکراری یا سقف پلن)", + "branchSelectHint": "در صندوق و نوبت‌دهی شعبه فعال را انتخاب کنید.", + "masterPlanHint": "اشتراک و مالیات فقط از حساب مالک کافه تنظیم می‌شود.", + "ownerOnly": "فقط مالک کافه می‌تواند شعب را مدیریت کند.", + "delete": "حذف شعبه", + "deleteTitle": "حذف شعبه؟", + "deleteWarning": "میزها، پرسنل، تنظیمات منوی شعبه و داده‌های وابسته حذف می‌شوند. تا ۷ روز می‌توانید شعبه را بازیابی کنید؛ پس از آن حذف دائمی انجام می‌شود.", + "deleteConfirm": "بله، حذف شعبه", + "deleteScheduled": "شعبه برای حذف ثبت شد. تا ۷ روز امکان بازیابی دارید.", + "deleteError": "حذف شعبه انجام نشد (شاید آخرین شعبه فعال باشد).", + "restore": "بازیابی", + "restored": "شعبه بازیابی شد.", + "restoreError": "بازیابی انجام نشد.", + "pendingTitle": "در انتظار حذف دائمی", + "pendingHint": "شعب زیر غیرفعال‌اند. پس از پایان مهلت، به‌طور کامل پاک می‌شوند.", + "purgeInDays": "حذف دائمی تا {days} روز دیگر", + "purgeInOneDay": "حذف دائمی تا فردا", + "purgeToday": "حذف دائمی امروز", + "review": "بررسی", + "reviewTitle": "جزئیات شعبه", + "location": "موقعیت" + }, + "subscription": { + "title": "اشتراک و پلن", + "subtitle": "پلن فعلی، مصرف و ارتقا", + "currentPlan": "پلن فعلی", + "expires": "انقضا", + "noExpiry": "—", + "refresh": "بروزرسانی", + "ordersToday": "سفارش امروز", + "customers": "مشتریان", + "smsUsage": "پیامک این ماه", + "paymentSuccess": "پرداخت موفق بود. پلن شما به‌روز شد.", + "paymentFailed": "پرداخت ناموفق بود.", + "loading": "در حال بارگذاری...", + "ownerOnly": "فقط مالک کافه می‌تواند اشتراک را مدیریت کند. شعب زیر پوشش پلن کافه اصلی هستند.", + "paymentMethod": "روش پرداخت", + "planExpired": "اشتراک منقضی شده", + "featureMenu3d": "منوی سه‌بعدی", + "featureDiscover": "پروفایل کشف (هوش مصنوعی)", + "featureOn": "فعال", + "featureOff": "غیرفعال — ارتقا دهید", + "featureMenu3dUpgrade": "منوی ۳D در پلن حرفه‌ای و بالاتر فعال است.", + "featureMenuAi3d": "تولید ۳D با AI", + "featureMenuAi3dUpgrade": "تولید ۳D با هوش مصنوعی در پلن کسب‌وکار و سازمانی (۱۰۰ بار در ماه) فعال است." + }, + "settings": { + "title": "تنظیمات", + "subtitle": "کافه، پرینتر و یکپارچه‌سازی‌ها", + "terminals": { + "title": "ترمینال‌های فعال", + "hint": "پلن شما حداکثر {max} ترمینال همزمان دارد.", + "thisDevice": "این دستگاه", + "empty": "ترمینالی ثبت نشده", + "revoke": "حذف", + "revoked": "ترمینال حذف شد", + "loading": "در حال بارگذاری…" + }, + "nav": { + "aria": "منوی تنظیمات", + "shop": "کافه و فروشگاه", + "shopGeneral": "پروفایل و اتصال‌ها", + "shopAppearance": "ظاهر و رنگ‌بندی", + "printer": "پرینتر", + "printerSettings": "تنظیمات پرینتر", + "printTest": "صفحه تست چاپ", + "shopDiscover": "کشف و AI" + }, + "appearance": { + "paletteSection": "پالت رنگ", + "paletteTitle": "انتخاب پالت آماده", + "paletteHint": "رنگ پالت روی پنل داشبورد و منوی QR مهمان اعمال می‌شود.", + "dashboardSection": "پنل مدیریت", + "dashboardTitle": "سبک داشبورد", + "dashboardDesc": "ظاهر صفحات پنل (صندوق، انبار، گزارش و…) — جدا از منوی QR میز.", + "dashboardPreviewSection": "پیش‌نمایش", + "dashboardPreviewTitle": "نمونه پنل داشبورد", + "dashboardPreviewHint": "نمونه سایدبار و کارت آیتم در همین پنل؛ با تغییر سبک پنل، فشردگی و گوشه‌ها به‌روز می‌شود.", + "panelStyle": "سبک پنل داشبورد", + "guestMenuStyle": "سبک نمایش منوی QR", + "menuTexture": "بافت پس‌زمینه منوی QR", + "guestMenuSection": "منوی QR میز", + "guestMenuTitle": "قالب منوی مهمان", + "guestMenuDesc": "مشتری با اسکن QR روی میز همین چیدمان و بافت را می‌بیند — جدا از ظاهر پنل شما.", + "guestMenuPreviewSection": "پیش‌نمایش", + "guestMenuPreviewHint": "پیش‌نمایش موبایل (منوی QR)", + "density": "فشردگی", + "radius": "گوشه‌ها", + "customSection": "رنگ سفارشی", + "customTitle": "رنگ‌های اختصاصی کافه", + "customHint": "هر فیلد خالی از پالت انتخاب‌شده استفاده می‌کند. شفافیت روی رنگ سفارشی یا پالت اعمال می‌شود.", + "colorOpacity": "شفافیت", + "resetCustom": "بازنشانی رنگ‌های سفارشی", + "previewSection": "پیش‌نمایش", + "previewTitle": "نمونه پنل و منو", + "previewNav": "منو", + "previewItem": "لاته", + "previewCta": "افزودن", + "saved": "ظاهر ذخیره شد.", + "palettes": { + "meezi-green": "میزی سبز", + "ocean-blue": "اقیانوسی", + "royal-purple": "بنفش سلطنتی", + "sunset-orange": "غروب نارنجی", + "rose-blush": "رز", + "charcoal-gold": "ذغالی طلایی", + "espresso": "اسپرسو", + "forest": "جنگلی", + "midnight": "نیمه‌شب", + "coral": "مرجانی", + "gold-luxury": "لوکس طلایی", + "mint-fresh": "نعنایی", + "wine-bar": "بار شراب", + "slate-modern": "اسلیت مدرن", + "cherry": "گیلاسی", + "teal-wave": "فیروزه‌ای", + "sand-cafe": "کافه شنی" + }, + "panelStyles": { + "flat": "فلت", + "modern": "مدرن", + "glass": "شیشه‌ای", + "minimal": "مینیمال", + "bold": "پررنگ", + "soft": "نرم", + "elevated": "برجسته", + "outline": "خطی" + }, + "menuStyles": { + "cards": "کارت", + "compact": "فشرده", + "grid": "شبکه", + "list": "لیست", + "magazine": "مجله‌ای", + "classic": "کلاسیک" + }, + "menuTextures": { + "none": "ساده", + "paper": "کاغذی", + "linen": "کتان", + "dots": "نقطه‌ای", + "grid": "شبکه‌ای", + "marble": "مرمر", + "wood": "چوب", + "warm": "گرم کافه" + }, + "densities": { + "compact": "فشرده", + "comfortable": "معمولی", + "spacious": "گشاد" + }, + "radiusOptions": { + "none": "تیز", + "sm": "کم", + "md": "متوسط", + "lg": "زیاد", + "full": "گرد" + }, + "colors": { + "primary": "رنگ اصلی", + "secondary": "رنگ ثانویه", + "accent": "تأکید / پرومو", + "background": "پس‌زمینه", + "surface": "کارت / سطح", + "text": "متن", + "textMuted": "متن کم‌رنگ", + "destructive": "خطا / حذف", + "success": "موفقیت" + } + }, + "taraz": "سامانه مودیان (تاراز)", + "tarazHint": "ارسال فاکتورهای روز گذشته به تاراز (در حالت دمو فقط ثبت می‌شود).", + "tarazSubmit": "ارسال به تاراز", + "tarazQueued": "درخواست ارسال ثبت شد.", + "snappfoodVendor": "شناسه فروشنده اسنپ‌فود", + "saveProfile": "ذخیره پروفایل", + "profile": { + "title": "پروفایل کافه", + "name": "نام کافه", + "city": "شهر", + "phone": "تلفن", + "address": "آدرس", + "description": "توضیحات", + "logo": "لوگو", + "uploadLogo": "بارگذاری لوگو", + "uploadCover": "بارگذاری کاور", + "saved": "پروفایل ذخیره شد.", + "reloginHint": "پلن به‌روز شد؛ در صورت نیاز یک‌بار خارج و وارد شوید." + }, + "plans": { + "compareLabel": "مقایسه پلن‌ها", + "compareHint": "امکانات هر پلن را مقایسه کنید و مناسب کافه خود انتخاب کنید.", + "featureColumn": "امکانات", + "popular": "پرفروش", + "current": "پلن فعلی", + "perMonth": "ماهانه", + "freePrice": "رایگان", + "customPrice": "تماس بگیرید", + "unlimited": "نامحدود", + "included": "فعال", + "currentPlanBtn": "پلن شما", + "contactSales": "تماس با فروش", + "subscribe": "خرید {plan}", + "names": { + "Free": "رایگان", + "Pro": "پرو", + "Business": "بیزنس", + "Enterprise": "سازمانی" + }, + "features": { + "ordersPerDay": "سفارش در روز", + "terminals": "ترمینال صندوق", + "crmCustomers": "مشتری CRM", + "smsPerMonth": "پیامک بازاریابی", + "branches": "شعبه", + "posKds": "صندوق و آشپزخانه", + "tablesQr": "میز و QR", + "menuReservations": "منو و رزرو", + "reports": "گزارش‌ها", + "hrModule": "منابع انسانی", + "snappfoodDelivery": "اسنپ‌فود / پیک", + "tarazTax": "سامانه مودیان (تاراز)", + "badges": "نشان اعتبار", + "whiteLabel": "برند اختصاصی", + "apiAccess": "API عمومی" + }, + "levels": { + "basic": "پایه", + "full": "کامل" + } + }, + "discoverProfile": { + "title": "پروفایل کشف و AI", + "subtitle": "برچسب‌ها برای پیشنهاد کافه به مهمان‌ها", + "save": "ذخیره", + "saved": "ذخیره شد", + "loading": "در حال بارگذاری..." + } + }, + "support": { + "title": "پشتیبانی میزی", + "subtitle": "تیکت بزنید تا تیم سامانه پاسخ دهد", + "newTicket": "تیکت جدید", + "subject": "موضوع", + "message": "پیام شما", + "submit": "ارسال تیکت", + "myTickets": "تیکت‌های من", + "messages": "پیام", + "created": "تیکت ثبت شد", + "createFailed": "ثبت تیکت ناموفق بود", + "empty": "هنوز تیکتی ندارید", + "loadFailed": "بارگذاری تیکت‌ها ناموفق بود.", + "retry": "تلاش دوباره", + "loading": "در حال بارگذاری...", + "notFound": "تیکت یافت نشد", + "back": "بازگشت", + "reply": "پاسخ شما", + "send": "ارسال", + "replySent": "پاسخ ارسال شد", + "replyFailed": "ارسال پاسخ ناموفق بود", + "fromAdmin": "پشتیبانی میزی", + "fromYou": "شما", + "closedHint": "این تیکت بسته شده و امکان پاسخ جدید نیست.", + "status": { + "open": "باز", + "inProgress": "در حال بررسی", + "waitingMerchant": "منتظر پاسخ شما", + "resolved": "حل‌شده", + "closed": "بسته" + } + }, + "admin": { + "nav": { + "title": "مدیریت سامانه", + "dashboard": "داشبورد", + "plans": "اشتراک و قیمت", + "integrations": "درگاه و پیامک", + "notifications": "اعلان‌ها", + "settings": "تنظیمات اپ", + "features": "قابلیت‌ها", + "cafes": "کافه‌ها", + "tickets": "تیکت‌ها", + "logout": "خروج" + }, + "auth": { + "title": "ورود مدیر سامانه", + "subtitle": "فقط حساب‌های مجاز میزی", + "phone": "موبایل", + "sendOtp": "ارسال کد", + "otp": "کد تأیید", + "login": "ورود", + "error": "خطا در ورود", + "devHint": "در حالت توسعه کد در لاگ Admin API چاپ می‌شود (DEV admin OTP)." + }, + "dashboard": { + "title": "خلاصه سامانه", + "totalCafes": "کل کافه‌ها", + "activeCafes": "فعال", + "openTickets": "تیکت باز", + "plans": "پلن‌های تعریف‌شده" + }, + "plans": { + "title": "پلن‌ها و قیمت‌گذاری", + "monthlyPrice": "قیمت ماهانه (تومان)", + "maxOrders": "سقف سفارش روزانه", + "saved": "پلن ذخیره شد" + }, + "settings": { + "title": "تنظیمات اپلیکیشن", + "saved": "ذخیره شد" + }, + "features": { + "title": "فعال/غیرفعال قابلیت‌ها", + "enabled": "فعال", + "disabled": "غیرفعال" + }, + "cafes": { + "title": "کافه‌های ثبت‌شده", + "suspended": "معلق", + "suspend": "تعلیق", + "activate": "فعال‌سازی", + "discoverProfile": { + "edit": "پروفایل کشف", + "title": "پروفایل کشف و AI", + "subtitle": "برچسب‌ها برای پیشنهاد کافه به مهمان‌ها", + "save": "ذخیره", + "saved": "ذخیره شد", + "loading": "در حال بارگذاری..." + } + }, + "integrations": { + "title": "درگاه پرداخت و کاوه‌نگار", + "save": "ذخیره تنظیمات", + "saved": "تنظیمات ذخیره شد", + "paymentTitle": "درگاه‌های پرداخت", + "kavenegarTitle": "کاوه‌نگار (پیامک)", + "active": "فعال برای اشتراک", + "enabled": "فعال", + "sandbox": "حالت تست", + "merchantId": "مرچنت آیدی", + "apiKey": "توکن API", + "username": "نام کاربری", + "password": "رمز عبور", + "branchCode": "کد شعبه", + "terminalCode": "کد ترمینال (اختیاری)", + "clientId": "Client ID", + "clientSecret": "Client Secret", + "baseUrl": "آدرس API (اختیاری)", + "taraHint": "تارا — اعتبار خرید. مستندات: api.tara-club.ir/club/api/v1 (login، trace، request، verify)", + "snappPayHint": "اسنپ‌پی — خرید اقساطی (BNPL). OAuth و payment token از پنل پذیرنده اسنپ‌پی", + "otpTemplate": "قالب OTP (نام الگو در پنل کاوه‌نگار)" + }, + "notifications": { + "title": "مرکز اعلان‌ها", + "broadcastTitle": "ارسال اعلان به همه کافه‌ها", + "broadcastTitlePlaceholder": "عنوان اعلان", + "broadcastBodyPlaceholder": "متن اعلان (اختیاری)", + "sendBroadcast": "ارسال به همه", + "broadcastSent": "اعلان به {count} کافه ارسال شد", + "allNotifications": "همه اعلان‌ها", + "empty": "اعلانی ثبت نشده است" + }, + "tickets": { + "title": "تیکت‌های پشتیبانی", + "messages": "پیام", + "loading": "بارگذاری...", + "empty": "تیکتی وجود ندارد", + "notFound": "تیکت یافت نشد", + "back": "لیست تیکت‌ها", + "replyPlaceholder": "پاسخ به کافه...", + "sendReply": "ارسال پاسخ", + "replySent": "پاسخ ارسال شد", + "replyFailed": "ارسال ناموفق بود", + "resolve": "علامت‌گذاری حل‌شده", + "close": "بستن تیکت", + "statusUpdated": "وضعیت تیکت به‌روز شد", + "closedHint": "تیکت بسته است — پاسخ جدید غیرفعال است.", + "fromAdmin": "پشتیبانی میزی", + "fromCafe": "کافه", + "filter": { + "all": "همه", + "open": "باز", + "closed": "بسته" + } + } + }, + "errors": { + "planLimit": "به سقف پلن رسیده‌اید. برای ادامه ارتقا دهید", + "notFound": "یافت نشد", + "unauthorized": "دسترسی ندارید", + "network": "خطای ارتباط با سرور" + }, + "discoverPublic": { + "brand": "میزی", + "title": "کافه‌یاب", + "subtitle": "کافه مناسب خودت را در تهران و کرج پیدا کن", + "searchPlaceholder": "بنویس: آروم، قرار عاشقانه، وای‌فای، رستری، کتاب‌کافه…", + "searchHint": "جستجوی هوشمند — فیلترها را خودکار تشخیص می‌دهد", + "aiDetectedLabel": "فیلترهای تشخیص‌داده‌شده:", + "aiDetectedClear": "پاک کردن", + "loading": "در حال بارگذاری…", + "empty": "کافه‌ای با این فیلترها پیدا نشد", + "resultCount": "{count} کافه", + "applyFilters": "اعمال فیلتر", + "clearFilters": "پاک کردن", + "viewCafe": "مشاهده کافه", + "backToList": "بازگشت به لیست", + "notFound": "کافه یافت نشد", + "exploreMore": "کافه‌های بیشتر", + "reviewCount": "{count} نظر", + "mapTitle": "موقعیت روی نقشه", + "openInNeshan": "باز کردن در نشان", + "reviewsTitle": "نظرات مهمان‌ها", + "ownerReply": "پاسخ کافه", + "coffeeAdvisor": { + "title": "مشاور نوشیدنی", + "subtitle": "بگویید برای چه منظوری می‌آیید تا پیشنهاد مناسب بگیرید", + "placeholder": "مثلاً: کار گروهی، قرار عاشقانه، انرژی برای امتحان…", + "submit": "پیشنهاد بده", + "loading": "در حال فکر کردن…", + "notConfigured": "مشاور هوشمند هنوز برای این کافه فعال نشده", + "failed": "پیشنهاد در دسترس نیست. بعداً دوباره تلاش کنید" + }, + "cities": { + "tehran": "تهران", + "karaj": "کرج" + }, + "sort": { + "rating": "بیشترین امتیاز", + "reviews": "بیشترین نظر", + "name": "نام" + }, + "openNow": "فقط باز", + "openNowLabel": "الان باز", + "closedLabel": "بسته", + "galleryTitle": "گالری تصاویر", + "workingHoursTitle": "ساعت کاری", + "instagramLabel": "اینستاگرام", + "websiteLabel": "وبسایت", + "days": { + "sat": "شنبه", + "sun": "یکشنبه", + "mon": "دوشنبه", + "tue": "سه‌شنبه", + "wed": "چهارشنبه", + "thu": "پنجشنبه", + "fri": "جمعه" + }, + "filters": { + "themes": "تم", + "vibes": "حس و حال", + "occasions": "مناسب برای", + "spaceFeatures": "فضا", + "noise": "سطح صدا", + "priceTier": "قیمت", + "size": "اندازه" + } + }, + "cafePublicProfile": { + "title": "پروفایل عمومی کافه", + "subtitle": "اطلاعاتی که به مهمانان در صفحه کافه‌یاب نمایش داده می‌شود", + "tabs": { + "info": "اطلاعات", + "gallery": "گالری", + "hours": "ساعت کاری", + "social": "شبکه‌های اجتماعی" + }, + "description": "توضیحات کافه", + "descriptionPlaceholder": "درباره کافه، فضا، نوشیدنی‌ها و تجربه‌ای که ارائه می‌دهید بنویسید…", + "instagram": "آدرس اینستاگرام (بدون @)", + "instagramPlaceholder": "mycafe.tehran", + "website": "آدرس وبسایت", + "websitePlaceholder": "https://mycafe.ir", + "gallery": "گالری تصاویر (حداکثر ۸ عکس)", + "galleryHint": "عکس با کیفیت از فضای کافه آپلود کنید — JPEG، PNG یا WebP تا ۵ مگابایت", + "uploadPhoto": "آپلود عکس", + "uploading": "در حال آپلود…", + "uploadFailed": "آپلود ناموفق بود", + "galleryFull": "گالری پر است. ابتدا یک عکس را حذف کنید", + "removePhoto": "حذف", + "workingHours": "ساعت کاری هر روز", + "isOpen": "باز است", + "openTime": "ساعت باز", + "closeTime": "ساعت بسته", + "days": { + "sat": "شنبه", + "sun": "یکشنبه", + "mon": "دوشنبه", + "tue": "سه‌شنبه", + "wed": "چهارشنبه", + "thu": "پنجشنبه", + "fri": "جمعه" + }, + "save": "ذخیره", + "saved": "ذخیره شد", + "saveFailed": "ذخیره ناموفق بود", + "loading": "در حال بارگذاری…" + }, + "discoverProfile": { + "sections": { + "themes": "تم و سبک فضا", + "occasions": "مناسب برای (چند انتخابی)", + "spaceFeatures": "امکانات فضا", + "vibes": "حس و حال", + "size": "اندازه", + "floors": "طبقات", + "noiseLevel": "سطح صدا", + "priceTier": "رده قیمت" + }, + "hints": { + "themes": "برای پیشنهاد هوشمند به مهمان — مثلاً مدرن، سنتی، پر گیاه", + "occasions": "قرار، خانواده، دوستان، پیدا کردن نفر جدید و …", + "spaceFeatures": "فضای باز، بسته، تراس، گیاه و …", + "vibes": "آرام، شلوغ، رمانتیک و …" + }, + "themes": { + "modern": "مدرن", + "minimal": "مینیمال", + "vintage": "رترو", + "industrial": "صنعتی", + "scandi": "اسکاندیناوی", + "persian_traditional": "سنتی ایرانی", + "book_cafe": "کتاب‌کافه", + "roastery": "رستری", + "dessert_focus": "دسرمحور", + "brunch": "برانچ", + "late_night": "شب‌گاه", + "plants_heavy": "پر گیاه", + "instagrammable": "عکاسی", + "heritage": "میراث", + "luxury": "لوکس", + "specialty_coffee": "قهوه تخصصی", + "tea_house": "چای‌خانه", + "art_gallery": "گالری هنر", + "sport_cafe": "کافه ورزشی", + "gaming_cafe": "گیمینگ کافه" + }, + "occasions": { + "date": "قرار عاشقانه", + "family": "با خانواده", + "friends": "با دوستان", + "finding_someone": "پیدا کردن نفر جدید", + "solo": "تنهایی", + "business_meeting": "جلسه کاری", + "study_work": "درس و کار", + "celebration": "جشن", + "quick_coffee": "قهوه سریع", + "breakfast": "صبحانه", + "brunch": "برانچ", + "after_dinner": "بعد از شام", + "group_large": "گروه بزرگ" + }, + "spaceFeatures": { + "indoor": "فضای بسته", + "outdoor": "فضای باز", + "terrace": "تراس", + "rooftop": "پشت‌بام", + "garden": "باغ", + "plants": "گیاه", + "wifi": "وای‌فای", + "parking": "پارکینگ", + "wheelchair": "ویلچر", + "kids_friendly": "مناسب کودک", + "pet_friendly": "حیوان خانگی", + "smoking_area": "سیگار", + "live_music": "موسیقی زنده", + "private_room": "اتاق خصوصی", + "counter_only": "فقط پیشخوان", + "takeaway": "بیرون‌بر", + "hookah": "قلیان", + "board_games": "بازی رومیزی", + "no_smoking": "بدون دود", + "prayer_room": "نمازخانه" + }, + "vibes": { + "quiet": "آرام", + "lively": "شلوغ و پرانرژی", + "romantic": "رمانتیک", + "cozy": "دنج", + "trendy": "ترندی", + "traditional": "سنتی", + "artistic": "هنری", + "luxury": "لوکس", + "casual": "راحت", + "study_friendly": "مناسب درس" + }, + "sizes": { + "tiny": "خیلی کوچک", + "cozy": "دنج", + "medium": "متوسط", + "large": "بزرگ", + "spacious": "فراخ" + }, + "floors": { + "one": "یک طبقه", + "two": "دو طبقه", + "three": "سه طبقه", + "multi": "چند طبقه" + }, + "noiseLevels": { + "quiet": "آرام", + "moderate": "متوسط", + "lively": "پرصدا" + }, + "priceTiers": { + "budget": "اقتصادی", + "mid": "میانه", + "premium": "پریمیوم" + } + } +} \ No newline at end of file diff --git a/web/dashboard/next.config.ts b/web/dashboard/next.config.ts new file mode 100644 index 0000000..f2ddb4b --- /dev/null +++ b/web/dashboard/next.config.ts @@ -0,0 +1,72 @@ +import type { NextConfig } from "next"; +import createNextIntlPlugin from "next-intl/plugin"; +import withPWAInit from "@ducanh2912/next-pwa"; + +const withNextIntl = createNextIntlPlugin("./src/i18n/request.ts"); + +const withPWA = withPWAInit({ + dest: "public", + cacheOnFrontEndNav: true, + aggressiveFrontEndNavCaching: true, + reloadOnOnline: true, + disable: process.env.NODE_ENV === "development", + workboxOptions: { + disableDevLogs: true, + runtimeCaching: [ + // App shell: cache-first, very long TTL + { + urlPattern: /\/_next\/static\//, + handler: "CacheFirst", + options: { + cacheName: "static-assets", + expiration: { maxEntries: 200, maxAgeSeconds: 30 * 24 * 60 * 60 }, + }, + }, + // API: NetworkFirst — show cached data when offline + { + urlPattern: /\/api\//, + handler: "NetworkFirst", + options: { + cacheName: "api-data", + networkTimeoutSeconds: 5, + expiration: { maxEntries: 300, maxAgeSeconds: 10 * 60 }, + }, + }, + // Menu images & media + { + urlPattern: /\.(?:png|jpg|jpeg|svg|gif|webp|ico)$/, + handler: "StaleWhileRevalidate", + options: { + cacheName: "media-cache", + expiration: { maxEntries: 300, maxAgeSeconds: 7 * 24 * 60 * 60 }, + }, + }, + ], + }, +}); + +const adminWebOrigin = + process.env.ADMIN_WEB_ORIGIN ?? "http://localhost:3102"; + +const nextConfig: NextConfig = { + output: "standalone", + experimental: { + optimizePackageImports: ["recharts", "lucide-react"], + }, + async redirects() { + return [ + { + source: "/:locale(fa|ar|en)/admin", + destination: `${adminWebOrigin}/:locale/admin`, + permanent: false, + }, + { + source: "/:locale(fa|ar|en)/admin/:path*", + destination: `${adminWebOrigin}/:locale/admin/:path*`, + permanent: false, + }, + ]; + }, +}; + +export default withPWA(withNextIntl(nextConfig)); diff --git a/web/dashboard/package-lock.json b/web/dashboard/package-lock.json new file mode 100644 index 0000000..2f88b66 --- /dev/null +++ b/web/dashboard/package-lock.json @@ -0,0 +1,9265 @@ +{ + "name": "meezi-dashboard", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "meezi-dashboard", + "version": "0.1.0", + "dependencies": { + "@google/model-viewer": "^4.2.0", + "@microsoft/signalr": "^8.0.7", + "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.2", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-slot": "^1.1.0", + "@tanstack/react-query": "^5.59.20", + "axios": "^1.7.7", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "date-fns-jalali": "^4.1.0-0", + "lucide-react": "^0.454.0", + "next": "16.2.6", + "next-intl": "4.12.0", + "react": "19.2.6", + "react-dom": "19.2.6", + "recharts": "^2.13.3", + "sonner": "^2.0.7", + "tailwind-merge": "^2.5.4", + "zustand": "^5.0.1" + }, + "devDependencies": { + "@playwright/test": "^1.49.0", + "@types/node": "^22.9.0", + "@types/react": "19.1.4", + "@types/react-dom": "19.1.4", + "autoprefixer": "^10.4.20", + "eslint": "^8.57.1", + "eslint-config-next": "16.2.6", + "postcss": "^8.4.47", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "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": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "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": { + "tslib": "^2.4.0" + } + }, + "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", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@formatjs/fast-memoize": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.5.tgz", + "integrity": "sha512-KLi3fan6WnCHmigd9pmEEN8Hid0v4wiFBW576M/d07KMWYecf1CvyMI3n34vCmHT4AoVqG2n702kiHbXjzZX2A==", + "license": "MIT" + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.10.tgz", + "integrity": "sha512-XeJihYLy1lCe19xfK1KWKG/betBOK2rB0luL8lSkjfvJj0zP+LTJvkC+RKd0jsFI8mWxN71LrarHSrEXE8xxOQ==", + "license": "MIT", + "dependencies": { + "@formatjs/icu-skeleton-parser": "2.1.9" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.9.tgz", + "integrity": "sha512-rsxswgHMfU1zUgB2byc08fesf83wLGjFnzLCEtuf00mx2doiqc6pYrf67raI37XqdRcGUviQepk2UKGqpng74Q==", + "license": "MIT" + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.8.8.tgz", + "integrity": "sha512-pBr2hVKWvkHVnfXegW+53NT9U2uaVQCc+EgzLPCCwXqBA3nvM5fPbK9IcJlNjV+NMKGyZ2F3ZSG78iGdxAAqbA==", + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "3.1.5" + } + }, + "node_modules/@google/model-viewer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@google/model-viewer/-/model-viewer-4.2.0.tgz", + "integrity": "sha512-RjpAI5cLs9CdvPcMRsOs8Bea/lNmGTTyaPyl16o9Fv6Qn8VSpgBMmXFr/11yb0hTrsojp2dOACEcY77R8hVUVA==", + "license": "Apache-2.0", + "dependencies": { + "@monogrid/gainmap-js": "^3.1.0", + "lit": "^3.2.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "three": "^0.182.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "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", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "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", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@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, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@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, + "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", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.6.0.tgz", + "integrity": "sha512-VHb0ALPMTlgKjM6yIxxoQNnpKyUKLD04VzeQdsiXkMqkvYlAHxq9glGLmgbb889/1GsohSOAjvQYoiBppXFqrQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@lit/reactive-element": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz", + "integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0" + } + }, + "node_modules/@microsoft/signalr": { + "version": "8.0.17", + "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-8.0.17.tgz", + "integrity": "sha512-5pM6xPtKZNJLO0Tq5nQasVyPFwi/WBY3QB5uc/v3dIPTpS1JXQbaXAQAPxFoQ5rTBFE094w8bbqkp17F9ReQvA==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "eventsource": "^2.0.2", + "fetch-cookie": "^2.0.3", + "node-fetch": "^2.6.7", + "ws": "^7.5.10" + } + }, + "node_modules/@monogrid/gainmap-js": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@monogrid/gainmap-js/-/gainmap-js-3.4.0.tgz", + "integrity": "sha512-2Z0FATFHaoYJ8b+Y4y4Hgfn3FRFwuU5zRrk+9dFWp4uGAdHGqVEdP7HP+gLA3X469KXHmfupJaUbKo1b/aDKIg==", + "license": "MIT", + "dependencies": { + "promise-worker-transferable": "^1.0.4" + }, + "peerDependencies": { + "three": ">= 0.159.0" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "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": { + "@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/@next/env": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.6.tgz", + "integrity": "sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.2.6.tgz", + "integrity": "sha512-Z8l6o4JWKUl755x4R+wogD86KPeU+Ckw4K+SYG4kHeOJtRenDeK+OSbGcqZpDtbwn9DsJVdir2UxmwXuinUbUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.6.tgz", + "integrity": "sha512-ZJGkkcNfYgrrMkqOdZ7zoLa1TOy0qpcMfk/z4Mh/FKUz40gVO+HNQWqmLxf67Z5WB64DRp0dhEbyHfel+6sJUg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.6.tgz", + "integrity": "sha512-v/YLBHIY132Ced3puBJ7YJKw1lqsCrgcNo2aRJlCEyQrrCeRJlvGlnmxhPxNQI3KE3N1DN5r9TPNPvka3nq5RQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.6.tgz", + "integrity": "sha512-RPOvqlYBbcQjkz9VQQDZ2T2bARIjXZV1KFlt+V2Mr6SW/e4I9fcKsaA0hdyf2FHoTlsV2xnBd5Y912rP/1Ce6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.6.tgz", + "integrity": "sha512-URUTu1+dMkxJsPFgm+OeEvq9wf5sujw0EvgYy80TDGHTSLTnIHeqb0Eu8A3sC95IRgjejQL+kC4mw+4yPxiAXA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.6.tgz", + "integrity": "sha512-DOj182mPV8G3UkrayLoREM5YEYI+Dk5wv7Ox9xl1fFibAELEsFD0lDPfHIeILlutMMfdyhlzYPELG3peuKaurw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.6.tgz", + "integrity": "sha512-HKQ5SP/V/ub73UvF7n/zeJlxk2kLmtL7Wzrg4WfmkjmNos5onJ2tKu7yZOPdL18A6Svfn3max29ym+ry7NkK4g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.6.tgz", + "integrity": "sha512-LZXpTlPyS5v7HhSmnvsLGP3iIYgYOBnc8r8ArlT55sGHV89bR2HlDdBjWQ+PY6SJMmk8TuVGFuxalnP3k/0Dwg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.6.tgz", + "integrity": "sha512-F0+4i0h9J6C4eE3EAPWsoCk7UW/dbzOjyzxY0qnDUOYFu6FFmdZ6l97/XdV3/Nz3VYyO7UWjyEJUXkGqcoXfMA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@playwright/test": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz", + "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.60.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", + "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "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-alert-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "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-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.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-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "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-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "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-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "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.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "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.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.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-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "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-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "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.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "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.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.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-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "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.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "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.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", + "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "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-label/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "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.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.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-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "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-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "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.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "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-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "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-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.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-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "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-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "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.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "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.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "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.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@schummar/icu-type-parser": { + "version": "1.21.5", + "resolved": "https://registry.npmjs.org/@schummar/icu-type-parser/-/icu-type-parser-1.21.5.tgz", + "integrity": "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==", + "license": "MIT" + }, + "node_modules/@swc/core": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.40.tgz", + "integrity": "sha512-2kwzJikRvgtNAG7MwVZY2vEzZjTxKIq5jXOihuSV/8U+Hej8Va22t65aKnJZs3P+NwojZvR8Mf8kyM7O+V8sQg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.26" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.15.40", + "@swc/core-darwin-x64": "1.15.40", + "@swc/core-linux-arm-gnueabihf": "1.15.40", + "@swc/core-linux-arm64-gnu": "1.15.40", + "@swc/core-linux-arm64-musl": "1.15.40", + "@swc/core-linux-ppc64-gnu": "1.15.40", + "@swc/core-linux-s390x-gnu": "1.15.40", + "@swc/core-linux-x64-gnu": "1.15.40", + "@swc/core-linux-x64-musl": "1.15.40", + "@swc/core-win32-arm64-msvc": "1.15.40", + "@swc/core-win32-ia32-msvc": "1.15.40", + "@swc/core-win32-x64-msvc": "1.15.40" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.40.tgz", + "integrity": "sha512-PaYyclfmQ++77D8ityYvmmVzHv9aG8ROwt2GfG6/ccloy4Hgf80qtOnzb9VYvPsUT7Ty1uhuDRhv3XYpf62qhQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.40.tgz", + "integrity": "sha512-HbbPzvfLBUXjIB1Ezks+//lNUjmLjfyd63XSwprJgrZaXYdm70kohXPJUWdqKZozolFxbPaO+xtBaiUp6BoueA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.40.tgz", + "integrity": "sha512-SlRZsCjOCPR2LvFs0Ri/Xrx/5o5TCt8vl4gW6mX1hEZOG0a625RxzRHpHdAQNGykmAN/7IeaFAJG+QnNmxlHcA==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.40.tgz", + "integrity": "sha512-Q8byxJt2fh8CR3EUX6snBpy47AoBVm+In/+Z3rjDHMjC38ZvR9/gtUUNCT0tfrn4EdVsO8/QPi59nxrxvqxvBQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.40.tgz", + "integrity": "sha512-4z0MgHU+7M0pZDqBN1El7mFXDI1SBwinfcUkAyA4v8QrhOIUOZltySt2aStQLZGrdXVXM4Y4ylfiTC04ED+MoQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-ppc64-gnu": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.40.tgz", + "integrity": "sha512-fLI4iUgeSZu0eRWUXwe6YzPFx9gHbFiPkl8Rp3mJfP8OpNR3nTQCGPvHdDh9xniW7mVvgMY4ni7A4VzqI1KrpA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-s390x-gnu": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.40.tgz", + "integrity": "sha512-YqeKMAb7d4nQSGMJQ454IlaCENpzcDqhvBE9+CPfdnYpnUXxd+BSrB6Xk0YjW8UyoEhUj4p6quATCxbsp6J3jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.40.tgz", + "integrity": "sha512-7HOuS1iGcme/j/TuL1TfmmLGiMQrjv/GmjyZeydl00FKPtpGXEldwqfI56xgd1YzrzoB2svWjxbGGyQ0TEASxg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.40.tgz", + "integrity": "sha512-h4kZYHc7dpc9P9u4brRJaS8Pl7tPVHAeiLSzw7T5RfIJgAoSdaCMKzI/2Uay9gFhaw8uyCDl0L5q37r0EpAfIA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.40.tgz", + "integrity": "sha512-+mQgKZXSj6mV38Zh05QaxSjUDmGP/R2JWlXZTDLSPkDzHU6p3GxN9eeSf5dfyDVU86946fmCvSzyl/ucImx8+A==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.40.tgz", + "integrity": "sha512-yvwdPLGd25mcj/mNatjNQ0lZujtQD6psH3v9PNmMb+fSzjbNG8KIDxjFWrcV+fsFVLOkyOmdJsFmX7NAFjVyPw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.15.40", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.40.tgz", + "integrity": "sha512-OXtKsLU1bVtInzzDEAY2sYiF/rl4tvAnLLLpuMp3HzAOQZ5A+i69AKDhA1YLQTaMAqO3vzyYNVAYVRMPtSYD4w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@swc/types": { + "version": "0.1.26", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.26.tgz", + "integrity": "sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.100.11", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.100.11.tgz", + "integrity": "sha512-lmE0994apShXPj8CUxgx4ch5yUJhE9k/+tVwihBvPOyerACWdBocfFg24t8+0RhtlTd7tEgchDkhlCxNssvDxw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.100.11", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.100.11.tgz", + "integrity": "sha512-J0f9s5x3LE1450nNNfYx+e/n0DMa0uOBdFJUy5r0RvmsXd4nB/n0rbHtHI1vYXhikNFan+wf51p6Tmp4c8ucrg==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.100.11" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "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": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.19.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", + "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.1.4", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.4.tgz", + "integrity": "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.4", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.4.tgz", + "integrity": "sha512-WxYAszDYgsMV31OVyoG4jbAgJI1Gw0Xq9V19zwhy6+hUUJlJIdZ3r/cbdmTqFv++SktQkZ/X+46yGFxp5XJBEg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.0.tgz", + "integrity": "sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.60.0", + "@typescript-eslint/type-utils": "8.60.0", + "@typescript-eslint/utils": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.60.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.0.tgz", + "integrity": "sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.60.0", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.0.tgz", + "integrity": "sha512-aZu74NNKJeUWqCjDddzdiKaS82dgYgV/vmf+Ui3ZdZejmgfXR/q+pRumgobnQ2cCJTgGTWp4ypiwsuofFubavg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.60.0", + "@typescript-eslint/types": "^8.60.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.0.tgz", + "integrity": "sha512-pFzqhllJMs+jghLQWzV00ds39xLzuyqPSev5pd8f4Ir0rtKR3ZLUB4/4dhjOFighWb9larvtfJvqL+4yKDI3Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.0.tgz", + "integrity": "sha512-BZPR3RGYlAXnly6ymAxfkVn5rCbZzQNou0rxv3GfWZ8cTQp+hhVd73khbGLAd8k1TlAPLISH337M+tAgAnaJDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.0.tgz", + "integrity": "sha512-SX46wEUtitCpq7AN38HkUU/+zvUpdKf7ephtWAFgckH8O7PQIyL5gvrhQgBLuEYgLfuKWOVvWVskMbuFHAz5xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0", + "@typescript-eslint/utils": "8.60.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.0.tgz", + "integrity": "sha512-AsE7x2XaAK+CVbeih0Fvbn+r1qHxtpLDJ3XUuFcIinT318T90yHMJC+Zgv+jUuDjQQd06HKwxnDu6sz1IcTilA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.0.tgz", + "integrity": "sha512-3AcZNBGMClm6CXDyo8kYvVGT/sx29sS0oBsIb9oZI2gunA4Vm2M3YHzRLPvsUBBsl+yB5FPtltq7gGH0iTlp9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.60.0", + "@typescript-eslint/tsconfig-utils": "8.60.0", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.0.tgz", + "integrity": "sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.60.0", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.0.tgz", + "integrity": "sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.60.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.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==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.11.4", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.4.tgz", + "integrity": "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz", + "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.31", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.31.tgz", + "integrity": "sha512-MujYO3eP72uvmSE0i4wltsodRfIpZATP3jvzRNRGGxgzId7aVocVJJV3nf01qnzzKFGxQVC9bpWxl5cjxTr/7Q==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "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", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/date-fns-jalali": { + "version": "4.1.0-0", + "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz", + "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "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==", + "license": "MIT" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.360", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.360.tgz", + "integrity": "sha512-GkcBt6YYAw9SxFWn+xVar4cLVGlXVuswwtRLBozi2zp0GjXs4ZnOrqV4zbXzg35n7w81hCkyJNYicgXlVHAmBA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", + "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-next": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.2.6.tgz", + "integrity": "sha512-z2ELYSkyrrJ6cuunTU8vhsT/RpouPkjaSah06nVW6Rg2Hpg0Vs8s497/e5s8G8qtdp4ccsiovz5P1rv+5VSW2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "16.2.6", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "16.4.0", + "typescript-eslint": "^8.46.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-next/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-equals": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fetch-cookie": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-2.2.0.tgz", + "integrity": "sha512-h9AgfjURuCgA2+2ISl8GbavpUdR+WGAM2McW/ovn4tVccegp8ZqCKWSBR8uRdM8dDNlx5WdKRWxBYUwteLDCNQ==", + "license": "Unlicense", + "dependencies": { + "set-cookie-parser": "^2.4.8", + "tough-cookie": "^4.0.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "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, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/icu-minify": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.12.0.tgz", + "integrity": "sha512-zDmM05uav3t3+kxSfRrNlmyXOdj2b+uHA+p04CG32eJabtaHbugXujuL+YfRkwP9joAnf0Uh+RMGCKD5NLa5rQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/amannn" + } + ], + "license": "MIT", + "dependencies": { + "@formatjs/icu-messageformat-parser": "^3.4.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/intl-messageformat": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.7.tgz", + "integrity": "sha512-+q6Ktg119nULZEpZ8YTuGOst9MyEzFtjD63FTGBlN1mLz0Z/MOUYDIvnpVKwq17eezIEh+cfJIebfJoCetpiNw==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/fast-memoize": "3.1.5", + "@formatjs/icu-messageformat-parser": "3.5.10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lit": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.3.tgz", + "integrity": "sha512-fycuvZg/hkpozL00lm1pEJH5nN/lr9ZXd6mJI2HSN4+Bzc+LDNdEApJ6HFbPkdFNHLvOplIIuJvxkS4XUxqirw==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-element": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", + "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-html": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.3.tgz", + "integrity": "sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.454.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.454.0.tgz", + "integrity": "sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/next": { + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/next/-/next-16.2.6.tgz", + "integrity": "sha512-qOVgKJg1+At15NpeUP+eJgCHvTCgXsogweq87Ri/Ix7PkqQHg4sdaXmSFqKlgaIXE4kW0g25LE68W87UANlHtw==", + "license": "MIT", + "dependencies": { + "@next/env": "16.2.6", + "@swc/helpers": "0.5.15", + "baseline-browser-mapping": "^2.9.19", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.2.6", + "@next/swc-darwin-x64": "16.2.6", + "@next/swc-linux-arm64-gnu": "16.2.6", + "@next/swc-linux-arm64-musl": "16.2.6", + "@next/swc-linux-x64-gnu": "16.2.6", + "@next/swc-linux-x64-musl": "16.2.6", + "@next/swc-win32-arm64-msvc": "16.2.6", + "@next/swc-win32-x64-msvc": "16.2.6", + "sharp": "^0.34.5" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-intl": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.12.0.tgz", + "integrity": "sha512-v8KpppWG0yLLlChJ3Of6uoPew9LeRDBAtY6vpJmF7YJmBZlHEzzoEL4w1g1dAU+VleEPNoXNm9hg1eEsKWV5hw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/amannn" + } + ], + "license": "MIT", + "dependencies": { + "@formatjs/intl-localematcher": "^0.8.1", + "@parcel/watcher": "^2.4.1", + "@swc/core": "^1.15.2", + "icu-minify": "^4.12.0", + "negotiator": "^1.0.0", + "next-intl-swc-plugin-extractor": "^4.12.0", + "po-parser": "^2.1.1", + "use-intl": "^4.12.0" + }, + "peerDependencies": { + "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/next-intl-swc-plugin-extractor": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.12.0.tgz", + "integrity": "sha512-jUxVEu1Nryjt4YgaDktSys7ioOgQfcNPF/SF2dbPNxbVb6U+P1INRgHeCVN+EC59H2rnTFIQwbddmOCrUWFr3g==", + "license": "MIT" + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-releases": { + "version": "2.0.44", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", + "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/playwright": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", + "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.60.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", + "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", + "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/po-parser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/po-parser/-/po-parser-2.1.1.tgz", + "integrity": "sha512-ECF4zHLbUItpUgE3OTtLKlPjeBN+fKEczj2zYjDfCGOzicNs0GK3Vg2IoAYwx7LH/XYw43fZQP6xnZ4TkNxSLQ==", + "license": "MIT" + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-import/node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/promise-worker-transferable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz", + "integrity": "sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw==", + "license": "Apache-2.0", + "dependencies": { + "is-promise": "^2.1.0", + "lie": "^3.0.2" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "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-smooth": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", + "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "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==", + "license": "MIT", + "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/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recharts": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", + "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^18.3.1", + "react-smooth": "^4.0.4", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "license": "MIT", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recharts/node_modules/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==", + "license": "MIT" + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "license": "MIT", + "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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz", + "integrity": "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "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", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "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" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/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" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.0.tgz", + "integrity": "sha512-9f65qWLZdAW9m1JaxBDUHcqRUfL8bkxxXL7XxEfI+F09q56PkBvIfCjLF3yInsDM/BBmwkqmCQdCZe/RYlIWEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.60.0", + "@typescript-eslint/parser": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0", + "@typescript-eslint/utils": "8.60.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.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==", + "license": "MIT", + "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-intl": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.12.0.tgz", + "integrity": "sha512-r+qVb7UI1+kiOhjYsmsNUCY+jrnjVopwGeFlmMyQj4YInlwZzgMeMSv9n8MqnWWy77HL5BVM8K2WgX50SbtcpA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/amannn" + } + ], + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "^3.1.0", + "@schummar/icu-type-parser": "1.21.5", + "icu-minify": "^4.12.0", + "intl-messageformat": "^11.1.0" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0" + } + }, + "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==", + "license": "MIT", + "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/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, + "node_modules/zustand": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.13.tgz", + "integrity": "sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/web/dashboard/package.json b/web/dashboard/package.json new file mode 100644 index 0000000..f228879 --- /dev/null +++ b/web/dashboard/package.json @@ -0,0 +1,50 @@ +{ + "name": "meezi-dashboard", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "typecheck": "tsc --noEmit -p tsconfig.typecheck.json", + "test:e2e": "playwright test", + "test:e2e:ui": "playwright test --ui" + }, + "dependencies": { + "@google/model-viewer": "^4.2.0", + "three": "^0.163.0", + "@microsoft/signalr": "^8.0.7", + "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.2", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-slot": "^1.1.0", + "@tanstack/react-query": "^5.59.20", + "axios": "^1.7.7", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "date-fns-jalali": "^4.1.0-0", + "lucide-react": "^0.454.0", + "next": "16.2.6", + "next-intl": "4.12.0", + "@ducanh2912/next-pwa": "^10.2.9", + "react": "19.2.6", + "react-dom": "19.2.6", + "recharts": "^2.13.3", + "sonner": "^2.0.7", + "tailwind-merge": "^2.5.4", + "zustand": "^5.0.1" + }, + "devDependencies": { + "@playwright/test": "^1.49.0", + "@types/node": "^22.9.0", + "@types/react": "19.1.4", + "@types/react-dom": "19.1.4", + "autoprefixer": "^10.4.20", + "eslint": "^8.57.1", + "eslint-config-next": "16.2.6", + "postcss": "^8.4.47", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3" + } +} diff --git a/web/dashboard/playwright.config.ts b/web/dashboard/playwright.config.ts new file mode 100644 index 0000000..20b8c20 --- /dev/null +++ b/web/dashboard/playwright.config.ts @@ -0,0 +1,29 @@ +import { defineConfig, devices } from "@playwright/test"; + +const baseURL = process.env.PLAYWRIGHT_BASE_URL ?? "http://localhost:3101"; +const apiURL = process.env.PLAYWRIGHT_API_URL ?? "http://localhost:5080"; + +export default defineConfig({ + testDir: "./e2e", + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 1 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: "list", + use: { + baseURL, + trace: "on-first-retry", + }, + projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }], + webServer: process.env.CI + ? undefined + : { + command: "npm run dev", + url: baseURL, + reuseExistingServer: true, + timeout: 120_000, + }, + globalSetup: undefined, +}); + +export { apiURL }; diff --git a/web/dashboard/postcss.config.mjs b/web/dashboard/postcss.config.mjs new file mode 100644 index 0000000..2ef30fc --- /dev/null +++ b/web/dashboard/postcss.config.mjs @@ -0,0 +1,9 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; + +export default config; diff --git a/web/dashboard/public/.gitkeep b/web/dashboard/public/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/web/dashboard/public/.gitkeep @@ -0,0 +1 @@ + diff --git a/web/dashboard/public/icons/icon-192.png b/web/dashboard/public/icons/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..37d557f4b70342704bcfa890930d26141bf609fc GIT binary patch literal 547 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE2}s`E_d9@rf$^26i(^Q|oVS+@c^MQK4j9Nh z;FJ7e|M38y)1@U$WjSZ|KDbp8ci=jYOOk>R^F)b`BMvHTN`?ZRjUJ;yLn|aKuO8X< VI@aIg5is%@JYD@<);T3K0RX!mm=OQ~ literal 0 HcmV?d00001 diff --git a/web/dashboard/public/icons/icon-512.png b/web/dashboard/public/icons/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d2ed7e392d5fab5fa3d210254749ddfa9ce9ceda GIT binary patch literal 1881 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&t&wwUqN(1_pKoPZ!6KiaBqu8uBt2@Eq7+ zB(eLT#Q$Q0sw0yapPZgk&d4$AD-%PQ1cSpAMg|wjQED^@MpMCPMi?y%MvKD{Q6toz Y*=AUputy*eSY; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/coupons/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/coupons/page.tsx new file mode 100644 index 0000000..8adab67 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/coupons/page.tsx @@ -0,0 +1,5 @@ +import { CouponsScreen } from "@/components/coupons/coupons-screen"; + +export default function CouponsPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/crm/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/crm/page.tsx new file mode 100644 index 0000000..2ca6d4c --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/crm/page.tsx @@ -0,0 +1,5 @@ +import { CrmScreen } from "@/components/crm/crm-screen"; + +export default function CrmPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/expenses/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/expenses/page.tsx new file mode 100644 index 0000000..b7eda66 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/expenses/page.tsx @@ -0,0 +1,5 @@ +import { ExpensesScreen } from "@/components/expenses/expenses-screen"; + +export default function ExpensesPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/hr/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/hr/page.tsx new file mode 100644 index 0000000..e0b7754 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/hr/page.tsx @@ -0,0 +1,5 @@ +import { HrScreen } from "@/components/hr/hr-screen"; + +export default function HrPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/inventory/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/inventory/page.tsx new file mode 100644 index 0000000..463a464 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/inventory/page.tsx @@ -0,0 +1,7 @@ +"use client"; + +import { InventoryScreen } from "@/components/inventory/inventory-screen"; + +export default function InventoryPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/kds/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/kds/page.tsx new file mode 100644 index 0000000..9d2d21f --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/kds/page.tsx @@ -0,0 +1,5 @@ +import { KdsScreen } from "@/components/kds/kds-screen"; + +export default function KdsPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/layout.tsx b/web/dashboard/src/app/[locale]/(dashboard)/layout.tsx new file mode 100644 index 0000000..f433341 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/layout.tsx @@ -0,0 +1,59 @@ +"use client"; + +import { useEffect } from "react"; +import { useLocale } from "next-intl"; +import { useRouter } from "@/i18n/routing"; +import { Sidebar } from "@/components/layout/sidebar"; +import { Topbar } from "@/components/layout/topbar"; +import { CafeThemeProvider } from "@/components/theme/cafe-theme-provider"; +import { useAuthStore } from "@/lib/stores/auth.store"; +import { useOfflineSync } from "@/lib/offline/use-offline-sync"; + +export default function DashboardLayout({ + children, +}: { + children: React.ReactNode; +}) { + const locale = useLocale(); + const router = useRouter(); + const user = useAuthStore((s) => s.user); + useOfflineSync(); // register online/offline listeners + load queue count + + useEffect(() => { + if (!user?.accessToken) { + router.replace("/login"); + } + }, [user, router]); + + const isRtl = locale !== "en"; + + const mainColumn = ( +
+ +
+ {children} +
+
+ ); + + return ( + +
+ {isRtl ? ( + <> + + {mainColumn} + + ) : ( + <> + + {mainColumn} + + )} +
+
+ ); +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/menu/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/menu/page.tsx new file mode 100644 index 0000000..8611910 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/menu/page.tsx @@ -0,0 +1,5 @@ +import { MenuAdminScreen } from "@/components/menu/menu-admin-screen"; + +export default function MenuPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/notifications/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/notifications/page.tsx new file mode 100644 index 0000000..03aecda --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/notifications/page.tsx @@ -0,0 +1,5 @@ +import { NotificationsScreen } from "@/components/notifications/notifications-screen"; + +export default function NotificationsPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/page.tsx new file mode 100644 index 0000000..2d062ba --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/page.tsx @@ -0,0 +1,5 @@ +import { OverviewScreen } from "@/components/overview/overview-screen"; + +export default function HomePage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/pos/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/pos/page.tsx new file mode 100644 index 0000000..e91cfb3 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/pos/page.tsx @@ -0,0 +1,13 @@ +import { Suspense } from "react"; +import { PosScreen } from "@/components/pos/pos-screen"; + +/** Full viewport height below topbar; no page scroll — only inner panes scroll. */ +export default function PosPage() { + return ( +
+ + + +
+ ); +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/queue/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/queue/page.tsx new file mode 100644 index 0000000..171dcda --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/queue/page.tsx @@ -0,0 +1,5 @@ +import { QueueScreen } from "@/components/queue/queue-screen"; + +export default function QueuePage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/reports/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/reports/page.tsx new file mode 100644 index 0000000..3311d2b --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/reports/page.tsx @@ -0,0 +1,5 @@ +import { ReportsScreen } from "@/components/reports/reports-screen"; + +export default function ReportsPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/reservations/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/reservations/page.tsx new file mode 100644 index 0000000..1f4e5ef --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/reservations/page.tsx @@ -0,0 +1,5 @@ +import { ReservationsScreen } from "@/components/reservations/reservations-screen"; + +export default function ReservationsPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/reviews/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/reviews/page.tsx new file mode 100644 index 0000000..b1c30e9 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/reviews/page.tsx @@ -0,0 +1,5 @@ +import { ReviewsScreen } from "@/components/reviews/reviews-screen"; + +export default function ReviewsPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/settings/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/settings/page.tsx new file mode 100644 index 0000000..ace034a --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/settings/page.tsx @@ -0,0 +1,10 @@ +import { Suspense } from "react"; +import { SettingsScreen } from "@/components/settings/settings-screen"; + +export default function SettingsPage() { + return ( + + + + ); +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/shifts/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/shifts/page.tsx new file mode 100644 index 0000000..da68689 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/shifts/page.tsx @@ -0,0 +1,5 @@ +import { ShiftsScreen } from "@/components/shifts/shifts-screen"; + +export default function ShiftsPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/sms/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/sms/page.tsx new file mode 100644 index 0000000..41d83c3 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/sms/page.tsx @@ -0,0 +1,5 @@ +import { SmsScreen } from "@/components/sms/sms-screen"; + +export default function SmsPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/subscription/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/subscription/page.tsx new file mode 100644 index 0000000..b8ccfff --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/subscription/page.tsx @@ -0,0 +1,10 @@ +import { Suspense } from "react"; +import { SubscriptionScreen } from "@/components/subscription/subscription-screen"; + +export default function SubscriptionPage() { + return ( + + + + ); +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/support/[ticketId]/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/support/[ticketId]/page.tsx new file mode 100644 index 0000000..ad63be3 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/support/[ticketId]/page.tsx @@ -0,0 +1,5 @@ +import { SupportTicketDetailScreen } from "@/components/support/support-screen"; + +export default function SupportTicketPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/support/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/support/page.tsx new file mode 100644 index 0000000..a4e8f82 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/support/page.tsx @@ -0,0 +1,5 @@ +import { SupportScreen } from "@/components/support/support-screen"; + +export default function SupportPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/tables/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/tables/page.tsx new file mode 100644 index 0000000..7f03cfc --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/tables/page.tsx @@ -0,0 +1,5 @@ +import { TablesScreen } from "@/components/tables/tables-screen"; + +export default function TablesPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(dashboard)/taxes/page.tsx b/web/dashboard/src/app/[locale]/(dashboard)/taxes/page.tsx new file mode 100644 index 0000000..ac42724 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(dashboard)/taxes/page.tsx @@ -0,0 +1,5 @@ +import { TaxesScreen } from "@/components/taxes/taxes-screen"; + +export default function TaxesPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(fullscreen)/layout.tsx b/web/dashboard/src/app/[locale]/(fullscreen)/layout.tsx new file mode 100644 index 0000000..668af83 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(fullscreen)/layout.tsx @@ -0,0 +1,25 @@ +"use client"; + +import { useEffect } from "react"; +import { useLocale } from "next-intl"; +import { useRouter } from "@/i18n/routing"; +import { useAuthStore } from "@/lib/stores/auth.store"; + +/** Full-viewport routes (queue TV display) — auth only, no dashboard chrome. */ +export default function FullscreenLayout({ children }: { children: React.ReactNode }) { + const locale = useLocale(); + const router = useRouter(); + const user = useAuthStore((s) => s.user); + + useEffect(() => { + if (!user?.accessToken) { + router.replace("/login"); + } + }, [user, router]); + + return ( +
+ {children} +
+ ); +} diff --git a/web/dashboard/src/app/[locale]/(fullscreen)/queue/display/page.tsx b/web/dashboard/src/app/[locale]/(fullscreen)/queue/display/page.tsx new file mode 100644 index 0000000..bea06d8 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(fullscreen)/queue/display/page.tsx @@ -0,0 +1,10 @@ +import { Suspense } from "react"; +import { QueueDisplayScreen } from "@/components/queue/queue-display-screen"; + +export default function QueueDisplayPage() { + return ( + + + + ); +} diff --git a/web/dashboard/src/app/[locale]/(public)/discover/[slug]/page.tsx b/web/dashboard/src/app/[locale]/(public)/discover/[slug]/page.tsx new file mode 100644 index 0000000..28a33e1 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(public)/discover/[slug]/page.tsx @@ -0,0 +1,10 @@ +import { PublicCafeDetailScreen } from "@/components/discover/public-cafe-detail-screen"; + +export default async function PublicCafeDetailPage({ + params, +}: { + params: Promise<{ locale: string; slug: string }>; +}) { + const { slug } = await params; + return ; +} diff --git a/web/dashboard/src/app/[locale]/(public)/discover/page.tsx b/web/dashboard/src/app/[locale]/(public)/discover/page.tsx new file mode 100644 index 0000000..d2c3ae8 --- /dev/null +++ b/web/dashboard/src/app/[locale]/(public)/discover/page.tsx @@ -0,0 +1,5 @@ +import { PublicDiscoverScreen } from "@/components/discover/public-discover-screen"; + +export default function PublicDiscoverPage() { + return ; +} diff --git a/web/dashboard/src/app/[locale]/(public)/layout.tsx b/web/dashboard/src/app/[locale]/(public)/layout.tsx new file mode 100644 index 0000000..0ac696f --- /dev/null +++ b/web/dashboard/src/app/[locale]/(public)/layout.tsx @@ -0,0 +1,6 @@ +import { Providers } from "@/components/providers"; + +/** Public consumer routes (discover) — no dashboard chrome. */ +export default function PublicLayout({ children }: { children: React.ReactNode }) { + return {children}; +} diff --git a/web/dashboard/src/app/[locale]/layout.tsx b/web/dashboard/src/app/[locale]/layout.tsx new file mode 100644 index 0000000..7a1ffca --- /dev/null +++ b/web/dashboard/src/app/[locale]/layout.tsx @@ -0,0 +1,61 @@ +import { NextIntlClientProvider } from "next-intl"; +import { getMessages, setRequestLocale } from "next-intl/server"; +import { notFound } from "next/navigation"; +import localFont from "next/font/local"; +import { routing } from "@/i18n/routing"; +import { Providers } from "@/components/providers"; +import "../globals.css"; + +const vazirmatn = localFont({ + src: "../../fonts/Vazirmatn-Variable.woff2", + variable: "--font-vazirmatn", + display: "swap", + weight: "100 900", +}); + +const inter = localFont({ + src: "../../fonts/Inter-Variable.woff2", + variable: "--font-inter", + display: "swap", + weight: "100 900", +}); + +export function generateStaticParams() { + return routing.locales.map((locale) => ({ locale })); +} + +export default async function LocaleLayout({ + children, + params, +}: { + children: React.ReactNode; + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + + if (!routing.locales.includes(locale as "fa" | "ar" | "en")) { + notFound(); + } + + setRequestLocale(locale); + const messages = await getMessages(); + const dir = locale === "en" ? "ltr" : "rtl"; + const fontClass = + locale === "en" + ? inter.variable + : vazirmatn.variable; + + return ( + + + + {children} + + + + ); +} diff --git a/web/dashboard/src/app/[locale]/login/page.tsx b/web/dashboard/src/app/[locale]/login/page.tsx new file mode 100644 index 0000000..c69468c --- /dev/null +++ b/web/dashboard/src/app/[locale]/login/page.tsx @@ -0,0 +1,144 @@ +"use client"; + +import { useState } from "react"; +import { useTranslations } from "next-intl"; +import { useRouter } from "@/i18n/routing"; +import { apiPost, ApiClientError } from "@/lib/api/client"; +import type { AuthTokenResponse } from "@/lib/api/types"; +import { useAuthStore } from "@/lib/stores/auth.store"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { LabeledField } from "@/components/ui/labeled-field"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; + +export default function LoginPage() { + const t = useTranslations("auth"); + const router = useRouter(); + const setAuth = useAuthStore((s) => s.setAuth); + + const [phone, setPhone] = useState("09121234567"); + const [code, setCode] = useState(""); + const [step, setStep] = useState<"phone" | "otp">("phone"); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const authErrorMessage = (err: unknown) => { + if (err instanceof ApiClientError) { + switch (err.code) { + case "RATE_LIMITED": + return t("rateLimited"); + case "NOT_FOUND": + return t("notFound"); + case "SMS_FAILED": + return t("smsFailed"); + case "INVALID_OTP": + return t("invalidOtp"); + default: + return err.message; + } + } + return err instanceof Error ? err.message : t("title"); + }; + + const sendOtp = async () => { + setLoading(true); + setError(null); + try { + await apiPost("/api/auth/send-otp", { phone }); + setStep("otp"); + } catch (e) { + setError(authErrorMessage(e)); + } finally { + setLoading(false); + } + }; + + const verifyOtp = async () => { + setLoading(true); + setError(null); + try { + const data = await apiPost("/api/auth/verify-otp", { + phone, + code, + }); + setAuth(data); + router.push("/pos"); + } catch (e) { + setError(authErrorMessage(e)); + } finally { + setLoading(false); + } + }; + + return ( +
+ + + {t("title")} +

{t("subtitle")}

+
+ + {step === "phone" ? ( +
{ + e.preventDefault(); + if (!loading) void sendOtp(); + }} + > + + setPhone(e.target.value)} + placeholder={t("phonePlaceholder")} + dir="ltr" + className="text-end" + autoComplete="tel" + /> + + +
+ ) : ( +
{ + e.preventDefault(); + if (!loading) void verifyOtp(); + }} + > + + setCode(e.target.value)} + placeholder={t("otpPlaceholder")} + maxLength={6} + dir="ltr" + className="text-center tracking-widest" + autoComplete="one-time-code" + /> + + + +
+ )} + {error && ( +

{error}

+ )} +
+
+
+ ); +} diff --git a/web/dashboard/src/app/[locale]/page.tsx b/web/dashboard/src/app/[locale]/page.tsx new file mode 100644 index 0000000..1c74d44 --- /dev/null +++ b/web/dashboard/src/app/[locale]/page.tsx @@ -0,0 +1,10 @@ +import { redirect } from "@/i18n/routing"; + +export default async function HomePage({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + redirect({ href: "/pos", locale }); +} diff --git a/web/dashboard/src/app/globals.css b/web/dashboard/src/app/globals.css new file mode 100644 index 0000000..7cec69e --- /dev/null +++ b/web/dashboard/src/app/globals.css @@ -0,0 +1,253 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + /* Meezi brand */ + --meezi-green: 162 76% 25%; + --meezi-green-tint: 162 52% 92%; + --meezi-amber: 38 78% 41%; + --meezi-danger: 0 58% 41%; + --meezi-info: 210 82% 28%; + + --background: 210 20% 98%; + --foreground: 222 47% 11%; + --card: 0 0% 100%; + --card-foreground: 222 47% 11%; + --primary: var(--meezi-green); + --primary-foreground: 0 0% 100%; + --secondary: 162 30% 94%; + --secondary-foreground: 162 76% 20%; + --muted: 210 25% 96%; + --muted-foreground: 215 16% 47%; + --accent: var(--meezi-green-tint); + --accent-foreground: 162 76% 20%; + --destructive: var(--meezi-danger); + --destructive-foreground: 0 0% 100%; + --border: 214 24% 88%; + --input: 214 24% 88%; + --ring: var(--meezi-green); + --radius: 0.75rem; + } + +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + font-family: var(--font-vazirmatn), var(--font-inter), system-ui, sans-serif; + } + + html[lang="en"] body { + font-family: var(--font-inter), system-ui, sans-serif; + } + + html[lang="fa"] body, + html[lang="ar"] body { + font-family: var(--font-vazirmatn), system-ui, sans-serif; + } +} + +/* Sonner portal — inherit Meezi fonts (toasts render outside main tree) */ +[data-sonner-toaster], +[data-sonner-toast], +[data-sonner-toast] [data-title], +[data-sonner-toast] [data-description], +[data-sonner-toast] [data-button], +[data-sonner-toast] [data-close-button] { + font-family: var(--font-vazirmatn), system-ui, sans-serif !important; +} + +html[lang="en"] [data-sonner-toaster], +html[lang="en"] [data-sonner-toast], +html[lang="en"] [data-sonner-toast] [data-title], +html[lang="en"] [data-sonner-toast] [data-description], +html[lang="en"] [data-sonner-toast] [data-button], +html[lang="en"] [data-sonner-toast] [data-close-button] { + font-family: var(--font-inter), system-ui, sans-serif !important; +} + +/* Per-café theme — panel + menu layout variants (data-* set by applyCafeTheme) */ +html[data-panel-style="glass"] .bg-card, +html[data-panel-style="glass"] .theme-preview-sidebar, +html[data-panel-style="glass"] .theme-preview-menu-card { + background: color-mix(in srgb, hsl(var(--card)) 82%, transparent) !important; + backdrop-filter: blur(10px); +} + +html[data-panel-style="bold"] .bg-card { + border-width: 2px; + border-color: hsl(var(--primary) / 0.35); +} + +html[data-panel-style="elevated"] .bg-card, +html[data-panel-style="elevated"] .theme-preview-menu-card { + box-shadow: 0 8px 24px hsl(var(--primary) / 0.12); +} + +html[data-panel-style="outline"] .bg-card { + background: transparent !important; + border-width: 2px; +} + +html[data-panel-style="soft"] .bg-card { + box-shadow: 0 2px 12px hsl(var(--primary) / 0.08); +} + +html[data-menu-style="compact"] .theme-preview-menu-card { + padding: 0.5rem; +} + +html[data-menu-style="grid"] [data-menu-grid="true"] { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.75rem; +} + +html[data-menu-style="list"] .theme-preview-menu-card { + display: flex; + align-items: center; + justify-content: space-between; +} + +html[data-density="compact"] { + --spacing-scale: 0.85; +} + +html[data-density="spacious"] { + --spacing-scale: 1.15; +} + +html[data-density="compact"] main { + padding: 1rem; +} + +html[data-density="spacious"] main { + padding: 2rem; +} + +/* QR guest menu — background textures (--qr-bg set inline from café theme) */ +[data-qr-texture] { + background-color: var(--qr-bg, #f5f5f4); +} + +[data-qr-texture="none"] { + background-image: none; +} + +[data-qr-texture="paper"] { + background-image: + repeating-linear-gradient( + 0deg, + transparent, + transparent 3px, + color-mix(in srgb, var(--qr-bg, #f5f5f4) 88%, #000 12%) 3px, + color-mix(in srgb, var(--qr-bg, #f5f5f4) 88%, #000 12%) 4px + ), + radial-gradient(ellipse 120% 80% at 50% 0%, color-mix(in srgb, var(--qr-bg) 70%, #fff 30%), var(--qr-bg)); +} + +[data-qr-texture="linen"] { + background-image: + repeating-linear-gradient( + 90deg, + transparent, + transparent 6px, + color-mix(in srgb, var(--qr-bg) 92%, #000 8%) 6px, + color-mix(in srgb, var(--qr-bg) 92%, #000 8%) 7px + ), + repeating-linear-gradient( + 0deg, + transparent, + transparent 6px, + color-mix(in srgb, var(--qr-bg) 94%, #000 6%) 6px, + color-mix(in srgb, var(--qr-bg) 94%, #000 6%) 7px + ); +} + +[data-qr-texture="dots"] { + background-image: radial-gradient( + circle, + color-mix(in srgb, var(--qr-bg) 75%, #000 25%) 1px, + transparent 1px + ); + background-size: 14px 14px; +} + +[data-qr-texture="grid"] { + background-image: + linear-gradient(color-mix(in srgb, var(--qr-bg) 80%, #000 20%) 1px, transparent 1px), + linear-gradient(90deg, color-mix(in srgb, var(--qr-bg) 80%, #000 20%) 1px, transparent 1px); + background-size: 20px 20px; +} + +[data-qr-texture="marble"] { + background-image: + radial-gradient(ellipse 70% 50% at 15% 20%, color-mix(in srgb, var(--qr-bg) 55%, #fff 45%), transparent 55%), + radial-gradient(ellipse 60% 45% at 85% 75%, color-mix(in srgb, var(--qr-bg) 60%, #ddd 40%), transparent 50%), + radial-gradient(ellipse 50% 40% at 50% 50%, color-mix(in srgb, var(--qr-bg) 75%, #eee 25%), transparent 60%); +} + +[data-qr-texture="wood"] { + background-image: repeating-linear-gradient( + 180deg, + color-mix(in srgb, var(--qr-bg) 85%, #5c4033 15%), + color-mix(in srgb, var(--qr-bg) 92%, #5c4033 8%) 2px, + color-mix(in srgb, var(--qr-bg) 78%, #3e2723 22%) 4px, + color-mix(in srgb, var(--qr-bg) 90%, #5c4033 10%) 6px + ); + background-size: 100% 8px; +} + +[data-qr-texture="warm"] { + background-image: + radial-gradient(circle at 30% 40%, color-mix(in srgb, var(--qr-bg) 70%, #d4a574 30%) 0%, transparent 45%), + radial-gradient(circle at 70% 60%, color-mix(in srgb, var(--qr-bg) 75%, #c9a87c 25%) 0%, transparent 40%), + repeating-linear-gradient( + 45deg, + transparent, + transparent 8px, + color-mix(in srgb, var(--qr-bg) 94%, #8b6914 6%) 8px, + color-mix(in srgb, var(--qr-bg) 94%, #8b6914 6%) 9px + ); +} + +/* QR guest menu — themed surfaces/text (vars from buildQrThemeCssVars) */ +[data-qr-guest-menu] { + color: var(--qr-text, #1c1917); +} + +[data-qr-guest-menu] .qr-surface { + background-color: var(--qr-surface, #fff); +} + +[data-qr-guest-menu] .qr-muted { + color: var(--qr-text-muted, #78716c); +} + +[data-qr-guest-menu] .qr-text { + color: var(--qr-text, #1c1917); +} + +[data-qr-guest-menu] .qr-fill-muted { + background-color: color-mix(in srgb, var(--qr-secondary, #e1f5ee) 45%, var(--qr-surface, #fff)); +} + +[data-qr-guest-menu] .qr-icon { + color: var(--qr-primary, #0f6e56); +} + +[data-qr-guest-menu] .qr-border { + border-color: color-mix(in srgb, var(--qr-primary, #0f6e56) 22%, transparent); +} + +/* Texture swatches in settings appearance picker */ +.qr-texture-swatch[data-qr-texture] { + min-height: 2.5rem; + border-radius: 0.5rem; + border: 1px solid hsl(var(--border) / 0.8); +} diff --git a/web/dashboard/src/app/layout.tsx b/web/dashboard/src/app/layout.tsx new file mode 100644 index 0000000..cd4a053 --- /dev/null +++ b/web/dashboard/src/app/layout.tsx @@ -0,0 +1,7 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return children; +} diff --git a/web/dashboard/src/app/manifest.ts b/web/dashboard/src/app/manifest.ts new file mode 100644 index 0000000..114e890 --- /dev/null +++ b/web/dashboard/src/app/manifest.ts @@ -0,0 +1,46 @@ +import type { MetadataRoute } from "next"; + +export default function manifest(): MetadataRoute.Manifest { + return { + name: "میزی — پنل مدیریت کافه", + short_name: "میزی", + description: "سیستم مدیریت کافه و رستوران میزی", + start_url: "/fa/pos", + display: "standalone", + background_color: "#ffffff", + theme_color: "#0F6E56", + orientation: "any", + categories: ["business", "productivity"], + lang: "fa", + dir: "rtl", + icons: [ + { + src: "/icons/icon-192.png", + sizes: "192x192", + type: "image/png", + purpose: "any", + }, + { + src: "/icons/icon-512.png", + sizes: "512x512", + type: "image/png", + purpose: "any", + }, + { + src: "/icons/icon-maskable-512.png", + sizes: "512x512", + type: "image/png", + purpose: "maskable", + }, + ], + screenshots: [ + { + src: "/screenshots/pos.png", + sizes: "1280x800", + type: "image/png", + form_factor: "wide", + label: "سیستم فروش حضوری", + }, + ], + }; +} diff --git a/web/dashboard/src/app/q/[code]/page.tsx b/web/dashboard/src/app/q/[code]/page.tsx new file mode 100644 index 0000000..8f5e494 --- /dev/null +++ b/web/dashboard/src/app/q/[code]/page.tsx @@ -0,0 +1,11 @@ +"use client"; + +import { useParams } from "next/navigation"; +import { QrGuestMenu } from "@/components/qr/qr-guest-menu"; + +export default function QrLandingPage() { + const params = useParams(); + const code = typeof params.code === "string" ? params.code : ""; + + return ; +} diff --git a/web/dashboard/src/app/q/error.tsx b/web/dashboard/src/app/q/error.tsx new file mode 100644 index 0000000..28ffb5d --- /dev/null +++ b/web/dashboard/src/app/q/error.tsx @@ -0,0 +1,29 @@ +"use client"; + +export default function QrError({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + return ( +
+

⚠️

+

خطا در بارگذاری منو

+

+ {error.message || "صفحه منوی میز قابل نمایش نیست."} +

+ +
+ ); +} diff --git a/web/dashboard/src/app/q/layout.tsx b/web/dashboard/src/app/q/layout.tsx new file mode 100644 index 0000000..2ad9dcb --- /dev/null +++ b/web/dashboard/src/app/q/layout.tsx @@ -0,0 +1,27 @@ +import { NextIntlClientProvider } from "next-intl"; +import localFont from "next/font/local"; +import faMessages from "../../../messages/fa.json"; +import { MeeziToaster } from "@/components/ui/meezi-toaster"; +import "../globals.css"; + +const vazirmatn = localFont({ + src: "../../fonts/Vazirmatn-Variable.woff2", + variable: "--font-vazirmatn", + display: "swap", + weight: "100 900", +}); + +export default function QrRootLayout({ children }: { children: React.ReactNode }) { + return ( + + + + {children} + + + + + ); +} diff --git a/web/dashboard/src/components/branches/branches-screen.tsx b/web/dashboard/src/components/branches/branches-screen.tsx new file mode 100644 index 0000000..0e4e5ce --- /dev/null +++ b/web/dashboard/src/components/branches/branches-screen.tsx @@ -0,0 +1,420 @@ +"use client"; + +import { useMemo, useState } from "react"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { useTranslations } from "next-intl"; +import { Building2, RotateCcw, Trash2, Eye } from "lucide-react"; +import { apiDelete, apiGet, apiPost } from "@/lib/api/client"; +import { isCafeOwner } from "@/lib/auth-permissions"; +import { useAuthStore } from "@/lib/stores/auth.store"; +import { useBranchStore } from "@/lib/stores/branch.store"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { LabeledField } from "@/components/ui/labeled-field"; +import { PageHeader } from "@/components/layout/page-header"; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from "@/components/ui/alert-dialog"; +import { cn } from "@/lib/utils"; + +type Branch = { + id: string; + name: string; + address?: string; + city?: string; + phone?: string; + loginPhone?: string; + managerName?: string; + isPendingDeletion?: boolean; + deletedAt?: string | null; + scheduledPermanentDeleteAt?: string | null; + daysUntilPermanentDelete?: number | null; +}; + +function purgeCountdownLabel( + branch: Branch, + t: (key: string, values?: Record) => string +): string { + const days = branch.daysUntilPermanentDelete ?? 0; + if (days <= 0) return t("purgeToday"); + if (days === 1) return t("purgeInOneDay"); + return t("purgeInDays", { days }); +} + +export function BranchesScreen() { + const t = useTranslations("branchesPage"); + const tCommon = useTranslations("common"); + const cafeId = useAuthStore((s) => s.user?.cafeId); + const role = useAuthStore((s) => s.user?.role); + const setBranchId = useBranchStore((s) => s.setBranchId); + const queryClient = useQueryClient(); + + const [newBranchName, setNewBranchName] = useState(""); + const [loginPhone, setLoginPhone] = useState(""); + const [managerName, setManagerName] = useState(""); + const [message, setMessage] = useState(null); + const [error, setError] = useState(null); + const [deleteTarget, setDeleteTarget] = useState(null); + const [reviewBranch, setReviewBranch] = useState(null); + + const { data: branches = [], isLoading } = useQuery({ + queryKey: ["branches", cafeId, "manage"], + queryFn: () => + apiGet( + `/api/cafes/${cafeId}/branches?includePendingDeletion=true` + ), + enabled: !!cafeId && isCafeOwner(role), + }); + + const activeBranches = useMemo( + () => branches.filter((b) => !b.isPendingDeletion), + [branches] + ); + const pendingBranches = useMemo( + () => branches.filter((b) => b.isPendingDeletion), + [branches] + ); + + const invalidate = () => { + void queryClient.invalidateQueries({ queryKey: ["branches", cafeId] }); + }; + + const createBranch = useMutation({ + mutationFn: () => + apiPost(`/api/cafes/${cafeId}/branches`, { + name: newBranchName.trim(), + loginPhone: loginPhone.trim(), + managerName: managerName.trim() || undefined, + }), + onSuccess: () => { + setNewBranchName(""); + setLoginPhone(""); + setManagerName(""); + setError(null); + setMessage(t("created")); + invalidate(); + }, + onError: () => setError(t("createError")), + }); + + const deleteBranch = useMutation({ + mutationFn: (id: string) => + apiDelete(`/api/cafes/${cafeId}/branches/${id}`), + onSuccess: (_, id) => { + setDeleteTarget(null); + setMessage(t("deleteScheduled")); + setError(null); + const current = useBranchStore.getState().branchId; + if (current === id) setBranchId(null); + invalidate(); + }, + onError: () => { + setDeleteTarget(null); + setError(t("deleteError")); + }, + }); + + const restoreBranch = useMutation({ + mutationFn: (id: string) => + apiPost(`/api/cafes/${cafeId}/branches/${id}/restore`, {}), + onSuccess: () => { + setMessage(t("restored")); + setError(null); + invalidate(); + }, + onError: () => setError(t("restoreError")), + }); + + if (!cafeId) return null; + + if (!isCafeOwner(role)) { + return ( +
+ +

{t("ownerOnly")}

+
+ ); + } + + const canSubmit = + newBranchName.trim().length > 0 && + loginPhone.trim().length >= 10 && + !createBranch.isPending; + + return ( +
+ + + {message ? ( +

+ {message} +

+ ) : null} + {error ? ( +

+ {error} +

+ ) : null} + + {pendingBranches.length > 0 ? ( + + + + {t("pendingTitle")} + +

{t("pendingHint")}

+
+ +
    + {pendingBranches.map((b) => ( +
  • +
    + +
    +

    {b.name}

    +

    + {purgeCountdownLabel(b, t)} +

    + {b.scheduledPermanentDeleteAt ? ( +

    + {new Date(b.scheduledPermanentDeleteAt).toLocaleString()} +

    + ) : null} +
    +
    +
    + + +
    +
  • + ))} +
+
+
+ ) : null} + + + + {t("listTitle")} + + + {isLoading ? ( +

{tCommon("loading")}

+ ) : activeBranches.length === 0 ? ( +

{t("empty")}

+ ) : ( +
    + {activeBranches.map((b) => ( +
  • +
    + {b.name} + {b.managerName ? ( +

    {b.managerName}

    + ) : null} +
    +
    +
    + {b.loginPhone ? ( + + {t("loginPhone")}: {b.loginPhone} + + ) : null} + {(b.city || b.address) && ( +

    {[b.city, b.address].filter(Boolean).join(" · ")}

    + )} +
    + + +
    +
  • + ))} +
+ )} + +
{ + e.preventDefault(); + if (canSubmit) createBranch.mutate(); + }} + > +

+ {t("addSection")} +

+
+ + setNewBranchName(e.target.value)} + /> + + + setLoginPhone(e.target.value)} + placeholder="09121234567" + dir="ltr" + className="text-end" + autoComplete="tel" + /> + + + setManagerName(e.target.value)} + placeholder={t("managerNamePlaceholder")} + /> + +
+ +

{t("masterPlanHint")}

+
+

{t("branchSelectHint")}

+
+
+ + !open && setDeleteTarget(null)} + > + + + {t("deleteTitle")} + {t("deleteWarning")} + + + {tCommon("cancel")} + deleteTarget && deleteBranch.mutate(deleteTarget.id)} + > + {t("deleteConfirm")} + + + + + + !open && setReviewBranch(null)} + > + + + {t("reviewTitle")} + +
+ {reviewBranch ? ( +
+
+
{t("newName")}
+
{reviewBranch.name}
+
+ {reviewBranch.managerName ? ( +
+
{t("managerName")}
+
{reviewBranch.managerName}
+
+ ) : null} + {reviewBranch.loginPhone ? ( +
+
{t("loginPhone")}
+
{reviewBranch.loginPhone}
+
+ ) : null} + {(reviewBranch.city || reviewBranch.address) && ( +
+
{t("location")}
+
+ {[reviewBranch.city, reviewBranch.address] + .filter(Boolean) + .join(" · ")} +
+
+ )} + {reviewBranch.isPendingDeletion ? ( +

+ {purgeCountdownLabel(reviewBranch, t)} +

+ ) : null} +
+ ) : null} +
+
+
+ + setReviewBranch(null)}> + {tCommon("confirm")} + + +
+
+
+ ); +} diff --git a/web/dashboard/src/components/coupons/coupons-screen.tsx b/web/dashboard/src/components/coupons/coupons-screen.tsx new file mode 100644 index 0000000..b30dccb --- /dev/null +++ b/web/dashboard/src/components/coupons/coupons-screen.tsx @@ -0,0 +1,142 @@ +"use client"; + +import { useState } from "react"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { useTranslations } from "next-intl"; +import { Plus } from "lucide-react"; +import { apiGet, apiPost } from "@/lib/api/client"; +import type { Coupon, CouponType } from "@/lib/api/types"; +import { useAuthStore } from "@/lib/stores/auth.store"; +import { formatNumber } from "@/lib/format"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { LabeledField } from "@/components/ui/labeled-field"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; + +export function CouponsScreen() { + const t = useTranslations("coupons"); + const tCommon = useTranslations("common"); + const cafeId = useAuthStore((s) => s.user?.cafeId); + const queryClient = useQueryClient(); + + const [showForm, setShowForm] = useState(false); + const [code, setCode] = useState(""); + const [type, setType] = useState("Percentage"); + const [value, setValue] = useState("10"); + + const { data: coupons = [], isLoading } = useQuery({ + queryKey: ["coupons", cafeId], + queryFn: () => apiGet(`/api/cafes/${cafeId}/coupons`), + enabled: !!cafeId, + }); + + const createCoupon = useMutation({ + mutationFn: () => + apiPost(`/api/cafes/${cafeId}/coupons`, { + code, + type, + value: Number(value), + isActive: true, + }), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["coupons", cafeId] }); + setShowForm(false); + setCode(""); + setValue("10"); + }, + }); + + if (!cafeId) return null; + + return ( +
+
+

{t("title")}

+ +
+ + {showForm && ( + + + + setCode(e.target.value)} + dir="ltr" + className="text-end" + /> + + + + + + setValue(e.target.value)} + type="number" + dir="ltr" + className="text-end" + /> + +
+ + +
+
+
+ )} + + {isLoading ? ( +

{tCommon("loading")}

+ ) : coupons.length === 0 ? ( +

{t("noCoupons")}

+ ) : ( +
+ {coupons.map((c) => ( + + +
+ {c.code} + + {c.isActive ? t("active") : t("inactive")} + +
+
+ +

+ {t("type")}: {t(`types.${c.type}`)} +

+

+ {t("value")}: {formatNumber(c.value)} + {c.type === "Percentage" ? "%" : " ت"} +

+

+ {t("usage")}: {formatNumber(c.usedCount)} + {c.usageLimit ? ` / ${formatNumber(c.usageLimit)}` : ""} +

+
+
+ ))} +
+ )} +
+ ); +} diff --git a/web/dashboard/src/components/crm/crm-screen.tsx b/web/dashboard/src/components/crm/crm-screen.tsx new file mode 100644 index 0000000..86cbe0e --- /dev/null +++ b/web/dashboard/src/components/crm/crm-screen.tsx @@ -0,0 +1,132 @@ +"use client"; + +import { useState } from "react"; +import { useQuery, useQueryClient } from "@tanstack/react-query"; +import { useTranslations } from "next-intl"; +import { Plus, Pencil, Search } from "lucide-react"; +import { apiGet } from "@/lib/api/client"; +import type { Customer } from "@/lib/api/types"; +import { useAuthStore } from "@/lib/stores/auth.store"; +import { formatNumber } from "@/lib/format"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { LabeledField } from "@/components/ui/labeled-field"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { CustomerWizard, type CustomerWizardMode } from "@/components/crm/customer-wizard"; + +export function CrmScreen() { + const t = useTranslations("crm"); + const tCommon = useTranslations("common"); + const cafeId = useAuthStore((s) => s.user?.cafeId); + const queryClient = useQueryClient(); + + const [search, setSearch] = useState(""); + const [debouncedSearch, setDebouncedSearch] = useState(""); + const [wizardOpen, setWizardOpen] = useState(false); + const [wizardMode, setWizardMode] = useState("create"); + const [editingCustomer, setEditingCustomer] = useState(null); + + const { data: customers = [], isLoading } = useQuery({ + queryKey: ["customers", cafeId, debouncedSearch], + queryFn: () => + apiGet( + `/api/cafes/${cafeId}/customers${debouncedSearch ? `?q=${encodeURIComponent(debouncedSearch)}` : ""}` + ), + enabled: !!cafeId, + }); + + const openWizard = (mode: CustomerWizardMode, customer?: Customer) => { + setWizardMode(mode); + setEditingCustomer(customer ?? null); + setWizardOpen(true); + }; + + const refreshCustomers = () => { + queryClient.invalidateQueries({ queryKey: ["customers", cafeId] }); + }; + + if (!cafeId) return null; + + return ( +
+
+

{t("title")}

+ +
+ +
+ + setSearch(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && setDebouncedSearch(search)} + /> + + +
+ + {isLoading ? ( +

{tCommon("loading")}

+ ) : customers.length === 0 ? ( +

{t("noCustomers")}

+ ) : ( +
+ {customers.map((c) => ( + + +
+ {c.name} + {t(`groups.${c.group}`)} +
+
+ +
+

+ {c.phone} +

+ {c.nationalId ? ( +

+ {t("nationalId")}: {c.nationalId} +

+ ) : null} +

+ {t("loyaltyPoints")}: {formatNumber(c.loyaltyPoints)} +

+
+ +
+
+ ))} +
+ )} + + setWizardOpen(false)} + onSaved={refreshCustomers} + /> +
+ ); +} diff --git a/web/dashboard/src/components/crm/customer-wizard.tsx b/web/dashboard/src/components/crm/customer-wizard.tsx new file mode 100644 index 0000000..c49f259 --- /dev/null +++ b/web/dashboard/src/components/crm/customer-wizard.tsx @@ -0,0 +1,363 @@ +"use client"; + +import { useEffect, useMemo, useState } from "react"; +import { useMutation } from "@tanstack/react-query"; +import { useTranslations } from "next-intl"; +import { ChevronLeft, ChevronRight, X } from "lucide-react"; +import { apiPatch, apiPost, ApiClientError } from "@/lib/api/client"; +import type { Customer, CustomerGroup } from "@/lib/api/types"; +import { useIsRtl } from "@/lib/use-is-rtl"; +import { formatNumber } from "@/lib/format"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { LabeledField } from "@/components/ui/labeled-field"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { cn } from "@/lib/utils"; + +const GROUPS: CustomerGroup[] = ["Regular", "Vip", "New", "Employee"]; +const STEP_COUNT = 4; + +export type CustomerWizardMode = "create" | "edit"; + +type CustomerWizardProps = { + open: boolean; + mode: CustomerWizardMode; + cafeId: string; + customer?: Customer | null; + onClose: () => void; + onSaved: () => void; +}; + +type FormState = { + name: string; + phone: string; + nationalId: string; + birthDateJalali: string; + group: CustomerGroup; + loyaltyPoints: string; + referredBy: string; +}; + +function emptyForm(): FormState { + return { + name: "", + phone: "", + nationalId: "", + birthDateJalali: "", + group: "Regular", + loyaltyPoints: "0", + referredBy: "", + }; +} + +function fromCustomer(c: Customer): FormState { + return { + name: c.name, + phone: c.phone, + nationalId: c.nationalId ?? "", + birthDateJalali: c.birthDateJalali ?? "", + group: c.group, + loyaltyPoints: String(c.loyaltyPoints), + referredBy: c.referredBy ?? "", + }; +} + +export function CustomerWizard({ + open, + mode, + cafeId, + customer, + onClose, + onSaved, +}: CustomerWizardProps) { + const t = useTranslations("crm.wizard"); + const tCrm = useTranslations("crm"); + const tCommon = useTranslations("common"); + const isRtl = useIsRtl(); + const numberLocale = isRtl ? "fa-IR" : "en-US"; + + const [step, setStep] = useState(1); + const [form, setForm] = useState(emptyForm); + const [error, setError] = useState(null); + + useEffect(() => { + if (!open) return; + setStep(1); + setError(null); + setForm(mode === "edit" && customer ? fromCustomer(customer) : emptyForm()); + }, [open, mode, customer]); + + const stepLabels = useMemo( + () => [t("steps.contact"), t("steps.profile"), t("steps.loyalty"), t("steps.confirm")], + [t] + ); + + const canNext = () => { + if (step === 1) return form.name.trim().length > 0 && form.phone.trim().length >= 10; + return true; + }; + + const save = useMutation({ + mutationFn: async () => { + const loyalty = parseInt(form.loyaltyPoints, 10) || 0; + if (mode === "create") { + return apiPost(`/api/cafes/${cafeId}/customers`, { + name: form.name.trim(), + phone: form.phone.trim(), + nationalId: form.nationalId.trim() || undefined, + birthDateJalali: form.birthDateJalali.trim() || undefined, + group: form.group, + referredBy: form.referredBy.trim() || undefined, + }); + } + if (!customer?.id) throw new Error("missing customer"); + return apiPatch(`/api/cafes/${cafeId}/customers/${customer.id}`, { + name: form.name.trim(), + phone: form.phone.trim(), + nationalId: form.nationalId.trim() || undefined, + birthDateJalali: form.birthDateJalali.trim() || undefined, + group: form.group, + loyaltyPoints: loyalty, + referredBy: form.referredBy.trim() || undefined, + }); + }, + onSuccess: () => { + onSaved(); + onClose(); + }, + onError: (err: Error) => { + const code = err instanceof ApiClientError ? err.code : ""; + if (code === "DUPLICATE_PHONE") setError(t("errors.duplicatePhone")); + else setError(t("errors.generic")); + }, + }); + + if (!open) return null; + + const BackIcon = isRtl ? ChevronRight : ChevronLeft; + const NextIcon = isRtl ? ChevronLeft : ChevronRight; + + return ( +
+ + +
+
+ + {mode === "create" ? t("titleCreate") : t("titleEdit")} + +

+ {t("stepOf", { current: step, total: STEP_COUNT })} +

+
+ +
+
+ {stepLabels.map((label, i) => { + const n = i + 1; + return ( +
+ ); + })} +
+

+ {stepLabels[step - 1]} +

+ + + + {error ? ( +

+ {error} +

+ ) : null} + + {step === 1 && ( +
+ + setForm((f) => ({ ...f, name: e.target.value }))} + autoFocus + /> + + + setForm((f) => ({ ...f, phone: e.target.value }))} + dir="ltr" + className="text-end" + inputMode="tel" + /> + +
+ )} + + {step === 2 && ( +
+ + setForm((f) => ({ ...f, nationalId: e.target.value }))} + dir="ltr" + className="text-end" + maxLength={10} + inputMode="numeric" + /> + + + setForm((f) => ({ ...f, birthDateJalali: e.target.value }))} + dir="ltr" + className="text-end" + placeholder="1400/01/01" + /> + +
+ )} + + {step === 3 && ( +
+ + + + + setForm((f) => ({ ...f, loyaltyPoints: e.target.value }))} + inputMode="numeric" + dir="ltr" + className="text-end" + disabled={mode === "create"} + /> + + {mode === "create" ? ( +

{t("loyaltyCreateHint")}

+ ) : null} + + setForm((f) => ({ ...f, referredBy: e.target.value }))} + dir="ltr" + className="text-end" + /> + +
+ )} + + {step === 4 && ( +
+
+
{tCrm("name")}
+
{form.name}
+
+
+
{tCrm("phone")}
+
+ {form.phone} +
+
+ {form.nationalId ? ( +
+
{tCrm("nationalId")}
+
{form.nationalId}
+
+ ) : null} + {form.birthDateJalali ? ( +
+
{tCrm("birthDate")}
+
{form.birthDateJalali}
+
+ ) : null} +
+
{tCrm("group")}
+
+ {tCrm(`groups.${form.group}`)} +
+
+
+
{tCrm("loyaltyPoints")}
+
{formatNumber(parseInt(form.loyaltyPoints, 10) || 0, numberLocale)}
+
+
+ )} +
+ +
+ {step > 1 ? ( + + ) : ( + + )} +
+ {step < STEP_COUNT ? ( + + ) : ( + + )} +
+ +
+ ); +} diff --git a/web/dashboard/src/components/discover/cafe-discover-profile-editor.tsx b/web/dashboard/src/components/discover/cafe-discover-profile-editor.tsx new file mode 100644 index 0000000..374b42c --- /dev/null +++ b/web/dashboard/src/components/discover/cafe-discover-profile-editor.tsx @@ -0,0 +1,187 @@ +"use client"; + +import { useTranslations } from "next-intl"; +import { + DISCOVER_TAXONOMY, + type CafeDiscoverProfile, + type DiscoverListField, + type DiscoverSingleField, + toggleListValue, +} from "@/lib/cafe-discover-profile"; +import { cn } from "@/lib/utils"; + +type CafeDiscoverProfileEditorProps = { + value: CafeDiscoverProfile; + onChange: (next: CafeDiscoverProfile) => void; + disabled?: boolean; +}; + +export function CafeDiscoverProfileEditor({ + value, + onChange, + disabled, +}: CafeDiscoverProfileEditorProps) { + const t = useTranslations("discoverProfile"); + + const setList = (field: DiscoverListField, id: string) => { + onChange({ ...value, [field]: toggleListValue(value[field], id) }); + }; + + const setSingle = (field: DiscoverSingleField, id: string) => { + onChange({ ...value, [field]: value[field] === id ? null : id }); + }; + + return ( +
+ + t(`themes.${id}`)} + onToggle={(id) => setList("themes", id)} + disabled={disabled} + /> + + + + t(`occasions.${id}`)} + onToggle={(id) => setList("occasions", id)} + disabled={disabled} + /> + + + + t(`spaceFeatures.${id}`)} + onToggle={(id) => setList("spaceFeatures", id)} + disabled={disabled} + /> + + + + t(`vibes.${id}`)} + onToggle={(id) => setList("vibes", id)} + disabled={disabled} + /> + + +
+ + t(`sizes.${id}`)} + onToggle={(id) => setSingle("size", id)} + disabled={disabled} + single + /> + + + t(`floors.${id}`)} + onToggle={(id) => setSingle("floors", id)} + disabled={disabled} + single + /> + + + t(`noiseLevels.${id}`)} + onToggle={(id) => setSingle("noiseLevel", id)} + disabled={disabled} + single + /> + + + t(`priceTiers.${id}`)} + onToggle={(id) => setSingle("priceTier", id)} + disabled={disabled} + single + /> + +
+
+ ); +} + +function ProfileSection({ + label, + hint, + children, +}: { + label: string; + hint?: string; + children: React.ReactNode; +}) { + return ( +
+

+ {label} +

+ {hint ?

{hint}

: null} + {children} +
+ ); +} + +function ChipGrid({ + ids, + selected, + label, + onToggle, + disabled, + single, +}: { + ids: readonly string[]; + selected: string[]; + label: (id: string) => string; + onToggle: (id: string) => void; + disabled?: boolean; + single?: boolean; +}) { + return ( +
+ {ids.map((id) => { + const active = selected.includes(id); + return ( + + ); + })} +
+ ); +} diff --git a/web/dashboard/src/components/discover/cafe-discover-profile-panel.tsx b/web/dashboard/src/components/discover/cafe-discover-profile-panel.tsx new file mode 100644 index 0000000..3483b82 --- /dev/null +++ b/web/dashboard/src/components/discover/cafe-discover-profile-panel.tsx @@ -0,0 +1,144 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { useTranslations } from "next-intl"; +import { apiGet, apiPut } from "@/lib/api/client"; +import { adminGet, adminPut } from "@/lib/api/admin-client"; +import { + EMPTY_DISCOVER_PROFILE, + type CafeDiscoverProfile, +} from "@/lib/cafe-discover-profile"; +import { CafeDiscoverProfileEditor } from "@/components/discover/cafe-discover-profile-editor"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { notify } from "@/lib/notify"; + +type ApiDiscoverProfile = { + themes: string[]; + size?: string | null; + floors?: string | null; + vibes: string[]; + occasions: string[]; + spaceFeatures: string[]; + noiseLevel?: string | null; + priceTier?: string | null; +}; + +function fromApi(d: ApiDiscoverProfile): CafeDiscoverProfile { + return { + themes: d.themes ?? [], + size: d.size ?? null, + floors: d.floors ?? null, + vibes: d.vibes ?? [], + occasions: d.occasions ?? [], + spaceFeatures: d.spaceFeatures ?? [], + noiseLevel: d.noiseLevel ?? null, + priceTier: d.priceTier ?? null, + }; +} + +function toApiBody(p: CafeDiscoverProfile) { + return { + themes: p.themes, + size: p.size, + floors: p.floors, + vibes: p.vibes, + occasions: p.occasions, + spaceFeatures: p.spaceFeatures, + noiseLevel: p.noiseLevel, + priceTier: p.priceTier, + }; +} + +type CafeDiscoverProfilePanelProps = { + cafeId: string; + mode: "merchant" | "admin"; + compact?: boolean; +}; + +export function CafeDiscoverProfilePanel({ + cafeId, + mode, + compact, +}: CafeDiscoverProfilePanelProps) { + const t = useTranslations( + mode === "admin" ? "admin.cafes.discoverProfile" : "settings.discoverProfile" + ); + const qc = useQueryClient(); + const [profile, setProfile] = useState(EMPTY_DISCOVER_PROFILE); + + const queryKey = + mode === "admin" + ? ["admin", "cafe-discover-profile", cafeId] + : ["cafe-discover-profile", cafeId]; + + const { data, isLoading } = useQuery({ + queryKey, + queryFn: async () => { + if (mode === "admin") { + const res = await adminGet( + `/api/admin/cafes/${cafeId}/discover-profile` + ); + return fromApi(res); + } + const res = await apiGet(`/api/cafes/${cafeId}/discover-profile`); + return fromApi(res); + }, + enabled: !!cafeId, + }); + + useEffect(() => { + if (data) setProfile(data); + }, [data]); + + const save = useMutation({ + mutationFn: () => { + const body = toApiBody(profile); + return mode === "admin" + ? adminPut(`/api/admin/cafes/${cafeId}/discover-profile`, body) + : apiPut(`/api/cafes/${cafeId}/discover-profile`, body); + }, + onSuccess: () => { + void qc.invalidateQueries({ queryKey }); + notify.success(t("saved")); + }, + }); + + const content = ( + <> + {!compact ? ( +

{t("subtitle")}

+ ) : null} + {isLoading ? ( +

{t("loading")}

+ ) : ( + + )} + + + ); + + if (compact) { + return
{content}
; + } + + return ( + + + {t("title")} + + {content} + + ); +} diff --git a/web/dashboard/src/components/discover/cafe-public-profile-panel.tsx b/web/dashboard/src/components/discover/cafe-public-profile-panel.tsx new file mode 100644 index 0000000..912ad4c --- /dev/null +++ b/web/dashboard/src/components/discover/cafe-public-profile-panel.tsx @@ -0,0 +1,347 @@ +"use client"; + +import { useRef, useState } from "react"; +import { useTranslations } from "next-intl"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { + fetchCafePublicProfile, + removeGalleryPhoto, + updateCafePublicProfile, + uploadGalleryPhoto, + type CafeProfileEdit, +} from "@/lib/api/cafe-public-profile"; +import type { WorkingHours } from "@/lib/api/public-discover"; +import { resolveMediaUrl } from "@/lib/api/client"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Card, CardContent } from "@/components/ui/card"; +import { cn } from "@/lib/utils"; + +type Props = { cafeId: string }; + +type Tab = "info" | "gallery" | "hours" | "social"; + +const DAY_KEYS: (keyof WorkingHours)[] = ["sat", "sun", "mon", "tue", "wed", "thu", "fri"]; + +export function CafePublicProfilePanel({ cafeId }: Props) { + const t = useTranslations("cafePublicProfile"); + const qc = useQueryClient(); + const [tab, setTab] = useState("info"); + const [saved, setSaved] = useState(false); + const fileInputRef = useRef(null); + + // ── Server state ────────────────────────────────────────────────────────── + const { data: profile, isLoading } = useQuery({ + queryKey: ["cafe-public-profile", cafeId], + queryFn: () => fetchCafePublicProfile(cafeId), + }); + + // ── Local edit state ────────────────────────────────────────────────────── + const [description, setDescription] = useState(""); + const [instagram, setInstagram] = useState(""); + const [website, setWebsite] = useState(""); + const [hours, setHours] = useState(emptyHours()); + const [initialized, setInitialized] = useState(false); + + // Populate local state once we get server data + if (profile && !initialized) { + setDescription(profile.description ?? ""); + setInstagram(profile.instagramHandle ?? ""); + setWebsite(profile.websiteUrl ?? ""); + setHours(profile.workingHours ?? emptyHours()); + setInitialized(true); + } + + // ── Save info/social/hours ──────────────────────────────────────────────── + const saveMutation = useMutation({ + mutationFn: () => + updateCafePublicProfile(cafeId, { + description, + instagramHandle: instagram || null, + websiteUrl: website || null, + workingHours: hours, + }), + onSuccess: (data) => { + qc.setQueryData(["cafe-public-profile", cafeId], data); + setSaved(true); + setTimeout(() => setSaved(false), 2000); + }, + }); + + // ── Gallery upload ──────────────────────────────────────────────────────── + const [uploading, setUploading] = useState(false); + const [uploadError, setUploadError] = useState(null); + + const handleFileChange = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + setUploading(true); + setUploadError(null); + try { + const gallery = await uploadGalleryPhoto(cafeId, file); + qc.setQueryData(["cafe-public-profile", cafeId], (old) => + old ? { ...old, galleryUrls: gallery } : old + ); + } catch (err: unknown) { + const msg = err instanceof Error ? err.message : t("uploadFailed"); + setUploadError(msg.includes("GALLERY_FULL") ? t("galleryFull") : t("uploadFailed")); + } finally { + setUploading(false); + if (fileInputRef.current) fileInputRef.current.value = ""; + } + }; + + const removeMutation = useMutation({ + mutationFn: (url: string) => removeGalleryPhoto(cafeId, url), + onSuccess: (gallery) => { + qc.setQueryData(["cafe-public-profile", cafeId], (old) => + old ? { ...old, galleryUrls: gallery } : old + ); + }, + }); + + // ── Hours helpers ───────────────────────────────────────────────────────── + const setDayField = ( + day: keyof WorkingHours, + field: "isOpen" | "open" | "close", + value: string | boolean + ) => { + setHours((prev) => ({ + ...prev, + [day]: { + ...((prev[day] as object) ?? { isOpen: false, open: "", close: "" }), + [field]: value, + }, + })); + }; + + if (isLoading) { + return

{t("loading")}

; + } + + const tabs: { id: Tab; label: string }[] = [ + { id: "info", label: t("tabs.info") }, + { id: "gallery", label: t("tabs.gallery") }, + { id: "hours", label: t("tabs.hours") }, + { id: "social", label: t("tabs.social") }, + ]; + + return ( +
+
+

{t("title")}

+

{t("subtitle")}

+
+ + {/* Tab bar */} +
+ {tabs.map((tb) => ( + + ))} +
+ + {/* ── Info tab ─────────────────────────────────────────────────────── */} + {tab === "info" && ( + + +
+ +