From 056218316f75aac539720dc07706a3297a5185fd Mon Sep 17 00:00:00 2001 From: byteful Date: Sat, 2 May 2026 01:43:14 -0400 Subject: [PATCH 01/30] realtime --- client/src/App.tsx | 2 + client/src/hooks/use-realtime.tsx | 373 ++++++++++++++++++++++++++++++ nginx/modl-panel.conf.example | 51 ++++ package-lock.json | 4 +- package.json | 2 +- vite.config.ts | 7 + 6 files changed, 436 insertions(+), 3 deletions(-) create mode 100644 client/src/hooks/use-realtime.tsx create mode 100644 nginx/modl-panel.conf.example diff --git a/client/src/App.tsx b/client/src/App.tsx index 4ec6673..dde434d 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -12,6 +12,7 @@ import { useIsMobile } from '@modl-gg/shared-web/hooks/use-mobile'; import { useDocumentTitle } from "@/hooks/use-document-title"; import { useProvisioningStatusCheck } from "@/hooks/use-provisioning-status"; import { usePublicSettings } from "@/hooks/use-public-settings"; +import { RealtimeProvider } from "@/hooks/use-realtime"; import { PlayerWindowProvider } from "@/contexts/PlayerWindowContext"; import { WelcomeModal } from "@/components/layout/WelcomeModal"; import { Loader2 } from "lucide-react"; @@ -246,6 +247,7 @@ function AppContent() { return ( <> + diff --git a/client/src/hooks/use-realtime.tsx b/client/src/hooks/use-realtime.tsx new file mode 100644 index 0000000..56afc5f --- /dev/null +++ b/client/src/hooks/use-realtime.tsx @@ -0,0 +1,373 @@ +import { useEffect, useMemo, useRef } from 'react'; +import { QueryClient, useQueryClient } from '@tanstack/react-query'; +import { create, fromBinary, toBinary } from '@bufbuild/protobuf'; +import { + AckKind, + AckSchema, + ClientHelloSchema, + ClientKind, + ErrorCode, + HeartbeatSchema, + RealtimeEnvelope, + RealtimeEnvelopeSchema, + ReconnectAction, + ReconnectReason, + Topic, +} from '@modl-gg/proto/modl/v1/realtime_pb.ts'; +import { useAuth } from '@/hooks/use-auth'; +import { getCurrentDomain } from '@/lib/api'; + +const REALTIME_PROTOCOL_VERSION = 1; +const HEARTBEAT_INTERVAL_MS = 30_000; +const INITIAL_RECONNECT_DELAY_MS = 1_000; +const MAX_RECONNECT_DELAY_MS = 30_000; +const MAX_ADVISED_RECONNECT_DELAY_MS = 60_000; +const RECENT_EVENT_ID_LIMIT = 256; +const REALTIME_PATH = '/api/v1/realtime/ws'; + +const PANEL_TOPICS = [ + Topic.PANEL_TICKETS, + Topic.PANEL_ASSIGNED_TICKETS, + Topic.PANEL_MIGRATIONS, +] as const; +const PANEL_TOPIC_SET = new Set(PANEL_TOPICS); + +type InvalidateQueries = Pick; +type InvalidationTarget = readonly unknown[]; + +export function isPanelRealtimeEnabled(): boolean { + return import.meta.env.VITE_REALTIME_ENABLED === 'true'; +} + +export function createRealtimeWebSocketUrl(location: Location): string { + const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; + return `${protocol}//${location.host}${REALTIME_PATH}`; +} + +export function getReconnectDelayMs(attempt: number, random: () => number = Math.random): number { + const cappedAttempt = Math.min(attempt, 5); + const baseDelay = Math.min(MAX_RECONNECT_DELAY_MS, INITIAL_RECONNECT_DELAY_MS * 2 ** cappedAttempt); + return baseDelay + Math.floor(random() * Math.min(baseDelay, 1_000)); +} + +export function getAdvisedReconnectDelayMs(retryAfterMs: number, random: () => number = Math.random): number { + const cappedDelay = Math.max(0, Math.min(retryAfterMs, MAX_ADVISED_RECONNECT_DELAY_MS)); + return cappedDelay + Math.floor(random() * Math.min(Math.max(cappedDelay, 1), 1_000)); +} + +export function getRequiredTopicForRealtimePayload(envelope: RealtimeEnvelope): Topic | null { + switch (envelope.payload.case) { + case 'ticketChanged': + return Topic.PANEL_TICKETS; + case 'assignedTicketSubscriptionChanged': + return Topic.PANEL_ASSIGNED_TICKETS; + case 'migrationStatusChanged': + return Topic.PANEL_MIGRATIONS; + default: + return null; + } +} + +export function getRealtimeInvalidationTargets(envelope: RealtimeEnvelope): InvalidationTarget[] { + switch (envelope.payload.case) { + case 'ticketChanged': { + const ticketId = envelope.payload.value.ticketId?.trim(); + return [ + ['/v1/panel/tickets'], + ['/v1/panel/tickets/counts'], + ...(ticketId ? [['/v1/panel/tickets', ticketId] as const] : []), + ]; + } + case 'assignedTicketSubscriptionChanged': + return [ + ['/v1/panel/ticket-subscriptions/updates'], + ['/v1/panel/ticket-subscriptions/assigned-updates'], + ]; + case 'migrationStatusChanged': + return [['/v1/panel/migration/status']]; + default: + return []; + } +} + +function getTopicInvalidationTargets(topic: Topic): InvalidationTarget[] { + switch (topic) { + case Topic.PANEL_TICKETS: + return [ + ['/v1/panel/tickets'], + ['/v1/panel/tickets/counts'], + ]; + case Topic.PANEL_ASSIGNED_TICKETS: + return [ + ['/v1/panel/ticket-subscriptions/updates'], + ['/v1/panel/ticket-subscriptions/assigned-updates'], + ]; + case Topic.PANEL_MIGRATIONS: + return [['/v1/panel/migration/status']]; + default: + return []; + } +} + +function getSubscribedRealtimeInvalidationTargets(topics: readonly Topic[]): InvalidationTarget[] { + const seen = new Set(); + const targets: InvalidationTarget[] = []; + + for (const topic of topics) { + if (!PANEL_TOPIC_SET.has(topic)) continue; + + for (const target of getTopicInvalidationTargets(topic)) { + const key = JSON.stringify(target); + if (seen.has(key)) continue; + seen.add(key); + targets.push(target); + } + } + + return targets; +} + +export function invalidateRealtimeTargets(queryClient: InvalidateQueries, targets: InvalidationTarget[]): void { + for (const queryKey of targets) { + void queryClient.invalidateQueries({ queryKey }); + } +} + +export function invalidateSubscribedRealtimeTargets(queryClient: InvalidateQueries, topics: readonly Topic[]): void { + invalidateRealtimeTargets(queryClient, getSubscribedRealtimeInvalidationTargets(topics)); +} + +function buildEnvelope(payload: RealtimeEnvelope['payload']): RealtimeEnvelope { + return create(RealtimeEnvelopeSchema, { + protocolVersion: REALTIME_PROTOCOL_VERSION, + payload, + }); +} + +function buildClientHello(serverDomain: string): RealtimeEnvelope { + return buildEnvelope({ + case: 'clientHello', + value: create(ClientHelloSchema, { + clientKind: ClientKind.PANEL, + protocolVersion: REALTIME_PROTOCOL_VERSION, + serverName: serverDomain, + supportedTopics: [...PANEL_TOPICS], + }), + }); +} + +function buildHeartbeat(sequence: bigint): RealtimeEnvelope { + return buildEnvelope({ + case: 'heartbeat', + value: create(HeartbeatSchema, { sequence }), + }); +} + +function buildTransportAck(eventId: string): RealtimeEnvelope { + return buildEnvelope({ + case: 'ack', + value: create(AckSchema, { + kind: AckKind.TRANSPORT, + eventId, + }), + }); +} + +function sendEnvelope(socket: WebSocket | null, envelope: RealtimeEnvelope): void { + if (!socket || socket.readyState !== WebSocket.OPEN) return; + socket.send(toBinary(RealtimeEnvelopeSchema, envelope)); +} + +function shouldStopForError(envelope: RealtimeEnvelope): boolean { + if (envelope.payload.case !== 'error') return false; + return envelope.payload.value.code === ErrorCode.UNAUTHORIZED + || envelope.payload.value.code === ErrorCode.FORBIDDEN + || envelope.payload.value.code === ErrorCode.UNSUPPORTED_PROTOCOL; +} + +function shouldStopForReconnectAdvice(envelope: RealtimeEnvelope): boolean { + if (envelope.payload.case !== 'reconnectAdvice') return false; + const advice = envelope.payload.value; + return advice.action === ReconnectAction.STOP + || advice.action === ReconnectAction.REAUTHENTICATE + || advice.reason === ReconnectReason.AUTH_EXPIRED + || advice.reason === ReconnectReason.PROTOCOL_UPGRADE; +} + +function markEventId(eventIds: string[], eventId: string): boolean { + if (!eventId) return true; + if (eventIds.includes(eventId)) return false; + eventIds.push(eventId); + if (eventIds.length > RECENT_EVENT_ID_LIMIT) { + eventIds.splice(0, eventIds.length - RECENT_EVENT_ID_LIMIT); + } + return true; +} + +export function useRealtimeInvalidation(): void { + const queryClient = useQueryClient(); + const { user, isLoading } = useAuth(); + const domain = getCurrentDomain(); + const authKey = useMemo(() => user ? `${domain}:${user.id}` : null, [domain, user]); + const stoppedAuthKeyRef = useRef(null); + + useEffect(() => { + if (!authKey) { + stoppedAuthKeyRef.current = null; + } + }, [authKey]); + + useEffect(() => { + if (!isPanelRealtimeEnabled() || isLoading || !authKey || typeof window === 'undefined') return; + if (stoppedAuthKeyRef.current === authKey) return; + + let active = true; + let socket: WebSocket | null = null; + let reconnectTimer: number | undefined; + let heartbeatTimer: number | undefined; + let reconnectAttempt = 0; + let heartbeatSequence = BigInt(0); + let connectedOnce = false; + let subscribedTopics: Topic[] = []; + let reconnectDelayOverrideMs: number | undefined; + const recentEventIds: string[] = []; + + const cleanupTimers = () => { + if (reconnectTimer !== undefined) { + window.clearTimeout(reconnectTimer); + reconnectTimer = undefined; + } + if (heartbeatTimer !== undefined) { + window.clearInterval(heartbeatTimer); + heartbeatTimer = undefined; + } + }; + + const stopForAuthSession = () => { + stoppedAuthKeyRef.current = authKey; + active = false; + cleanupTimers(); + socket?.close(); + socket = null; + }; + + const scheduleReconnect = () => { + if (!active || reconnectTimer !== undefined) return; + const delayMs = reconnectDelayOverrideMs !== undefined + ? getAdvisedReconnectDelayMs(reconnectDelayOverrideMs) + : getReconnectDelayMs(reconnectAttempt++); + reconnectDelayOverrideMs = undefined; + reconnectTimer = window.setTimeout(() => { + reconnectTimer = undefined; + connect(); + }, delayMs); + }; + + const startHeartbeat = () => { + if (heartbeatTimer !== undefined) { + window.clearInterval(heartbeatTimer); + } + heartbeatTimer = window.setInterval(() => { + heartbeatSequence += BigInt(1); + sendEnvelope(socket, buildHeartbeat(heartbeatSequence)); + }, HEARTBEAT_INTERVAL_MS); + }; + + const handleEnvelope = (envelope: RealtimeEnvelope) => { + if (envelope.eventId) { + sendEnvelope(socket, buildTransportAck(envelope.eventId)); + } + + if (shouldStopForError(envelope) || shouldStopForReconnectAdvice(envelope)) { + stopForAuthSession(); + return; + } + + switch (envelope.payload.case) { + case 'serverHello': + reconnectAttempt = 0; + subscribedTopics = envelope.payload.value.acceptedTopics.filter((topic) => PANEL_TOPIC_SET.has(topic)); + if (connectedOnce) { + invalidateSubscribedRealtimeTargets(queryClient, subscribedTopics); + } + connectedOnce = true; + break; + case 'heartbeat': + break; + case 'reconnectAdvice': + if (envelope.payload.value.action === ReconnectAction.RECONNECT && envelope.payload.value.retryAfterMs !== undefined) { + reconnectDelayOverrideMs = envelope.payload.value.retryAfterMs; + } + if (envelope.payload.value.action === ReconnectAction.RESYNC) { + invalidateSubscribedRealtimeTargets(queryClient, subscribedTopics); + } + break; + case 'ticketChanged': + case 'assignedTicketSubscriptionChanged': + case 'migrationStatusChanged': { + const requiredTopic = getRequiredTopicForRealtimePayload(envelope); + if (requiredTopic !== null && subscribedTopics.includes(requiredTopic) && markEventId(recentEventIds, envelope.eventId)) { + invalidateRealtimeTargets(queryClient, getRealtimeInvalidationTargets(envelope)); + } + break; + } + default: + break; + } + }; + + const connect = () => { + if (!active) return; + const nextSocket = new WebSocket(createRealtimeWebSocketUrl(window.location)); + socket = nextSocket; + nextSocket.binaryType = 'arraybuffer'; + + nextSocket.onopen = () => { + sendEnvelope(nextSocket, buildClientHello(domain)); + startHeartbeat(); + }; + + nextSocket.onmessage = async (event) => { + try { + const data = event.data instanceof Blob + ? new Uint8Array(await event.data.arrayBuffer()) + : new Uint8Array(event.data); + handleEnvelope(fromBinary(RealtimeEnvelopeSchema, data)); + } catch { + nextSocket.close(1003, 'Invalid realtime frame'); + } + }; + + nextSocket.onclose = (event) => { + if (socket === nextSocket) socket = null; + if (heartbeatTimer !== undefined) { + window.clearInterval(heartbeatTimer); + heartbeatTimer = undefined; + } + if (event.code === 1008 || event.code === 1013) { + stopForAuthSession(); + return; + } + scheduleReconnect(); + }; + + nextSocket.onerror = () => { + nextSocket.close(); + }; + }; + + connect(); + + return () => { + active = false; + cleanupTimers(); + socket?.close(); + socket = null; + }; + }, [authKey, isLoading, queryClient]); +} + +export function RealtimeProvider(): null { + useRealtimeInvalidation(); + return null; +} diff --git a/nginx/modl-panel.conf.example b/nginx/modl-panel.conf.example new file mode 100644 index 0000000..c721e52 --- /dev/null +++ b/nginx/modl-panel.conf.example @@ -0,0 +1,51 @@ +# Example panel nginx config for same-origin realtime WebSocket proxying. +# Install manually and adapt server_name/root/upstream names for the target host. +# Install/include backend/nginx/modl-websocket-map.conf.example once at nginx http scope. +# Do not include the shared map from every vhost when installing multiple examples. + +upstream modl_panel { + server 127.0.0.1:3000; +} + +include /etc/nginx/conf.d/modl-backend-upstream.conf; + +server { + listen 443 ssl http2; + server_name panel.modl.example; + + location = /api/v1/realtime/ws { + # Keep aligned with modl.realtime.ws.max-frame-bytes. + client_max_body_size 64k; + + proxy_pass http://modl_backend/v1/realtime/ws; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_buffering off; + proxy_request_buffering off; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + } + + location /api/ { + proxy_pass http://modl_backend/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location / { + proxy_pass http://modl_panel; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/package-lock.json b/package-lock.json index 2638be1..a80fc16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "AGPL-3.0-only", "dependencies": { "@hookform/resolvers": "^3.10.0", - "@modl-gg/proto": "^1.0.0", + "@modl-gg/proto": "^1.1.0", "@modl-gg/replay-viewer": "^1.16.0", "@modl-gg/shared-web": "^1.0.5", "@radix-ui/react-accordion": "^1.2.4", @@ -3716,7 +3716,7 @@ } }, "node_modules/@modl-gg/proto": { - "version": "1.0.0", + "version": "1.1.0", "license": "AGPL-3.0-only", "dependencies": { "@bufbuild/protobuf": "^2.0.0" diff --git a/package.json b/package.json index c501ccc..5d334e4 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@hookform/resolvers": "^3.10.0", - "@modl-gg/proto": "^1.0.0", + "@modl-gg/proto": "^1.1.0", "@modl-gg/replay-viewer": "^1.16.0", "@modl-gg/shared-web": "^1.0.5", "@radix-ui/react-accordion": "^1.2.4", diff --git a/vite.config.ts b/vite.config.ts index 4bad16c..f3e2154 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -67,6 +67,13 @@ export default defineConfig(({ mode }) => { server: { port: 3000, proxy: { + '/api/v1/realtime/ws': { + target: 'http://localhost:8080', + changeOrigin: true, + secure: false, + ws: true, + rewrite: (path) => path.replace(/^\/api/, ''), + }, '/api': { target: 'http://localhost:8080', changeOrigin: true, From 0fcaad42c3af07acc2f84c6f65e9012acea1955c Mon Sep 17 00:00:00 2001 From: Rudra <80184082+byteful@users.noreply.github.com> Date: Mon, 18 May 2026 02:48:57 -0500 Subject: [PATCH 02/30] alert system #113 (#100) --- .../dashboard/DashboardAlertsSection.tsx | 122 + client/src/hooks/use-data.tsx | 28 + client/src/locales/de.json | 14 + client/src/locales/en.json | 14 + client/src/locales/es.json | 14 + client/src/locales/nl.json | 14 + client/src/pages/home.tsx | 12 +- package-lock.json | 2933 +---------------- 8 files changed, 227 insertions(+), 2924 deletions(-) create mode 100644 client/src/components/dashboard/DashboardAlertsSection.tsx diff --git a/client/src/components/dashboard/DashboardAlertsSection.tsx b/client/src/components/dashboard/DashboardAlertsSection.tsx new file mode 100644 index 0000000..210bbb3 --- /dev/null +++ b/client/src/components/dashboard/DashboardAlertsSection.tsx @@ -0,0 +1,122 @@ +import { Badge } from '@modl-gg/shared-web/components/ui/badge'; +import { StatusBanner } from '@modl-gg/shared-web/components/ui/status-banner'; +import { useTranslation } from 'react-i18next'; +import type { SystemAlert, SystemAlertSeverity } from '@/hooks/use-data'; + +interface DashboardAlertsSectionProps { + alerts?: SystemAlert[]; + loading?: boolean; + error?: boolean; +} + +type AlertBannerVariant = 'info' | 'warning' | 'error'; + +const severityVariant: Record = { + BASIC: 'info', + WARNING: 'warning', + CRITICAL: 'error', +}; + +function normalizeSeverity(severity: unknown): string | null { + if (typeof severity !== 'string' || severity.trim().length === 0) { + return null; + } + + return severity.trim(); +} + +function isKnownSeverity(severity: string): severity is SystemAlertSeverity { + return severity === 'BASIC' || severity === 'WARNING' || severity === 'CRITICAL'; +} + +function getSeverityVariant(severity: unknown): AlertBannerVariant { + const normalizedSeverity = normalizeSeverity(severity); + if (!normalizedSeverity || !isKnownSeverity(normalizedSeverity)) { + return 'info'; + } + + return severityVariant[normalizedSeverity]; +} + +function getSeverityTitle(severity: unknown, t: ReturnType['t']) { + const normalizedSeverity = normalizeSeverity(severity); + + if (!normalizedSeverity) { + return t('dashboard.alerts.unknownSeverity', { severity: t('dashboard.alerts.unknownSeverityValue') }); + } + + if (isKnownSeverity(normalizedSeverity)) { + return t(`dashboard.alerts.levels.${normalizedSeverity}`); + } + + return t('dashboard.alerts.unknownSeverity', { severity: normalizedSeverity }); +} + +function formatExpiryDate(expiresAt?: string) { + if (!expiresAt) { + return null; + } + + const expiryDate = new Date(expiresAt); + if (Number.isNaN(expiryDate.getTime())) { + return null; + } + + return expiryDate.toLocaleString(); +} + +export function DashboardAlertsSection({ alerts = [], loading, error }: DashboardAlertsSectionProps) { + const { t } = useTranslation(); + + if (error) { + return ( + +

{t('dashboard.alerts.loadErrorDescription')}

+
+ ); + } + + if (loading) { + return ( + +

{t('dashboard.alerts.loadingDescription')}

+
+ ); + } + + if (alerts.length === 0) { + return null; + } + + return ( +
+ {alerts.map((alert) => { + const expiresAt = formatExpiryDate(alert.expiresAt); + + return ( + + {t('dashboard.alerts.expires', { date: expiresAt })} + + ) : undefined} + > +

{alert.message}

+
+ ); + })} +
+ ); +} diff --git a/client/src/hooks/use-data.tsx b/client/src/hooks/use-data.tsx index 15d9ae4..10d5487 100644 --- a/client/src/hooks/use-data.tsx +++ b/client/src/hooks/use-data.tsx @@ -1169,6 +1169,34 @@ export function useRecentPunishments(limit: number = 10) { }); } +export type SystemAlertSeverity = 'BASIC' | 'WARNING' | 'CRITICAL'; +export type SystemAlertAudience = 'ALL_PANEL_USERS' | 'SUPER_ADMINS_ONLY'; + +export interface SystemAlert { + id: string; + message: string; + severity: SystemAlertSeverity; + audience: SystemAlertAudience; + expiresAt?: string; + createdAt?: string; + updatedAt?: string; +} + +export function useDashboardAlerts() { + return useQuery({ + queryKey: ['/v1/panel/dashboard/alerts'], + queryFn: async () => { + const res = await apiFetch('/v1/panel/dashboard/alerts'); + if (!res.ok) { + throw new Error('Failed to fetch dashboard alerts'); + } + return res.json() as Promise; + }, + staleTime: 60 * 1000, + refetchOnWindowFocus: true, + }); +} + export function useTicketSubscriptionUpdates(limit: number = 10) { return useQuery({ queryKey: ['/v1/panel/ticket-subscriptions/updates', limit], diff --git a/client/src/locales/de.json b/client/src/locales/de.json index 5daf035..bfc949b 100644 --- a/client/src/locales/de.json +++ b/client/src/locales/de.json @@ -960,6 +960,20 @@ "refreshed": "Dashboard aktualisiert", "refreshedDesc": "Alle Dashboard-Daten wurden aktualisiert.", "refreshError": "Dashboard konnte nicht aktualisiert werden. Bitte versuche es erneut.", + "alerts": { + "expires": "Läuft ab am {{date}}", + "unknownSeverity": "Hinweis ({{severity}})", + "unknownSeverityValue": "Unbekannt", + "loadingTitle": "Hinweise werden geladen", + "loadingDescription": "Aktuelle Systemhinweise werden geprüft.", + "loadErrorTitle": "Hinweise konnten nicht geladen werden", + "loadErrorDescription": "Systemhinweise konnten nicht geladen werden. Andere Dashboard-Daten können trotzdem aktuell sein.", + "levels": { + "BASIC": "Hinweis", + "WARNING": "Warnung", + "CRITICAL": "Kritischer Hinweis" + } + }, "recentTickets": { "title": "Kürzlich geöffnete Tickets", "noMessage": "Keine Nachricht verfügbar", diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 44e0664..a6e2218 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -967,6 +967,20 @@ "refreshed": "Dashboard Refreshed", "refreshedDesc": "All dashboard data has been updated.", "refreshError": "Failed to refresh dashboard. Please try again.", + "alerts": { + "expires": "Expires {{date}}", + "unknownSeverity": "Alert ({{severity}})", + "unknownSeverityValue": "Unknown", + "loadingTitle": "Loading alerts", + "loadingDescription": "Checking for current system alerts.", + "loadErrorTitle": "Unable to load alerts", + "loadErrorDescription": "System alerts could not be loaded. Other dashboard data may still be current.", + "levels": { + "BASIC": "Notice", + "WARNING": "Warning", + "CRITICAL": "Critical Alert" + } + }, "recentTickets": { "title": "Recently Opened Tickets", "noMessage": "No message available", diff --git a/client/src/locales/es.json b/client/src/locales/es.json index 80a9d81..4f31bb2 100644 --- a/client/src/locales/es.json +++ b/client/src/locales/es.json @@ -960,6 +960,20 @@ "refreshed": "Panel actualizado", "refreshedDesc": "Todos los datos del panel han sido actualizados.", "refreshError": "No se pudo actualizar el panel. Por favor inténtalo de nuevo.", + "alerts": { + "expires": "Caduca el {{date}}", + "unknownSeverity": "Alerta ({{severity}})", + "unknownSeverityValue": "Desconocida", + "loadingTitle": "Cargando alertas", + "loadingDescription": "Comprobando alertas actuales del sistema.", + "loadErrorTitle": "No se pudieron cargar las alertas", + "loadErrorDescription": "No se pudieron cargar las alertas del sistema. Otros datos del panel aún pueden estar actualizados.", + "levels": { + "BASIC": "Aviso", + "WARNING": "Advertencia", + "CRITICAL": "Alerta crítica" + } + }, "recentTickets": { "title": "Tickets abiertos recientemente", "noMessage": "No hay mensaje disponible", diff --git a/client/src/locales/nl.json b/client/src/locales/nl.json index d2c1a4f..7e61615 100644 --- a/client/src/locales/nl.json +++ b/client/src/locales/nl.json @@ -960,6 +960,20 @@ "refreshed": "Dashboard vernieuwd", "refreshedDesc": "Alle dashboardgegevens zijn bijgewerkt.", "refreshError": "Dashboard vernieuwen mislukt. Probeer het opnieuw.", + "alerts": { + "expires": "Verloopt op {{date}}", + "unknownSeverity": "Melding ({{severity}})", + "unknownSeverityValue": "Onbekend", + "loadingTitle": "Meldingen laden", + "loadingDescription": "Actuele systeemmeldingen worden gecontroleerd.", + "loadErrorTitle": "Meldingen konden niet worden geladen", + "loadErrorDescription": "Systeemmeldingen konden niet worden geladen. Andere dashboardgegevens kunnen nog steeds actueel zijn.", + "levels": { + "BASIC": "Melding", + "WARNING": "Waarschuwing", + "CRITICAL": "Kritieke melding" + } + }, "recentTickets": { "title": "Recent geopende tickets", "noMessage": "Geen bericht beschikbaar", diff --git a/client/src/pages/home.tsx b/client/src/pages/home.tsx index 034cd74..9881074 100644 --- a/client/src/pages/home.tsx +++ b/client/src/pages/home.tsx @@ -11,13 +11,15 @@ import { useRecentTickets, useRecentPunishments, useAssignedTicketUpdates, - useMarkTicketAsRead + useMarkTicketAsRead, + useDashboardAlerts } from '@/hooks/use-data'; import { useToast } from '@modl-gg/shared-web/hooks/use-toast'; import PageContainer from '@/components/layout/PageContainer'; import { RecentTicketsSection } from '@/components/dashboard/RecentTicketsSection'; import { RecentPunishmentsSection } from '@/components/dashboard/RecentPunishmentsSection'; import { AssignedTicketUpdatesSection } from '@/components/dashboard/AssignedTicketUpdatesSection'; +import { DashboardAlertsSection } from '@/components/dashboard/DashboardAlertsSection'; const Home = () => { const [isSpinning, setIsSpinning] = useState(false); @@ -29,6 +31,7 @@ const Home = () => { const { data: recentTicketsData, isLoading: isLoadingTickets, refetch: refetchTickets } = useRecentTickets(3); const { data: recentPunishmentsData, isLoading: isLoadingPunishments, refetch: refetchPunishments } = useRecentPunishments(5); const { data: assignedUpdatesData, isLoading: isLoadingUpdates, refetch: refetchUpdates } = useAssignedTicketUpdates(10); + const { data: alertsData, isLoading: isLoadingAlerts, isError: isAlertsError, refetch: refetchAlerts } = useDashboardAlerts(); // Mutations for updates management const markTicketAsReadMutation = useMarkTicketAsRead(); @@ -41,6 +44,7 @@ const Home = () => { refetchTickets(), refetchPunishments(), refetchUpdates(), + refetchAlerts(), new Promise(resolve => setTimeout(resolve, 800)) ]); @@ -91,6 +95,12 @@ const Home = () => { + + {/* Assigned Ticket Updates - Full Width */} =10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/code-frame": { - "version": "7.29.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/compat-data": { - "version": "7.29.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/core": { - "version": "7.29.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "@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" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/generator": { - "version": "7.29.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/helper-globals": { - "version": "7.28.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/helpers": { - "version": "7.28.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/parser": { - "version": "7.29.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/template": { - "version": "7.28.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/traverse": { - "version": "7.29.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@babel/types": { - "version": "7.29.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "../replay/modl-replay-viewer/node_modules/@img/colour": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "../replay/modl-replay-viewer/node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "../replay/modl-replay-viewer/node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "../replay/modl-replay-viewer/node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "../replay/modl-replay-viewer/node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "../replay/modl-replay-viewer/node_modules/@microsoft/api-extractor": { - "version": "7.57.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@microsoft/api-extractor-model": "7.33.4", - "@microsoft/tsdoc": "~0.16.0", - "@microsoft/tsdoc-config": "~0.18.1", - "@rushstack/node-core-library": "5.20.3", - "@rushstack/rig-package": "0.7.2", - "@rushstack/terminal": "0.22.3", - "@rushstack/ts-command-line": "5.3.3", - "diff": "~8.0.2", - "lodash": "~4.17.23", - "minimatch": "10.2.1", - "resolve": "~1.22.1", - "semver": "~7.5.4", - "source-map": "~0.6.1", - "typescript": "5.8.2" - }, - "bin": { - "api-extractor": "bin/api-extractor" - } - }, - "../replay/modl-replay-viewer/node_modules/@microsoft/api-extractor-model": { - "version": "7.33.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@microsoft/tsdoc": "~0.16.0", - "@microsoft/tsdoc-config": "~0.18.1", - "@rushstack/node-core-library": "5.20.3" - } - }, - "../replay/modl-replay-viewer/node_modules/@microsoft/api-extractor/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "../replay/modl-replay-viewer/node_modules/@microsoft/api-extractor/node_modules/semver": { - "version": "7.5.4", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "../replay/modl-replay-viewer/node_modules/@microsoft/api-extractor/node_modules/typescript": { - "version": "5.8.2", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "../replay/modl-replay-viewer/node_modules/@microsoft/api-extractor/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, - "../replay/modl-replay-viewer/node_modules/@microsoft/tsdoc": { - "version": "0.16.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@microsoft/tsdoc-config": { - "version": "0.18.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@microsoft/tsdoc": "0.16.0", - "ajv": "~8.18.0", - "jju": "~1.4.0", - "resolve": "~1.22.2" - } - }, - "../replay/modl-replay-viewer/node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "../replay/modl-replay-viewer/node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "../replay/modl-replay-viewer/node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "../replay/modl-replay-viewer/node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "../replay/modl-replay-viewer/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "../replay/modl-replay-viewer/node_modules/@rushstack/node-core-library": { - "version": "5.20.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "~8.18.0", - "ajv-draft-04": "~1.0.0", - "ajv-formats": "~3.0.1", - "fs-extra": "~11.3.0", - "import-lazy": "~4.0.0", - "jju": "~1.4.0", - "resolve": "~1.22.1", - "semver": "~7.5.4" - }, - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/@rushstack/node-core-library/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "../replay/modl-replay-viewer/node_modules/@rushstack/node-core-library/node_modules/semver": { - "version": "7.5.4", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "../replay/modl-replay-viewer/node_modules/@rushstack/node-core-library/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, - "../replay/modl-replay-viewer/node_modules/@rushstack/problem-matcher": { - "version": "0.2.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/@rushstack/rig-package": { - "version": "0.7.2", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "~1.22.1", - "strip-json-comments": "~3.1.1" - } - }, - "../replay/modl-replay-viewer/node_modules/@rushstack/terminal": { - "version": "0.22.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@rushstack/node-core-library": "5.20.3", - "@rushstack/problem-matcher": "0.2.1", - "supports-color": "~8.1.1" - }, - "peerDependencies": { - "@types/node": "*" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/@rushstack/ts-command-line": { - "version": "5.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@rushstack/terminal": "0.22.3", - "@types/argparse": "1.0.38", - "argparse": "~1.0.9", - "string-argv": "~0.3.1" - } - }, - "../replay/modl-replay-viewer/node_modules/@tweenjs/tween.js": { - "version": "23.1.3", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@types/argparse": { - "version": "1.0.38", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@types/babel__core": { - "version": "7.20.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "../replay/modl-replay-viewer/node_modules/@types/babel__generator": { - "version": "7.27.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@types/babel__template": { - "version": "7.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@types/babel__traverse": { - "version": "7.28.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "../replay/modl-replay-viewer/node_modules/@types/estree": { - "version": "1.0.8", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@types/prop-types": { - "version": "15.7.15", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@types/react": { - "version": "18.3.28", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.2.2" - } - }, - "../replay/modl-replay-viewer/node_modules/@types/react-dom": { - "version": "18.3.7", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@types/stats.js": { - "version": "0.17.4", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@types/three": { - "version": "0.170.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@tweenjs/tween.js": "~23.1.3", - "@types/stats.js": "*", - "@types/webxr": "*", - "@webgpu/types": "*", - "fflate": "~0.8.2", - "meshoptimizer": "~0.18.1" - } - }, - "../replay/modl-replay-viewer/node_modules/@types/webxr": { - "version": "0.5.24", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@vitest/expect": { - "version": "2.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "../replay/modl-replay-viewer/node_modules/@vitest/mocker": { - "version": "2.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "2.1.9", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.12" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/@vitest/mocker/node_modules/estree-walker": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@vitest/pretty-format": { - "version": "2.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "../replay/modl-replay-viewer/node_modules/@vitest/runner": { - "version": "2.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "2.1.9", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "../replay/modl-replay-viewer/node_modules/@vitest/runner/node_modules/pathe": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@vitest/snapshot": { - "version": "2.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.9", - "magic-string": "^0.30.12", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "../replay/modl-replay-viewer/node_modules/@vitest/snapshot/node_modules/pathe": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@vitest/spy": { - "version": "2.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^3.0.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "../replay/modl-replay-viewer/node_modules/@vitest/utils": { - "version": "2.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.9", - "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "../replay/modl-replay-viewer/node_modules/@volar/language-core": { - "version": "2.4.28", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/source-map": "2.4.28" - } - }, - "../replay/modl-replay-viewer/node_modules/@volar/source-map": { - "version": "2.4.28", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@volar/typescript": { - "version": "2.4.28", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/language-core": "2.4.28", - "path-browserify": "^1.0.1", - "vscode-uri": "^3.0.8" - } - }, - "../replay/modl-replay-viewer/node_modules/@vue/compiler-core": { - "version": "3.5.29", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@vue/shared": "3.5.29", - "entities": "^7.0.1", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" - } - }, - "../replay/modl-replay-viewer/node_modules/@vue/compiler-dom": { - "version": "3.5.29", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.29", - "@vue/shared": "3.5.29" - } - }, - "../replay/modl-replay-viewer/node_modules/@vue/compiler-vue2": { - "version": "2.7.16", - "dev": true, - "license": "MIT", - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@vue/language-core": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@volar/language-core": "~2.4.11", - "@vue/compiler-dom": "^3.5.0", - "@vue/compiler-vue2": "^2.7.16", - "@vue/shared": "^3.5.0", - "alien-signals": "^0.4.9", - "minimatch": "^9.0.3", - "muggle-string": "^0.4.1", - "path-browserify": "^1.0.1" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/@vue/language-core/node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@vue/language-core/node_modules/brace-expansion": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/@vue/language-core/node_modules/minimatch": { - "version": "9.0.9", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "../replay/modl-replay-viewer/node_modules/@vue/shared": { - "version": "3.5.29", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/@webgpu/types": { - "version": "0.1.69", - "dev": true, - "license": "BSD-3-Clause" - }, - "../replay/modl-replay-viewer/node_modules/acorn": { - "version": "8.16.0", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "../replay/modl-replay-viewer/node_modules/ajv": { - "version": "8.18.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "../replay/modl-replay-viewer/node_modules/ajv-draft-04": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^8.5.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/ajv-formats": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/alien-signals": { - "version": "0.4.14", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/any-promise": { - "version": "1.3.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/anymatch": { - "version": "3.1.3", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "../replay/modl-replay-viewer/node_modules/arg": { - "version": "5.0.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "../replay/modl-replay-viewer/node_modules/assertion-error": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "../replay/modl-replay-viewer/node_modules/balanced-match": { - "version": "4.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "../replay/modl-replay-viewer/node_modules/baseline-browser-mapping": { - "version": "2.10.0", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/binary-extensions": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../replay/modl-replay-viewer/node_modules/brace-expansion": { - "version": "5.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "../replay/modl-replay-viewer/node_modules/braces": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "../replay/modl-replay-viewer/node_modules/browserslist": { - "version": "4.28.1", - "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.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "../replay/modl-replay-viewer/node_modules/cac": { - "version": "6.7.14", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "../replay/modl-replay-viewer/node_modules/camelcase-css": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "../replay/modl-replay-viewer/node_modules/caniuse-lite": { - "version": "1.0.30001777", - "dev": true, - "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" - }, - "../replay/modl-replay-viewer/node_modules/chai": { - "version": "5.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "../replay/modl-replay-viewer/node_modules/check-error": { - "version": "2.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "../replay/modl-replay-viewer/node_modules/chokidar": { - "version": "3.6.0", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "../replay/modl-replay-viewer/node_modules/commander": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "../replay/modl-replay-viewer/node_modules/compare-versions": { - "version": "6.1.1", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/confbox": { - "version": "0.2.4", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/convert-source-map": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/cssesc": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "../replay/modl-replay-viewer/node_modules/csstype": { - "version": "3.2.3", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/de-indent": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/debug": { - "version": "4.4.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/deep-eql": { - "version": "5.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "../replay/modl-replay-viewer/node_modules/detect-libc": { - "version": "2.1.2", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "../replay/modl-replay-viewer/node_modules/didyoumean": { - "version": "1.2.2", - "dev": true, - "license": "Apache-2.0" - }, - "../replay/modl-replay-viewer/node_modules/diff": { - "version": "8.0.3", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "../replay/modl-replay-viewer/node_modules/dlv": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/electron-to-chromium": { - "version": "1.5.307", - "dev": true, - "license": "ISC" - }, - "../replay/modl-replay-viewer/node_modules/entities": { - "version": "7.0.1", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "../replay/modl-replay-viewer/node_modules/es-module-lexer": { - "version": "1.7.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/esbuild": { - "version": "0.21.5", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "../replay/modl-replay-viewer/node_modules/escalade": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "../replay/modl-replay-viewer/node_modules/estree-walker": { - "version": "2.0.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/expect-type": { - "version": "1.3.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/exsolve": { - "version": "1.0.8", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/fast-deep-equal": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/fast-glob": { - "version": "3.3.3", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "../replay/modl-replay-viewer/node_modules/fast-uri": { - "version": "3.1.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "../replay/modl-replay-viewer/node_modules/fastq": { - "version": "1.20.1", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "../replay/modl-replay-viewer/node_modules/fflate": { - "version": "0.8.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/fill-range": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "../replay/modl-replay-viewer/node_modules/fs-extra": { - "version": "11.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "../replay/modl-replay-viewer/node_modules/function-bind": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../replay/modl-replay-viewer/node_modules/gensync": { - "version": "1.0.0-beta.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../replay/modl-replay-viewer/node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "../replay/modl-replay-viewer/node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "license": "ISC" - }, - "../replay/modl-replay-viewer/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "../replay/modl-replay-viewer/node_modules/hasown": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "../replay/modl-replay-viewer/node_modules/he": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "../replay/modl-replay-viewer/node_modules/import-lazy": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "../replay/modl-replay-viewer/node_modules/is-binary-path": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "../replay/modl-replay-viewer/node_modules/is-core-module": { - "version": "2.16.1", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../replay/modl-replay-viewer/node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "../replay/modl-replay-viewer/node_modules/jiti": { - "version": "1.21.7", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "../replay/modl-replay-viewer/node_modules/jju": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/jsesc": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "../replay/modl-replay-viewer/node_modules/json-schema-traverse": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/json5": { - "version": "2.2.3", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "../replay/modl-replay-viewer/node_modules/jsonfile": { - "version": "6.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "../replay/modl-replay-viewer/node_modules/kolorist": { - "version": "1.8.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/lilconfig": { - "version": "3.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "../replay/modl-replay-viewer/node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/local-pkg": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "mlly": "^1.7.4", - "pkg-types": "^2.3.0", - "quansync": "^0.2.11" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "../replay/modl-replay-viewer/node_modules/lodash": { - "version": "4.17.23", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/loose-envify": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "../replay/modl-replay-viewer/node_modules/loupe": { - "version": "3.2.1", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/lru-cache": { - "version": "5.1.1", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "../replay/modl-replay-viewer/node_modules/magic-string": { - "version": "0.30.21", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "../replay/modl-replay-viewer/node_modules/merge2": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "../replay/modl-replay-viewer/node_modules/meshoptimizer": { - "version": "0.18.1", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/micromatch": { - "version": "4.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "../replay/modl-replay-viewer/node_modules/minecraft-assets": { - "version": "1.17.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/minecraft-data": { - "version": "3.105.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/minimatch": { - "version": "10.2.1", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "../replay/modl-replay-viewer/node_modules/mlly": { - "version": "1.8.1", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.16.0", - "pathe": "^2.0.3", - "pkg-types": "^1.3.1", - "ufo": "^1.6.3" - } - }, - "../replay/modl-replay-viewer/node_modules/mlly/node_modules/confbox": { - "version": "0.1.8", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/mlly/node_modules/pkg-types": { - "version": "1.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "../replay/modl-replay-viewer/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/muggle-string": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/mz": { - "version": "2.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/nanoid": { - "version": "3.3.11", - "dev": true, - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/node-releases": { - "version": "2.0.36", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/normalize-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/object-assign": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/object-hash": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "../replay/modl-replay-viewer/node_modules/path-browserify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/pathe": { - "version": "2.0.3", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/pathval": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, - "../replay/modl-replay-viewer/node_modules/picocolors": { - "version": "1.1.1", - "dev": true, - "license": "ISC" - }, - "../replay/modl-replay-viewer/node_modules/picomatch": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "../replay/modl-replay-viewer/node_modules/pify": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/pirates": { - "version": "4.0.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "../replay/modl-replay-viewer/node_modules/pkg-types": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", - "pathe": "^2.0.3" - } - }, - "../replay/modl-replay-viewer/node_modules/postcss": { - "version": "8.5.8", - "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.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "../replay/modl-replay-viewer/node_modules/postcss-import": { - "version": "15.1.0", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/postcss-js": { - "version": "4.1.0", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/postcss-load-config": { - "version": "6.0.1", - "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 - } - } - }, - "../replay/modl-replay-viewer/node_modules/postcss-nested": { - "version": "6.2.0", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/postcss-selector-parser": { - "version": "6.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "../replay/modl-replay-viewer/node_modules/postcss-value-parser": { - "version": "4.2.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/quansync": { - "version": "0.2.11", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/antfu" - }, - { - "type": "individual", - "url": "https://github.com/sponsors/sxzz" - } - ], - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/queue-microtask": { - "version": "1.2.3", - "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" - }, - "../replay/modl-replay-viewer/node_modules/react": { - "version": "18.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/react-dom": { - "version": "18.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "../replay/modl-replay-viewer/node_modules/react-refresh": { - "version": "0.17.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/read-cache": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, - "../replay/modl-replay-viewer/node_modules/readdirp": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/require-from-string": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/resolve": { - "version": "1.22.11", - "dev": true, - "license": "MIT", - "dependencies": { - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/reusify": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/rollup": { - "version": "4.59.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" - } - }, - "../replay/modl-replay-viewer/node_modules/run-parallel": { - "version": "1.2.0", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/scheduler": { - "version": "0.23.2", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "../replay/modl-replay-viewer/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "../replay/modl-replay-viewer/node_modules/sharp": { - "version": "0.34.5", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/sharp/node_modules/semver": { - "version": "7.7.4", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "../replay/modl-replay-viewer/node_modules/siginfo": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "../replay/modl-replay-viewer/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/source-map-js": { - "version": "1.2.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "../replay/modl-replay-viewer/node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, - "../replay/modl-replay-viewer/node_modules/stackback": { - "version": "0.0.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/std-env": { - "version": "3.10.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/string-argv": { - "version": "0.3.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6.19" - } - }, - "../replay/modl-replay-viewer/node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../replay/modl-replay-viewer/node_modules/sucrase": { - "version": "3.35.1", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "../replay/modl-replay-viewer/node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../replay/modl-replay-viewer/node_modules/tailwindcss": { - "version": "3.4.19", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/thenify": { - "version": "3.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/thenify-all": { - "version": "1.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "../replay/modl-replay-viewer/node_modules/three": { - "version": "0.170.0", - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/tinybench": { - "version": "2.9.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/tinyexec": { - "version": "0.3.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/tinyglobby": { - "version": "0.2.15", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "../replay/modl-replay-viewer/node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "../replay/modl-replay-viewer/node_modules/tinypool": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/tinyrainbow": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/tinyspy": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/to-regex-range": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "../replay/modl-replay-viewer/node_modules/ts-interface-checker": { - "version": "0.1.13", - "dev": true, - "license": "Apache-2.0" - }, - "../replay/modl-replay-viewer/node_modules/typescript": { - "version": "5.6.3", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "../replay/modl-replay-viewer/node_modules/ufo": { - "version": "1.6.3", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/universalify": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "../replay/modl-replay-viewer/node_modules/update-browserslist-db": { - "version": "1.2.3", - "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" - } - }, - "../replay/modl-replay-viewer/node_modules/util-deprecate": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/vite": { - "version": "5.4.21", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/vite-node": { - "version": "2.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.7", - "es-module-lexer": "^1.5.4", - "pathe": "^1.1.2", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "../replay/modl-replay-viewer/node_modules/vite-node/node_modules/pathe": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/vite-plugin-dts": { - "version": "4.5.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@microsoft/api-extractor": "^7.50.1", - "@rollup/pluginutils": "^5.1.4", - "@volar/typescript": "^2.4.11", - "@vue/language-core": "2.2.0", - "compare-versions": "^6.1.1", - "debug": "^4.4.0", - "kolorist": "^1.8.0", - "local-pkg": "^1.0.0", - "magic-string": "^0.30.17" - }, - "peerDependencies": { - "typescript": "*", - "vite": "*" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/vitest": { - "version": "2.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.9", - "@vitest/mocker": "2.1.9", - "@vitest/pretty-format": "^2.1.9", - "@vitest/runner": "2.1.9", - "@vitest/snapshot": "2.1.9", - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "debug": "^4.3.7", - "expect-type": "^1.1.0", - "magic-string": "^0.30.12", - "pathe": "^1.1.2", - "std-env": "^3.8.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.1", - "tinypool": "^1.0.1", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.9", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.9", - "@vitest/ui": "2.1.9", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "../replay/modl-replay-viewer/node_modules/vitest/node_modules/pathe": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/vscode-uri": { - "version": "3.1.0", - "dev": true, - "license": "MIT" - }, - "../replay/modl-replay-viewer/node_modules/why-is-node-running": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "../replay/modl-replay-viewer/node_modules/yallist": { - "version": "3.1.1", - "dev": true, - "license": "ISC" - }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "license": "MIT", @@ -3723,8 +802,16 @@ } }, "node_modules/@modl-gg/replay-viewer": { - "resolved": "../replay/modl-replay-viewer", - "link": true + "version": "1.16.0", + "resolved": "https://nexus.modl.gg/repository/npm-releases/@modl-gg/replay-viewer/-/replay-viewer-1.16.0.tgz", + "integrity": "sha512-qwcgL9/gJf7aoXOnSNIlc3dsEA+G53hJaD0eExXyAhC4eCpE4/sveRR6eyCiXco/fxEh3ufVwr4Mb4mEBpbeoQ==", + "dependencies": { + "three": "^0.170.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } }, "node_modules/@modl-gg/shared-web": { "version": "1.0.5", From 8d73cbfce3fc677636f30cbb3afc0aabf800263d Mon Sep 17 00:00:00 2001 From: byteful Date: Mon, 18 May 2026 03:02:10 -0500 Subject: [PATCH 03/30] visual fixes --- .../dashboard/DashboardAlertsSection.tsx | 28 +------ client/src/locales/de.json | 4 - client/src/locales/en.json | 4 - client/src/locales/es.json | 4 - client/src/locales/nl.json | 4 - client/src/pages/home.tsx | 84 +++++++++++++------ nginx/modl-panel.conf.example | 51 ----------- 7 files changed, 59 insertions(+), 120 deletions(-) delete mode 100644 nginx/modl-panel.conf.example diff --git a/client/src/components/dashboard/DashboardAlertsSection.tsx b/client/src/components/dashboard/DashboardAlertsSection.tsx index 210bbb3..9363846 100644 --- a/client/src/components/dashboard/DashboardAlertsSection.tsx +++ b/client/src/components/dashboard/DashboardAlertsSection.tsx @@ -5,8 +5,6 @@ import type { SystemAlert, SystemAlertSeverity } from '@/hooks/use-data'; interface DashboardAlertsSectionProps { alerts?: SystemAlert[]; - loading?: boolean; - error?: boolean; } type AlertBannerVariant = 'info' | 'warning' | 'error'; @@ -65,33 +63,9 @@ function formatExpiryDate(expiresAt?: string) { return expiryDate.toLocaleString(); } -export function DashboardAlertsSection({ alerts = [], loading, error }: DashboardAlertsSectionProps) { +export function DashboardAlertsSection({ alerts = [] }: DashboardAlertsSectionProps) { const { t } = useTranslation(); - if (error) { - return ( - -

{t('dashboard.alerts.loadErrorDescription')}

-
- ); - } - - if (loading) { - return ( - -

{t('dashboard.alerts.loadingDescription')}

-
- ); - } - if (alerts.length === 0) { return null; } diff --git a/client/src/locales/de.json b/client/src/locales/de.json index bfc949b..4376509 100644 --- a/client/src/locales/de.json +++ b/client/src/locales/de.json @@ -964,10 +964,6 @@ "expires": "Läuft ab am {{date}}", "unknownSeverity": "Hinweis ({{severity}})", "unknownSeverityValue": "Unbekannt", - "loadingTitle": "Hinweise werden geladen", - "loadingDescription": "Aktuelle Systemhinweise werden geprüft.", - "loadErrorTitle": "Hinweise konnten nicht geladen werden", - "loadErrorDescription": "Systemhinweise konnten nicht geladen werden. Andere Dashboard-Daten können trotzdem aktuell sein.", "levels": { "BASIC": "Hinweis", "WARNING": "Warnung", diff --git a/client/src/locales/en.json b/client/src/locales/en.json index a6e2218..ed6675f 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -971,10 +971,6 @@ "expires": "Expires {{date}}", "unknownSeverity": "Alert ({{severity}})", "unknownSeverityValue": "Unknown", - "loadingTitle": "Loading alerts", - "loadingDescription": "Checking for current system alerts.", - "loadErrorTitle": "Unable to load alerts", - "loadErrorDescription": "System alerts could not be loaded. Other dashboard data may still be current.", "levels": { "BASIC": "Notice", "WARNING": "Warning", diff --git a/client/src/locales/es.json b/client/src/locales/es.json index 4f31bb2..c6f2222 100644 --- a/client/src/locales/es.json +++ b/client/src/locales/es.json @@ -964,10 +964,6 @@ "expires": "Caduca el {{date}}", "unknownSeverity": "Alerta ({{severity}})", "unknownSeverityValue": "Desconocida", - "loadingTitle": "Cargando alertas", - "loadingDescription": "Comprobando alertas actuales del sistema.", - "loadErrorTitle": "No se pudieron cargar las alertas", - "loadErrorDescription": "No se pudieron cargar las alertas del sistema. Otros datos del panel aún pueden estar actualizados.", "levels": { "BASIC": "Aviso", "WARNING": "Advertencia", diff --git a/client/src/locales/nl.json b/client/src/locales/nl.json index 7e61615..0649791 100644 --- a/client/src/locales/nl.json +++ b/client/src/locales/nl.json @@ -964,10 +964,6 @@ "expires": "Verloopt op {{date}}", "unknownSeverity": "Melding ({{severity}})", "unknownSeverityValue": "Onbekend", - "loadingTitle": "Meldingen laden", - "loadingDescription": "Actuele systeemmeldingen worden gecontroleerd.", - "loadErrorTitle": "Meldingen konden niet worden geladen", - "loadErrorDescription": "Systeemmeldingen konden niet worden geladen. Andere dashboardgegevens kunnen nog steeds actueel zijn.", "levels": { "BASIC": "Melding", "WARNING": "Waarschuwing", diff --git a/client/src/pages/home.tsx b/client/src/pages/home.tsx index 9881074..971e8fa 100644 --- a/client/src/pages/home.tsx +++ b/client/src/pages/home.tsx @@ -6,6 +6,8 @@ import { Moon } from 'lucide-react'; import { Button } from '@modl-gg/shared-web/components/ui/button'; +import { Card, CardContent } from '@modl-gg/shared-web/components/ui/card'; +import { Skeleton } from '@modl-gg/shared-web/components/ui/skeleton'; import { useTheme } from 'next-themes'; import { useRecentTickets, @@ -21,6 +23,33 @@ import { RecentPunishmentsSection } from '@/components/dashboard/RecentPunishmen import { AssignedTicketUpdatesSection } from '@/components/dashboard/AssignedTicketUpdatesSection'; import { DashboardAlertsSection } from '@/components/dashboard/DashboardAlertsSection'; +function DashboardLoadingSkeleton() { + return ( + <> + + + + + + + + +
+ {Array.from({ length: 2 }).map((_, index) => ( + + + + + + + + + ))} +
+ + ); +} + const Home = () => { const [isSpinning, setIsSpinning] = useState(false); const { toast } = useToast(); @@ -31,7 +60,8 @@ const Home = () => { const { data: recentTicketsData, isLoading: isLoadingTickets, refetch: refetchTickets } = useRecentTickets(3); const { data: recentPunishmentsData, isLoading: isLoadingPunishments, refetch: refetchPunishments } = useRecentPunishments(5); const { data: assignedUpdatesData, isLoading: isLoadingUpdates, refetch: refetchUpdates } = useAssignedTicketUpdates(10); - const { data: alertsData, isLoading: isLoadingAlerts, isError: isAlertsError, refetch: refetchAlerts } = useDashboardAlerts(); + const { data: alertsData, isLoading: isLoadingAlerts, refetch: refetchAlerts } = useDashboardAlerts(); + const isInitialDashboardLoading = isLoadingTickets || isLoadingPunishments || isLoadingUpdates || isLoadingAlerts; // Mutations for updates management const markTicketAsReadMutation = useMarkTicketAsRead(); @@ -80,7 +110,7 @@ const Home = () => { size="icon" className="text-muted-foreground" onClick={handleRefreshData} - disabled={isSpinning} + disabled={isSpinning || isInitialDashboardLoading} > @@ -95,33 +125,35 @@ const Home = () => { - + {isInitialDashboardLoading ? ( + + ) : ( + <> + - {/* Assigned Ticket Updates - Full Width */} - + {/* Assigned Ticket Updates - Full Width */} + - {/* Dashboard Grid */} -
- {/* Recent Tickets */} - + {/* Dashboard Grid */} +
+ {/* Recent Tickets */} + - {/* Recent Punishments */} - -
+ {/* Recent Punishments */} + +
+ + )} ); diff --git a/nginx/modl-panel.conf.example b/nginx/modl-panel.conf.example deleted file mode 100644 index c721e52..0000000 --- a/nginx/modl-panel.conf.example +++ /dev/null @@ -1,51 +0,0 @@ -# Example panel nginx config for same-origin realtime WebSocket proxying. -# Install manually and adapt server_name/root/upstream names for the target host. -# Install/include backend/nginx/modl-websocket-map.conf.example once at nginx http scope. -# Do not include the shared map from every vhost when installing multiple examples. - -upstream modl_panel { - server 127.0.0.1:3000; -} - -include /etc/nginx/conf.d/modl-backend-upstream.conf; - -server { - listen 443 ssl http2; - server_name panel.modl.example; - - location = /api/v1/realtime/ws { - # Keep aligned with modl.realtime.ws.max-frame-bytes. - client_max_body_size 64k; - - proxy_pass http://modl_backend/v1/realtime/ws; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_buffering off; - proxy_request_buffering off; - proxy_read_timeout 120s; - proxy_send_timeout 120s; - } - - location /api/ { - proxy_pass http://modl_backend/; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - location / { - proxy_pass http://modl_panel; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } -} From 2ddfbdd13956afb2b664f3aa6a1d01c66666f4c0 Mon Sep 17 00:00:00 2001 From: byteful Date: Mon, 18 May 2026 03:09:43 -0500 Subject: [PATCH 04/30] Update DashboardAlertsSection.tsx --- .../dashboard/DashboardAlertsSection.tsx | 46 ++++++------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/client/src/components/dashboard/DashboardAlertsSection.tsx b/client/src/components/dashboard/DashboardAlertsSection.tsx index 9363846..fbc05d0 100644 --- a/client/src/components/dashboard/DashboardAlertsSection.tsx +++ b/client/src/components/dashboard/DashboardAlertsSection.tsx @@ -1,6 +1,6 @@ -import { Badge } from '@modl-gg/shared-web/components/ui/badge'; import { StatusBanner } from '@modl-gg/shared-web/components/ui/status-banner'; import { useTranslation } from 'react-i18next'; +import ReactMarkdown from 'react-markdown'; import type { SystemAlert, SystemAlertSeverity } from '@/hooks/use-data'; interface DashboardAlertsSectionProps { @@ -50,19 +50,6 @@ function getSeverityTitle(severity: unknown, t: ReturnType - {alerts.map((alert) => { - const expiresAt = formatExpiryDate(alert.expiresAt); - - return ( - - {t('dashboard.alerts.expires', { date: expiresAt })} - - ) : undefined} - > -

{alert.message}

-
- ); - })} + {alerts.map((alert) => ( + +
+ {alert.message} +
+
+ ))} ); } From b9ac0012248b5f891a16ab5e152ab0a7979984b0 Mon Sep 17 00:00:00 2001 From: Rudra <80184082+byteful@users.noreply.github.com> Date: Thu, 21 May 2026 05:11:06 -0500 Subject: [PATCH 05/30] fix #92 and #114 (#101) --- client/src/components/player-replays-list.tsx | 129 ++++++++++++++++++ .../src/components/settings/UsageSettings.tsx | 113 +++++++++++++++ .../src/components/windows/PlayerWindow.tsx | 14 +- client/src/hooks/use-data.tsx | 86 ++++++++++++ client/src/locales/de.json | 23 ++++ client/src/locales/en.json | 23 ++++ client/src/locales/es.json | 23 ++++ client/src/locales/nl.json | 23 ++++ client/src/pages/player-detail-page.tsx | 15 +- 9 files changed, 445 insertions(+), 4 deletions(-) create mode 100644 client/src/components/player-replays-list.tsx diff --git a/client/src/components/player-replays-list.tsx b/client/src/components/player-replays-list.tsx new file mode 100644 index 0000000..3fecf2e --- /dev/null +++ b/client/src/components/player-replays-list.tsx @@ -0,0 +1,129 @@ +import { Loader2, Play, TriangleAlert } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; +import { useLocation } from 'wouter'; +import { Badge } from '@modl-gg/shared-web/components/ui/badge'; +import { Button } from '@modl-gg/shared-web/components/ui/button'; +import { usePlayerReplays } from '@/hooks/use-data'; +import { formatDateWithTime } from '@/utils/date-utils'; +import { formatFileSize } from '@/utils/file-utils'; + +interface PlayerReplaysListProps { + playerId: string; +} + +const isRawReplayId = (replayReference: string) => ( + !replayReference.includes('://') + && !replayReference.includes('/') + && !replayReference.includes('?') + && !replayReference.includes('#') +); + +const getReplayIdFromReference = (replayUrl?: string) => { + const replayReference = replayUrl?.trim(); + if (!replayReference) { + return ''; + } + + if (isRawReplayId(replayReference)) { + return replayReference; + } + + try { + const parsedReplayUrl = new URL(replayReference, window.location.origin); + return parsedReplayUrl.searchParams.get('id') || ''; + } catch { + return ''; + } +}; + +const getReplayId = (replay: { replayId?: string; replayUrl?: string; matchSource?: string }) => { + if (replay.matchSource === 'TICKET_FALLBACK') { + return getReplayIdFromReference(replay.replayUrl) || replay.replayId || ''; + } + + return replay.replayId || getReplayIdFromReference(replay.replayUrl); +}; + +const PlayerReplaysList = ({ playerId }: PlayerReplaysListProps) => { + const { t } = useTranslation(); + const [, navigate] = useLocation(); + const { data: replays, isLoading, error } = usePlayerReplays(playerId); + + if (isLoading) { + return ( +
+ + {t('player.loadingReplays')} +
+ ); + } + + if (error) { + return ( +
+ + {t('player.replaysLoadFailed')} +
+ ); + } + + if (!replays || replays.length === 0) { + return ( +
+

{t('player.noReplays')}

+
+ ); + } + + return ( +
+ {replays.map((replay) => { + const replayId = getReplayId(replay); + const canOpenReplay = Boolean(replayId) + && (replay.matchSource === 'TICKET_FALLBACK' || replay.status === 'COMPLETE'); + + return ( +
+
+
+
+ + + {replay.targetName || replay.targetUuid || t('player.unknownPlayer')} + + {replay.status && ( + + {replay.status} + + )} + {replay.matchSource && ( + + {replay.matchSource} + + )} +
+
+ {t('player.replayCreated')}: {replay.createdAt ? formatDateWithTime(replay.createdAt) : t('common.unknown')} + {t('player.replayMcVersion')}: {replay.mcVersion || t('common.unknown')} + {t('player.replaySize')}: {typeof replay.fileSize === 'number' ? formatFileSize(replay.fileSize) : t('common.unknown')} + {t('player.replayId')}: {replayId || t('common.unknown')} +
+
+ +
+
+ ); + })} +
+ ); +}; + +export default PlayerReplaysList; diff --git a/client/src/components/settings/UsageSettings.tsx b/client/src/components/settings/UsageSettings.tsx index b5bde95..c298975 100644 --- a/client/src/components/settings/UsageSettings.tsx +++ b/client/src/components/settings/UsageSettings.tsx @@ -9,11 +9,13 @@ import { Progress } from '@modl-gg/shared-web/components/ui/progress'; import { Card, CardContent, CardHeader, CardTitle } from '@modl-gg/shared-web/components/ui/card'; import { Badge } from '@modl-gg/shared-web/components/ui/badge'; import { Checkbox } from '@modl-gg/shared-web/components/ui/checkbox'; +import { Switch } from '@modl-gg/shared-web/components/ui/switch'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@modl-gg/shared-web/components/ui/select'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@modl-gg/shared-web/components/ui/table'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@modl-gg/shared-web/components/ui/alert-dialog'; import { useToast } from '@modl-gg/shared-web/hooks/use-toast'; import { formatFileSize } from '@/utils/file-utils'; +import { useReplayRetentionSettings, useUpdateReplayRetentionSettings } from '@/hooks/use-data'; interface StorageFile { id: string; @@ -114,6 +116,10 @@ const UsageSettings = () => { const [newOverageLimit, setNewOverageLimit] = useState(0); const [currentPage, setCurrentPage] = useState(1); const [itemsPerPage, setItemsPerPage] = useState(25); + const [replayRetentionEnabled, setReplayRetentionEnabled] = useState(true); + const [replayRetentionDays, setReplayRetentionDays] = useState(7); + const { data: replayRetentionSettings, isLoading: isLoadingReplayRetention, error: replayRetentionError } = useReplayRetentionSettings(); + const updateReplayRetentionSettings = useUpdateReplayRetentionSettings(); const DEFAULT_AI_LIMIT = 1000; useEffect(() => { @@ -121,6 +127,15 @@ const UsageSettings = () => { fetchStorageSettings(); }, []); + useEffect(() => { + if (!replayRetentionSettings?.data) { + return; + } + + setReplayRetentionEnabled(Boolean(replayRetentionSettings.data.enabled)); + setReplayRetentionDays(Number(replayRetentionSettings.data.days || 7)); + }, [replayRetentionSettings]); + const fetchStorageData = async () => { try { setLoading(true); @@ -365,6 +380,36 @@ const fetchStorageData = async () => { } }; + const handleSaveReplayRetention = () => { + const days = Math.min(365, Math.max(1, Math.floor(Number(replayRetentionDays) || 1))); + const expectedVersion = Number(replayRetentionSettings?._meta?.version ?? 0); + + updateReplayRetentionSettings.mutate({ + expectedVersion, + enabled: replayRetentionEnabled, + days, + }, { + onSuccess: (envelope) => { + if (envelope?.data) { + setReplayRetentionEnabled(Boolean(envelope.data.enabled)); + setReplayRetentionDays(Number(envelope.data.days || days)); + } + + toast({ + title: t('toast.success'), + description: t('settings.usage.replayRetentionSaved'), + }); + }, + onError: (error: any) => { + toast({ + title: t('toast.error'), + description: error?.message || t('settings.usage.replayRetentionSaveFailed'), + variant: "destructive", + }); + }, + }); + }; + const getTypeColor = (type: string): string => { switch (type) { case 'ticket': return 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300'; @@ -784,6 +829,74 @@ const fetchStorageData = async () => { )} + + + + + {t('settings.usage.replayRetention')} + + + +
+ {replayRetentionError && ( +
+ {t('settings.usage.replayRetentionLoadFailed')} +
+ )} + +
+
+ +

+ {t('settings.usage.replayRetentionEnabledDesc')} +

+
+ +
+ +
+ + setReplayRetentionDays(Number(event.target.value))} + disabled={!replayRetentionEnabled || isLoadingReplayRetention || updateReplayRetentionSettings.isPending} + /> +

+ {replayRetentionEnabled + ? t('settings.usage.replayRetentionDaysDesc') + : t('settings.usage.replayRetentionDisabledDesc')} +

+
+ +
+ + {replayRetentionEnabled + ? t('settings.usage.replayRetentionActive', { days: Math.max(1, Math.floor(Number(replayRetentionDays) || 1)) }) + : t('settings.usage.replayRetentionOff')} + + +
+
+
+
+ {t('settings.usage.systemStatus')} diff --git a/client/src/components/windows/PlayerWindow.tsx b/client/src/components/windows/PlayerWindow.tsx index 895eab1..e5e7852 100644 --- a/client/src/components/windows/PlayerWindow.tsx +++ b/client/src/components/windows/PlayerWindow.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { Eye, TriangleAlert, History, Link2, StickyNote, Ticket, UserRound, Shield, FileText, Loader2, - ChevronDown, ChevronRight, Settings, Plus, X + ChevronDown, ChevronRight, Settings, Plus, X, Play } from 'lucide-react'; import { useLocation } from 'wouter'; import { Button } from '@modl-gg/shared-web/components/ui/button'; @@ -17,6 +17,7 @@ import { usePermissions } from '@/hooks/use-permissions'; import { toast } from '@modl-gg/shared-web/hooks/use-toast'; import PlayerPunishment, { PlayerPunishmentData } from '@/components/ui/player-punishment'; import MediaUpload from '@/components/MediaUpload'; +import PlayerReplaysList from '@/components/player-replays-list'; import { formatDateWithTime } from '@/utils/date-utils'; import { getAvatarUrl, apiFetch } from '@/lib/api'; import { formatTicketStatusLabel, normalizeTicketStatus } from '@/lib/ticket-enums'; @@ -1503,7 +1504,7 @@ const PlayerWindow = ({ playerId, isOpen, onClose, initialPosition }: PlayerWind - + {t('player.tabs.history')} @@ -1520,6 +1521,10 @@ const PlayerWindow = ({ playerId, isOpen, onClose, initialPosition }: PlayerWind {t('player.tabs.tickets')} + + + {t('player.tabs.replays')} + {t('player.tabs.names')} @@ -2975,6 +2980,11 @@ const PlayerWindow = ({ playerId, isOpen, onClose, initialPosition }: PlayerWind )} + +

{t('player.playerReplays')}

+ +
+

{t('player.previousNames')}

diff --git a/client/src/hooks/use-data.tsx b/client/src/hooks/use-data.tsx index 10d5487..b0493fa 100644 --- a/client/src/hooks/use-data.tsx +++ b/client/src/hooks/use-data.tsx @@ -18,6 +18,12 @@ function toSettingsEnvelope(payload: any): SettingsEnvelope { if (payload && typeof payload === 'object' && 'data' in payload) { return payload as SettingsEnvelope; } + if (payload && typeof payload === 'object' && '_data' in payload) { + return { + data: payload._data as T, + _meta: payload._meta || null, + }; + } return { data: payload as T, _meta: { @@ -27,6 +33,23 @@ function toSettingsEnvelope(payload: any): SettingsEnvelope { }; } +export interface ReplayRetentionSettings { + enabled: boolean; + days: number; +} + +export interface PlayerReplaySummary { + replayId: string; + targetUuid: string; + targetName: string; + mcVersion: string; + fileSize: number; + createdAt: string; + status: string; + replayUrl: string; + matchSource: string; +} + export function usePlayer(uuid: string) { return useQuery({ queryKey: ['/v1/panel/players', uuid], @@ -611,6 +634,50 @@ export function useTicketLabelSettings() { }); } +export function useReplayRetentionSettings() { + return useQuery | null>({ + queryKey: ['/v1/panel/settings/replay-retention'], + queryFn: async () => { + const res = await apiFetch('/v1/panel/settings/replay-retention'); + if (!res.ok) { + if (res.status === 401 || res.status === 403) { + return null; + } + throw new Error('Failed to fetch replay retention settings'); + } + return toSettingsEnvelope(await res.json()); + }, + staleTime: 1000 * 60 * 5, + refetchOnWindowFocus: false + }); +} + +export function useUpdateReplayRetentionSettings() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async (settings: ReplayRetentionSettings & { expectedVersion: number }) => { + const res = await apiFetch('/v1/panel/settings/replay-retention', { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(settings) + }); + + if (!res.ok) { + const errorText = await res.text(); + throw new Error(errorText || 'Failed to update replay retention settings'); + } + + return toSettingsEnvelope(await res.json()); + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['/v1/panel/settings/replay-retention'] }); + }, + }); +} + export function useStats() { return useQuery({ queryKey: ['/v1/panel/stats'], @@ -822,6 +889,25 @@ export function usePlayerAllTickets(uuid: string) { }); } +export function usePlayerReplays(uuid: string) { + return useQuery({ + queryKey: ['/v1/panel/players', uuid, 'replays'], + queryFn: async () => { + const res = await apiFetch(`/v1/panel/players/${uuid}/replays`); + if (!res.ok) { + if (res.status === 404) { + return []; + } + throw new Error('Failed to fetch player replays'); + } + return res.json(); + }, + enabled: !!uuid, + staleTime: 30000, + refetchOnWindowFocus: true + }); +} + export function useModifyPunishment() { const { user } = useAuth(); diff --git a/client/src/locales/de.json b/client/src/locales/de.json index 4376509..0764879 100644 --- a/client/src/locales/de.json +++ b/client/src/locales/de.json @@ -751,6 +751,17 @@ "storageOverage": "Speicherüberschreitung", "costThisMonth": "Kosten diesen Monat", "storageRate": "$0,08 pro GB pro Monat", + "replayRetention": "Replay-Aufbewahrung", + "replayRetentionEnabled": "Automatische Replay-Bereinigung aktivieren", + "replayRetentionEnabledDesc": "Gespeicherte Replays nach der konfigurierten Aufbewahrungszeit automatisch löschen.", + "replayRetentionDays": "Aufbewahrungszeitraum (Tage)", + "replayRetentionDaysDesc": "Gespeicherte Replays, die älter als diese Anzahl von Tagen sind, können bereinigt werden.", + "replayRetentionDisabledDesc": "Automatische Replay-Bereinigung ist deaktiviert. Gespeicherte Replays bleiben erhalten, bis sie manuell gelöscht werden.", + "replayRetentionActive": "Replays werden nach {{days}} Tagen gelöscht", + "replayRetentionOff": "Automatische Bereinigung deaktiviert", + "replayRetentionSaved": "Replay-Aufbewahrungseinstellungen gespeichert.", + "replayRetentionSaveFailed": "Replay-Aufbewahrungseinstellungen konnten nicht gespeichert werden.", + "replayRetentionLoadFailed": "Replay-Aufbewahrungseinstellungen konnten nicht geladen werden.", "systemStatus": "Systemstatus", "totalFiles": "Dateien gesamt", "selected": "Ausgewählt", @@ -1386,6 +1397,7 @@ "tabConnectedShort": "Verknüpft", "tabNotes": "Notizen", "tabTickets": "Tickets", + "tabReplays": "Replays", "tabNames": "Namen", "tabPunish": "Bestrafen", "tabs": { @@ -1393,6 +1405,7 @@ "connected": "Verbunden", "notes": "Notizen", "tickets": "Tickets", + "replays": "Replays", "names": "Namen", "punish": "Bestrafen" }, @@ -1456,6 +1469,16 @@ "playerTickets": "Spieler-Tickets", "loadingTickets": "Tickets werden geladen...", "noTickets": "Keine Tickets für diesen Spieler gefunden.", + "playerReplays": "Spieler-Replays", + "loadingReplays": "Replays werden geladen...", + "noReplays": "Keine Replays für diesen Spieler gefunden.", + "replaysLoadFailed": "Replays für diesen Spieler konnten nicht geladen werden.", + "openReplay": "Replay öffnen", + "replayCreated": "Erstellt", + "replayMcVersion": "Minecraft", + "replaySize": "Größe", + "replayId": "Replay-ID", + "unknownPlayer": "Unbekannter Spieler", "previousNames": "Frühere Namen", "missingInfo": "Fehlende Informationen", "selectPunishmentType": "Bitte wähle einen Straftyp aus, bevor du ihn anwendest.", diff --git a/client/src/locales/en.json b/client/src/locales/en.json index ed6675f..453a41c 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -758,6 +758,17 @@ "storageOverage": "Storage Overage", "costThisMonth": "Cost this month", "storageRate": "$0.08 per GB per month", + "replayRetention": "Replay Retention", + "replayRetentionEnabled": "Enable automatic replay cleanup", + "replayRetentionEnabledDesc": "Automatically delete stored replays after the configured retention period.", + "replayRetentionDays": "Retention period (days)", + "replayRetentionDaysDesc": "Stored replays older than this many days are eligible for cleanup.", + "replayRetentionDisabledDesc": "Automatic replay cleanup is disabled. Stored replays will be retained until manually deleted.", + "replayRetentionActive": "Deleting replays after {{days}} days", + "replayRetentionOff": "Automatic cleanup disabled", + "replayRetentionSaved": "Replay retention settings saved.", + "replayRetentionSaveFailed": "Failed to save replay retention settings.", + "replayRetentionLoadFailed": "Failed to load replay retention settings.", "systemStatus": "System Status", "totalFiles": "Total files", "selected": "Selected", @@ -1393,6 +1404,7 @@ "tabConnectedShort": "Linked", "tabNotes": "Notes", "tabTickets": "Tickets", + "tabReplays": "Replays", "tabNames": "Names", "tabPunish": "Punish", "tabs": { @@ -1400,6 +1412,7 @@ "connected": "Connected", "notes": "Notes", "tickets": "Tickets", + "replays": "Replays", "names": "Names", "punish": "Punish" }, @@ -1463,6 +1476,16 @@ "playerTickets": "Player Tickets", "loadingTickets": "Loading tickets...", "noTickets": "No tickets found for this player.", + "playerReplays": "Player Replays", + "loadingReplays": "Loading replays...", + "noReplays": "No replays found for this player.", + "replaysLoadFailed": "Failed to load replays for this player.", + "openReplay": "Open Replay", + "replayCreated": "Created", + "replayMcVersion": "Minecraft", + "replaySize": "Size", + "replayId": "Replay ID", + "unknownPlayer": "Unknown player", "previousNames": "Previous Names", "missingInfo": "Missing information", "selectPunishmentType": "Please select a punishment type before applying.", diff --git a/client/src/locales/es.json b/client/src/locales/es.json index c6f2222..6d587e8 100644 --- a/client/src/locales/es.json +++ b/client/src/locales/es.json @@ -751,6 +751,17 @@ "storageOverage": "Exceso de almacenamiento", "costThisMonth": "Costo este mes", "storageRate": "$0,08 por GB por mes", + "replayRetention": "Retención de repeticiones", + "replayRetentionEnabled": "Habilitar limpieza automática de repeticiones", + "replayRetentionEnabledDesc": "Eliminar automáticamente las repeticiones almacenadas después del periodo de retención configurado.", + "replayRetentionDays": "Periodo de retención (días)", + "replayRetentionDaysDesc": "Las repeticiones almacenadas con más de esta cantidad de días podrán limpiarse.", + "replayRetentionDisabledDesc": "La limpieza automática de repeticiones está deshabilitada. Las repeticiones almacenadas se conservarán hasta que se eliminen manualmente.", + "replayRetentionActive": "Eliminando repeticiones después de {{days}} días", + "replayRetentionOff": "Limpieza automática deshabilitada", + "replayRetentionSaved": "Configuración de retención de repeticiones guardada.", + "replayRetentionSaveFailed": "No se pudo guardar la configuración de retención de repeticiones.", + "replayRetentionLoadFailed": "No se pudo cargar la configuración de retención de repeticiones.", "systemStatus": "Estado del sistema", "totalFiles": "Total de archivos", "selected": "Seleccionados", @@ -1386,6 +1397,7 @@ "tabConnectedShort": "Vinculado", "tabNotes": "Notas", "tabTickets": "Tickets", + "tabReplays": "Repeticiones", "tabNames": "Nombres", "tabPunish": "Sancionar", "tabs": { @@ -1393,6 +1405,7 @@ "connected": "Conectado", "notes": "Notas", "tickets": "Tickets", + "replays": "Repeticiones", "names": "Nombres", "punish": "Sancionar" }, @@ -1456,6 +1469,16 @@ "playerTickets": "Tickets del jugador", "loadingTickets": "Cargando tickets...", "noTickets": "No se encontraron tickets para este jugador.", + "playerReplays": "Repeticiones del jugador", + "loadingReplays": "Cargando repeticiones...", + "noReplays": "No se encontraron repeticiones para este jugador.", + "replaysLoadFailed": "No se pudieron cargar las repeticiones de este jugador.", + "openReplay": "Abrir repetición", + "replayCreated": "Creada", + "replayMcVersion": "Minecraft", + "replaySize": "Tamaño", + "replayId": "ID de repetición", + "unknownPlayer": "Jugador desconocido", "previousNames": "Nombres anteriores", "missingInfo": "Información faltante", "selectPunishmentType": "Por favor selecciona un tipo de sanción antes de aplicar.", diff --git a/client/src/locales/nl.json b/client/src/locales/nl.json index 0649791..cf32f49 100644 --- a/client/src/locales/nl.json +++ b/client/src/locales/nl.json @@ -751,6 +751,17 @@ "storageOverage": "Opslagoverschrijding", "costThisMonth": "Kosten deze maand", "storageRate": "$0,08 per GB per maand", + "replayRetention": "Replaybewaring", + "replayRetentionEnabled": "Automatische replay-opruiming inschakelen", + "replayRetentionEnabledDesc": "Verwijder opgeslagen replays automatisch na de ingestelde bewaartermijn.", + "replayRetentionDays": "Bewaartermijn (dagen)", + "replayRetentionDaysDesc": "Opgeslagen replays ouder dan dit aantal dagen komen in aanmerking voor opruiming.", + "replayRetentionDisabledDesc": "Automatische replay-opruiming is uitgeschakeld. Opgeslagen replays blijven bewaard totdat ze handmatig worden verwijderd.", + "replayRetentionActive": "Replays worden na {{days}} dagen verwijderd", + "replayRetentionOff": "Automatische opruiming uitgeschakeld", + "replayRetentionSaved": "Replaybewaarinstellingen opgeslagen.", + "replayRetentionSaveFailed": "Replaybewaarinstellingen opslaan mislukt.", + "replayRetentionLoadFailed": "Replaybewaarinstellingen laden mislukt.", "systemStatus": "Systeemstatus", "totalFiles": "Totaal bestanden", "selected": "Geselecteerd", @@ -1386,6 +1397,7 @@ "tabConnectedShort": "Gekoppeld", "tabNotes": "Notities", "tabTickets": "Tickets", + "tabReplays": "Replays", "tabNames": "Namen", "tabPunish": "Bestraffen", "tabs": { @@ -1393,6 +1405,7 @@ "connected": "Verbonden", "notes": "Notities", "tickets": "Tickets", + "replays": "Replays", "names": "Namen", "punish": "Bestraffen" }, @@ -1456,6 +1469,16 @@ "playerTickets": "Spelertickets", "loadingTickets": "Tickets laden...", "noTickets": "Geen tickets gevonden voor deze speler.", + "playerReplays": "Spelerreplays", + "loadingReplays": "Replays laden...", + "noReplays": "Geen replays gevonden voor deze speler.", + "replaysLoadFailed": "Replays voor deze speler laden mislukt.", + "openReplay": "Replay openen", + "replayCreated": "Gemaakt", + "replayMcVersion": "Minecraft", + "replaySize": "Grootte", + "replayId": "Replay-ID", + "unknownPlayer": "Onbekende speler", "previousNames": "Vorige namen", "missingInfo": "Ontbrekende informatie", "selectPunishmentType": "Selecteer een straftype voordat je het toepast.", diff --git a/client/src/pages/player-detail-page.tsx b/client/src/pages/player-detail-page.tsx index b908d03..d6871ab 100644 --- a/client/src/pages/player-detail-page.tsx +++ b/client/src/pages/player-detail-page.tsx @@ -4,7 +4,7 @@ import { useRoute, useLocation } from 'wouter'; import { ArrowLeft, Ban, RefreshCcw, Search, History, Link2, StickyNote, Ticket, UserRound, Shield, FileText, Upload, Loader2, - ChevronDown, ChevronRight, Settings, Plus, X + ChevronDown, ChevronRight, Settings, Plus, X, Play } from 'lucide-react'; import { getAvatarUrl } from '@/lib/api'; import { Button } from '@modl-gg/shared-web/components/ui/button'; @@ -19,6 +19,7 @@ import { toast } from '@modl-gg/shared-web/hooks/use-toast'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@modl-gg/shared-web/components/ui/select'; import PlayerPunishment, { PlayerPunishmentData } from '@/components/ui/player-punishment'; import MediaUpload from '@/components/MediaUpload'; +import PlayerReplaysList from '@/components/player-replays-list'; import { formatDateWithTime } from '@/utils/date-utils'; import { apiFetch } from '@/lib/api'; import { formatTicketStatusLabel, normalizeTicketStatus } from '@/lib/ticket-enums'; @@ -1232,12 +1233,13 @@ const PlayerDetailPage = () => { {t('player.tabConnected')} {t('player.tabNotes')} {t('player.tabTickets')} + {t('player.tabReplays')} {t('player.tabNames')} {t('player.tabPunish')} ) : ( - + {t('player.tabHistory')} @@ -1254,6 +1256,10 @@ const PlayerDetailPage = () => { {t('player.tabTickets')} + + + {t('player.tabReplays')} + {t('player.tabNames')} @@ -2565,6 +2571,11 @@ const PlayerDetailPage = () => {
+ +

{t('player.playerReplays')}

+ +
+

Previous Names

From 13580ba467144af44db84bfb7de4bf4fc350a3cd Mon Sep 17 00:00:00 2001 From: byteful Date: Mon, 18 May 2026 03:29:57 -0500 Subject: [PATCH 06/30] locale fix --- client/src/locales/de.json | 1 + client/src/locales/en.json | 1 + client/src/locales/es.json | 1 + client/src/locales/nl.json | 1 + 4 files changed, 4 insertions(+) diff --git a/client/src/locales/de.json b/client/src/locales/de.json index 0764879..25dccff 100644 --- a/client/src/locales/de.json +++ b/client/src/locales/de.json @@ -1032,6 +1032,7 @@ "label": "Label", "assignee": "Zugewiesen an", "unassigned": "Nicht zugewiesen", + "hidden": "Ausgeblendet", "newest": "Neueste", "oldest": "Älteste", "recentlyUpdated": "Kürzlich aktualisiert", diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 453a41c..3ac6560 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -1039,6 +1039,7 @@ "label": "Label", "assignee": "Assignee", "unassigned": "Unassigned", + "hidden": "Hidden", "newest": "Newest", "oldest": "Oldest", "recentlyUpdated": "Recently Updated", diff --git a/client/src/locales/es.json b/client/src/locales/es.json index 6d587e8..2ad51ad 100644 --- a/client/src/locales/es.json +++ b/client/src/locales/es.json @@ -1032,6 +1032,7 @@ "label": "Etiqueta", "assignee": "Asignado a", "unassigned": "Sin asignar", + "hidden": "Oculto", "newest": "Más nuevos", "oldest": "Más antiguos", "recentlyUpdated": "Actualizado recientemente", diff --git a/client/src/locales/nl.json b/client/src/locales/nl.json index cf32f49..cc50ed4 100644 --- a/client/src/locales/nl.json +++ b/client/src/locales/nl.json @@ -1032,6 +1032,7 @@ "label": "Label", "assignee": "Toegewezen aan", "unassigned": "Niet toegewezen", + "hidden": "Verborgen", "newest": "Nieuwste", "oldest": "Oudste", "recentlyUpdated": "Recent bijgewerkt", From 00a38a483b188336fbca1cd95fac754436dd36f0 Mon Sep 17 00:00:00 2001 From: byteful Date: Thu, 21 May 2026 23:33:56 -0500 Subject: [PATCH 07/30] build script fix --- .github/workflows/build.yml | 17 +- package-lock.json | 1317 +++++++++++++++++++++++++++++------ 2 files changed, 1121 insertions(+), 213 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c19e0d..ff433d6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,10 +11,9 @@ on: jobs: build: runs-on: ubuntu-latest - + permissions: contents: read - packages: read steps: - name: Checkout code @@ -24,21 +23,15 @@ jobs: uses: actions/setup-node@v4 with: node-version: '23' - registry-url: 'https://npm.pkg.github.com' - scope: '@modl-gg' - - name: Configure npm for GitHub Packages + - name: Configure npm for Nexus run: | - rm .npmrc - echo "@modl-gg:registry=https://npm.pkg.github.com" >> .npmrc - echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> .npmrc - env: - NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + echo "//nexus.modl.gg/repository/npm-releases/:_auth=$(echo -n '${{ secrets.NEXUS_USER }}:${{ secrets.NEXUS_PASS }}' | base64)" >> ~/.npmrc + echo "//nexus.modl.gg/repository/npm-releases/:always-auth=true" >> ~/.npmrc + echo "@modl-gg:registry=https://nexus.modl.gg/repository/npm-releases/" >> ~/.npmrc - name: Install dependencies run: npm i - env: - NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Run build run: npm run build diff --git a/package-lock.json b/package-lock.json index dfd2cfd..3367c7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -93,6 +93,8 @@ }, "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==", "license": "MIT", "engines": { "node": ">=10" @@ -103,6 +105,8 @@ }, "node_modules/@babel/code-frame": { "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", "dependencies": { @@ -115,7 +119,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", "dev": true, "license": "MIT", "engines": { @@ -124,6 +130,8 @@ }, "node_modules/@babel/core": { "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", "dependencies": { @@ -153,6 +161,8 @@ }, "node_modules/@babel/generator": { "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", "dependencies": { @@ -168,6 +178,8 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", "dependencies": { @@ -183,6 +195,8 @@ }, "node_modules/@babel/helper-globals": { "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, "license": "MIT", "engines": { @@ -191,6 +205,8 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", "dependencies": { @@ -203,6 +219,8 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", "dependencies": { @@ -219,6 +237,8 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", "engines": { @@ -227,6 +247,8 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { @@ -235,6 +257,8 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "license": "MIT", "engines": { @@ -243,6 +267,8 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", "engines": { @@ -251,6 +277,8 @@ }, "node_modules/@babel/helpers": { "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, "license": "MIT", "dependencies": { @@ -262,7 +290,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.2", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", "dev": true, "license": "MIT", "dependencies": { @@ -277,6 +307,8 @@ }, "node_modules/@babel/plugin-transform-react-jsx-self": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, "license": "MIT", "dependencies": { @@ -291,6 +323,8 @@ }, "node_modules/@babel/plugin-transform-react-jsx-source": { "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, "license": "MIT", "dependencies": { @@ -305,6 +339,8 @@ }, "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" @@ -312,6 +348,8 @@ }, "node_modules/@babel/template": { "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "license": "MIT", "dependencies": { @@ -325,6 +363,8 @@ }, "node_modules/@babel/traverse": { "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, "license": "MIT", "dependencies": { @@ -342,6 +382,8 @@ }, "node_modules/@babel/types": { "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", "dependencies": { @@ -353,7 +395,9 @@ } }, "node_modules/@bufbuild/protobuf": { - "version": "2.11.0", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.0.tgz", + "integrity": "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==", "license": "(Apache-2.0 AND BSD-3-Clause)" }, "node_modules/@esbuild/aix-ppc64": { @@ -614,6 +658,8 @@ }, "node_modules/@esbuild/linux-x64": { "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", "cpu": [ "x64" ], @@ -724,6 +770,8 @@ }, "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" @@ -731,6 +779,8 @@ }, "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", @@ -739,6 +789,8 @@ }, "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" @@ -750,10 +802,14 @@ }, "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/@hookform/resolvers": { "version": "3.10.0", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.10.0.tgz", + "integrity": "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag==", "license": "MIT", "peerDependencies": { "react-hook-form": "^7.0.0" @@ -761,6 +817,8 @@ }, "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==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -769,6 +827,8 @@ }, "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==", "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -777,6 +837,8 @@ }, "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==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -784,10 +846,14 @@ }, "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==", "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==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -796,6 +862,8 @@ }, "node_modules/@modl-gg/proto": { "version": "1.1.0", + "resolved": "https://nexus.modl.gg/repository/npm-releases/@modl-gg/proto/-/proto-1.1.0.tgz", + "integrity": "sha512-Bqwde7W4NJxCsmCPztK0DKGZZfEYkg59CueJ9BC2EF/e0q8uf131/LcuVUD5rXtt/ovXRAbzhvMY5VbQNISGLw==", "license": "AGPL-3.0-only", "dependencies": { "@bufbuild/protobuf": "^2.0.0" @@ -815,6 +883,8 @@ }, "node_modules/@modl-gg/shared-web": { "version": "1.0.5", + "resolved": "https://nexus.modl.gg/repository/npm-releases/@modl-gg/shared-web/-/shared-web-1.0.5.tgz", + "integrity": "sha512-LBLIcOCHtUysNxVmXRXeeyezInIlNnoO4tvLjkXtZYR1ZYfiUylFgHQXsTCKNRLHbLXjl3Vh/Qx9fIvDCgFkUA==", "license": "AGPL-3.0-only", "dependencies": { "@radix-ui/react-accordion": "^1.2.0", @@ -870,10 +940,14 @@ }, "node_modules/@modl-gg/shared-web/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/@modl-gg/shared-web/node_modules/lucide-react": { "version": "0.395.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.395.0.tgz", + "integrity": "sha512-6hzdNH5723A4FLaYZWpK50iyZH8iS2Jq5zuPRRotOFkhu6kxxJiebVdJ72tCR5XkiIeYFOU5NUawFZOac+VeYw==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0" @@ -881,10 +955,14 @@ }, "node_modules/@modl-gg/shared-web/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/@modl-gg/shared-web/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", @@ -906,6 +984,8 @@ }, "node_modules/@modl-gg/shared-web/node_modules/vaul": { "version": "0.9.9", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-0.9.9.tgz", + "integrity": "sha512-7afKg48srluhZwIkaU+lgGtFCUsYBSGOl8vcc8N/M3YQlZFlynHD15AE+pwrYdc826o7nrIND4lL9Y6b9WWZZQ==", "license": "MIT", "dependencies": { "@radix-ui/react-dialog": "^1.1.1" @@ -917,6 +997,8 @@ }, "node_modules/@modl-gg/shared-web/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", @@ -936,7 +1018,9 @@ } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.4.6", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.11.tgz", + "integrity": "sha512-o9rAHc0IpIjuPSxRutWpE1F62x7n+4mVS4rCNHkzhIUMQcc18bb6xEq5wd2NdN0WjepIyXIppRshYI2kQDOZVA==", "license": "MIT", "dependencies": { "sparse-bitfield": "^3.0.3" @@ -944,6 +1028,8 @@ }, "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==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -955,6 +1041,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==", "license": "MIT", "engines": { "node": ">= 8" @@ -962,6 +1050,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==", "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -973,14 +1063,20 @@ }, "node_modules/@radix-ui/number": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", "license": "MIT" }, "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-accordion": { "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -1010,6 +1106,8 @@ }, "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", @@ -1036,6 +1134,8 @@ }, "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" @@ -1052,6 +1152,8 @@ }, "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" @@ -1073,6 +1175,8 @@ }, "node_modules/@radix-ui/react-aspect-ratio": { "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.8.tgz", + "integrity": "sha512-5nZrJTF7gH+e0nZS7/QxFz6tJV4VimhQb1avEgtsJxvvIp5JilL+c58HICsKzPxghdwaDt48hEfPM1au4zGy+w==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.4" @@ -1094,6 +1198,8 @@ }, "node_modules/@radix-ui/react-aspect-ratio/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" @@ -1115,6 +1221,8 @@ }, "node_modules/@radix-ui/react-avatar": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz", + "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==", "license": "MIT", "dependencies": { "@radix-ui/react-context": "1.1.3", @@ -1140,6 +1248,8 @@ }, "node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1153,6 +1263,8 @@ }, "node_modules/@radix-ui/react-avatar/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" @@ -1174,6 +1286,8 @@ }, "node_modules/@radix-ui/react-checkbox": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -1202,6 +1316,8 @@ }, "node_modules/@radix-ui/react-collapsible": { "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -1230,6 +1346,8 @@ }, "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", @@ -1254,6 +1372,8 @@ }, "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" @@ -1270,6 +1390,8 @@ }, "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": "*", @@ -1283,6 +1405,8 @@ }, "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": "*", @@ -1296,6 +1420,8 @@ }, "node_modules/@radix-ui/react-context-menu": { "version": "2.2.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz", + "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -1322,6 +1448,8 @@ }, "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", @@ -1356,6 +1484,8 @@ }, "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" @@ -1372,6 +1502,8 @@ }, "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": "*", @@ -1385,6 +1517,8 @@ }, "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", @@ -1410,6 +1544,8 @@ }, "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", @@ -1437,6 +1573,8 @@ }, "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": "*", @@ -1450,6 +1588,8 @@ }, "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", @@ -1473,6 +1613,8 @@ }, "node_modules/@radix-ui/react-hover-card": { "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz", + "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -1502,6 +1644,8 @@ }, "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" @@ -1518,6 +1662,8 @@ }, "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" @@ -1539,6 +1685,8 @@ }, "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" @@ -1560,6 +1708,8 @@ }, "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", @@ -1598,6 +1748,8 @@ }, "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" @@ -1614,6 +1766,8 @@ }, "node_modules/@radix-ui/react-menubar": { "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz", + "integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -1644,6 +1798,8 @@ }, "node_modules/@radix-ui/react-navigation-menu": { "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz", + "integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -1678,6 +1834,8 @@ }, "node_modules/@radix-ui/react-popover": { "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", + "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -1713,6 +1871,8 @@ }, "node_modules/@radix-ui/react-popover/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" @@ -1729,6 +1889,8 @@ }, "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", @@ -1759,6 +1921,8 @@ }, "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", @@ -1781,6 +1945,8 @@ }, "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", @@ -1803,6 +1969,8 @@ }, "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" @@ -1824,6 +1992,8 @@ }, "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" @@ -1840,6 +2010,8 @@ }, "node_modules/@radix-ui/react-progress": { "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz", + "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==", "license": "MIT", "dependencies": { "@radix-ui/react-context": "1.1.3", @@ -1862,6 +2034,8 @@ }, "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-context": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -1875,6 +2049,8 @@ }, "node_modules/@radix-ui/react-progress/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" @@ -1896,6 +2072,8 @@ }, "node_modules/@radix-ui/react-radio-group": { "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -1926,6 +2104,8 @@ }, "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", @@ -1955,6 +2135,8 @@ }, "node_modules/@radix-ui/react-scroll-area": { "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", + "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", "license": "MIT", "dependencies": { "@radix-ui/number": "1.1.1", @@ -1984,6 +2166,8 @@ }, "node_modules/@radix-ui/react-select": { "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", "license": "MIT", "dependencies": { "@radix-ui/number": "1.1.1", @@ -2025,6 +2209,8 @@ }, "node_modules/@radix-ui/react-select/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" @@ -2041,6 +2227,8 @@ }, "node_modules/@radix-ui/react-separator": { "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", + "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.4" @@ -2062,6 +2250,8 @@ }, "node_modules/@radix-ui/react-separator/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" @@ -2083,6 +2273,8 @@ }, "node_modules/@radix-ui/react-slider": { "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", + "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==", "license": "MIT", "dependencies": { "@radix-ui/number": "1.1.1", @@ -2114,6 +2306,8 @@ }, "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" @@ -2130,6 +2324,8 @@ }, "node_modules/@radix-ui/react-switch": { "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2157,6 +2353,8 @@ }, "node_modules/@radix-ui/react-tabs": { "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", + "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2185,6 +2383,8 @@ }, "node_modules/@radix-ui/react-toast": { "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz", + "integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2217,6 +2417,8 @@ }, "node_modules/@radix-ui/react-toggle": { "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz", + "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2240,6 +2442,8 @@ }, "node_modules/@radix-ui/react-toggle-group": { "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz", + "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2267,6 +2471,8 @@ }, "node_modules/@radix-ui/react-tooltip": { "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2299,6 +2505,8 @@ }, "node_modules/@radix-ui/react-tooltip/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" @@ -2315,6 +2523,8 @@ }, "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": "*", @@ -2328,6 +2538,8 @@ }, "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", @@ -2345,6 +2557,8 @@ }, "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" @@ -2361,6 +2575,8 @@ }, "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" @@ -2377,6 +2593,8 @@ }, "node_modules/@radix-ui/react-use-is-hydrated": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", "license": "MIT", "dependencies": { "use-sync-external-store": "^1.5.0" @@ -2393,6 +2611,8 @@ }, "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": "*", @@ -2406,6 +2626,8 @@ }, "node_modules/@radix-ui/react-use-previous": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2419,6 +2641,8 @@ }, "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" @@ -2435,6 +2659,8 @@ }, "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" @@ -2451,6 +2677,8 @@ }, "node_modules/@radix-ui/react-visually-hidden": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.3" @@ -2472,29 +2700,39 @@ }, "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/@react-dnd/asap": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", + "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==", "license": "MIT" }, "node_modules/@react-dnd/invariant": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", + "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==", "license": "MIT" }, "node_modules/@react-dnd/shallowequal": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", + "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==", "license": "MIT" }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", "dev": true, "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", - "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", + "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", "cpu": [ "arm" ], @@ -2505,9 +2743,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", - "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", + "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", "cpu": [ "arm64" ], @@ -2518,9 +2756,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", - "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", + "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", "cpu": [ "arm64" ], @@ -2531,9 +2769,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", - "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", + "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", "cpu": [ "x64" ], @@ -2544,9 +2782,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", - "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", + "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", "cpu": [ "arm64" ], @@ -2557,9 +2795,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", - "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", + "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", "cpu": [ "x64" ], @@ -2570,9 +2808,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", - "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", + "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", "cpu": [ "arm" ], @@ -2586,9 +2824,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", - "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", + "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", "cpu": [ "arm" ], @@ -2602,9 +2840,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", - "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", + "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", "cpu": [ "arm64" ], @@ -2618,9 +2856,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", - "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", + "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", "cpu": [ "arm64" ], @@ -2634,9 +2872,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", - "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", + "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", "cpu": [ "loong64" ], @@ -2650,9 +2888,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", - "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", + "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", "cpu": [ "loong64" ], @@ -2666,9 +2904,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", - "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", + "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", "cpu": [ "ppc64" ], @@ -2682,9 +2920,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", - "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", + "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", "cpu": [ "ppc64" ], @@ -2698,9 +2936,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", - "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", + "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", "cpu": [ "riscv64" ], @@ -2714,9 +2952,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", - "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", + "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", "cpu": [ "riscv64" ], @@ -2730,9 +2968,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", - "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", + "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", "cpu": [ "s390x" ], @@ -2746,7 +2984,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.1", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", + "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", "cpu": [ "x64" ], @@ -2760,9 +3000,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", - "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", + "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", "cpu": [ "x64" ], @@ -2776,9 +3016,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", - "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", + "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", "cpu": [ "x64" ], @@ -2789,9 +3029,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", - "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", + "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", "cpu": [ "arm64" ], @@ -2802,9 +3042,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", - "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", + "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", "cpu": [ "arm64" ], @@ -2815,9 +3055,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", - "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", + "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", "cpu": [ "ia32" ], @@ -2828,9 +3068,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", - "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", + "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", "cpu": [ "x64" ], @@ -2841,9 +3081,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", - "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", + "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", "cpu": [ "x64" ], @@ -2855,65 +3095,79 @@ }, "node_modules/@simplewebauthn/browser": { "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.3.0.tgz", + "integrity": "sha512-BE/UWv6FOToAdVk0EokzkqQQDOWtNydYlY6+OrmiZ5SCNmb41VehttboTetUM3T/fr6EAFYVXjz4My2wg230rQ==", "license": "MIT" }, "node_modules/@standard-schema/spec": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "license": "MIT" }, "node_modules/@standard-schema/utils": { "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", "license": "MIT" }, "node_modules/@stripe/stripe-js": { "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.9.0.tgz", + "integrity": "sha512-ggs5k+/0FUJcIgNY08aZTqpBTtbExkJMYMLSMwyucrhtWexVOEY1KJmhBsxf+E/Q15f5rbwBpj+t0t2AW2oCsQ==", "license": "MIT", "engines": { "node": ">=12.16" } }, "node_modules/@tailwindcss/node": { - "version": "4.2.2", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz", + "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==", "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.19.0", + "enhanced-resolve": "^5.21.0", "jiti": "^2.6.1", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.2.2" + "tailwindcss": "4.3.0" } }, "node_modules/@tailwindcss/node/node_modules/tailwindcss": { - "version": "4.2.2", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", + "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==", "license": "MIT" }, "node_modules/@tailwindcss/oxide": { - "version": "4.2.2", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz", + "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==", "license": "MIT", "engines": { "node": ">= 20" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.2.2", - "@tailwindcss/oxide-darwin-arm64": "4.2.2", - "@tailwindcss/oxide-darwin-x64": "4.2.2", - "@tailwindcss/oxide-freebsd-x64": "4.2.2", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.2", - "@tailwindcss/oxide-linux-arm64-gnu": "4.2.2", - "@tailwindcss/oxide-linux-arm64-musl": "4.2.2", - "@tailwindcss/oxide-linux-x64-gnu": "4.2.2", - "@tailwindcss/oxide-linux-x64-musl": "4.2.2", - "@tailwindcss/oxide-wasm32-wasi": "4.2.2", - "@tailwindcss/oxide-win32-arm64-msvc": "4.2.2", - "@tailwindcss/oxide-win32-x64-msvc": "4.2.2" + "@tailwindcss/oxide-android-arm64": "4.3.0", + "@tailwindcss/oxide-darwin-arm64": "4.3.0", + "@tailwindcss/oxide-darwin-x64": "4.3.0", + "@tailwindcss/oxide-freebsd-x64": "4.3.0", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", + "@tailwindcss/oxide-linux-x64-musl": "4.3.0", + "@tailwindcss/oxide-wasm32-wasi": "4.3.0", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" } }, "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.2.tgz", - "integrity": "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz", + "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==", "cpu": [ "arm64" ], @@ -2927,9 +3181,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.2.tgz", - "integrity": "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz", + "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==", "cpu": [ "arm64" ], @@ -2943,9 +3197,9 @@ } }, "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.2.tgz", - "integrity": "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz", + "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==", "cpu": [ "x64" ], @@ -2959,9 +3213,9 @@ } }, "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.2.tgz", - "integrity": "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz", + "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==", "cpu": [ "x64" ], @@ -2975,9 +3229,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.2.tgz", - "integrity": "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz", + "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==", "cpu": [ "arm" ], @@ -2991,9 +3245,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.2.tgz", - "integrity": "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz", + "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==", "cpu": [ "arm64" ], @@ -3010,9 +3264,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.2.tgz", - "integrity": "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz", + "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==", "cpu": [ "arm64" ], @@ -3029,7 +3283,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.2.2", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz", + "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==", "cpu": [ "x64" ], @@ -3046,9 +3302,9 @@ } }, "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.2.tgz", - "integrity": "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz", + "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==", "cpu": [ "x64" ], @@ -3065,9 +3321,9 @@ } }, "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.2.tgz", - "integrity": "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz", + "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==", "bundleDependencies": [ "@napi-rs/wasm-runtime", "@emnapi/core", @@ -3082,10 +3338,10 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "^1.8.1", - "@emnapi/runtime": "^1.8.1", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.1.1", + "@emnapi/core": "^1.10.0", + "@emnapi/runtime": "^1.10.0", + "@emnapi/wasi-threads": "^1.2.1", + "@napi-rs/wasm-runtime": "^1.1.4", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, @@ -3094,9 +3350,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz", - "integrity": "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz", + "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==", "cpu": [ "arm64" ], @@ -3110,9 +3366,9 @@ } }, "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.2.tgz", - "integrity": "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz", + "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==", "cpu": [ "x64" ], @@ -3127,6 +3383,8 @@ }, "node_modules/@tailwindcss/typography": { "version": "0.5.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz", + "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==", "dev": true, "license": "MIT", "dependencies": { @@ -3137,23 +3395,29 @@ } }, "node_modules/@tailwindcss/vite": { - "version": "4.2.2", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.0.tgz", + "integrity": "sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==", "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.2.2", - "@tailwindcss/oxide": "4.2.2", - "tailwindcss": "4.2.2" + "@tailwindcss/node": "4.3.0", + "@tailwindcss/oxide": "4.3.0", + "tailwindcss": "4.3.0" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "node_modules/@tailwindcss/vite/node_modules/tailwindcss": { - "version": "4.2.2", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", + "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==", "license": "MIT" }, "node_modules/@tanstack/query-core": { - "version": "5.99.0", + "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", @@ -3161,10 +3425,12 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.99.0", + "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.99.0" + "@tanstack/query-core": "5.100.11" }, "funding": { "type": "github", @@ -3176,6 +3442,8 @@ }, "node_modules/@types/babel__core": { "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "license": "MIT", "dependencies": { @@ -3188,6 +3456,8 @@ }, "node_modules/@types/babel__generator": { "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, "license": "MIT", "dependencies": { @@ -3196,6 +3466,8 @@ }, "node_modules/@types/babel__template": { "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "license": "MIT", "dependencies": { @@ -3205,6 +3477,8 @@ }, "node_modules/@types/babel__traverse": { "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3213,18 +3487,26 @@ }, "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": "*" @@ -3232,10 +3514,14 @@ }, "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": "*" @@ -3243,6 +3529,8 @@ }, "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": "*" @@ -3250,25 +3538,35 @@ }, "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/debug": { "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", "license": "MIT", "dependencies": { "@types/ms": "*" } }, "node_modules/@types/estree": { - "version": "1.0.8", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, "node_modules/@types/estree-jsx": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", "license": "MIT", "dependencies": { "@types/estree": "*" @@ -3276,6 +3574,8 @@ }, "node_modules/@types/hast": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "license": "MIT", "dependencies": { "@types/unist": "*" @@ -3283,6 +3583,8 @@ }, "node_modules/@types/mdast": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "license": "MIT", "dependencies": { "@types/unist": "*" @@ -3290,10 +3592,14 @@ }, "node_modules/@types/ms": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", "license": "MIT" }, "node_modules/@types/node": { "version": "20.16.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz", + "integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==", "devOptional": true, "license": "MIT", "dependencies": { @@ -3302,10 +3608,14 @@ }, "node_modules/@types/prop-types": { "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.28", + "version": "18.3.29", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.29.tgz", + "integrity": "sha512-ch0qJdr2JY0r04NXSprbK6TXOgnaJ1Tz23fm5W+z0/CBah6BSBc3n96h7K9GOtwh0HrilNWHIBzE1Ko4Dcw/Wg==", "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -3314,6 +3624,8 @@ }, "node_modules/@types/react-dom": { "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "devOptional": true, "license": "MIT", "peerDependencies": { @@ -3322,34 +3634,48 @@ }, "node_modules/@types/unist": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, "node_modules/@types/use-sync-external-store": { "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", "license": "MIT" }, "node_modules/@types/uuid": { "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "dev": true, "license": "MIT" }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", "license": "MIT" }, "node_modules/@types/whatwg-url": { "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", "license": "MIT", "dependencies": { "@types/webidl-conversions": "*" } }, "node_modules/@ungap/structured-clone": { - "version": "1.3.0", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", "license": "ISC" }, "node_modules/@vitejs/plugin-react": { "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", "dev": true, "license": "MIT", "dependencies": { @@ -3369,10 +3695,14 @@ }, "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==", "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==", "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -3384,10 +3714,14 @@ }, "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==", "license": "MIT" }, "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" @@ -3397,7 +3731,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.27", + "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": [ { @@ -3415,8 +3751,8 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.28.1", - "caniuse-lite": "^1.0.30001774", + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -3433,6 +3769,8 @@ }, "node_modules/bail": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", "license": "MIT", "funding": { "type": "github", @@ -3440,7 +3778,9 @@ } }, "node_modules/baseline-browser-mapping": { - "version": "2.10.18", + "version": "2.10.31", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.31.tgz", + "integrity": "sha512-MujYO3eP72uvmSE0i4wltsodRfIpZATP3jvzRNRGGxgzId7aVocVJJV3nf01qnzzKFGxQVC9bpWxl5cjxTr/7Q==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3452,6 +3792,8 @@ }, "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==", "license": "MIT", "engines": { "node": ">=8" @@ -3462,6 +3804,8 @@ }, "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==", "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -3472,6 +3816,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": [ { @@ -3504,6 +3850,8 @@ }, "node_modules/bson": { "version": "6.10.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", + "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", "license": "Apache-2.0", "engines": { "node": ">=16.20.1" @@ -3511,13 +3859,17 @@ }, "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==", "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001787", + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", "dev": true, "funding": [ { @@ -3537,6 +3889,8 @@ }, "node_modules/ccount": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", "license": "MIT", "funding": { "type": "github", @@ -3545,6 +3899,8 @@ }, "node_modules/character-entities": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", "license": "MIT", "funding": { "type": "github", @@ -3553,6 +3909,8 @@ }, "node_modules/character-entities-html4": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", "license": "MIT", "funding": { "type": "github", @@ -3561,6 +3919,8 @@ }, "node_modules/character-entities-legacy": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", "license": "MIT", "funding": { "type": "github", @@ -3569,6 +3929,8 @@ }, "node_modules/character-reference-invalid": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", "license": "MIT", "funding": { "type": "github", @@ -3577,6 +3939,8 @@ }, "node_modules/chokidar": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "license": "MIT", "dependencies": { "anymatch": "~3.1.2", @@ -3599,6 +3963,8 @@ }, "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==", "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -3609,6 +3975,8 @@ }, "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" @@ -3619,6 +3987,8 @@ }, "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" @@ -3626,6 +3996,8 @@ }, "node_modules/cmdk": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", + "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "^1.1.1", @@ -3640,6 +4012,8 @@ }, "node_modules/comma-separated-tokens": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", "license": "MIT", "funding": { "type": "github", @@ -3648,6 +4022,8 @@ }, "node_modules/commander": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "license": "MIT", "engines": { "node": ">= 6" @@ -3655,11 +4031,15 @@ }, "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/cookie": { "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3667,10 +4047,14 @@ }, "node_modules/cookie-signature": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, "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==", "license": "MIT", "bin": { "cssesc": "bin/cssesc" @@ -3681,10 +4065,14 @@ }, "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" @@ -3695,6 +4083,8 @@ }, "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" @@ -3702,6 +4092,8 @@ }, "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" @@ -3709,6 +4101,8 @@ }, "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" @@ -3716,6 +4110,8 @@ }, "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" @@ -3726,6 +4122,8 @@ }, "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" @@ -3733,6 +4131,8 @@ }, "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", @@ -3747,6 +4147,8 @@ }, "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" @@ -3757,6 +4159,8 @@ }, "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" @@ -3767,6 +4171,8 @@ }, "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" @@ -3777,6 +4183,8 @@ }, "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" @@ -3784,6 +4192,8 @@ }, "node_modules/date-fns": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", "license": "MIT", "funding": { "type": "github", @@ -3792,6 +4202,8 @@ }, "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" @@ -3807,10 +4219,14 @@ }, "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/decode-named-character-reference": { "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", "license": "MIT", "dependencies": { "character-entities": "^2.0.0" @@ -3822,6 +4238,8 @@ }, "node_modules/depd": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -3829,6 +4247,8 @@ }, "node_modules/dequal": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "license": "MIT", "engines": { "node": ">=6" @@ -3836,6 +4256,8 @@ }, "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" @@ -3843,10 +4265,14 @@ }, "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/devlop": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "license": "MIT", "dependencies": { "dequal": "^2.0.0" @@ -3858,14 +4284,20 @@ }, "node_modules/didyoumean": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "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==", "license": "MIT" }, "node_modules/dnd-core": { "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", + "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", "license": "MIT", "dependencies": { "@react-dnd/asap": "^5.0.1", @@ -3875,6 +4307,8 @@ }, "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", @@ -3882,16 +4316,22 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.335", + "version": "1.5.361", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.361.tgz", + "integrity": "sha512-Q6Hts7N9FnJc5LeGRINFvLhCI9xZmNtTDe5ZbcVezQz7cU4a8Aua3GH1b8J2XY8Al9PF+OCwYqhgsOOheMdvkA==", "dev": true, "license": "ISC" }, "node_modules/embla-carousel": { "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", + "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", "license": "MIT" }, "node_modules/embla-carousel-react": { "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.6.0.tgz", + "integrity": "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==", "license": "MIT", "dependencies": { "embla-carousel": "8.6.0", @@ -3903,17 +4343,21 @@ }, "node_modules/embla-carousel-reactive-utils": { "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.6.0.tgz", + "integrity": "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==", "license": "MIT", "peerDependencies": { "embla-carousel": "8.6.0" } }, "node_modules/enhanced-resolve": { - "version": "5.20.1", + "version": "5.21.6", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", + "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -3921,13 +4365,17 @@ }, "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-toolkit": { - "version": "1.45.1", + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz", + "integrity": "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==", "license": "MIT", "workspaces": [ "docs", @@ -3936,6 +4384,8 @@ }, "node_modules/esbuild": { "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -3972,6 +4422,8 @@ }, "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": { @@ -3980,6 +4432,8 @@ }, "node_modules/estree-util-is-identifier-name": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", "license": "MIT", "funding": { "type": "opencollective", @@ -3988,10 +4442,14 @@ }, "node_modules/eventemitter3": { "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "license": "MIT" }, "node_modules/express-session": { "version": "1.19.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.19.0.tgz", + "integrity": "sha512-0csaMkGq+vaiZTmSMMGkfdCOabYv192VbytFypcvI0MANrp+4i/7yEkJ0sbAEhycQjntaKGzYfjfXQyVb7BHMA==", "license": "MIT", "dependencies": { "cookie": "~0.7.2", @@ -4013,6 +4471,8 @@ }, "node_modules/express-session/node_modules/debug": { "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -4020,18 +4480,26 @@ }, "node_modules/express-session/node_modules/ms": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/extend": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, "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==", "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" @@ -4039,6 +4507,8 @@ }, "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==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -4053,6 +4523,8 @@ }, "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==", "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -4063,6 +4535,8 @@ }, "node_modules/fastq": { "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -4070,6 +4544,8 @@ }, "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==", "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -4080,6 +4556,8 @@ }, "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": { @@ -4092,6 +4570,8 @@ }, "node_modules/framer-motion": { "version": "11.18.2", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz", + "integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==", "license": "MIT", "dependencies": { "motion-dom": "^11.18.1", @@ -4131,6 +4611,8 @@ }, "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" @@ -4138,6 +4620,8 @@ }, "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": { @@ -4146,6 +4630,8 @@ }, "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" @@ -4153,6 +4639,8 @@ }, "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==", "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -4163,10 +4651,14 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, "node_modules/hasown": { - "version": "2.0.2", + "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" @@ -4177,6 +4669,8 @@ }, "node_modules/hast-util-to-jsx-runtime": { "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -4202,6 +4696,8 @@ }, "node_modules/hast-util-whitespace": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -4213,6 +4709,8 @@ }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "license": "BSD-3-Clause", "dependencies": { "react-is": "^16.7.0" @@ -4220,10 +4718,14 @@ }, "node_modules/hoist-non-react-statics/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/html-parse-stringify": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", "license": "MIT", "dependencies": { "void-elements": "3.1.0" @@ -4231,6 +4733,8 @@ }, "node_modules/html-url-attributes": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", "license": "MIT", "funding": { "type": "opencollective", @@ -4239,6 +4743,8 @@ }, "node_modules/i18next": { "version": "25.10.10", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.10.10.tgz", + "integrity": "sha512-cqUW2Z3EkRx7NqSyywjkgCLK7KLCL6IFVFcONG7nVYIJ3ekZ1/N5jUsihHV6Bq37NfhgtczxJcxduELtjTwkuQ==", "funding": [ { "type": "individual", @@ -4268,6 +4774,8 @@ }, "node_modules/immer": { "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", "license": "MIT", "funding": { "type": "opencollective", @@ -4276,10 +4784,14 @@ }, "node_modules/inline-style-parser": { "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, "node_modules/input-otp": { "version": "1.4.2", + "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.2.tgz", + "integrity": "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==", "license": "MIT", "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", @@ -4288,6 +4800,8 @@ }, "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" @@ -4295,6 +4809,8 @@ }, "node_modules/is-alphabetical": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", "license": "MIT", "funding": { "type": "github", @@ -4303,6 +4819,8 @@ }, "node_modules/is-alphanumerical": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", "license": "MIT", "dependencies": { "is-alphabetical": "^2.0.0", @@ -4315,6 +4833,8 @@ }, "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==", "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -4324,10 +4844,12 @@ } }, "node_modules/is-core-module": { - "version": "2.16.1", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "hasown": "^2.0.3" }, "engines": { "node": ">= 0.4" @@ -4338,6 +4860,8 @@ }, "node_modules/is-decimal": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", "license": "MIT", "funding": { "type": "github", @@ -4346,6 +4870,8 @@ }, "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" @@ -4353,6 +4879,8 @@ }, "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" @@ -4363,6 +4891,8 @@ }, "node_modules/is-hexadecimal": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", "license": "MIT", "funding": { "type": "github", @@ -4371,6 +4901,8 @@ }, "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==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -4378,6 +4910,8 @@ }, "node_modules/is-plain-obj": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "license": "MIT", "engines": { "node": ">=12" @@ -4387,7 +4921,9 @@ } }, "node_modules/jiti": { - "version": "2.6.1", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -4395,10 +4931,14 @@ }, "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/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": { @@ -4410,6 +4950,8 @@ }, "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": { @@ -4421,6 +4963,8 @@ }, "node_modules/kareem": { "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", "license": "Apache-2.0", "engines": { "node": ">=12.0.0" @@ -4428,6 +4972,8 @@ }, "node_modules/lightningcss": { "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -4601,6 +5147,8 @@ }, "node_modules/lightningcss-linux-x64-gnu": { "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], @@ -4685,6 +5233,8 @@ }, "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==", "license": "MIT", "engines": { "node": ">=14" @@ -4695,14 +5245,20 @@ }, "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==", "license": "MIT" }, "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/longest-streak": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", "license": "MIT", "funding": { "type": "github", @@ -4711,6 +5267,8 @@ }, "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" @@ -4721,6 +5279,8 @@ }, "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": { @@ -4729,6 +5289,8 @@ }, "node_modules/lucide-react": { "version": "0.453.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.453.0.tgz", + "integrity": "sha512-kL+RGZCcJi9BvJtzg2kshO192Ddy9hv3ij+cPrVPWSRzgCWCVazoQJxOjAwgK53NomL07HB7GPHW120FimjNhQ==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" @@ -4736,6 +5298,8 @@ }, "node_modules/magic-string": { "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -4743,6 +5307,8 @@ }, "node_modules/mdast-util-from-markdown": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -4765,6 +5331,8 @@ }, "node_modules/mdast-util-mdx-expression": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -4781,6 +5349,8 @@ }, "node_modules/mdast-util-mdx-jsx": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -4803,6 +5373,8 @@ }, "node_modules/mdast-util-mdxjs-esm": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -4819,6 +5391,8 @@ }, "node_modules/mdast-util-phrasing": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -4831,6 +5405,8 @@ }, "node_modules/mdast-util-to-hast": { "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -4850,6 +5426,8 @@ }, "node_modules/mdast-util-to-markdown": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -4869,6 +5447,8 @@ }, "node_modules/mdast-util-to-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0" @@ -4880,10 +5460,14 @@ }, "node_modules/memory-pager": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "license": "MIT", "engines": { "node": ">= 8" @@ -4891,6 +5475,8 @@ }, "node_modules/micromark": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", "funding": [ { "type": "GitHub Sponsors", @@ -4924,6 +5510,8 @@ }, "node_modules/micromark-core-commonmark": { "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", "funding": [ { "type": "GitHub Sponsors", @@ -4956,6 +5544,8 @@ }, "node_modules/micromark-factory-destination": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", "funding": [ { "type": "GitHub Sponsors", @@ -4975,6 +5565,8 @@ }, "node_modules/micromark-factory-label": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", "funding": [ { "type": "GitHub Sponsors", @@ -4995,6 +5587,8 @@ }, "node_modules/micromark-factory-space": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -5013,6 +5607,8 @@ }, "node_modules/micromark-factory-title": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", "funding": [ { "type": "GitHub Sponsors", @@ -5033,6 +5629,8 @@ }, "node_modules/micromark-factory-whitespace": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", "funding": [ { "type": "GitHub Sponsors", @@ -5053,6 +5651,8 @@ }, "node_modules/micromark-util-character": { "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -5071,6 +5671,8 @@ }, "node_modules/micromark-util-chunked": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", "funding": [ { "type": "GitHub Sponsors", @@ -5088,6 +5690,8 @@ }, "node_modules/micromark-util-classify-character": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", "funding": [ { "type": "GitHub Sponsors", @@ -5107,6 +5711,8 @@ }, "node_modules/micromark-util-combine-extensions": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", "funding": [ { "type": "GitHub Sponsors", @@ -5125,6 +5731,8 @@ }, "node_modules/micromark-util-decode-numeric-character-reference": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", "funding": [ { "type": "GitHub Sponsors", @@ -5142,6 +5750,8 @@ }, "node_modules/micromark-util-decode-string": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", "funding": [ { "type": "GitHub Sponsors", @@ -5162,6 +5772,8 @@ }, "node_modules/micromark-util-encode": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", "funding": [ { "type": "GitHub Sponsors", @@ -5176,6 +5788,8 @@ }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", "funding": [ { "type": "GitHub Sponsors", @@ -5190,6 +5804,8 @@ }, "node_modules/micromark-util-normalize-identifier": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", "funding": [ { "type": "GitHub Sponsors", @@ -5207,6 +5823,8 @@ }, "node_modules/micromark-util-resolve-all": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", "funding": [ { "type": "GitHub Sponsors", @@ -5224,6 +5842,8 @@ }, "node_modules/micromark-util-sanitize-uri": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "funding": [ { "type": "GitHub Sponsors", @@ -5243,6 +5863,8 @@ }, "node_modules/micromark-util-subtokenize": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", "funding": [ { "type": "GitHub Sponsors", @@ -5263,6 +5885,8 @@ }, "node_modules/micromark-util-symbol": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -5277,6 +5901,8 @@ }, "node_modules/micromark-util-types": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "funding": [ { "type": "GitHub Sponsors", @@ -5291,6 +5917,8 @@ }, "node_modules/micromatch": { "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -5302,10 +5930,14 @@ }, "node_modules/mitt": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "license": "MIT" }, "node_modules/mongodb": { "version": "6.20.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.20.0.tgz", + "integrity": "sha512-Tl6MEIU3K4Rq3TSHd+sZQqRBoGlFsOgNrH5ltAcFBV62Re3Fd+FcaVf8uSEQFOJ51SDowDVttBTONMfoYWrWlQ==", "license": "Apache-2.0", "dependencies": { "@mongodb-js/saslprep": "^1.3.0", @@ -5350,6 +5982,8 @@ }, "node_modules/mongodb-connection-string-url": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", "license": "Apache-2.0", "dependencies": { "@types/whatwg-url": "^11.0.2", @@ -5357,7 +5991,9 @@ } }, "node_modules/mongoose": { - "version": "8.23.0", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.24.0.tgz", + "integrity": "sha512-EEZwOibDPZ5uZN3bFapfnRskEbdljAf6sP9ln6u+P4e5IfkOAh6Tqw2g8/Tag++KHOAJ095WXT/c0uqRq4Vckg==", "license": "MIT", "dependencies": { "bson": "^6.10.4", @@ -5378,6 +6014,8 @@ }, "node_modules/motion-dom": { "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", + "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==", "license": "MIT", "dependencies": { "motion-utils": "^11.18.1" @@ -5385,10 +6023,14 @@ }, "node_modules/motion-utils": { "version": "11.18.1", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", + "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", "license": "MIT" }, "node_modules/mpath": { "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", "license": "MIT", "engines": { "node": ">=4.0.0" @@ -5396,6 +6038,8 @@ }, "node_modules/mquery": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", "license": "MIT", "dependencies": { "debug": "4.x" @@ -5406,10 +6050,14 @@ }, "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==", "license": "MIT", "dependencies": { "any-promise": "^1.0.0", @@ -5418,7 +6066,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.11", + "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", @@ -5435,6 +6085,8 @@ }, "node_modules/next-themes": { "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", "license": "MIT", "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", @@ -5442,12 +6094,19 @@ } }, "node_modules/node-releases": { - "version": "2.0.37", + "version": "2.0.45", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.45.tgz", + "integrity": "sha512-iIbHXV9eBB2nB0wa7oTsrrXq+qQt+9SIlx9AX3T96YgobtEQfis5n6TJ6vV+3QP8DwdriEAcGhARaFCu37peBg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "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==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5455,6 +6114,8 @@ }, "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" @@ -5462,6 +6123,8 @@ }, "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==", "license": "MIT", "engines": { "node": ">= 6" @@ -5469,6 +6132,8 @@ }, "node_modules/on-headers": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -5476,6 +6141,8 @@ }, "node_modules/parse-entities": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", @@ -5493,10 +6160,14 @@ }, "node_modules/parse-entities/node_modules/@types/unist": { "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, "node_modules/parseurl": { "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -5504,14 +6175,20 @@ }, "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==", "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==", "license": "MIT", "engines": { "node": ">=8.6" @@ -5522,6 +6199,8 @@ }, "node_modules/pify": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5529,13 +6208,17 @@ }, "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==", "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/postcss": { - "version": "8.5.9", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "funding": [ { "type": "opencollective", @@ -5552,7 +6235,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5562,6 +6245,8 @@ }, "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==", "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", @@ -5577,6 +6262,8 @@ }, "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==", "funding": [ { "type": "opencollective", @@ -5600,6 +6287,8 @@ }, "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==", "funding": [ { "type": "opencollective", @@ -5640,6 +6329,8 @@ }, "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==", "funding": [ { "type": "opencollective", @@ -5663,6 +6354,8 @@ }, "node_modules/postcss-nested/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==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -5674,6 +6367,8 @@ }, "node_modules/postcss-selector-parser": { "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, "license": "MIT", "dependencies": { @@ -5686,10 +6381,14 @@ }, "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==", "license": "MIT" }, "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", @@ -5699,10 +6398,14 @@ }, "node_modules/prop-types/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/property-information": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", "license": "MIT", "funding": { "type": "github", @@ -5711,6 +6414,8 @@ }, "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" @@ -5718,6 +6423,8 @@ }, "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==", "funding": [ { "type": "github", @@ -5736,6 +6443,8 @@ }, "node_modules/random-bytes": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -5743,6 +6452,8 @@ }, "node_modules/react": { "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -5752,7 +6463,9 @@ } }, "node_modules/react-day-picker": { - "version": "8.10.1", + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.2.tgz", + "integrity": "sha512-LK68OTbHB3oJNhl9cA0qVizzp3o26w61YSjAFkYi67N86iro32wx86kSNeFU/hq+gI8m1yzWhnomMLfZ041RzQ==", "license": "MIT", "funding": { "type": "individual", @@ -5760,11 +6473,13 @@ }, "peerDependencies": { "date-fns": "^2.28.0 || ^3.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/react-dnd": { "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd/-/react-dnd-16.0.1.tgz", + "integrity": "sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q==", "license": "MIT", "dependencies": { "@react-dnd/invariant": "^4.0.1", @@ -5793,6 +6508,8 @@ }, "node_modules/react-dnd-html5-backend": { "version": "16.0.1", + "resolved": "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz", + "integrity": "sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw==", "license": "MIT", "dependencies": { "dnd-core": "^16.0.1" @@ -5800,6 +6517,8 @@ }, "node_modules/react-dom": { "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", @@ -5810,7 +6529,9 @@ } }, "node_modules/react-hook-form": { - "version": "7.72.1", + "version": "7.76.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.76.0.tgz", + "integrity": "sha512-eKtLGgFeSgkHqQD8J59AMZ9a4uD1D83iSIzt4YlTGD7liDen5rrjcUO1rVIGd9yC1gofryjtHbv+4ny4hkLWlw==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -5825,6 +6546,8 @@ }, "node_modules/react-i18next": { "version": "16.6.6", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.6.6.tgz", + "integrity": "sha512-ZgL2HUoW34UKUkOV7uSQFE1CDnRPD+tCR3ywSuWH7u2iapnz86U8Bi3Vrs620qNDzCf1F47NxglCEkchCTDOHw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.29.2", @@ -5850,18 +6573,24 @@ }, "node_modules/react-icons": { "version": "5.6.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.6.0.tgz", + "integrity": "sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==", "license": "MIT", "peerDependencies": { "react": "*" } }, "node_modules/react-is": { - "version": "19.2.5", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.6.tgz", + "integrity": "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw==", "license": "MIT", "peer": true }, "node_modules/react-markdown": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5887,6 +6616,8 @@ }, "node_modules/react-refresh": { "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, "license": "MIT", "engines": { @@ -5895,6 +6626,8 @@ }, "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", @@ -5918,6 +6651,8 @@ }, "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", @@ -5938,6 +6673,8 @@ }, "node_modules/react-resizable-panels": { "version": "2.1.9", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.1.9.tgz", + "integrity": "sha512-z77+X08YDIrgAes4jl8xhnUu1LNIRp4+E7cv4xHmLOxxUPO/ML7PSrE813b90vj7xvQ1lcf7g2uA9GeMZonjhQ==", "license": "MIT", "peerDependencies": { "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", @@ -5945,7 +6682,9 @@ } }, "node_modules/react-router": { - "version": "7.14.0", + "version": "7.15.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.15.1.tgz", + "integrity": "sha512-R8rl9HhgikFYoPJymnUtPXWbnDb3oget6lQnfIoupbt61aT9aOhRkDsY2XRhZRyX1Z/8a5sL74fXmFNm3NRK5A==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -5965,10 +6704,12 @@ } }, "node_modules/react-router-dom": { - "version": "7.14.0", + "version": "7.15.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.15.1.tgz", + "integrity": "sha512-AzF62gjY6U9rkMq4RfP/r2EVtQ7DMfNMjyOp/flLTCrtRylLiK4wT4pSq6O8rOXZ2eXdZYJPEYe+ifomiv+Igg==", "license": "MIT", "dependencies": { - "react-router": "7.14.0" + "react-router": "7.15.1" }, "engines": { "node": ">=20.0.0" @@ -5980,6 +6721,8 @@ }, "node_modules/react-router/node_modules/cookie": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", "license": "MIT", "engines": { "node": ">=18" @@ -5991,6 +6734,8 @@ }, "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", @@ -6004,6 +6749,8 @@ }, "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", @@ -6024,6 +6771,8 @@ }, "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", @@ -6038,6 +6787,8 @@ }, "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==", "license": "MIT", "dependencies": { "pify": "^2.3.0" @@ -6045,6 +6796,8 @@ }, "node_modules/readdirp": { "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -6055,6 +6808,8 @@ }, "node_modules/recharts": { "version": "3.8.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.1.tgz", + "integrity": "sha512-mwzmO1s9sFL0TduUpwndxCUNoXsBw3u3E/0+A+cLcrSfQitSG62L32N69GhqUrrT5qKcAE3pCGVINC6pqkBBQg==", "license": "MIT", "workspaces": [ "www" @@ -6083,13 +6838,17 @@ }, "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/@reduxjs/toolkit": { - "version": "2.11.2", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz", + "integrity": "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", @@ -6113,7 +6872,9 @@ } }, "node_modules/recharts/node_modules/@reduxjs/toolkit/node_modules/immer": { - "version": "11.1.4", + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.8.tgz", + "integrity": "sha512-/tbkHMW7y10Lx6i1crLjD4/OhNkRG+Fo7byZHtah0547nIeXYcpIXaUh0IAQY6gO5459qpGGYapcEOHtFXkIuA==", "license": "MIT", "funding": { "type": "opencollective", @@ -6121,7 +6882,9 @@ } }, "node_modules/recharts/node_modules/react-redux": { - "version": "9.2.0", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz", + "integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==", "license": "MIT", "dependencies": { "@types/use-sync-external-store": "^0.0.6", @@ -6143,10 +6906,14 @@ }, "node_modules/recharts/node_modules/redux": { "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", "license": "MIT" }, "node_modules/recharts/node_modules/redux-thunk": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", "license": "MIT", "peerDependencies": { "redux": "^5.0.0" @@ -6154,6 +6921,8 @@ }, "node_modules/redux": { "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.9.2" @@ -6161,6 +6930,8 @@ }, "node_modules/regexparam": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-3.0.0.tgz", + "integrity": "sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==", "license": "MIT", "engines": { "node": ">=8" @@ -6168,6 +6939,8 @@ }, "node_modules/remark-parse": { "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -6182,6 +6955,8 @@ }, "node_modules/remark-rehype": { "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -6197,10 +6972,14 @@ }, "node_modules/reselect": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", "license": "MIT" }, "node_modules/resolve": { "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -6220,6 +6999,8 @@ }, "node_modules/reusify": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -6227,7 +7008,9 @@ } }, "node_modules/rollup": { - "version": "4.60.1", + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", + "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -6240,36 +7023,44 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.1", - "@rollup/rollup-android-arm64": "4.60.1", - "@rollup/rollup-darwin-arm64": "4.60.1", - "@rollup/rollup-darwin-x64": "4.60.1", - "@rollup/rollup-freebsd-arm64": "4.60.1", - "@rollup/rollup-freebsd-x64": "4.60.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", - "@rollup/rollup-linux-arm-musleabihf": "4.60.1", - "@rollup/rollup-linux-arm64-gnu": "4.60.1", - "@rollup/rollup-linux-arm64-musl": "4.60.1", - "@rollup/rollup-linux-loong64-gnu": "4.60.1", - "@rollup/rollup-linux-loong64-musl": "4.60.1", - "@rollup/rollup-linux-ppc64-gnu": "4.60.1", - "@rollup/rollup-linux-ppc64-musl": "4.60.1", - "@rollup/rollup-linux-riscv64-gnu": "4.60.1", - "@rollup/rollup-linux-riscv64-musl": "4.60.1", - "@rollup/rollup-linux-s390x-gnu": "4.60.1", - "@rollup/rollup-linux-x64-gnu": "4.60.1", - "@rollup/rollup-linux-x64-musl": "4.60.1", - "@rollup/rollup-openbsd-x64": "4.60.1", - "@rollup/rollup-openharmony-arm64": "4.60.1", - "@rollup/rollup-win32-arm64-msvc": "4.60.1", - "@rollup/rollup-win32-ia32-msvc": "4.60.1", - "@rollup/rollup-win32-x64-gnu": "4.60.1", - "@rollup/rollup-win32-x64-msvc": "4.60.1", + "@rollup/rollup-android-arm-eabi": "4.60.4", + "@rollup/rollup-android-arm64": "4.60.4", + "@rollup/rollup-darwin-arm64": "4.60.4", + "@rollup/rollup-darwin-x64": "4.60.4", + "@rollup/rollup-freebsd-arm64": "4.60.4", + "@rollup/rollup-freebsd-x64": "4.60.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", + "@rollup/rollup-linux-arm-musleabihf": "4.60.4", + "@rollup/rollup-linux-arm64-gnu": "4.60.4", + "@rollup/rollup-linux-arm64-musl": "4.60.4", + "@rollup/rollup-linux-loong64-gnu": "4.60.4", + "@rollup/rollup-linux-loong64-musl": "4.60.4", + "@rollup/rollup-linux-ppc64-gnu": "4.60.4", + "@rollup/rollup-linux-ppc64-musl": "4.60.4", + "@rollup/rollup-linux-riscv64-gnu": "4.60.4", + "@rollup/rollup-linux-riscv64-musl": "4.60.4", + "@rollup/rollup-linux-s390x-gnu": "4.60.4", + "@rollup/rollup-linux-x64-gnu": "4.60.4", + "@rollup/rollup-linux-x64-musl": "4.60.4", + "@rollup/rollup-openbsd-x64": "4.60.4", + "@rollup/rollup-openharmony-arm64": "4.60.4", + "@rollup/rollup-win32-arm64-msvc": "4.60.4", + "@rollup/rollup-win32-ia32-msvc": "4.60.4", + "@rollup/rollup-win32-x64-gnu": "4.60.4", + "@rollup/rollup-win32-x64-msvc": "4.60.4", "fsevents": "~2.3.2" } }, + "node_modules/rollup/node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, "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==", "funding": [ { "type": "github", @@ -6291,6 +7082,8 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -6309,6 +7102,8 @@ }, "node_modules/scheduler": { "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -6316,6 +7111,8 @@ }, "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": { @@ -6324,14 +7121,20 @@ }, "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/sift": { "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", "license": "MIT" }, "node_modules/slugify": { "version": "1.6.9", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz", + "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==", "license": "MIT", "engines": { "node": ">=8.0.0" @@ -6339,6 +7142,8 @@ }, "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" @@ -6346,6 +7151,8 @@ }, "node_modules/space-separated-tokens": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "license": "MIT", "funding": { "type": "github", @@ -6354,6 +7161,8 @@ }, "node_modules/sparse-bitfield": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "license": "MIT", "dependencies": { "memory-pager": "^1.0.2" @@ -6361,6 +7170,8 @@ }, "node_modules/stringify-entities": { "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "license": "MIT", "dependencies": { "character-entities-html4": "^2.0.0", @@ -6373,6 +7184,8 @@ }, "node_modules/style-to-js": { "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", "license": "MIT", "dependencies": { "style-to-object": "1.0.14" @@ -6380,6 +7193,8 @@ }, "node_modules/style-to-object": { "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", "license": "MIT", "dependencies": { "inline-style-parser": "0.2.7" @@ -6387,6 +7202,8 @@ }, "node_modules/sucrase": { "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", @@ -6407,6 +7224,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==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -6417,6 +7236,8 @@ }, "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", @@ -6425,6 +7246,8 @@ }, "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==", "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -6460,6 +7283,8 @@ }, "node_modules/tailwindcss-animate": { "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", "license": "MIT", "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" @@ -6467,6 +7292,8 @@ }, "node_modules/tailwindcss/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==", "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -6474,6 +7301,8 @@ }, "node_modules/tailwindcss/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==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -6484,7 +7313,9 @@ } }, "node_modules/tapable": { - "version": "2.3.2", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "license": "MIT", "engines": { "node": ">=6" @@ -6496,6 +7327,8 @@ }, "node_modules/thenify": { "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "license": "MIT", "dependencies": { "any-promise": "^1.0.0" @@ -6503,6 +7336,8 @@ }, "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==", "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" @@ -6513,14 +7348,20 @@ }, "node_modules/three": { "version": "0.170.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.170.0.tgz", + "integrity": "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==", "license": "MIT" }, "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==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -6535,6 +7376,8 @@ }, "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==", "license": "MIT", "engines": { "node": ">=12.0.0" @@ -6550,6 +7393,8 @@ }, "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==", "license": "MIT", "engines": { "node": ">=12" @@ -6560,6 +7405,8 @@ }, "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==", "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -6570,6 +7417,8 @@ }, "node_modules/tr46": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", "license": "MIT", "dependencies": { "punycode": "^2.3.1" @@ -6580,6 +7429,8 @@ }, "node_modules/trim-lines": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", "license": "MIT", "funding": { "type": "github", @@ -6588,6 +7439,8 @@ }, "node_modules/trough": { "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", "license": "MIT", "funding": { "type": "github", @@ -6596,14 +7449,20 @@ }, "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==", "license": "Apache-2.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/tw-animate-css": { "version": "1.4.0", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", + "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/Wombosvideo" @@ -6611,6 +7470,8 @@ }, "node_modules/typescript": { "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -6623,6 +7484,8 @@ }, "node_modules/uid-safe": { "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", "license": "MIT", "dependencies": { "random-bytes": "~1.0.0" @@ -6633,11 +7496,15 @@ }, "node_modules/undici-types": { "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "devOptional": true, "license": "MIT" }, "node_modules/unified": { "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -6655,6 +7522,8 @@ }, "node_modules/unist-util-is": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -6666,6 +7535,8 @@ }, "node_modules/unist-util-position": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -6677,6 +7548,8 @@ }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -6688,6 +7561,8 @@ }, "node_modules/unist-util-visit": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -6701,6 +7576,8 @@ }, "node_modules/unist-util-visit-parents": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -6713,6 +7590,8 @@ }, "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": [ { @@ -6742,6 +7621,8 @@ }, "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" @@ -6761,6 +7642,8 @@ }, "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", @@ -6781,6 +7664,8 @@ }, "node_modules/use-sync-external-store": { "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -6788,10 +7673,14 @@ }, "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==", "license": "MIT" }, "node_modules/uuid": { - "version": "11.1.0", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -6803,6 +7692,8 @@ }, "node_modules/vaul": { "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.2.tgz", + "integrity": "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==", "license": "MIT", "dependencies": { "@radix-ui/react-dialog": "^1.1.1" @@ -6814,6 +7705,8 @@ }, "node_modules/vfile": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -6826,6 +7719,8 @@ }, "node_modules/vfile-message": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -6838,6 +7733,8 @@ }, "node_modules/victory-vendor": { "version": "37.3.6", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", + "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", "license": "MIT AND ISC", "dependencies": { "@types/d3-array": "^3.0.3", @@ -6858,6 +7755,8 @@ }, "node_modules/vite": { "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "license": "MIT", "dependencies": { "esbuild": "^0.21.3", @@ -6915,6 +7814,8 @@ }, "node_modules/void-elements": { "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6922,6 +7823,8 @@ }, "node_modules/webidl-conversions": { "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -6929,6 +7832,8 @@ }, "node_modules/whatwg-url": { "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", "license": "MIT", "dependencies": { "tr46": "^5.1.0", @@ -6939,7 +7844,9 @@ } }, "node_modules/wouter": { - "version": "3.9.0", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/wouter/-/wouter-3.10.0.tgz", + "integrity": "sha512-zTfddD80zc2/J5l8JKcdvzOK6AwP0kpyHEI3DxRN2bn8U1oJPnrSVm8v+X3WwDamvLAOxTO7ZvkxkpRWlyeJ1Q==", "license": "Unlicense", "dependencies": { "mitt": "^3.0.1", @@ -6952,11 +7859,15 @@ }, "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/zod": { "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -6964,6 +7875,8 @@ }, "node_modules/zod-validation-error": { "version": "3.5.4", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.5.4.tgz", + "integrity": "sha512-+hEiRIiPobgyuFlEojnqjJnhFvg4r/i3cqgcm67eehZf/WBaK3g6cD02YU9mtdVxZjv8CzCA9n/Rhrs3yAAvAw==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -6974,6 +7887,8 @@ }, "node_modules/zwitch": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", "license": "MIT", "funding": { "type": "github", From b3b869821363f614e74392690579be60acced7a9 Mon Sep 17 00:00:00 2001 From: byteful Date: Tue, 26 May 2026 20:40:09 -0500 Subject: [PATCH 08/30] performance fixes --- .env.example | 3 + client/index.html | 5 +- client/src/App.tsx | 2 +- client/src/components/ArticleMediaUpload.tsx | 57 +- client/src/components/EvidenceUpload.tsx | 55 +- client/src/components/TicketAttachments.tsx | 122 +++- .../AssignedTicketUpdatesSection.tsx | 20 +- .../dashboard/RecentTicketsSection.tsx | 39 +- .../dashboard/TicketSubscriptionsSection.tsx | 21 +- .../knowledgebase/CategoryDisplay.tsx | 8 +- .../src/components/layout/ResizableWindow.tsx | 65 +- client/src/components/layout/Sidebar.tsx | 136 ++-- .../components/settings/BillingSettings.tsx | 23 +- .../components/settings/DomainSettings.tsx | 55 +- .../components/settings/GeneralSettings.tsx | 75 +- .../settings/HomepageCardSettings.tsx | 78 ++- .../components/settings/InviteStaffModal.tsx | 2 +- .../settings/KnowledgebaseSettings.tsx | 4 +- .../src/components/settings/MigrationTool.tsx | 26 +- .../components/settings/PasskeySettings.tsx | 2 +- .../components/settings/StaffRolesCard.tsx | 36 +- .../components/settings/TicketSettings.tsx | 9 +- .../src/components/settings/UsageSettings.tsx | 79 +-- client/src/components/ui/clickable-player.tsx | 2 +- client/src/components/ui/empty-state.tsx | 21 + .../src/components/ui/markdown-renderer.tsx | 24 +- client/src/components/ui/notice.tsx | 38 + client/src/components/ui/page-title.tsx | 14 + client/src/components/ui/status-badge.tsx | 29 + client/src/contexts/DashboardContext.tsx | 20 +- client/src/contexts/PlayerWindowContext.tsx | 46 +- client/src/hooks/use-auth.tsx | 79 ++- client/src/hooks/use-data.tsx | 36 +- client/src/hooks/use-permissions.tsx | 12 +- client/src/hooks/use-player-lookup.tsx | 21 +- client/src/hooks/use-public-settings.tsx | 1 - client/src/hooks/use-realtime.tsx | 3 + client/src/hooks/use-sidebar.tsx | 12 +- client/src/lib/queryClient.ts | 3 +- client/src/locales/de.json | 6 - client/src/locales/en.json | 6 - client/src/locales/es.json | 6 - client/src/locales/nl.json | 6 - client/src/pages/HomePage.tsx | 42 +- client/src/pages/RateLimitPage.tsx | 33 +- client/src/pages/api-docs.tsx | 11 +- client/src/pages/audit.tsx | 354 ++++++---- client/src/pages/lookup-page.tsx | 7 + client/src/pages/player-ticket.tsx | 82 +-- client/src/pages/settings.tsx | 2 +- client/src/pages/submit-ticket.tsx | 51 +- client/src/pages/ticket-detail.tsx | 69 +- client/src/pages/tickets.tsx | 662 +++++++++++------- tsconfig.json | 1 + vite.config.ts | 35 +- 55 files changed, 1593 insertions(+), 1063 deletions(-) create mode 100644 client/src/components/ui/empty-state.tsx create mode 100644 client/src/components/ui/notice.tsx create mode 100644 client/src/components/ui/page-title.tsx create mode 100644 client/src/components/ui/status-badge.tsx diff --git a/.env.example b/.env.example index 18437ed..0c50a2c 100644 --- a/.env.example +++ b/.env.example @@ -6,3 +6,6 @@ VITE_API_BASE_URL=https://api.modl.gg # Stripe (public key only - safe to expose) VITE_STRIPE_PUBLISHABLE_KEY=pk_live_xxx + +# Enables the realtime WebSocket client (defaults off until backend publishers ship). +VITE_REALTIME_ENABLED=false diff --git a/client/index.html b/client/index.html index 0431adb..8363223 100644 --- a/client/index.html +++ b/client/index.html @@ -3,12 +3,13 @@ - Loading... + modl - + +
diff --git a/client/src/App.tsx b/client/src/App.tsx index dde434d..21870fa 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -217,7 +217,7 @@ function AppContent() { if (!hasSeenModal && isOnPanelHomePage && !isFromProvisioning && !isOnExcludedPage && !isOnPlayerTicketPage && !isOnAcceptInvitationPage && user?.role === 'Super Admin') { setWelcomeModalOpen(true); } - }, [location, user]); + }, [location, user?.role]); const handleCloseWelcomeModal = () => { localStorage.setItem("hasSeenWelcomeModal", "true"); diff --git a/client/src/components/ArticleMediaUpload.tsx b/client/src/components/ArticleMediaUpload.tsx index 557b7e2..0eaa4ef 100644 --- a/client/src/components/ArticleMediaUpload.tsx +++ b/client/src/components/ArticleMediaUpload.tsx @@ -1,11 +1,12 @@ import React, { useState } from 'react'; -import { Image as ImageIcon, Upload, Copy, Check, Trash2 } from 'lucide-react'; +import { Image as ImageIcon, Upload, Copy, Check, Trash2, Loader2 } from 'lucide-react'; import { Button } from '@modl-gg/shared-web/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@modl-gg/shared-web/components/ui/card'; import { Badge } from '@modl-gg/shared-web/components/ui/badge'; import { useToast } from '@modl-gg/shared-web/hooks/use-toast'; import { Input } from '@modl-gg/shared-web/components/ui/input'; import { Label } from '@modl-gg/shared-web/components/ui/label'; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@modl-gg/shared-web/components/ui/alert-dialog'; import MediaUpload from './MediaUpload'; import { useMediaUpload } from '@/hooks/use-media-upload'; import { formatFileSize } from '@/utils/file-utils'; @@ -42,6 +43,7 @@ export function ArticleMediaUpload({ const { t } = useTranslation(); const [media, setMedia] = useState(existingMedia); const [copiedUrl, setCopiedUrl] = useState(null); + const [deletingIds, setDeletingIds] = useState>(new Set()); const { config, deleteMedia } = useMediaUpload(); const { toast } = useToast(); @@ -71,6 +73,11 @@ export function ArticleMediaUpload({ }; const handleDeleteMedia = async (mediaItem: ArticleMedia) => { + setDeletingIds(prev => { + const next = new Set(prev); + next.add(mediaItem.id); + return next; + }); try { await deleteMedia(mediaItem.key); const updatedMedia = media.filter(m => m.id !== mediaItem.id); @@ -87,6 +94,12 @@ export function ArticleMediaUpload({ description: t('upload.deleteMediaFailed'), variant: "destructive", }); + } finally { + setDeletingIds(prev => { + const next = new Set(prev); + next.delete(mediaItem.id); + return next; + }); } }; @@ -200,14 +213,40 @@ export function ArticleMediaUpload({ )} {!readonly && ( - + + + + + + + {t('upload.deleteMediaTitle', 'Delete media?')} + + {t('upload.deleteMediaConfirm', { name: item.fileName, defaultValue: 'This will permanently remove "{{name}}". Articles referencing this media will show a broken image.' })} + + + + {t('common.cancel')} + handleDeleteMedia(item)} + className="bg-destructive text-destructive-foreground hover:bg-destructive/90" + > + {t('common.delete')} + + + + )}
diff --git a/client/src/components/EvidenceUpload.tsx b/client/src/components/EvidenceUpload.tsx index f818d15..d6ede1d 100644 --- a/client/src/components/EvidenceUpload.tsx +++ b/client/src/components/EvidenceUpload.tsx @@ -1,8 +1,9 @@ import React, { useState } from 'react'; -import { Shield, FileText, Image, Video, Eye, Trash2 } from 'lucide-react'; +import { Shield, FileText, Image, Video, Eye, Trash2, Loader2 } from 'lucide-react'; import { Button } from '@modl-gg/shared-web/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@modl-gg/shared-web/components/ui/card'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@modl-gg/shared-web/components/ui/dialog'; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@modl-gg/shared-web/components/ui/alert-dialog'; import { Badge } from '@modl-gg/shared-web/components/ui/badge'; import { useToast } from '@modl-gg/shared-web/hooks/use-toast'; import MediaUpload from './MediaUpload'; @@ -41,6 +42,7 @@ export function EvidenceUpload({ }: EvidenceUploadProps) { const { t } = useTranslation(); const [evidence, setEvidence] = useState(existingEvidence); + const [deletingIds, setDeletingIds] = useState>(new Set()); const { deleteMedia } = useMediaUpload(); const { toast } = useToast(); @@ -71,6 +73,11 @@ export function EvidenceUpload({ }; const handleDeleteEvidence = async (evidenceItem: EvidenceItem) => { + setDeletingIds(prev => { + const next = new Set(prev); + next.add(evidenceItem.id); + return next; + }); try { await deleteMedia(evidenceItem.key); const updatedEvidence = evidence.filter(e => e.id !== evidenceItem.id); @@ -87,6 +94,12 @@ export function EvidenceUpload({ description: t('upload.deleteEvidenceFailed'), variant: "destructive", }); + } finally { + setDeletingIds(prev => { + const next = new Set(prev); + next.delete(evidenceItem.id); + return next; + }); } }; @@ -184,13 +197,39 @@ export function EvidenceUpload({ {!readonly && ( - + + + + + + + {t('upload.deleteEvidenceTitle', 'Delete evidence?')} + + {t('upload.deleteEvidenceConfirm', { name: item.fileName, defaultValue: 'This will permanently remove "{{name}}". This action cannot be undone.' })} + + + + {t('common.cancel')} + handleDeleteEvidence(item)} + className="bg-destructive text-destructive-foreground hover:bg-destructive/90" + > + {t('common.delete')} + + + + )} diff --git a/client/src/components/TicketAttachments.tsx b/client/src/components/TicketAttachments.tsx index bb2b79c..3c993dc 100644 --- a/client/src/components/TicketAttachments.tsx +++ b/client/src/components/TicketAttachments.tsx @@ -1,9 +1,10 @@ import React, { useState } from 'react'; -import { Paperclip, Download, Eye, Trash2, FileText, Image, Video, File } from 'lucide-react'; +import { Paperclip, Download, Eye, Trash2, FileText, Image, Video, File, Loader2 } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { Button } from '@modl-gg/shared-web/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@modl-gg/shared-web/components/ui/card'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@modl-gg/shared-web/components/ui/dialog'; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@modl-gg/shared-web/components/ui/alert-dialog'; import { Badge } from '@modl-gg/shared-web/components/ui/badge'; import { useToast } from '@modl-gg/shared-web/hooks/use-toast'; import MediaUpload from './MediaUpload'; @@ -43,6 +44,7 @@ export function TicketAttachments({ }: TicketAttachmentsProps & { compact?: boolean }) { const { t } = useTranslation(); const [attachments, setAttachments] = useState(existingAttachments); + const [deletingIds, setDeletingIds] = useState>(new Set()); const { config, deleteMedia } = useMediaUpload(); const { toast } = useToast(); @@ -85,6 +87,11 @@ export function TicketAttachments({ return; } + setDeletingIds(prev => { + const next = new Set(prev); + next.add(attachment.id); + return next; + }); try { await deleteMedia(attachment.key); const updatedAttachments = attachments.filter(a => a.id !== attachment.id); @@ -101,6 +108,12 @@ export function TicketAttachments({ description: t('upload.deleteAttachmentFailed'), variant: "destructive", }); + } finally { + setDeletingIds(prev => { + const next = new Set(prev); + next.delete(attachment.id); + return next; + }); } }; @@ -181,13 +194,52 @@ export function TicketAttachments({ {getFileIcon(attachment.fileType)} {truncatedName} {!readonly && ( - + publicMode ? ( + + ) : ( + + + + + + + {t('upload.deleteAttachmentTitle', 'Delete attachment?')} + + {t('upload.deleteAttachmentConfirm', { name: attachment.fileName, defaultValue: 'This will permanently remove "{{name}}". This action cannot be undone.' })} + + + + {t('common.cancel')} + handleDeleteAttachment(attachment)} + className="bg-destructive text-destructive-foreground hover:bg-destructive/90" + > + {t('common.delete')} + + + + + ) )} ); @@ -265,14 +317,52 @@ export function TicketAttachments({ {!readonly && ( - + publicMode ? ( + + ) : ( + + + + + + + {t('upload.deleteAttachmentTitle', 'Delete attachment?')} + + {t('upload.deleteAttachmentConfirm', { name: attachment.fileName, defaultValue: 'This will permanently remove "{{name}}". This action cannot be undone.' })} + + + + {t('common.cancel')} + handleDeleteAttachment(attachment)} + className="bg-destructive text-destructive-foreground hover:bg-destructive/90" + > + {t('common.delete')} + + + + + ) )} diff --git a/client/src/components/dashboard/AssignedTicketUpdatesSection.tsx b/client/src/components/dashboard/AssignedTicketUpdatesSection.tsx index 5c7400a..47dc3f3 100644 --- a/client/src/components/dashboard/AssignedTicketUpdatesSection.tsx +++ b/client/src/components/dashboard/AssignedTicketUpdatesSection.tsx @@ -7,6 +7,7 @@ import { useLocation } from 'wouter'; import { formatTimeAgo } from '@/utils/date-utils'; import { stripMarkdown } from '@/utils/markdown-utils'; import { useTranslation } from 'react-i18next'; +import { StatusBadge } from '@/components/ui/status-badge'; const INITIAL_VISIBLE = 2; const LOAD_MORE_COUNT = 2; @@ -113,7 +114,7 @@ export function AssignedTicketUpdatesSection({ {updates.slice(0, visibleCount).map((update) => (
handleTicketClick(update.ticketId)} >
@@ -121,26 +122,23 @@ export function AssignedTicketUpdatesSection({ {update.ticketTitle}
-
-
+ {update.isStaffReply ? t('dashboard.assignedTickets.staff') : t('dashboard.assignedTickets.player')} - + diff --git a/client/src/components/dashboard/RecentTicketsSection.tsx b/client/src/components/dashboard/RecentTicketsSection.tsx index c6bc689..7b1a81f 100644 --- a/client/src/components/dashboard/RecentTicketsSection.tsx +++ b/client/src/components/dashboard/RecentTicketsSection.tsx @@ -5,6 +5,23 @@ import { useLocation } from 'wouter'; import { formatTimeAgo } from '@/utils/date-utils'; import { stripMarkdown } from '@/utils/markdown-utils'; import { useTranslation } from 'react-i18next'; +import { StatusBadge } from '@/components/ui/status-badge'; + +type Intent = 'info' | 'success' | 'warning' | 'destructive' | 'neutral'; + +const statusIntents: Record = { + open: 'info', + closed: 'success', + unfinished: 'neutral', +}; + +const priorityIntents: Record = { + low: 'neutral', + normal: 'info', + medium: 'info', + high: 'warning', + urgent: 'destructive', +}; export interface RecentTicket { id: string; @@ -22,20 +39,6 @@ interface RecentTicketsSectionProps { loading: boolean; } -const statusColors: Record = { - open: 'bg-blue-500/20 text-blue-500', - closed: 'bg-green-500/20 text-green-500', - unfinished: 'bg-gray-500/20 text-gray-500' -}; - -const priorityColors: Record = { - low: 'bg-gray-500/20 text-gray-500', - normal: 'bg-blue-500/20 text-blue-500', - medium: 'bg-blue-500/20 text-blue-500', - high: 'bg-orange-500/20 text-orange-500', - urgent: 'bg-red-500/20 text-red-500' -}; - export function RecentTicketsSection({ tickets, loading }: RecentTicketsSectionProps) { const { t } = useTranslation(); const [, setLocation] = useLocation(); @@ -102,14 +105,14 @@ export function RecentTicketsSection({ tickets, loading }: RecentTicketsSectionP

{ticket.title}

{ticket.priority && ( - + {ticket.priority.toUpperCase()} - + )} {ticket.status && ( - + {ticket.status.replace('_', ' ').toUpperCase()} - + )}
diff --git a/client/src/components/dashboard/TicketSubscriptionsSection.tsx b/client/src/components/dashboard/TicketSubscriptionsSection.tsx index b29c791..7aeb9e8 100644 --- a/client/src/components/dashboard/TicketSubscriptionsSection.tsx +++ b/client/src/components/dashboard/TicketSubscriptionsSection.tsx @@ -6,6 +6,7 @@ import { useLocation } from 'wouter'; import { useToast } from '@modl-gg/shared-web/hooks/use-toast'; import { formatTimeAgo } from '@/utils/date-utils'; import { useTranslation } from 'react-i18next'; +import { StatusBadge } from '@/components/ui/status-badge'; export interface TicketSubscriptionUpdate { id: string; @@ -128,7 +129,7 @@ export function TicketSubscriptionsSection({ updates.slice(0, 5).map((update) => (
{ handleTicketClick(update.ticketId); }} @@ -138,26 +139,23 @@ export function TicketSubscriptionsSection({ {update.ticketTitle}
-
-
+ {update.isStaffReply ? t('dashboard.subscriptions.staff') : t('dashboard.subscriptions.player')} - + @@ -170,6 +168,7 @@ export function TicketSubscriptionsSection({ handleUnsubscribe(update.ticketId, update.ticketTitle); }} title="Unsubscribe" + aria-label="Unsubscribe" > diff --git a/client/src/components/knowledgebase/CategoryDisplay.tsx b/client/src/components/knowledgebase/CategoryDisplay.tsx index e4b576b..2911b34 100644 --- a/client/src/components/knowledgebase/CategoryDisplay.tsx +++ b/client/src/components/knowledgebase/CategoryDisplay.tsx @@ -18,20 +18,20 @@ interface CategoryDisplayProps { const CategoryDisplay: React.FC = ({ name, description, articles, slug }) => { return (
-

{name}

- {description &&

{description}

} +

{name}

+ {description &&

{description}

} {articles && articles.length > 0 ? (
    {articles.map(article => (
  • - + {article.title}
  • ))}
) : ( -

No articles in this category yet.

+

No articles in this category yet.

)}
); diff --git a/client/src/components/layout/ResizableWindow.tsx b/client/src/components/layout/ResizableWindow.tsx index 51802f7..788dbde 100644 --- a/client/src/components/layout/ResizableWindow.tsx +++ b/client/src/components/layout/ResizableWindow.tsx @@ -38,9 +38,12 @@ const ResizableWindow = ({ const windowRef = useRef(null); const headerRef = useRef(null); const minimizedHeaderRef = useRef(null); + const initialPositionRef = useRef(initialPosition); const [isDragging, setIsDragging] = useState(false); const [position, setPosition] = useState(initialPosition); const [size, setSize] = useState(initialSize); + const positionRef = useRef(position); + const sizeRef = useRef(size); const [isMaximized, setIsMaximized] = useState(false); const [isMinimized, setIsMinimized] = useState(false); const [dragStart, setDragStart] = useState({ x: 0, y: 0 }); @@ -51,62 +54,72 @@ const ResizableWindow = ({ }>({ position: initialPosition, size: initialSize }); const [isInitialized, setIsInitialized] = useState(false); + useEffect(() => { + positionRef.current = position; + }, [position]); + + useEffect(() => { + sizeRef.current = size; + }, [size]); + // Initialize position once useEffect(() => { if (!isOpen || !windowRef.current || isInitialized) return; - -// Use the global last known window configuration for player windows + + const initial = initialPositionRef.current; + + // Use the global last known window configuration for player windows if (id.startsWith('player-')) { - // Apply the size from the last window + // Apply the size from the last window setSize(lastPlayerWindowConfig.size); - + // Stagger the position slightly for multiple windows const offset = 20; const totalOpen = document.querySelectorAll('.resizable-window').length - 1; - - if (typeof lastPlayerWindowConfig.position.x === 'number' && + + if (typeof lastPlayerWindowConfig.position.x === 'number' && typeof lastPlayerWindowConfig.position.y === 'number') { - setPosition({ + setPosition({ x: lastPlayerWindowConfig.position.x + (offset * totalOpen), y: lastPlayerWindowConfig.position.y + (offset * totalOpen) }); } else { setPosition(lastPlayerWindowConfig.position); } - + setIsInitialized(true); } // Center the window if initial position is percentage based - if (typeof initialPosition.x === 'string' && initialPosition.x.includes('%')) { + if (typeof initial.x === 'string' && initial.x.includes('%')) { const windowWidth = windowRef.current.offsetWidth; const windowHeight = windowRef.current.offsetHeight; const viewportWidth = window.innerWidth; const viewportHeight = window.innerHeight; - + // Safe parsing of percentage values let xPercent = 0.5; // Default to 50% let yPercent = 0.5; // Default to 50% - - if (typeof initialPosition.x === 'string') { - const parsedX = parseFloat(initialPosition.x); + + if (typeof initial.x === 'string') { + const parsedX = parseFloat(initial.x); if (!isNaN(parsedX)) { xPercent = parsedX / 100; } } - - if (typeof initialPosition.y === 'string') { - const parsedY = parseFloat(initialPosition.y); + + if (typeof initial.y === 'string') { + const parsedY = parseFloat(initial.y); if (!isNaN(parsedY)) { yPercent = parsedY / 100; } } - + const xPos = viewportWidth * xPercent - windowWidth * xPercent; const yPos = viewportHeight * yPercent - windowHeight * yPercent; - + setPosition({ x: xPos, y: yPos }); setIsInitialized(true); - + // Store this as the last known configuration if it's a player window if (id.startsWith('player-')) { // Update the global config @@ -114,7 +127,7 @@ const ResizableWindow = ({ lastPlayerWindowConfig.position = { x: xPos, y: yPos }; } } - }, [isOpen, initialPosition, isInitialized, id]); + }, [isOpen, isInitialized, id]); // Handle dragging useEffect(() => { @@ -138,14 +151,14 @@ const ResizableWindow = ({ const handleMouseUp = () => { setIsDragging(false); - + // Save position for new windows if (id.startsWith('player-')) { - // Update the global window state - lastPlayerWindowConfig.size = size; + // Update the global window state using freshest values via refs + lastPlayerWindowConfig.size = sizeRef.current; lastPlayerWindowConfig.position = { - x: typeof position.x === 'number' ? position.x : 0, - y: typeof position.y === 'number' ? position.y : 0 + x: typeof positionRef.current.x === 'number' ? positionRef.current.x : 0, + y: typeof positionRef.current.y === 'number' ? positionRef.current.y : 0 }; } }; @@ -159,7 +172,7 @@ const ResizableWindow = ({ document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); }; - }, [isDragging, dragStart]); + }, [isDragging, dragStart, id]); const handleMouseDown = (e: React.MouseEvent) => { if (!windowRef.current) return; diff --git a/client/src/components/layout/Sidebar.tsx b/client/src/components/layout/Sidebar.tsx index c4e9d6e..03f6717 100644 --- a/client/src/components/layout/Sidebar.tsx +++ b/client/src/components/layout/Sidebar.tsx @@ -1,7 +1,7 @@ import { useLocation } from "wouter"; import { cn } from "@/lib/utils"; import { useSidebar } from "@/hooks/use-sidebar"; -import { useState, useEffect, useRef } from "react"; +import { useState, useEffect, useMemo, useRef } from "react"; import { useTranslation } from "react-i18next"; import { Home, @@ -19,31 +19,46 @@ import { import { Button } from "@modl-gg/shared-web/components/ui/button"; import { Input } from "@modl-gg/shared-web/components/ui/input"; import { useDashboard } from "@/contexts/DashboardContext"; -import PlayerWindow from "../../components/windows/PlayerWindow"; +import { usePlayerWindow } from "@/contexts/PlayerWindowContext"; import serverLogo from "../../assets/server-logo.png"; import { usePublicSettings } from "@/hooks/use-public-settings"; import { usePunishmentLookup } from "@/hooks/use-player-lookup"; import { usePermissions, PERMISSIONS } from "@/hooks/use-permissions"; import { useAuth } from "@/hooks/use-auth"; import { usePlayerSearch } from "@/hooks/use-data"; -import { useQuery } from '@tanstack/react-query'; +import { useIsFetching } from '@tanstack/react-query'; import { queryClient } from "@/lib/queryClient"; import { apiFetch } from "@/lib/api"; +interface Player { + uuid?: string; + minecraftUuid?: string; + username?: string; + status?: string; + lastOnline?: string; + isOnline?: boolean; + online?: boolean; + data?: any; +} + +const HOME_ICON = ; +const SEARCH_ICON = ; +const TICKET_ICON = ; +const AUDIT_ICON = ; +const SETTINGS_ICON = ; + const Sidebar = () => { const { t } = useTranslation(); const { isSearchActive, setIsSearchActive } = useSidebar(); const { openLookupWindow: openDashboardLookupWindow } = useDashboard(); + const { openPlayerWindow: openPlayerWindowFromContext } = usePlayerWindow(); const [location, navigate] = useLocation(); const { data: publicSettings } = usePublicSettings(); const { hasPermission } = usePermissions(); const { user } = useAuth(); - - // Check if permissions are still loading from server - const { isLoading: permissionsLoading } = useQuery({ - queryKey: ['userPermissions', user?.role], - enabled: false, // We just want the loading state - }); + + const fetchingCount = useIsFetching({ queryKey: ['userPermissions', user?.role] }); + const permissionsLoading = fetchingCount > 0; const [isLookupOpen, setIsLookupOpen] = useState(false); const [isLookupClosing, setIsLookupClosing] = useState(false); const [searchQuery, setSearchQuery] = useState(""); @@ -85,52 +100,34 @@ const Sidebar = () => { // Function to handle player selection and update recent searches const handlePlayerSelect = (player: Player) => { const uuid = getPlayerUuid(player); - + if (!uuid) return; // Guard against empty UUID - + // Update recent searches const timestamp = Date.now(); const existing = recentSearches.filter(s => getPlayerUuid(s.player) !== uuid); const newSearches = [{player, timestamp}, ...existing].slice(0, 10); setRecentSearches(newSearches); - + // Save to localStorage localStorage.setItem('recentPlayerSearches', JSON.stringify(newSearches)); - + // Open player window and close lookup const url = new URL(window.location.href); url.searchParams.set("player", uuid); window.history.pushState({}, "", url.toString()); - openPlayerWindow(uuid); + openPlayerWindow(uuid, player.username); closeLookup(); }; - // Track multiple windows with a map of id -> isOpen state - const [playerWindows, setPlayerWindows] = useState>( - {}, - ); const closeTimeoutRef = useRef(null); // Function to open player window when clicked from search - const openPlayerWindow = (playerId: string) => { - // Add this window to our tracked windows - setPlayerWindows((prev) => ({ - ...prev, - [playerId]: true, // Set this player's window to open - })); + const openPlayerWindow = (playerId: string, username?: string) => { + openPlayerWindowFromContext(playerId, username); openDashboardLookupWindow(); // Also open at dashboard level for tracking }; - // Function to close a specific player window - const closePlayerWindow = (playerId: string) => { - setPlayerWindows((prev) => { - // Create a new object excluding this player - const newWindows = { ...prev }; - delete newWindows[playerId]; - return newWindows; - }); - }; - const openLookup = () => { if (!isLookupOpen && !isLookupClosing) { setIsLookupOpen(true); @@ -191,14 +188,10 @@ const Sidebar = () => { const playerIdFromUrl = url.searchParams.get("player"); if (playerIdFromUrl) { - // Open this player's window - setPlayerWindows((prev) => ({ - ...prev, - [playerIdFromUrl]: true, - })); + openPlayerWindowFromContext(playerIdFromUrl); openDashboardLookupWindow(); } - }, [openDashboardLookupWindow]); + }, [openDashboardLookupWindow, openPlayerWindowFromContext]); // Clean up any timeouts when component unmounts useEffect(() => { @@ -246,11 +239,11 @@ const Sidebar = () => { } }; - const allNavItems = [ + const allNavItems = useMemo(() => [ { name: t('nav.home'), path: "/panel", - icon: , + icon: HOME_ICON, onClick: () => { if (isLookupOpen) closeLookup(); navigate("/panel"); @@ -259,7 +252,7 @@ const Sidebar = () => { { name: t('nav.lookup'), path: "/panel/lookup", - icon: , + icon: SEARCH_ICON, onClick: () => { if (isLookupOpen) { closeLookup(); @@ -271,7 +264,7 @@ const Sidebar = () => { { name: t('nav.tickets'), path: "/panel/tickets", - icon: , + icon: TICKET_ICON, onClick: () => { if (isLookupOpen) closeLookup(); navigate("/panel/tickets"); @@ -280,7 +273,7 @@ const Sidebar = () => { { name: t('nav.audit'), path: "/panel/audit", - icon: , + icon: AUDIT_ICON, permission: PERMISSIONS.ADMIN_AUDIT_VIEW, onClick: () => { if (isLookupOpen) closeLookup(); @@ -290,13 +283,13 @@ const Sidebar = () => { { name: t('nav.settings'), path: "/panel/settings", - icon: , + icon: SETTINGS_ICON, onClick: () => { if (isLookupOpen) closeLookup(); navigate("/panel/settings"); }, }, - ]; + ], [t, isLookupOpen, navigate]); // Filter nav items based on permissions // Don't show permission-based items while permissions are loading to prevent flash @@ -309,17 +302,6 @@ const Sidebar = () => { // Calculate sidebar height dynamically (navItems * 56px + top/bottom padding of 32px) const sidebarHeight = Math.max(200, navItems.length * 56 + 16); - interface Player { - uuid?: string; - minecraftUuid?: string; - username?: string; - status?: string; - lastOnline?: string; - isOnline?: boolean; - online?: boolean; - data?: any; - } - const isPlayerOnline = (player: Player) => { if (player.status === 'Online') return true; if (player.isOnline !== undefined) return player.isOnline; @@ -559,9 +541,9 @@ const Sidebar = () => {
{t('search.playersFound')}
- {filteredLookups.map((player: Player, index: number) => ( + {filteredLookups.map((player: Player) => (
)} - {/* Render multiple player windows with offset positioning */} - {Object.entries(playerWindows).map(([playerId, isOpen], index) => ( - { - // Close this specific window - closePlayerWindow(playerId); - - // Update URL parameters - we keep other players in the URL - const url = new URL(window.location.href); - url.searchParams.delete("player"); - - // If we have other windows open, add the first one to the URL - const remainingPlayers = Object.keys(playerWindows).filter( - (id) => id !== playerId, - ); - if (remainingPlayers.length > 0) { - url.searchParams.set("player", remainingPlayers[0]); - } - - window.history.pushState({}, "", url.toString()); - }} - /> - ))}
); diff --git a/client/src/components/settings/BillingSettings.tsx b/client/src/components/settings/BillingSettings.tsx index bd19266..96410ad 100644 --- a/client/src/components/settings/BillingSettings.tsx +++ b/client/src/components/settings/BillingSettings.tsx @@ -35,6 +35,7 @@ import { StatusBanner } from '@modl-gg/shared-web/components/ui/status-banner'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@modl-gg/shared-web/components/ui/alert-dialog'; import { Slider } from '@modl-gg/shared-web/components/ui/slider'; import { Label } from '@modl-gg/shared-web/components/ui/label'; +import { StatusBadge } from '@/components/ui/status-badge'; // Initialize Stripe lazily - only when a valid key is present let stripePromise: ReturnType | null = null; @@ -322,22 +323,22 @@ const BillingSettings = () => { // Special handling for cancelled subscriptions if (normalizedStatus === 'CANCELED') { if (!currentPeriodEnd) { - return {t('settings.billing.expired')}; + return {t('settings.billing.expired')}; } const endDate = new Date(currentPeriodEnd); const today = new Date(); if (endDate <= today) { - return {t('settings.billing.expired')}; + return {t('settings.billing.expired')}; } else { - return {t('settings.billing.cancelled')}; + return {t('settings.billing.cancelled')}; } } switch (normalizedStatus) { case 'ACTIVE': - return {t('status.active')}; + return {t('status.active')}; case 'TRIALING': - return {t('settings.billing.trial')}; + return {t('settings.billing.trial')}; case 'PAST_DUE': return {t('settings.billing.pastDue')}; default: @@ -353,10 +354,10 @@ const BillingSettings = () => { {isCurrent && plan.id === 'premium' && (
- + {t('settings.billing.currentPlan')} - +
)} @@ -374,7 +375,7 @@ const BillingSettings = () => { {plan.features.map((feature, index) => (
{feature.included ? ( - + ) : (
)} @@ -495,7 +496,7 @@ const BillingSettings = () => {
- + {t('settings.billing.premiumSubscription')} — $9.99/month @@ -705,7 +706,7 @@ const BillingSettings = () => {
- + {t('settings.billing.upgradeToPremium')} {t('settings.billing.upgradeToPremiumDesc')} @@ -739,7 +740,7 @@ const BillingSettings = () => {
{premiumFeatures.map((feature, index) => (
- + {feature.icon && (
{feature.icon} diff --git a/client/src/components/settings/DomainSettings.tsx b/client/src/components/settings/DomainSettings.tsx index 46aaf86..d7ddc6f 100644 --- a/client/src/components/settings/DomainSettings.tsx +++ b/client/src/components/settings/DomainSettings.tsx @@ -6,8 +6,9 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@modl import { Input } from '@modl-gg/shared-web/components/ui/input'; import { Label } from '@modl-gg/shared-web/components/ui/label'; import { StatusBanner } from '@modl-gg/shared-web/components/ui/status-banner'; -import { Badge } from '@modl-gg/shared-web/components/ui/badge'; import { Separator } from '@modl-gg/shared-web/components/ui/separator'; +import { StatusBadge } from '@/components/ui/status-badge'; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@modl-gg/shared-web/components/ui/alert-dialog'; import { useToast } from '@modl-gg/shared-web/hooks/use-toast'; import { apiFetch, getCurrentDomain } from '@/lib/api'; import { useAuth } from '@/hooks/use-auth'; @@ -278,13 +279,13 @@ const DomainSettings: React.FC = () => { }); }; - const getStatusColor = (status: string) => { + const getStatusIntent = (status: string): 'success' | 'warning' | 'info' | 'destructive' | 'neutral' => { switch (status) { - case 'active': return 'bg-green-500'; - case 'pending': return 'bg-yellow-500'; - case 'verifying': return 'bg-blue-500'; - case 'error': return 'bg-red-500'; - default: return 'bg-gray-500'; + case 'active': return 'success'; + case 'pending': return 'warning'; + case 'verifying': return 'info'; + case 'error': return 'destructive'; + default: return 'neutral'; } }; @@ -392,9 +393,9 @@ const DomainSettings: React.FC = () => {
- + {getStatusText(domainStatus.status)} - + {domainStatus.domain}
@@ -421,14 +422,34 @@ const DomainSettings: React.FC = () => { )} - + + + + + + + {t('settings.domain.removeDomainTitle', 'Remove custom domain?')} + + {t('settings.domain.removeDomainConfirm', "Traffic to this domain will stop working immediately. You'll need to update your DNS / panel config to restore access.")} + + + + {t('common.cancel')} + + {t('common.remove')} + + + +
diff --git a/client/src/components/settings/GeneralSettings.tsx b/client/src/components/settings/GeneralSettings.tsx index f0d0c5d..09d3462 100644 --- a/client/src/components/settings/GeneralSettings.tsx +++ b/client/src/components/settings/GeneralSettings.tsx @@ -6,6 +6,7 @@ import { Input } from '@modl-gg/shared-web/components/ui/input'; import { Label } from '@modl-gg/shared-web/components/ui/label'; import { Separator } from '@modl-gg/shared-web/components/ui/separator'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@modl-gg/shared-web/components/ui/collapsible'; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@modl-gg/shared-web/components/ui/alert-dialog'; import { useAuth } from '@/hooks/use-auth'; import { usePermissions } from '@/hooks/use-permissions'; import BillingSettings from './BillingSettings'; @@ -261,10 +262,22 @@ const GeneralSettings = ({ {showApiKey ? (fullApiKey || apiKey) : maskApiKey(apiKey)} - -
@@ -272,14 +285,56 @@ const GeneralSettings = ({
- - + + + + + + + {t('settings.general.regenerateApiKeyTitle', 'Regenerate API key?')} + + {t('settings.general.regenerateApiKeyConfirm', 'The old key will stop working immediately and any Minecraft servers using it will lose access until updated.')} + + + + {t('common.cancel')} + + {t('settings.general.regenerate')} + + + + + + + + + + + {t('settings.general.revokeApiKeyTitle', 'Revoke API key?')} + + {t('settings.general.revokeApiKeyConfirm', 'This will immediately invalidate the key. Minecraft servers using this key will lose access. This cannot be undone.')} + + + + {t('common.cancel')} + + {t('settings.general.revoke')} + + + +
) : ( diff --git a/client/src/components/settings/HomepageCardSettings.tsx b/client/src/components/settings/HomepageCardSettings.tsx index 672be9b..d02d98e 100644 --- a/client/src/components/settings/HomepageCardSettings.tsx +++ b/client/src/components/settings/HomepageCardSettings.tsx @@ -10,50 +10,52 @@ import { useToast } from '@modl-gg/shared-web/hooks/use-toast'; import { queryClient } from '@/lib/queryClient'; import { apiFetch } from '@/lib/api'; import { useQuery, useMutation } from '@tanstack/react-query'; -import { Plus, Edit, Trash2, GripVertical, Eye, EyeOff } from 'lucide-react'; +import { + Plus, Edit, Trash2, GripVertical, Eye, EyeOff, + Shield, UserPlus, MessageCircle, Mail, Phone, Scale, + Users, User, UserCheck, UserX, Crown, Award, + BookOpen, Book, FileText, ScrollText, Newspaper, + Library, GraduationCap, HelpCircle, Info, AlertCircle, + ExternalLink, Link as LinkIcon, ArrowRight, ChevronRight, Home, + Search, Download, Upload, Share, + MessageSquare, Send, Inbox, Bell, Megaphone, + Radio, Headphones, Mic, Video, Calendar, + Gamepad2, Zap, Server, Globe, Wifi, Signal, + Activity, BarChart, TrendingUp, Target, Trophy, + Settings, Wrench, Cog, Sliders, Filter, + Lock, Unlock, Key, ShieldCheck, ShieldAlert, + Minus, Check, X, AlertTriangle, CheckCircle, + XCircle, Clock, Timer, Pause, Play, + CreditCard, DollarSign, Gift, Star, Heart, ThumbsUp, + Flag, Map, Compass, Navigation, Bookmark, Tag, +} from 'lucide-react'; import { Switch } from '@modl-gg/shared-web/components/ui/switch'; import { Label } from '@modl-gg/shared-web/components/ui/label'; -import * as LucideIcons from 'lucide-react'; import { DndProvider, useDrag, useDrop, DropTargetMonitor } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; -// Get list of curated icons suitable for homepage cards -const getAvailableIcons = () => { - return [ - // Common actions - 'Shield', 'UserPlus', 'MessageCircle', 'Mail', 'Phone', 'Scale', - 'Users', 'User', 'UserCheck', 'UserX', 'Crown', 'Award', - - // Content & knowledge - 'BookOpen', 'Book', 'FileText', 'File', 'ScrollText', 'Newspaper', - 'Library', 'GraduationCap', 'HelpCircle', 'Info', 'AlertCircle', - - // Navigation & links - 'ExternalLink', 'Link', 'ArrowRight', 'ChevronRight', 'Home', - 'Search', 'Eye', 'Download', 'Upload', 'Share', - - // Communication - 'MessageSquare', 'Send', 'Inbox', 'Bell', 'Megaphone', - 'Radio', 'Headphones', 'Mic', 'Video', 'Calendar', - - // Games & servers - 'Gamepad2', 'Zap', 'Server', 'Globe', 'Wifi', 'Signal', - 'Activity', 'BarChart', 'TrendingUp', 'Target', 'Trophy', - - // Settings & tools - 'Settings', 'Tool', 'Wrench', 'Cog', 'Sliders', 'Filter', - 'Lock', 'Unlock', 'Key', 'ShieldCheck', 'ShieldAlert', - - // Actions & status - 'Plus', 'Minus', 'Check', 'X', 'AlertTriangle', 'CheckCircle', - 'XCircle', 'Clock', 'Timer', 'Pause', 'Play', 'Stop', - - // Commerce & misc - 'CreditCard', 'DollarSign', 'Gift', 'Star', 'Heart', 'ThumbsUp', - 'Flag', 'Map', 'Compass', 'Navigation', 'Bookmark', 'Tag' - ].sort(); +// Allowlist of icons selectable for homepage cards; keep in sync with HomePage.tsx ICONS map. +const ICONS: Record> = { + Shield, UserPlus, MessageCircle, Mail, Phone, Scale, + Users, User, UserCheck, UserX, Crown, Award, + BookOpen, Book, FileText, ScrollText, Newspaper, + Library, GraduationCap, HelpCircle, Info, AlertCircle, + ExternalLink, Link: LinkIcon, ArrowRight, ChevronRight, Home, + Search, Eye, Download, Upload, Share, + MessageSquare, Send, Inbox, Bell, Megaphone, + Radio, Headphones, Mic, Video, Calendar, + Gamepad2, Zap, Server, Globe, Wifi, Signal, + Activity, BarChart, TrendingUp, Target, Trophy, + Settings, Wrench, Cog, Sliders, Filter, + Lock, Unlock, Key, ShieldCheck, ShieldAlert, + Plus, Minus, Check, X, AlertTriangle, CheckCircle, + XCircle, Clock, Timer, Pause, Play, + CreditCard, DollarSign, Gift, Star, Heart, ThumbsUp, + Flag, Map, Compass, Navigation, Bookmark, Tag, }; +const getAvailableIcons = () => Object.keys(ICONS).sort(); + interface HomepageCard { id: string; title: string; @@ -423,7 +425,7 @@ const HomepageCardSettings: React.FC = () => { }; const IconPreview = ({ iconName, color }: { iconName: string; color?: string }) => { - const IconComponent = (LucideIcons as any)[iconName] || LucideIcons.BookOpen; + const IconComponent = ICONS[iconName] || BookOpen; return ; }; diff --git a/client/src/components/settings/InviteStaffModal.tsx b/client/src/components/settings/InviteStaffModal.tsx index 5e15b9a..059f550 100644 --- a/client/src/components/settings/InviteStaffModal.tsx +++ b/client/src/components/settings/InviteStaffModal.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; -import * as z from 'zod'; +import { z } from 'zod'; import { Button } from '@modl-gg/shared-web/components/ui/button'; import { Dialog, diff --git a/client/src/components/settings/KnowledgebaseSettings.tsx b/client/src/components/settings/KnowledgebaseSettings.tsx index c17d0e5..d9d1c76 100644 --- a/client/src/components/settings/KnowledgebaseSettings.tsx +++ b/client/src/components/settings/KnowledgebaseSettings.tsx @@ -188,9 +188,9 @@ const CategoryItem: React.FC = ({ ) : ( - + )} - +
diff --git a/client/src/components/settings/MigrationTool.tsx b/client/src/components/settings/MigrationTool.tsx index 470b8c0..239612e 100644 --- a/client/src/components/settings/MigrationTool.tsx +++ b/client/src/components/settings/MigrationTool.tsx @@ -76,15 +76,15 @@ const MigrationTool: React.FC = () => { switch (status) { case 'idle': case 'building_json': - return ; + return ; case 'uploading_json': - return ; + return ; case 'processing_data': - return ; + return ; case 'completed': - return ; + return ; case 'failed': - return ; + return ; default: return ; } @@ -164,7 +164,7 @@ const MigrationTool: React.FC = () => { {/* Active Migration Progress */} {isActive && currentMigration && ( - +
@@ -210,7 +210,7 @@ const MigrationTool: React.FC = () => { {currentMigration.progress.totalRecords && ` / ${currentMigration.progress.totalRecords}`} {currentMigration.progress.recordsSkipped > 0 && ( - + {t('settings.migration.skipped', { count: currentMigration.progress.recordsSkipped })} )} @@ -237,9 +237,9 @@ const MigrationTool: React.FC = () => { + ) : isCancelled ? ( - + ) : undefined} > {isSuccess ? ( @@ -265,7 +265,7 @@ const MigrationTool: React.FC = () => { {onCooldown && !isActive && ( } + icon={} > {t('settings.migration.cooldownActive', { time: formatCooldownTime(cooldownRemainingMs) })} @@ -325,9 +325,9 @@ const MigrationTool: React.FC = () => { >
{entry.status === 'completed' ? ( - + ) : ( - + )}

@@ -343,7 +343,7 @@ const MigrationTool: React.FC = () => { {t('settings.migration.recordsCount', { count: entry.recordsProcessed })}

{entry.recordsSkipped > 0 && ( -

+

{t('settings.migration.skipped', { count: entry.recordsSkipped })}

)} diff --git a/client/src/components/settings/PasskeySettings.tsx b/client/src/components/settings/PasskeySettings.tsx index e26c12e..df74955 100644 --- a/client/src/components/settings/PasskeySettings.tsx +++ b/client/src/components/settings/PasskeySettings.tsx @@ -316,7 +316,7 @@ const PasskeySettings = () => { {t('common.cancel')} - {t('common.remove')} + {t('common.remove')} diff --git a/client/src/components/settings/StaffRolesCard.tsx b/client/src/components/settings/StaffRolesCard.tsx index 40735fd..51d11bf 100644 --- a/client/src/components/settings/StaffRolesCard.tsx +++ b/client/src/components/settings/StaffRolesCard.tsx @@ -265,7 +265,7 @@ const DraggableRoleCard: React.FC = ({ )} {role.name === 'Super Admin' && ( - + {t('settings.roles.highestRank')} )} @@ -276,6 +276,7 @@ const DraggableRoleCard: React.FC = ({ size="sm" onClick={() => onEditRole(role)} disabled={role.name === 'Super Admin' || (roleOrderMap.get(currentUserRole || '') ?? 999) >= getRoleOrder(role)} + aria-label={t('common.edit')} > @@ -284,6 +285,7 @@ const DraggableRoleCard: React.FC = ({ size="sm" onClick={() => onDeleteRole(role)} disabled={role.name === 'Super Admin' || (roleOrderMap.get(currentUserRole || '') ?? 999) >= getRoleOrder(role)} + aria-label={t('common.delete')} > @@ -885,29 +887,29 @@ export default function StaffRolesCard() { {/* Delete Confirmation Dialog */} - !open && setDeleteConfirmRole(null)}> - - - {t('settings.roles.deleteRoleTitle')} - + !open && setDeleteConfirmRole(null)}> + + + {t('settings.roles.deleteRoleTitle')} + {t('settings.roles.deleteRoleConfirm', { name: deleteConfirmRole?.name })} - - - - - - - - + + + + {/* Role Reorder Confirmation Dialog */} diff --git a/client/src/components/settings/TicketSettings.tsx b/client/src/components/settings/TicketSettings.tsx index 8a14fb3..8c8087c 100644 --- a/client/src/components/settings/TicketSettings.tsx +++ b/client/src/components/settings/TicketSettings.tsx @@ -21,6 +21,7 @@ import { TicketFormField, TicketFormSection, TicketFormSettings, TicketFormsConf import { useBillingStatus } from '@/hooks/use-data'; import { useAuth } from '@/hooks/use-auth'; import { hasPremiumAccess } from '@/lib/backend-enums'; +import { StatusBadge } from '@/components/ui/status-badge'; // Label type definition interface Label { @@ -2191,10 +2192,10 @@ const TicketSettings = ({

{t('settings.tickets.aiModerationSettings')}

{!isPremiumUser() && ( - + Premium - + )}
@@ -2218,12 +2219,12 @@ const TicketSettings = ({
{!isPremiumUser() ? (
- +

{t('settings.tickets.premiumFeature')}

{t('settings.tickets.aiModerationPremiumDesc')}

- diff --git a/client/src/components/settings/UsageSettings.tsx b/client/src/components/settings/UsageSettings.tsx index c298975..c2d3935 100644 --- a/client/src/components/settings/UsageSettings.tsx +++ b/client/src/components/settings/UsageSettings.tsx @@ -16,6 +16,7 @@ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, import { useToast } from '@modl-gg/shared-web/hooks/use-toast'; import { formatFileSize } from '@/utils/file-utils'; import { useReplayRetentionSettings, useUpdateReplayRetentionSettings } from '@/hooks/use-data'; +import { Notice } from '@/components/ui/notice'; interface StorageFile { id: string; @@ -412,12 +413,12 @@ const fetchStorageData = async () => { const getTypeColor = (type: string): string => { switch (type) { - case 'ticket': return 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300'; - case 'evidence': return 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300'; - case 'logs': return 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300'; - case 'backup': return 'bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-300'; - case 'replay': return 'bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-300'; - default: return 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300'; + case 'ticket': return 'bg-info/20 text-info border-info/30'; + case 'evidence': return 'bg-destructive/20 text-destructive border-destructive/30'; + case 'logs': return 'bg-success/20 text-success border-success/30'; + case 'backup': return 'bg-accent/20 text-accent border-accent/30'; + case 'replay': return 'bg-warning/20 text-warning border-warning/30'; + default: return 'bg-muted text-muted-foreground border-border'; } }; @@ -609,20 +610,14 @@ const fetchStorageData = async () => { {/* Free User Limit Warning */} {!storageUsage?.quota?.isPaid && storageUsage?.quota?.baseUsagePercentage >= 80 && ( -
-
- -
-

{t('settings.usage.storageLimitWarning')}

-

- {t('settings.usage.storageLimitWarningDesc', { percentage: storageUsage.quota.baseUsagePercentage, limit: storageUsage.quota.baseLimitFormatted })} -

-

- {t('settings.usage.upgradePremiumStorage')} -

-
-
-
+ +

+ {t('settings.usage.storageLimitWarningDesc', { percentage: storageUsage.quota.baseUsagePercentage, limit: storageUsage.quota.baseLimitFormatted })} +

+

+ {t('settings.usage.upgradePremiumStorage')} +

+
)} {/* Storage Overview */} @@ -896,40 +891,6 @@ const fetchStorageData = async () => {
- - - - {t('settings.usage.systemStatus')} - - -
-
- {t('settings.usage.totalFiles')}: - {files.length} -
-
- {t('settings.usage.selected')}: - {selectedFiles.size} -
-
- {t('settings.usage.filtered')}: - {filteredAndSortedFiles.length} -
-
- {t('settings.usage.canUpload')}: - - {storageUsage.quota?.canUpload ? t('common.yes') : t('common.no')} - -
-
- {t('settings.usage.aiAvailable')}: - - {storageUsage.isPremium && storageUsage.aiQuota ? t('common.yes') : t('common.no')} - -
-
-
-
)} @@ -1089,6 +1050,7 @@ const fetchStorageData = async () => { variant="ghost" size="sm" onClick={() => window.open(file.url, '_blank')} + aria-label={t('common.download')} > @@ -1096,8 +1058,9 @@ const fetchStorageData = async () => { variant="ghost" size="sm" onClick={() => handleDeleteFile(file.id)} + aria-label={t('common.delete')} > - +
@@ -1177,7 +1140,7 @@ const fetchStorageData = async () => { {t('common.cancel')} - + {t('common.delete')} @@ -1232,8 +1195,8 @@ const fetchStorageData = async () => {
)} -
-

+

+

{t('common.important')}: {t('settings.usage.overageLimitWarning')}

diff --git a/client/src/components/ui/clickable-player.tsx b/client/src/components/ui/clickable-player.tsx index f013dec..9fe9b61 100644 --- a/client/src/components/ui/clickable-player.tsx +++ b/client/src/components/ui/clickable-player.tsx @@ -100,7 +100,7 @@ export function ClickablePlayer({ return ( + {icon &&
{icon}
} +

{title}

+ {description &&

{description}

} + {action &&
{action}
} +
+ ); +} diff --git a/client/src/components/ui/markdown-renderer.tsx b/client/src/components/ui/markdown-renderer.tsx index 87a34f1..4933c3d 100644 --- a/client/src/components/ui/markdown-renderer.tsx +++ b/client/src/components/ui/markdown-renderer.tsx @@ -81,19 +81,13 @@ const processMarkdownContent = (content: string, disableClickablePlayers = false }; const MarkdownRenderer = ({ content, className, allowHtml = false, disableClickablePlayers = false }: MarkdownRendererProps) => { - // Guard against undefined/null content - render empty for falsy values - if (content === undefined || content === null) { - return null; - } - - // For empty strings, just return an empty container - if (content === '') { - return
; - } - - const processedContent = processMarkdownContent(content, disableClickablePlayers); const { data: mediaConfig } = useMediaUploadConfig(); + const processedContent = useMemo( + () => processMarkdownContent(content ?? '', disableClickablePlayers), + [content, disableClickablePlayers] + ); + const normalizedCdnHost = useMemo(() => { const rawDomain = mediaConfig?.cdnDomain?.trim(); if (!rawDomain) return null; @@ -106,6 +100,14 @@ const MarkdownRenderer = ({ content, className, allowHtml = false, disableClicka } }, [mediaConfig?.cdnDomain]); + if (content === undefined || content === null) { + return null; + } + + if (content === '') { + return
; + } + const getTrustedMediaKind = (href?: string): 'image' | 'video' | null => { if (!href || !normalizedCdnHost) return null; diff --git a/client/src/components/ui/notice.tsx b/client/src/components/ui/notice.tsx new file mode 100644 index 0000000..3072411 --- /dev/null +++ b/client/src/components/ui/notice.tsx @@ -0,0 +1,38 @@ +import { type ReactNode } from 'react'; +import { cn } from '@/lib/utils'; +import { AlertCircle, Info, AlertTriangle, CheckCircle2 } from 'lucide-react'; + +type Variant = 'info' | 'success' | 'warning' | 'error'; + +const styles: Record = { + info: 'bg-info/10 text-info border-info/20', + success: 'bg-success/10 text-success border-success/20', + warning: 'bg-warning/10 text-warning border-warning/20', + error: 'bg-destructive/10 text-destructive border-destructive/20', +}; + +const icons: Record = { + info: , + success: , + warning: , + error: , +}; + +export interface NoticeProps { + variant?: Variant; + title?: string; + children?: ReactNode; + className?: string; +} + +export function Notice({ variant = 'info', title, children, className }: NoticeProps) { + return ( +
+ {icons[variant]} +
+ {title &&
{title}
} + {children &&
{children}
} +
+
+ ); +} diff --git a/client/src/components/ui/page-title.tsx b/client/src/components/ui/page-title.tsx new file mode 100644 index 0000000..de1fa5f --- /dev/null +++ b/client/src/components/ui/page-title.tsx @@ -0,0 +1,14 @@ +import { type ReactNode } from 'react'; +import { cn } from '@/lib/utils'; + +export function PageTitle({ children, className }: { children: ReactNode; className?: string }) { + return

{children}

; +} + +export function SectionTitle({ children, className }: { children: ReactNode; className?: string }) { + return

{children}

; +} + +export function StatValue({ children, className }: { children: ReactNode; className?: string }) { + return
{children}
; +} diff --git a/client/src/components/ui/status-badge.tsx b/client/src/components/ui/status-badge.tsx new file mode 100644 index 0000000..03cc051 --- /dev/null +++ b/client/src/components/ui/status-badge.tsx @@ -0,0 +1,29 @@ +import { Badge } from '@modl-gg/shared-web/components/ui/badge'; +import { cn } from '@/lib/utils'; +import { type ReactNode } from 'react'; + +type Intent = 'info' | 'success' | 'warning' | 'destructive' | 'neutral'; + +const styles: Record = { + info: 'bg-info/20 text-info border-info/30', + success: 'bg-success/20 text-success border-success/30', + warning: 'bg-warning/20 text-warning border-warning/30', + destructive: 'bg-destructive/20 text-destructive border-destructive/30', + neutral: 'bg-muted text-muted-foreground border-border', +}; + +export function StatusBadge({ + intent = 'neutral', + children, + className, +}: { + intent?: Intent; + children: ReactNode; + className?: string; +}) { + return ( + + {children} + + ); +} diff --git a/client/src/contexts/DashboardContext.tsx b/client/src/contexts/DashboardContext.tsx index 5ddb146..ab01600 100644 --- a/client/src/contexts/DashboardContext.tsx +++ b/client/src/contexts/DashboardContext.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useReducer, ReactNode, useCallback } from 'react'; +import { createContext, useContext, useReducer, useMemo, ReactNode, useCallback } from 'react'; import { WindowPosition, WindowState } from '@modl-gg/shared-web/types'; import { windowActions, initialWindowState } from '@/lib/window-manager'; @@ -55,16 +55,16 @@ export const DashboardProvider = ({ children }: { children: ReactNode }) => { dispatch({ type: 'UPDATE_SIZE', id, size }); }, []); + const contextValue = useMemo(() => ({ + windowState, + openLookupWindow, + closeLookupWindow, + updateWindowPosition, + updateWindowSize + }), [windowState, openLookupWindow, closeLookupWindow, updateWindowPosition, updateWindowSize]); + return ( - + {children} ); diff --git a/client/src/contexts/PlayerWindowContext.tsx b/client/src/contexts/PlayerWindowContext.tsx index a9669bd..f9585d5 100644 --- a/client/src/contexts/PlayerWindowContext.tsx +++ b/client/src/contexts/PlayerWindowContext.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useState, useCallback, ReactNode } from 'react'; +import { createContext, useContext, useState, useCallback, useMemo, ReactNode } from 'react'; import { createPortal } from 'react-dom'; import PlayerWindow from '@/components/windows/PlayerWindow'; @@ -29,7 +29,7 @@ const getNextWindowPosition = (existingWindows: PlayerWindowState[]): WindowPosi const baseX = 100; const baseY = 100; const offset = 50; - + const count = existingWindows.length; return { x: baseX + (count * offset), @@ -37,20 +37,38 @@ const getNextWindowPosition = (existingWindows: PlayerWindowState[]): WindowPosi }; }; +const setPlayerUrlParam = (playerId: string) => { + if (typeof window === 'undefined') return; + const url = new URL(window.location.href); + if (url.searchParams.get('player') === playerId) return; + url.searchParams.set('player', playerId); + window.history.replaceState({}, '', url.toString()); +}; + +const clearPlayerUrlParam = (playerId: string) => { + if (typeof window === 'undefined') return; + const url = new URL(window.location.href); + if (url.searchParams.get('player') !== playerId) return; + url.searchParams.delete('player'); + url.searchParams.delete('punishment'); + window.history.replaceState({}, '', url.toString()); +}; + export function PlayerWindowProvider({ children }: { children: ReactNode }) { const [windows, setWindows] = useState([]); const openPlayerWindow = useCallback((playerId: string, username?: string) => { + setPlayerUrlParam(playerId); setWindows(prevWindows => { const windowId = generateWindowId(playerId); - + const existingWindowIndex = prevWindows.findIndex(w => w.id === windowId); if (existingWindowIndex !== -1) { const existingWindow = prevWindows[existingWindowIndex]; const otherWindows = prevWindows.filter((_, index) => index !== existingWindowIndex); return [...otherWindows, { ...existingWindow, isOpen: true }]; } - + const position = getNextWindowPosition(prevWindows); const newWindow: PlayerWindowState = { id: windowId, @@ -58,31 +76,31 @@ export function PlayerWindowProvider({ children }: { children: ReactNode }) { isOpen: true, position }; - + return [...prevWindows, newWindow]; }); }, []); const closePlayerWindow = useCallback((windowId: string) => { - setWindows(prevWindows => - prevWindows.map(window => - window.id === windowId - ? { ...window, isOpen: false } - : window - ) - ); + setWindows(prevWindows => { + const closing = prevWindows.find(w => w.id === windowId); + if (closing) { + clearPlayerUrlParam(closing.playerId); + } + return prevWindows.filter(w => w.id !== windowId); + }); }, []); const focusPlayerWindow = useCallback((playerId: string, username?: string) => { openPlayerWindow(playerId, username); }, [openPlayerWindow]); - const contextValue: PlayerWindowContextType = { + const contextValue = useMemo(() => ({ windows, openPlayerWindow, closePlayerWindow, focusPlayerWindow - }; + }), [windows, openPlayerWindow, closePlayerWindow, focusPlayerWindow]); return ( diff --git a/client/src/hooks/use-auth.tsx b/client/src/hooks/use-auth.tsx index 4b06594..7181b7b 100644 --- a/client/src/hooks/use-auth.tsx +++ b/client/src/hooks/use-auth.tsx @@ -1,4 +1,4 @@ -import { createContext, ReactNode, useContext, useState, useEffect } from "react"; +import { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from "react"; import { useLocation } from "wouter"; import { useToast } from "@modl-gg/shared-web/hooks/use-toast"; import { getApiUrl, getCurrentDomain } from "@/lib/api"; @@ -66,7 +66,7 @@ export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); - const fetchAuthenticatedUser = async (): Promise => { + const fetchAuthenticatedUser = useCallback(async (): Promise => { const response = await authFetch('/v1/panel/auth/me'); if (!response.ok) { return null; @@ -74,12 +74,12 @@ export function AuthProvider({ children }: { children: ReactNode }) { const userData = await response.json(); return mapUserFromMeResponse(userData); - }; + }, []); - const refreshUser = async () => { + const refreshUser = useCallback(async () => { const authenticatedUser = await fetchAuthenticatedUser(); setUser(authenticatedUser); - }; + }, [fetchAuthenticatedUser]); useEffect(() => { const checkSession = async () => { @@ -96,16 +96,19 @@ export function AuthProvider({ children }: { children: ReactNode }) { }; checkSession(); - }, []); + }, [fetchAuthenticatedUser]); useEffect(() => { const lang = user?.language || 'en'; + const dateFormat = user?.dateFormat || 'MM/DD/YYYY'; setDateLocale(lang); - setDateFormat(user?.dateFormat || 'MM/DD/YYYY'); - i18n.changeLanguage(lang); + setDateFormat(dateFormat); + if (lang !== i18n.language) { + i18n.changeLanguage(lang); + } }, [user?.language, user?.dateFormat]); - const requestEmailVerification = async (email: string): Promise => { + const requestEmailVerification = useCallback(async (email: string): Promise => { try { const response = await authFetch('/v1/panel/auth/send-email-code', { method: 'POST', @@ -144,9 +147,9 @@ export function AuthProvider({ children }: { children: ReactNode }) { }); return undefined; } - }; + }, [toast]); - const login = async (email: string, code: string): Promise => { + const login = useCallback(async (email: string, code: string): Promise => { setIsLoading(true); try { const response = await authFetch('/v1/panel/auth/verify-email-code', { @@ -207,9 +210,9 @@ export function AuthProvider({ children }: { children: ReactNode }) { setIsLoading(false); return false; } - }; + }, [fetchAuthenticatedUser, toast]); - const checkPasskeyOptions = async (email: string): Promise => { + const checkPasskeyOptions = useCallback(async (email: string): Promise => { try { const response = await authFetch('/v1/panel/auth/webauthn/login/options', { method: 'POST', @@ -228,9 +231,9 @@ export function AuthProvider({ children }: { children: ReactNode }) { } catch { return { hasPasskeys: false }; } - }; + }, []); - const loginWithPasskey = async (challengeId: string, optionsJson: any): Promise => { + const loginWithPasskey = useCallback(async (challengeId: string, optionsJson: any): Promise => { setIsLoading(true); try { const optionsJSON = optionsJson?.publicKey ?? optionsJson; @@ -289,9 +292,9 @@ export function AuthProvider({ children }: { children: ReactNode }) { setIsLoading(false); return false; } - }; + }, [fetchAuthenticatedUser, toast]); - const loginWithDiscoverablePasskey = async (): Promise => { + const loginWithDiscoverablePasskey = useCallback(async (): Promise => { setIsLoading(true); try { const startRes = await authFetch('/v1/panel/auth/webauthn/login/start', { @@ -364,9 +367,9 @@ export function AuthProvider({ children }: { children: ReactNode }) { setIsLoading(false); return false; } - }; + }, [fetchAuthenticatedUser, toast]); - const logout = async () => { + const logout = useCallback(async () => { setIsLoading(true); let shouldRedirectToAuth = false; @@ -424,22 +427,32 @@ export function AuthProvider({ children }: { children: ReactNode }) { navigate('/auth'); } } - }; + }, [fetchAuthenticatedUser, navigate, toast]); + + const contextValue = useMemo(() => ({ + user, + isLoading, + refreshUser, + login, + logout, + requestEmailVerification, + checkPasskeyOptions, + loginWithPasskey, + loginWithDiscoverablePasskey, + }), [ + user, + isLoading, + refreshUser, + login, + logout, + requestEmailVerification, + checkPasskeyOptions, + loginWithPasskey, + loginWithDiscoverablePasskey, + ]); return ( - + {children} ); diff --git a/client/src/hooks/use-data.tsx b/client/src/hooks/use-data.tsx index b0493fa..0de24f0 100644 --- a/client/src/hooks/use-data.tsx +++ b/client/src/hooks/use-data.tsx @@ -5,6 +5,7 @@ import { useAuth } from './use-auth'; import { apiFetch } from '@/lib/api'; import { isPublicPage } from '@/utils/routes'; import { getApiErrorMessage } from '@/utils/email-validation'; +import { isPanelRealtimeEnabled } from './use-realtime'; type SettingsEnvelope = { data: T; @@ -64,7 +65,7 @@ export function usePlayer(uuid: string) { return res.json(); }, enabled: !!uuid, - staleTime: 1000, + staleTime: 30_000, refetchOnWindowFocus: true }); } @@ -83,7 +84,7 @@ export function useLinkedAccounts(uuid: string) { return res.json(); }, enabled: !!uuid, - staleTime: 1000, + staleTime: 30_000, refetchOnWindowFocus: true }); } @@ -185,7 +186,7 @@ export function useTicket(id: string) { enabled: !!id, retry: false, staleTime: 30000, - gcTime: 60000, + gcTime: 1000 * 60 * 10, refetchOnWindowFocus: true }); } @@ -243,6 +244,7 @@ export function useUpdateTicket() { onSuccess: (data) => { queryClient.invalidateQueries({ queryKey: ['/v1/panel/tickets', data._id] }); queryClient.invalidateQueries({ queryKey: ['/v1/panel/tickets'] }); + queryClient.invalidateQueries({ queryKey: ['/v1/panel/tickets/counts'] }); } }); } @@ -403,7 +405,7 @@ export function useStaff() { } return res.json(); }, - staleTime: 1000 * 60, + staleTime: 1000 * 60 * 5, }); } @@ -678,21 +680,6 @@ export function useUpdateReplayRetentionSettings() { }); } -export function useStats() { - return useQuery({ - queryKey: ['/v1/panel/stats'], - queryFn: async () => { - const res = await apiFetch('/v1/panel/stats'); - if (!res.ok) { - throw new Error('Failed to fetch stats'); - } - return res.json(); - }, - staleTime: 5 * 60 * 1000, - refetchOnWindowFocus: true, - }); -} - export function useBillingStatus() { return useQuery({ queryKey: ['/v1/panel/billing/status'], @@ -865,7 +852,7 @@ export function usePanelTicket(id: string) { }, enabled: !!id, staleTime: 30000, - gcTime: 60000, + gcTime: 1000 * 60 * 10, refetchOnWindowFocus: true }); } @@ -1205,7 +1192,6 @@ export function useAssignMinecraftPlayer() { }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['/v1/panel/staff'] }); - queryClient.invalidateQueries({ queryKey: ['/v1/panel/staff/available-players'] }); }, }); } @@ -1279,7 +1265,7 @@ export function useDashboardAlerts() { return res.json() as Promise; }, staleTime: 60 * 1000, - refetchOnWindowFocus: true, + refetchOnWindowFocus: false, }); } @@ -1396,7 +1382,8 @@ export function useTicketStatusCounts(options?: { return res.json() as Promise<{ open: number; closed: number }>; }, staleTime: 30000, - refetchOnWindowFocus: true + refetchOnWindowFocus: true, + placeholderData: keepPreviousData, }); } @@ -1495,6 +1482,7 @@ export function usePlayerSearch(searchQuery: string, debounceMs: number = 300) { } export function useMigrationStatus() { + const realtimeEnabled = isPanelRealtimeEnabled(); return useQuery({ queryKey: ['/v1/panel/migration/status'], queryFn: async () => { @@ -1504,7 +1492,7 @@ export function useMigrationStatus() { } return res.json(); }, - refetchInterval: (query) => { + refetchInterval: realtimeEnabled ? false : (query) => { const data = query.state.data; const currentMigration = data?.currentMigration; const isActive = currentMigration && diff --git a/client/src/hooks/use-permissions.tsx b/client/src/hooks/use-permissions.tsx index d28a7a6..f9a5c20 100644 --- a/client/src/hooks/use-permissions.tsx +++ b/client/src/hooks/use-permissions.tsx @@ -153,7 +153,7 @@ export function usePermissions() { return permissions.some(permission => hasPermission(permission)); }, [user, hasPermission]); - const canAccessSettingsTab = (tabName: keyof typeof SETTINGS_PERMISSIONS): boolean => { + const canAccessSettingsTab = useCallback((tabName: keyof typeof SETTINGS_PERMISSIONS): boolean => { if (!user) return false; if (tabName === 'tags') { return hasAnyPermission([ @@ -166,14 +166,14 @@ export function usePermissions() { if (!requiredPermissions || !Array.isArray(requiredPermissions)) return false; if (requiredPermissions.length === 0) return true; return hasAnyPermission(requiredPermissions as unknown as string[]); - }; + }, [user, hasAnyPermission]); - const getAccessibleSettingsTabs = (): string[] => { + const getAccessibleSettingsTabs = useCallback((): string[] => { if (!user) return ['account']; - + const allTabs = Object.keys(SETTINGS_PERMISSIONS) as (keyof typeof SETTINGS_PERMISSIONS)[]; return allTabs.filter(tab => canAccessSettingsTab(tab)); - }; + }, [user, canAccessSettingsTab]); const { data: rolesData } = useQuery({ queryKey: ['/v1/panel/roles'], @@ -188,7 +188,7 @@ export function usePermissions() { const roleHierarchy = useMemo(() => { return rolesData?.roles ? buildRoleHierarchy(rolesData.roles) : new Map(); - }, [rolesData]); + }, [rolesData?.roles]); const canModifyUserRole = (targetUserRole: string, newRole?: string, targetUserId?: string): boolean => { if (!user) return false; diff --git a/client/src/hooks/use-player-lookup.tsx b/client/src/hooks/use-player-lookup.tsx index bb2c17b..496ee33 100644 --- a/client/src/hooks/use-player-lookup.tsx +++ b/client/src/hooks/use-player-lookup.tsx @@ -1,3 +1,4 @@ +import { useEffect, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { apiFetch } from '@/lib/api'; @@ -92,13 +93,23 @@ interface PunishmentLookupResult { }; } -export function usePunishmentLookup(punishmentId: string) { +export function usePunishmentLookup(punishmentId: string, debounceMs: number = 300) { + const [debouncedId, setDebouncedId] = useState(punishmentId); + + useEffect(() => { + const timer = setTimeout(() => { + setDebouncedId(punishmentId); + }, debounceMs); + + return () => clearTimeout(timer); + }, [punishmentId, debounceMs]); + return useQuery({ - queryKey: ['punishment-lookup', punishmentId], + queryKey: ['punishment-lookup', debouncedId], queryFn: async (): Promise => { - if (!punishmentId) throw new Error('No punishment ID provided'); + if (!debouncedId) throw new Error('No punishment ID provided'); - const res = await apiFetch(`/v1/panel/players/punishments/${punishmentId}`); + const res = await apiFetch(`/v1/panel/players/punishments/${debouncedId}`); if (!res.ok) { if (res.status === 404) { throw new Error('Punishment not found'); @@ -121,7 +132,7 @@ export function usePunishmentLookup(punishmentId: string) { }, }; }, - enabled: !!punishmentId && punishmentId.length > 0, + enabled: !!debouncedId && debouncedId.length > 0, staleTime: 1000 * 60 * 5, retry: false }); diff --git a/client/src/hooks/use-public-settings.tsx b/client/src/hooks/use-public-settings.tsx index 10913d9..f56ee76 100644 --- a/client/src/hooks/use-public-settings.tsx +++ b/client/src/hooks/use-public-settings.tsx @@ -40,7 +40,6 @@ export function usePublicSettings() { staleTime: 1000 * 30, gcTime: 1000 * 60 * 10, refetchOnWindowFocus: true, - refetchInterval: 1000 * 60, retry: 1, }); } diff --git a/client/src/hooks/use-realtime.tsx b/client/src/hooks/use-realtime.tsx index 56afc5f..962c636 100644 --- a/client/src/hooks/use-realtime.tsx +++ b/client/src/hooks/use-realtime.tsx @@ -312,6 +312,9 @@ export function useRealtimeInvalidation(): void { break; } default: + if (import.meta.env.DEV) { + console.warn('[realtime] unhandled envelope payload case:', envelope.payload?.case); + } break; } }; diff --git a/client/src/hooks/use-sidebar.tsx b/client/src/hooks/use-sidebar.tsx index b6134b1..8168696 100644 --- a/client/src/hooks/use-sidebar.tsx +++ b/client/src/hooks/use-sidebar.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useState, ReactNode } from 'react'; +import { createContext, useContext, useMemo, useState, ReactNode } from 'react'; interface SidebarContextType { isSearchActive: boolean; @@ -10,11 +10,13 @@ const SidebarContext = createContext(undefined); export const SidebarProvider = ({ children }: { children: ReactNode }) => { const [isSearchActive, setIsSearchActive] = useState(false); + const value = useMemo( + () => ({ isSearchActive, setIsSearchActive }), + [isSearchActive] + ); + return ( - + {children} ); diff --git a/client/src/lib/queryClient.ts b/client/src/lib/queryClient.ts index 3a84d6b..819f1db 100644 --- a/client/src/lib/queryClient.ts +++ b/client/src/lib/queryClient.ts @@ -64,7 +64,8 @@ export const queryClient = new QueryClient({ queryFn: getQueryFn({ on401: "throw" }), refetchInterval: false, refetchOnWindowFocus: false, - staleTime: Infinity, + refetchOnReconnect: true, + staleTime: 30_000, retry: (failureCount, error) => { if (failureCount >= 1) return false; if (error instanceof Error) { diff --git a/client/src/locales/de.json b/client/src/locales/de.json index 25dccff..7dd7cbb 100644 --- a/client/src/locales/de.json +++ b/client/src/locales/de.json @@ -762,12 +762,6 @@ "replayRetentionSaved": "Replay-Aufbewahrungseinstellungen gespeichert.", "replayRetentionSaveFailed": "Replay-Aufbewahrungseinstellungen konnten nicht gespeichert werden.", "replayRetentionLoadFailed": "Replay-Aufbewahrungseinstellungen konnten nicht geladen werden.", - "systemStatus": "Systemstatus", - "totalFiles": "Dateien gesamt", - "selected": "Ausgewählt", - "filtered": "Gefiltert", - "canUpload": "Kann hochladen", - "aiAvailable": "KI verfügbar", "fileManagement": "Dateiverwaltung", "searchFiles": "Suchen", "searchPlaceholder": "Dateien suchen...", diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 3ac6560..df64436 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -769,12 +769,6 @@ "replayRetentionSaved": "Replay retention settings saved.", "replayRetentionSaveFailed": "Failed to save replay retention settings.", "replayRetentionLoadFailed": "Failed to load replay retention settings.", - "systemStatus": "System Status", - "totalFiles": "Total files", - "selected": "Selected", - "filtered": "Filtered", - "canUpload": "Can upload", - "aiAvailable": "AI available", "fileManagement": "File Management", "searchFiles": "Search", "searchPlaceholder": "Search files...", diff --git a/client/src/locales/es.json b/client/src/locales/es.json index 2ad51ad..0187785 100644 --- a/client/src/locales/es.json +++ b/client/src/locales/es.json @@ -762,12 +762,6 @@ "replayRetentionSaved": "Configuración de retención de repeticiones guardada.", "replayRetentionSaveFailed": "No se pudo guardar la configuración de retención de repeticiones.", "replayRetentionLoadFailed": "No se pudo cargar la configuración de retención de repeticiones.", - "systemStatus": "Estado del sistema", - "totalFiles": "Total de archivos", - "selected": "Seleccionados", - "filtered": "Filtrados", - "canUpload": "Puede subir", - "aiAvailable": "IA disponible", "fileManagement": "Gestión de archivos", "searchFiles": "Buscar", "searchPlaceholder": "Buscar archivos...", diff --git a/client/src/locales/nl.json b/client/src/locales/nl.json index cc50ed4..26b16c3 100644 --- a/client/src/locales/nl.json +++ b/client/src/locales/nl.json @@ -762,12 +762,6 @@ "replayRetentionSaved": "Replaybewaarinstellingen opgeslagen.", "replayRetentionSaveFailed": "Replaybewaarinstellingen opslaan mislukt.", "replayRetentionLoadFailed": "Replaybewaarinstellingen laden mislukt.", - "systemStatus": "Systeemstatus", - "totalFiles": "Totaal bestanden", - "selected": "Geselecteerd", - "filtered": "Gefilterd", - "canUpload": "Kan uploaden", - "aiAvailable": "AI beschikbaar", "fileManagement": "Bestandsbeheer", "searchFiles": "Zoeken", "searchPlaceholder": "Bestanden zoeken...", diff --git a/client/src/pages/HomePage.tsx b/client/src/pages/HomePage.tsx index 42cb51d..672a0fc 100644 --- a/client/src/pages/HomePage.tsx +++ b/client/src/pages/HomePage.tsx @@ -1,17 +1,52 @@ import React, { useState, useEffect } from 'react'; import { Link } from 'wouter'; -import { Search, Shield, MessageCircle, UserPlus, FileText, BookOpen, ChevronDown, LogIn, Sun, Moon } from 'lucide-react'; +import { + Search, Shield, MessageCircle, UserPlus, FileText, BookOpen, ChevronDown, LogIn, Sun, Moon, + Mail, Phone, Scale, Users, User, UserCheck, UserX, Crown, Award, + Book, ScrollText, Newspaper, Library, GraduationCap, HelpCircle, Info, AlertCircle, + ExternalLink, Link as LinkIcon, ArrowRight, ChevronRight, Home, + Eye, Download, Upload, Share, + MessageSquare, Send, Inbox, Bell, Megaphone, + Radio, Headphones, Mic, Video, Calendar, + Gamepad2, Zap, Server, Globe, Wifi, Signal, + Activity, BarChart, TrendingUp, Target, Trophy, + Settings, Wrench, Cog, Sliders, Filter, + Lock, Unlock, Key, ShieldCheck, ShieldAlert, + Plus, Minus, Check, X, AlertTriangle, CheckCircle, + XCircle, Clock, Timer, Pause, Play, + CreditCard, DollarSign, Gift, Star, Heart, ThumbsUp, + Flag, Map, Compass, Navigation, Bookmark, Tag, +} from 'lucide-react'; import { Button } from '@modl-gg/shared-web/components/ui/button'; import { Input } from '@modl-gg/shared-web/components/ui/input'; import { Card, CardContent, CardHeader, CardTitle } from '@modl-gg/shared-web/components/ui/card'; import { Collapsible, CollapsibleTrigger } from '@modl-gg/shared-web/components/ui/collapsible'; import { useTheme } from 'next-themes'; import serverLogo from '@/assets/server-logo.png'; -import * as LucideIcons from 'lucide-react'; import { usePublicSettings } from '@/hooks/use-public-settings'; import { useAuth } from '@/hooks/use-auth'; import { apiFetch } from '@/lib/api'; +// Allowlist of icons usable by homepage cards; mirrors HomepageCardSettings curated list. +const ICONS: Record> = { + Shield, UserPlus, MessageCircle, Mail, Phone, Scale, + Users, User, UserCheck, UserX, Crown, Award, + BookOpen, Book, FileText, ScrollText, Newspaper, + Library, GraduationCap, HelpCircle, Info, AlertCircle, + ExternalLink, Link: LinkIcon, ArrowRight, ChevronRight, Home, + Search, Eye, Download, Upload, Share, + MessageSquare, Send, Inbox, Bell, Megaphone, + Radio, Headphones, Mic, Video, Calendar, + Gamepad2, Zap, Server, Globe, Wifi, Signal, + Activity, BarChart, TrendingUp, Target, Trophy, + Settings, Wrench, Cog, Sliders, Filter, + Lock, Unlock, Key, ShieldCheck, ShieldAlert, + Plus, Minus, Check, X, AlertTriangle, CheckCircle, + XCircle, Clock, Timer, Pause, Play, + CreditCard, DollarSign, Gift, Star, Heart, ThumbsUp, + Flag, Map, Compass, Navigation, Bookmark, Tag, +}; + // Types for knowledgebase data interface ArticleStub { id: string; @@ -137,8 +172,7 @@ const HomePage: React.FC = () => { // Function to get the icon component from Lucide const getIconComponent = (iconName: string) => { - const IconComponent = (LucideIcons as any)[iconName]; - return IconComponent || BookOpen; // Fallback to BookOpen if icon not found + return ICONS[iconName] || BookOpen; // Fallback to BookOpen if icon not found }; // Function to toggle expanded state for category dropdown cards diff --git a/client/src/pages/RateLimitPage.tsx b/client/src/pages/RateLimitPage.tsx index 394b595..be6040f 100644 --- a/client/src/pages/RateLimitPage.tsx +++ b/client/src/pages/RateLimitPage.tsx @@ -3,6 +3,7 @@ import { useRouter } from 'wouter'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@modl-gg/shared-web/components/ui/card'; import { Button } from '@modl-gg/shared-web/components/ui/button'; import { AlertCircle, Clock, RefreshCw } from 'lucide-react'; +import { Notice } from '@/components/ui/notice'; import { useTranslation } from 'react-i18next'; interface RateLimitInfo { @@ -88,31 +89,31 @@ export default function RateLimitPage() { }; return ( -
+
-
- +
+
- + {t('pages.rateLimit.title')} - + {t('pages.rateLimit.description')} - + {/* Time remaining display */} {timeLeft > 0 && ( -
+
- - + + {t('pages.rateLimit.timeRemaining')}
-
+
{formatTime(timeLeft)}
@@ -120,23 +121,23 @@ export default function RateLimitPage() { {/* Rate limit details */} {rateLimitInfo.rateLimit && ( -
+
{t('pages.rateLimit.rateLimitLabel')} {rateLimitInfo.rateLimit}
)} {/* Custom message */} {rateLimitInfo.message && ( -
+
{rateLimitInfo.message}
)} {/* Security note */} {rateLimitInfo.securityNote && ( -
- {t('pages.rateLimit.securityInfo')} {rateLimitInfo.securityNote} -
+ + {rateLimitInfo.securityNote} + )} {/* Action buttons */} @@ -173,7 +174,7 @@ export default function RateLimitPage() {
{/* Help text */} -
+
{t('pages.rateLimit.helpText')}
diff --git a/client/src/pages/api-docs.tsx b/client/src/pages/api-docs.tsx index c003fdd..e9da3c6 100644 --- a/client/src/pages/api-docs.tsx +++ b/client/src/pages/api-docs.tsx @@ -319,11 +319,12 @@ const ApiDocs = () => { {endpoint.routes.map((route, index) => (
- {route.method} diff --git a/client/src/pages/audit.tsx b/client/src/pages/audit.tsx index 40543f2..ab6b6e2 100644 --- a/client/src/pages/audit.tsx +++ b/client/src/pages/audit.tsx @@ -1,4 +1,4 @@ -import { useState, useMemo, useEffect } from 'react'; +import { useState, useMemo, useEffect, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { ChevronDown, @@ -25,12 +25,14 @@ import { ChevronLeft, ChevronRight } from 'lucide-react'; -import { getApiUrl, getCurrentDomain, apiFetch } from '@/lib/api'; +import { apiFetch } from '@/lib/api'; import { Button } from '@modl-gg/shared-web/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@modl-gg/shared-web/components/ui/card'; import { Badge } from '@modl-gg/shared-web/components/ui/badge'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@modl-gg/shared-web/components/ui/select'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogPortal } from '@modl-gg/shared-web/components/ui/dialog'; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@modl-gg/shared-web/components/ui/alert-dialog'; +import { Textarea } from '@modl-gg/shared-web/components/ui/textarea'; import { subDays } from 'date-fns'; import { formatDateOnly } from '@/utils/date-utils'; import { useLogs } from '@/hooks/use-data'; @@ -165,55 +167,37 @@ const formatDurationDetailed = (date: Date) => { // API functions const fetchAnalyticsOverview = async () => { - const response = await fetch(getApiUrl('/v1/panel/analytics/overview'), { - credentials: 'include', - headers: { 'X-Server-Domain': getCurrentDomain() } - }); + const response = await apiFetch('/v1/panel/analytics/overview'); if (!response.ok) throw new Error('Failed to fetch analytics overview'); return response.json(); }; const fetchStaffPerformance = async (period = '30d') => { - const response = await fetch(getApiUrl(`/v1/panel/audit/staff-performance?period=${period}`), { - credentials: 'include', - headers: { 'X-Server-Domain': getCurrentDomain() } - }); + const response = await apiFetch(`/v1/panel/audit/staff-performance?period=${period}`); if (!response.ok) throw new Error('Failed to fetch staff performance'); return response.json(); }; const fetchTicketAnalytics = async (period = '30d') => { - const response = await fetch(getApiUrl(`/v1/panel/analytics/tickets?period=${period}`), { - credentials: 'include', - headers: { 'X-Server-Domain': getCurrentDomain() } - }); + const response = await apiFetch(`/v1/panel/analytics/tickets?period=${period}`); if (!response.ok) throw new Error('Failed to fetch ticket analytics'); return response.json(); }; const fetchPunishmentAnalytics = async (period = '30d') => { - const response = await fetch(getApiUrl(`/v1/panel/analytics/punishments?period=${period}`), { - credentials: 'include', - headers: { 'X-Server-Domain': getCurrentDomain() } - }); + const response = await apiFetch(`/v1/panel/analytics/punishments?period=${period}`); if (!response.ok) throw new Error('Failed to fetch punishment analytics'); return response.json(); }; const fetchPlayerActivity = async (period = '30d') => { - const response = await fetch(getApiUrl(`/v1/panel/analytics/player-activity?period=${period}`), { - credentials: 'include', - headers: { 'X-Server-Domain': getCurrentDomain() } - }); + const response = await apiFetch(`/v1/panel/analytics/player-activity?period=${period}`); if (!response.ok) throw new Error('Failed to fetch player activity'); return response.json(); }; const fetchAuditLogsAnalytics = async (period = '7d') => { - const response = await fetch(getApiUrl(`/v1/panel/analytics/audit-logs?period=${period}`), { - credentials: 'include', - headers: { 'X-Server-Domain': getCurrentDomain() } - }); + const response = await apiFetch(`/v1/panel/analytics/audit-logs?period=${period}`); if (!response.ok) throw new Error('Failed to fetch audit logs analytics'); return response.json(); }; @@ -239,10 +223,7 @@ interface ActivePunishment { } const fetchPunishmentsList = async (status: string): Promise => { - const response = await fetch(getApiUrl(`/v1/panel/audit/punishments/active?status=${status}`), { - credentials: 'include', - headers: { 'X-Server-Domain': getCurrentDomain() } - }); + const response = await apiFetch(`/v1/panel/audit/punishments/active?status=${status}`); if (!response.ok) throw new Error('Failed to fetch punishments'); return response.json(); }; @@ -254,7 +235,7 @@ const CustomTooltip = ({ active, payload, label, formatValue, formatName }: any)
{label &&

{label}

} {payload.map((entry: any, index: number) => ( -
+
{ @@ -481,7 +463,7 @@ const BulkPunishmentActionsModal = ({ activePunishments, onSuccess }: { return durationValue * (multipliers[durationUnit] || multipliers.days); }; - const handleSubmit = async () => { + const handleSubmit = () => { if (selectedTypes.size === 0) { toast({ title: 'No types selected', description: 'Select at least one punishment type.', variant: 'destructive' }); return; @@ -490,12 +472,11 @@ const BulkPunishmentActionsModal = ({ activePunishments, onSuccess }: { toast({ title: 'Reason required', description: 'Please provide a reason.', variant: 'destructive' }); return; } + setConfirmOpen(true); + }; - const actionLabel = operation === 'pardon' ? 'pardon' : 'set expiration on'; - if (!window.confirm(`Are you sure you want to ${actionLabel} ${previewCount} punishment(s)? This cannot be undone.`)) { - return; - } - + const performSubmit = async () => { + setConfirmOpen(false); setIsSubmitting(true); try { const endpoint = operation === 'pardon' @@ -667,6 +648,25 @@ const BulkPunishmentActionsModal = ({ activePunishments, onSuccess }: {
+ + + + Confirm Bulk Action + + {`Are you sure you want to ${operation === 'pardon' ? 'pardon' : 'set expiration on'} ${previewCount} punishment(s)? This cannot be undone.`} + + + + Cancel + + Confirm + + + + ); }; @@ -679,6 +679,13 @@ const StaffDetailModal = ({ staff, isOpen, onClose, initialPeriod = '30d' }: { initialPeriod?: string }) => { const [selectedPeriod, setSelectedPeriod] = useState(initialPeriod); + const [rollbackDialog, setRollbackDialog] = useState<{ open: boolean; punishmentId: string | null; summary: string; reason: string; submitting: boolean }>({ + open: false, + punishmentId: null, + summary: '', + reason: '', + submitting: false, + }); const { toast } = useToast(); const { t } = useTranslation(); const { openPlayerWindow, windows } = usePlayerWindow(); @@ -710,6 +717,78 @@ const StaffDetailModal = ({ staff, isOpen, onClose, initialPeriod = '30d' }: { const recentTickets = staffDetails?.tickets || []; const evidenceCount = staffDetails?.evidenceUploads || 0; + const openRollbackDialog = useCallback((punishmentId: string, summary: string) => { + setRollbackDialog({ open: true, punishmentId, summary, reason: '', submitting: false }); + }, []); + + const handleConfirmRollback = useCallback(async () => { + const { punishmentId, reason } = rollbackDialog; + if (!punishmentId || !reason.trim()) return; + setRollbackDialog(prev => ({ ...prev, submitting: true })); + try { + const response = await apiFetch(`/v1/panel/audit/punishments/${punishmentId}/rollback`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ reason: reason.trim() }) + }); + + const responseData = await response.json(); + + if (!response.ok) { + throw new Error(responseData.error || `HTTP ${response.status}: ${response.statusText}`); + } + + toast({ + title: t('audit.punishmentRolledBack'), + description: t('audit.punishmentRolledBackSuccess', { message: responseData.message }) + }); + setRollbackDialog({ open: false, punishmentId: null, summary: '', reason: '', submitting: false }); + refetch(); + } catch (error) { + console.error('Rollback error:', error); + toast({ + title: t('audit.rollbackFailed'), + description: t('audit.rollbackFailedWithError', { error: error instanceof Error ? error.message : t('audit.unknownError') }), + variant: 'destructive' + }); + setRollbackDialog(prev => ({ ...prev, submitting: false })); + } + }, [rollbackDialog, refetch, toast, t]); + + // Format helpers hoisted out of the .map for the recent punishments table + const formatRecentPunishmentDuration = useCallback((duration: any): string => { + const durationNum = typeof duration === 'number' ? duration : Number(duration); + if (!durationNum || durationNum === -1 || isNaN(durationNum)) return t('audit.permanent'); + + const days = Math.floor(durationNum / (1000 * 60 * 60 * 24)); + const hours = Math.floor((durationNum % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor((durationNum % (1000 * 60 * 60)) / (1000 * 60)); + + if (days > 0) return `${days}d ${hours}h`; + if (hours > 0) return `${hours}h ${minutes}m`; + return `${minutes}m`; + }, [t]); + + const getRecentPunishmentStatus = useCallback((punishment: any) => { + const hasPardon = punishment.modifications?.some((mod: any) => + mod.type === 'MANUAL_PARDON' || + mod.type === 'APPEAL_ACCEPT' || + mod.type === 'Pardoned' || + mod.type === 'Appeal Accepted' || + mod.type === 'Appeal Approved' + ); + + if (hasPardon || punishment.rolledBack) { + return { status: t('audit.pardoned'), isActive: false, variant: 'outline' as const, color: 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 border-green-300 dark:border-green-700' }; + } + + if (punishment.active === false) { + return { status: t('status.inactive'), isActive: false, variant: 'outline' as const, color: 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 border-gray-300 dark:border-gray-700' }; + } + + return { status: t('status.active'), isActive: true, variant: 'outline' as const, color: 'bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 border-red-300 dark:border-red-700' }; + }, [t]); + return ( {recentPunishments.length > 0 ? recentPunishments.map((punishment: any, index: number) => { - // Format duration helper function - const formatDuration = (duration: any) => { - const durationNum = typeof duration === 'number' ? duration : Number(duration); - if (!durationNum || durationNum === -1 || isNaN(durationNum)) return t('audit.permanent'); - - const days = Math.floor(durationNum / (1000 * 60 * 60 * 24)); - const hours = Math.floor((durationNum % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); - const minutes = Math.floor((durationNum % (1000 * 60 * 60)) / (1000 * 60)); - - if (days > 0) return `${days}d ${hours}h`; - if (hours > 0) return `${hours}h ${minutes}m`; - return `${minutes}m`; - }; - - // Determine punishment status - const getPunishmentStatus = (punishment: any) => { - // Check for pardoned/appeal accepted modifications - const hasPardon = punishment.modifications?.some((mod: any) => - mod.type === 'MANUAL_PARDON' || - mod.type === 'APPEAL_ACCEPT' || - mod.type === 'Pardoned' || - mod.type === 'Appeal Accepted' || - mod.type === 'Appeal Approved' - ); - - if (hasPardon || punishment.rolledBack) { - return { status: t('audit.pardoned'), isActive: false, variant: 'outline' as const, color: 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 border-green-300 dark:border-green-700' }; - } - - if (punishment.active === false) { - return { status: t('status.inactive'), isActive: false, variant: 'outline' as const, color: 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 border-gray-300 dark:border-gray-700' }; - } - - return { status: t('status.active'), isActive: true, variant: 'outline' as const, color: 'bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 border-red-300 dark:border-red-700' }; - }; - - const statusInfo = getPunishmentStatus(punishment); + const statusInfo = getRecentPunishmentStatus(punishment); + const punishmentRowKey = punishment.id || `recent-punishment-${index}`; return ( - +
+ { + if (!o) setRollbackDialog({ open: false, punishmentId: null, summary: '', reason: '', submitting: false }); + }} + > + + + {t('audit.rollbackThisPunishment')} + {rollbackDialog.summary} + +
+ +