From 27a3402a2ad53088a1b8eac2294da2692a297c64 Mon Sep 17 00:00:00 2001 From: Marcelo Santos Date: Sat, 15 Nov 2025 21:18:35 +0000 Subject: [PATCH 1/7] Update content --- .gitignore | 1 + next-env.d.ts | 5 + src/App.tsx | 8 +- src/content/common/navigation.json | 40 +++---- src/content/en/eventos.json | 9 +- src/content/en/fidelidade.json | 73 ------------- src/content/en/gestao-estoque.json | 10 ++ src/content/en/home.json | 49 +++++---- src/content/en/realtime.json | 10 ++ src/content/es/eventos.json | 9 +- src/content/es/fidelidade.json | 73 ------------- src/content/es/gestao-estoque.json | 10 ++ src/content/es/home.json | 38 +++---- src/content/es/integracoes.json | 2 +- src/content/es/menu-digital.json | 2 +- src/content/es/painel.json | 2 +- src/content/es/realtime.json | 10 ++ src/content/fr/eventos.json | 9 +- src/content/fr/fidelidade.json | 73 ------------- src/content/fr/gestao-estoque.json | 10 ++ src/content/fr/home.json | 161 ++--------------------------- src/content/fr/menu-digital.json | 2 +- src/content/fr/realtime.json | 10 ++ src/content/pt/blog.json | 2 +- src/content/pt/eventos.json | 41 +------- src/content/pt/fidelidade.json | 73 ------------- src/content/pt/gestao-estoque.json | 10 ++ src/content/pt/home.json | 38 +++---- src/content/pt/integracoes.json | 2 +- src/content/pt/menu-digital.json | 2 +- src/content/pt/painel.json | 2 +- src/content/pt/realtime.json | 10 ++ src/globals.css | 12 +-- src/pages/Eventos.tsx | 6 +- src/pages/Fidelidade.tsx | 8 -- src/pages/GestaoEstoque.tsx | 8 ++ src/pages/Realtime.tsx | 8 ++ 37 files changed, 228 insertions(+), 610 deletions(-) create mode 100644 next-env.d.ts delete mode 100644 src/content/en/fidelidade.json create mode 100644 src/content/en/gestao-estoque.json create mode 100644 src/content/en/realtime.json delete mode 100644 src/content/es/fidelidade.json create mode 100644 src/content/es/gestao-estoque.json create mode 100644 src/content/es/realtime.json delete mode 100644 src/content/fr/fidelidade.json create mode 100644 src/content/fr/gestao-estoque.json create mode 100644 src/content/fr/realtime.json delete mode 100644 src/content/pt/fidelidade.json create mode 100644 src/content/pt/gestao-estoque.json create mode 100644 src/content/pt/realtime.json delete mode 100644 src/pages/Fidelidade.tsx create mode 100644 src/pages/GestaoEstoque.tsx create mode 100644 src/pages/Realtime.tsx diff --git a/.gitignore b/.gitignore index b33e7c1..0d4c535 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ playwright/.cache/ # Lighthouse CI .lighthouseci/ +.next/ \ No newline at end of file diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..1b3be08 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/src/App.tsx b/src/App.tsx index 11e4cd0..59fb1c2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,8 +20,8 @@ const TermsOfService = lazy(() => import("./pages/legal/TermsOfService")); const Painel = lazy(() => import("./pages/Painel")); const MenuDigital = lazy(() => import("./pages/MenuDigital")); const Fornecedores = lazy(() => import("./pages/Fornecedores")); -const Fidelidade = lazy(() => import("./pages/Fidelidade")); -const Eventos = lazy(() => import("./pages/Eventos")); +const Realtime = lazy(() => import("./pages/Realtime")); +const GestaoEstoque = lazy(() => import("./pages/GestaoEstoque")); const Integracoes = lazy(() => import("./pages/Integracoes")); // Simple loading fallback @@ -53,8 +53,8 @@ const App = () => ( } /> } /> } /> - } /> - } /> + } /> + } /> } /> } /> } /> diff --git a/src/content/common/navigation.json b/src/content/common/navigation.json index 9ecdadc..e84c35a 100644 --- a/src/content/common/navigation.json +++ b/src/content/common/navigation.json @@ -64,41 +64,41 @@ } }, { - "id": "fidelidade", + "id": "realtime", "type": "link", - "href": "/fidelidade", + "href": "/realtime", "localeAware": true, "depth": "surface", "label": { - "pt": "Fidelidade", - "en": "Loyalty", - "es": "Fidelidad", - "fr": "Fidélité" + "pt": "Sincronização (Tempo Real)", + "en": "Realtime", + "es": "Sincronización", + "fr": "Temps réel" }, "description": { - "pt": "Campanhas personalizadas e recompensas automáticas para clientes fiéis.", - "en": "Personalized campaigns and automated rewards for loyal guests.", - "es": "Campañas personalizadas y recompensas automáticas para clientes fieles.", - "fr": "Campagnes personnalisées et récompenses automatiques pour les clients fidèles." + "pt": "Sincronize pedidos, mesas e estoque em tempo real com broadcast entre dispositivos.", + "en": "Sync orders, tables and stock in realtime with device broadcast.", + "es": "Sincroniza pedidos, mesas y stock en tiempo real con broadcast entre dispositivos.", + "fr": "Synchronisez commandes, tables et stocks en temps réel avec broadcast entre appareils." } }, { - "id": "eventos", + "id": "gestao-estoque", "type": "link", - "href": "/eventos", + "href": "/gestao-estoque", "localeAware": true, "depth": "surface", "label": { - "pt": "Eventos", - "en": "Events", - "es": "Eventos", - "fr": "Événements" + "pt": "Gestão do Estoque", + "en": "Inventory & Operations", + "es": "Gestión de Inventario", + "fr": "Gestion des stocks" }, "description": { - "pt": "Agenda integrada com reservas, checklist da equipe e pós-evento.", - "en": "Integrated calendar with reservations, staff checklists, and follow-ups.", - "es": "Agenda integrada con reservas, checklist del equipo y seguimiento.", - "fr": "Agenda intégré avec réservations, checklist d'équipe et suivi." + "pt": "Controle itens, movimentações de stock e registros de vendas a partir do painel.", + "en": "Manage items, stock movements and sales records from a central panel.", + "es": "Controle artículos, movimientos de stock y registros de ventas desde un panel central.", + "fr": "Gérez articles, mouvements de stock et enregistrements de ventes depuis un panneau central." } }, { diff --git a/src/content/en/eventos.json b/src/content/en/eventos.json index 6ced3bf..e61ed21 100644 --- a/src/content/en/eventos.json +++ b/src/content/en/eventos.json @@ -1,9 +1,8 @@ { - "seo": { - "title": "Event Management | Boteco Pro", - "description": "Plan schedules, staff, and guest experiences with smart checklists and post-event analytics." - }, - "hero": { + "archived": true, + "redirect": "/gestao-estoque", + "note": "This page was removed — see /gestao-estoque for inventory & operations features." +} "title": "Flawless events from kickoff to encore", "subtitle": "Manage reservations, production, and team communication through a collaborative visual board.", "cta": { diff --git a/src/content/en/fidelidade.json b/src/content/en/fidelidade.json deleted file mode 100644 index bbf8d86..0000000 --- a/src/content/en/fidelidade.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "seo": { - "title": "Omnichannel Loyalty Program | Boteco Pro", - "description": "Launch segmented campaigns with automated rewards and measure their impact on recurrence and spend." - }, - "hero": { - "title": "Turn guests into loyal fans", - "subtitle": "Deploy clubs, cashback, and personalized challenges powered by real-time insights.", - "cta": { - "label": "Build my program", - "href": "/contact" - } - }, - "benefits": { - "title": "Predictable retention with personalized journeys", - "items": [ - { - "title": "Dynamic segmentation", - "description": "Create rules by frequency, spend, or preferences and deliver benefits automatically." - }, - { - "title": "Digital wallet", - "description": "Guests collect points, stamps, or credits in a ready-to-use app integrated with your POS." - }, - { - "title": "Retention analytics", - "description": "Visualize cohorts, churn, and average visit gap to adjust campaigns." - } - ] - }, - "workflow": { - "title": "How to launch loyalty campaigns", - "steps": [ - { - "title": "Set objectives", - "description": "Choose targets for visits, spend, or frequency and pick your audiences." - }, - { - "title": "Activate rewards", - "description": "Configure stamps, vouchers, or VIP experiences with automated notifications." - }, - { - "title": "Evaluate results", - "description": "Track adoption, redemption, and financial impact to iterate fast." - } - ] - }, - "highlights": { - "title": "Features guests will love", - "items": [ - { - "title": "Inclusive gamification", - "description": "Accessible challenges with screen-reader support, alt text, and synced progress." - }, - { - "title": "Omnichannel messaging", - "description": "Send push, email, or SMS with automatically localized templates." - }, - { - "title": "Payment integrations", - "description": "Redeem rewards right at the register with anti-fraud validation." - } - ] - }, - "cta": { - "title": "Create fans who return every week", - "description": "Personalize loyalty journeys without complicating operations.", - "button": { - "label": "Schedule a consultation", - "href": "/contact" - } - } -} diff --git a/src/content/en/gestao-estoque.json b/src/content/en/gestao-estoque.json new file mode 100644 index 0000000..8eb6594 --- /dev/null +++ b/src/content/en/gestao-estoque.json @@ -0,0 +1,10 @@ +{ + "seo": {"title": "Inventory & Operations | Boteco Pro"}, + "hero": { + "title": "Inventory, Orders and Sales Management", + "description": "Manage inventory, stock movements and sales records with automated updates.", + "cta": {"label": "Learn about Inventory", "href": "/contact"} + }, + "benefits": ["Inventory control", "Stock movements", "Sales records and simple daily reports"], + "cta": {"label": "Request demo", "href": "/contact"} +} diff --git a/src/content/en/home.json b/src/content/en/home.json index 708944c..c050610 100644 --- a/src/content/en/home.json +++ b/src/content/en/home.json @@ -6,23 +6,20 @@ "demoCta": "Try the demo", "demoCtaAria": "Try the Boteco Pro demo (opens in a new tab)" }, - "features": [ + "faq": [ { - "title": "Omnichannel Digital Menu", - "description": "Update the menu in real time and deliver inclusive QR experiences." + "question": "Can I manage suppliers and operations together?", + "answer": "Yes — manage quotes, deliveries, inventory and staff in collaborative flows within the platform." }, { - "title": "Smart Purchasing", - "description": "Centralize suppliers, contracts, and deliveries with automated alerts." - }, - { - "title": "Loyalty and Insights", - "description": "Launch personalized campaigns and track results with rich dashboards." + "question": "Is there inventory control ready to use?", + "answer": "Yes. Track items, stock movements and simple daily reports to keep operations aligned." } ], + "description": "Centralize suppliers, contracts, and deliveries with automated alerts.", "solutions": { "title": "Connected solutions for your operation", - "subtitle": "Bring digital menu, suppliers, loyalty, events, and integrations together in one ecosystem.", + "subtitle": "Bring digital menu, suppliers, realtime sync and inventory management together in one ecosystem.", "items": [ { "title": "Digital Menu", @@ -38,16 +35,16 @@ "ctaLabel": "Streamline purchasing" }, { - "title": "Loyalty Program", - "description": "Digital wallet, segmented campaigns, and real-time retention metrics.", - "href": "/fidelidade", - "ctaLabel": "Engage guests" + "title": "Realtime Synchronization", + "description": "Keep orders, tables and stock in sync across devices with device-to-device broadcast.", + "href": "/realtime", + "ctaLabel": "Learn about realtime" }, { - "title": "Events and Experiences", - "description": "Collaborative checklists, integrated reservations, and post-event reports.", - "href": "/eventos", - "ctaLabel": "Plan the calendar" + "title": "Inventory & Operations", + "description": "Manage items, stock movements and sales records with simple daily reports.", + "href": "/gestao-estoque", + "ctaLabel": "Manage inventory" }, { "title": "Native Integrations", @@ -97,7 +94,7 @@ } ] }, - "platformCarousel": { + "ecosystem": { "title": "See the Boteco Pro ecosystem in action", "items": [ { @@ -113,10 +110,10 @@ "href": "/menu-digital" }, { - "title": "Omnichannel loyalty", - "description": "Segmented campaigns, cashback, and automations to boost recurrence.", - "ctaLabel": "Build loyalty", - "href": "/fidelidade" + "title": "Realtime & Operations", + "description": "Automatic updates for orders, tables and stock with activity indicators.", + "ctaLabel": "Learn about realtime", + "href": "/realtime" } ] }, @@ -129,7 +126,7 @@ } ] }, - "faq": { + "faqSection": { "title": "Frequently Asked Questions", "items": [ { @@ -146,7 +143,7 @@ } ] }, - "ecosystemCta": { + "contact": { "title": "Connect hospitality with technology", "description": "Talk to the Boteco Pro team to craft digital journeys that delight guests from booking to re-engagement.", "actions": [ @@ -162,7 +159,7 @@ } ] }, - "finalCta": { + "readyToTransform": { "title": "Ready to transform your business?", "button": "Contact Us" } diff --git a/src/content/en/realtime.json b/src/content/en/realtime.json new file mode 100644 index 0000000..a4284ab --- /dev/null +++ b/src/content/en/realtime.json @@ -0,0 +1,10 @@ +{ + "seo": {"title": "Realtime Sync | Boteco Pro"}, + "hero": { + "title": "Realtime Synchronization & Broadcast", + "description": "Keep orders, tables and stock in sync across devices with near-instant updates.", + "cta": {"label": "Learn about Realtime", "href": "/contact"} + }, + "benefits": ["Automatic updates for orders, tables and stock", "Activity indicators and operational status", "Device-to-device broadcast"], + "cta": {"label": "Request demo", "href": "/contact"} +} diff --git a/src/content/es/eventos.json b/src/content/es/eventos.json index 2b664ac..24d0246 100644 --- a/src/content/es/eventos.json +++ b/src/content/es/eventos.json @@ -1,9 +1,8 @@ { - "seo": { - "title": "Gestión de Eventos | Boteco Pro", - "description": "Planifica agendas, equipos y experiencias de clientes con checklists inteligentes y reportes post-evento." - }, - "hero": { + "archived": true, + "redirect": "/gestao-estoque", + "note": "Este contenido fue eliminado — consulte /gestao-estoque para inventario y operaciones." +} "title": "Eventos impecables de principio a fin", "subtitle": "Controla reservas, producción y comunicación del equipo en un tablero visual colaborativo.", "cta": { diff --git a/src/content/es/fidelidade.json b/src/content/es/fidelidade.json deleted file mode 100644 index b635b11..0000000 --- a/src/content/es/fidelidade.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "seo": { - "title": "Programa de Fidelidad Omnicanal | Boteco Pro", - "description": "Lanza campañas segmentadas con recompensas automáticas y mide el impacto en recurrencia y gasto." - }, - "hero": { - "title": "Convierte a los clientes en fans leales", - "subtitle": "Crea clubes, cashback y desafíos personalizados con insights en tiempo real.", - "cta": { - "label": "Crear programa", - "href": "/contacto" - } - }, - "benefits": { - "title": "Retención predecible con jornadas personalizadas", - "items": [ - { - "title": "Segmentación dinámica", - "description": "Define reglas por frecuencia, ticket o preferencias y entrega beneficios automáticamente." - }, - { - "title": "Billetera digital", - "description": "Los clientes acumulan puntos, sellos o créditos en una app integrada al POS." - }, - { - "title": "Analítica de retención", - "description": "Visualiza cohorts, churn y tiempo promedio entre visitas para ajustar campañas." - } - ] - }, - "workflow": { - "title": "Cómo lanzar campañas de fidelidad", - "steps": [ - { - "title": "Define objetivos", - "description": "Elige metas de visitas, ticket o frecuencia y selecciona tus audiencias." - }, - { - "title": "Activa recompensas", - "description": "Configura sellos, cupones o experiencias VIP con notificaciones automáticas." - }, - { - "title": "Evalúa resultados", - "description": "Sigue adhesión, rescate e impacto financiero para iterar rápido." - } - ] - }, - "highlights": { - "title": "Funcionalidades que encantan", - "items": [ - { - "title": "Gamificación inclusiva", - "description": "Desafíos accesibles con lectura de pantalla, textos alternativos y progreso sincronizado." - }, - { - "title": "Mensajería omnicanal", - "description": "Envía push, e-mail o SMS con plantillas traducidas automáticamente." - }, - { - "title": "Integración con pagos", - "description": "Canje directo en caja con validación antifraude." - } - ] - }, - "cta": { - "title": "Crea fans que regresen cada semana", - "description": "Personaliza jornadas de fidelidad sin complicar la operación.", - "button": { - "label": "Agendar consultoría", - "href": "/contacto" - } - } -} diff --git a/src/content/es/gestao-estoque.json b/src/content/es/gestao-estoque.json new file mode 100644 index 0000000..eab12cb --- /dev/null +++ b/src/content/es/gestao-estoque.json @@ -0,0 +1,10 @@ +{ + "seo": {"title": "Gestión de Inventario y Operaciones | Boteco Pro"}, + "hero": { + "title": "Gestión de Inventario, Pedidos y Ventas", + "description": "Controle inventario, movimientos de stock y registros de ventas con actualizaciones automáticas.", + "cta": {"label": "Conocer Gestión de Inventario", "href": "/contacto"} + }, + "benefits": ["Control de inventario", "Movimientos de stock", "Registros de ventas y reportes simples del día"], + "cta": {"label": "Solicitar demo", "href": "/contacto"} +} diff --git a/src/content/es/home.json b/src/content/es/home.json index ac48d34..7e87d6e 100644 --- a/src/content/es/home.json +++ b/src/content/es/home.json @@ -16,13 +16,13 @@ "description": "Centraliza proveedores, contratos y entregas con alertas automáticas." }, { - "title": "Fidelización e insights", - "description": "Lanza campañas personalizadas y monitorea resultados con paneles completos." + "title": "Inventario, Pedidos y Ventas", + "description": "Gestiona inventario, movimientos de stock y registros de ventas con actualizaciones automáticas." } ], "solutions": { "title": "Soluciones conectadas para tu operación", - "subtitle": "Integra menú digital, proveedores, fidelidad, eventos e integraciones en un solo ecosistema.", + "subtitle": "Integra menú digital, proveedores, sincronización en tiempo real y gestión de inventario en un solo ecosistema.", "items": [ { "title": "Menú digital", @@ -38,16 +38,16 @@ "ctaLabel": "Optimizar compras" }, { - "title": "Programa de fidelidad", - "description": "Billetera digital, campañas segmentadas y métricas de retención en tiempo real.", - "href": "/fidelidade", - "ctaLabel": "Enganchar clientes" + "title": "Sincronización en Tiempo Real", + "description": "Sincroniza pedidos, mesas y stock entre dispositivos con broadcast y baja latencia.", + "href": "/realtime", + "ctaLabel": "Conocer sincronización" }, { - "title": "Eventos y experiencias", - "description": "Checklists colaborativos, reservas integradas y reportes post-evento.", - "href": "/eventos", - "ctaLabel": "Planificar agenda" + "title": "Gestión de Inventario y Operaciones", + "description": "Controla artículos, movimientos y ventas con informes simples diarios.", + "href": "/gestao-estoque", + "ctaLabel": "Gestionar inventario" }, { "title": "Integraciones nativas", @@ -113,10 +113,10 @@ "href": "/menu-digital" }, { - "title": "Fidelidad omnicanal", - "description": "Campañas segmentadas, cashback y automatizaciones para aumentar la recurrencia.", - "ctaLabel": "Crear fidelidad", - "href": "/fidelidade" + "title": "Sincronización y operaciones", + "description": "Actualizaciones automáticas de pedidos, mesas y stock con indicadores de actividad.", + "ctaLabel": "Conocer sincronización", + "href": "/realtime" } ] }, @@ -137,12 +137,12 @@ "answer": "Sí. Boteco Pro sincroniza carta, pedidos y pagos para actualizar inventario y reportes automáticamente." }, { - "question": "¿Puedo gestionar proveedores y eventos juntos?", - "answer": "Controlas cotizaciones, entregas, agenda de eventos y equipo en flujos colaborativos dentro de la plataforma." + "question": "¿Puedo gestionar proveedores y operaciones juntos?", + "answer": "Controlas cotizaciones, entregas, inventario y equipo en flujos colaborativos dentro de la plataforma." }, { - "question": "¿Hay un programa de fidelidad listo para usar?", - "answer": "Sí. Configura puntos, cashback o sellos con notificaciones automáticas y métricas de retención." + "question": "¿Hay control de inventario listo para usar?", + "answer": "Sí. Controla artículos, movimientos de stock y reportes simples del día para mantener la operación." } ] }, diff --git a/src/content/es/integracoes.json b/src/content/es/integracoes.json index a05e932..6980308 100644 --- a/src/content/es/integracoes.json +++ b/src/content/es/integracoes.json @@ -50,7 +50,7 @@ "items": [ { "title": "Webhooks y API GraphQL", - "description": "Accede a eventos en tiempo real y construye integraciones personalizadas con seguridad." + "description": "Accede a sincronización en tiempo real y construye integraciones personalizadas con seguridad." }, { "title": "Biblioteca de conectores", diff --git a/src/content/es/menu-digital.json b/src/content/es/menu-digital.json index f324cdf..9b36aba 100644 --- a/src/content/es/menu-digital.json +++ b/src/content/es/menu-digital.json @@ -58,7 +58,7 @@ }, { "title": "Promociones por turno", - "description": "Programa ofertas para almuerzo, happy hour o eventos especiales sin duplicar trabajo." + "description": "Programa ofertas para almuerzo, happy hour o turnos especiales sin duplicar trabajo." } ] }, diff --git a/src/content/es/painel.json b/src/content/es/painel.json index 2653cca..205bbd4 100644 --- a/src/content/es/painel.json +++ b/src/content/es/painel.json @@ -45,7 +45,7 @@ "web-form": "Formulario del sitio", "instagram": "Instagram", "referral": "Referencia", - "events": "Eventos", + "events": "Operaciones", "partnership": "Alianzas" } }, diff --git a/src/content/es/realtime.json b/src/content/es/realtime.json new file mode 100644 index 0000000..6939251 --- /dev/null +++ b/src/content/es/realtime.json @@ -0,0 +1,10 @@ +{ + "seo": {"title": "Sincronización en Tiempo Real | Boteco Pro"}, + "hero": { + "title": "Sincronización y Broadcast en Tiempo Real", + "description": "Actualiza pedidos, mesas y stock automáticamente entre dispositivos con baja latencia.", + "cta": {"label": "Conocer Sincronización", "href": "/contacto"} + }, + "benefits": ["Actualización automática de pedidos, mesas y stock", "Indicadores de actividad y estado operativo", "Broadcast entre dispositivos"], + "cta": {"label": "Solicitar demo", "href": "/contacto"} +} diff --git a/src/content/fr/eventos.json b/src/content/fr/eventos.json index 74645c0..fbad851 100644 --- a/src/content/fr/eventos.json +++ b/src/content/fr/eventos.json @@ -1,9 +1,8 @@ { - "seo": { - "title": "Gestion d'Événements | Boteco Pro", - "description": "Planifiez agendas, équipes et expérience client avec des check-lists intelligentes et des rapports post-événement." - }, - "hero": { + "archived": true, + "redirect": "/gestao-estoque", + "note": "Ce contenu a été supprimé — voir /gestao-estoque pour inventaire et opérations." +} "title": "Des événements impeccables du brief au débrief", "subtitle": "Gérez réservations, production et communication d'équipe via un tableau visuel collaboratif.", "cta": { diff --git a/src/content/fr/fidelidade.json b/src/content/fr/fidelidade.json deleted file mode 100644 index 33e9c54..0000000 --- a/src/content/fr/fidelidade.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "seo": { - "title": "Programme de Fidélité Omnicanal | Boteco Pro", - "description": "Lancez des campagnes segmentées avec récompenses automatiques et mesurez leur impact sur la récurrence." - }, - "hero": { - "title": "Transformez vos clients en fans fidèles", - "subtitle": "Déployez clubs, cashback et défis personnalisés avec des insights en temps réel.", - "cta": { - "label": "Créer mon programme", - "href": "/contact" - } - }, - "benefits": { - "title": "Rétention prévisible grâce à des parcours personnalisés", - "items": [ - { - "title": "Segmentation dynamique", - "description": "Définissez des règles par fréquence, panier ou préférences et distribuez les avantages automatiquement." - }, - { - "title": "Portefeuille digital", - "description": "Les clients accumulent points, tampons ou crédits dans une appli prête à l'emploi connectée au POS." - }, - { - "title": "Analytique de fidélité", - "description": "Visualisez cohortes, churn et délai moyen entre visites pour ajuster vos campagnes." - } - ] - }, - "workflow": { - "title": "Comment lancer vos campagnes de fidélité", - "steps": [ - { - "title": "Définissez vos objectifs", - "description": "Choisissez vos cibles de visites, panier ou fréquence et sélectionnez les audiences." - }, - { - "title": "Activez les récompenses", - "description": "Configurez tampons, bons ou expériences VIP avec notifications automatiques." - }, - { - "title": "Évaluez les résultats", - "description": "Suivez adoption, échanges et impact financier pour itérer rapidement." - } - ] - }, - "highlights": { - "title": "Des fonctionnalités qui enchantent", - "items": [ - { - "title": "Gamification inclusive", - "description": "Défis accessibles avec support lecteur d'écran, textes alternatifs et progression synchronisée." - }, - { - "title": "Communication omnicanale", - "description": "Envoyez push, e-mails ou SMS avec modèles automatiquement localisés." - }, - { - "title": "Intégration aux paiements", - "description": "Utilisez les récompenses directement en caisse avec validation anti-fraude." - } - ] - }, - "cta": { - "title": "Créez des fans qui reviennent chaque semaine", - "description": "Personnalisez vos parcours de fidélité sans complexifier l'opération.", - "button": { - "label": "Planifier une session", - "href": "/contact" - } - } -} diff --git a/src/content/fr/gestao-estoque.json b/src/content/fr/gestao-estoque.json new file mode 100644 index 0000000..4552589 --- /dev/null +++ b/src/content/fr/gestao-estoque.json @@ -0,0 +1,10 @@ +{ + "seo": {"title": "Gestion des Stocks & Opérations | Boteco Pro"}, + "hero": { + "title": "Gestion des stocks, commandes et ventes", + "description": "Contrôlez l'inventaire, les mouvements de stock et les ventes avec des mises à jour automatiques.", + "cta": {"label": "Découvrir la gestion des stocks", "href": "/contact"} + }, + "benefits": ["Contrôle d'inventaire", "Mouvements de stock", "Enregistrements de ventes et rapports simples quotidiens"], + "cta": {"label": "Demander une démo", "href": "/contact"} +} diff --git a/src/content/fr/home.json b/src/content/fr/home.json index e0bd257..7709132 100644 --- a/src/content/fr/home.json +++ b/src/content/fr/home.json @@ -6,164 +6,15 @@ "demoCta": "Essayer la démo", "demoCtaAria": "Essayer la démo Boteco Pro (s'ouvre dans un nouvel onglet)" }, - "features": [ + "faq": [ { - "title": "Menu numérique omnicanal", - "description": "Mettez la carte à jour en temps réel et offrez une expérience QR inclusive." + "question": "Existe-t-il un contrôle d'inventaire prêt à l'emploi?", + "answer": "Oui. Gérez articles, mouvements de stock et rapports simples quotidiens pour garder l'exploitation alignée." }, { - "title": "Achats intelligents", - "description": "Centralisez fournisseurs, contrats et livraisons avec des alertes automatiques." - }, - { - "title": "Fidélisation et insights", - "description": "Lancez des campagnes personnalisées et suivez les résultats via des tableaux de bord complets." + "question": "Puis-je gérer fournisseurs et opérations ensemble?", + "answer": "Vous pilotez devis, livraisons, inventaire et équipes dans des flux collaboratifs au sein de la plateforme." } ], - "solutions": { - "title": "Des solutions connectées pour votre opération", - "subtitle": "Réunissez menu numérique, fournisseurs, fidélité, événements et intégrations dans un même écosystème.", - "items": [ - { - "title": "Menu numérique", - "description": "QR codes avec médias responsives, traductions et suggestions d'upsell intelligentes.", - "href": "/menu-digital", - "ctaLabel": "Découvrir le menu", - "badge": "QR" - }, - { - "title": "Gestion fournisseurs", - "description": "Devis, contrats et livraisons avec traçabilité complète et alertes préventives.", - "href": "/fornecedores", - "ctaLabel": "Optimiser les achats" - }, - { - "title": "Programme de fidélité", - "description": "Portefeuille digital, campagnes segmentées et métriques de rétention en temps réel.", - "href": "/fidelidade", - "ctaLabel": "Engager les clients" - }, - { - "title": "Événements et expériences", - "description": "Check-lists collaboratives, réservations intégrées et rapports post-événement.", - "href": "/eventos", - "ctaLabel": "Planifier le calendrier" - }, - { - "title": "Intégrations natives", - "description": "Connecteurs pour POS, livraison, comptabilité et BI sans friction.", - "href": "/integracoes", - "ctaLabel": "Explorer les intégrations" - } - ] - }, - "howItWorks": { - "title": "Comment ça marche", - "steps": [ - { - "title": "Inscrivez votre établissement", - "description": "Démarrez en quelques minutes, c'est simple et rapide." - }, - { - "title": "Configurez votre carte", - "description": "Ajoutez vos produits et tarifs en toute simplicité." - }, - { - "title": "Commencez à servir", - "description": "Servez vos clients avec rapidité et efficacité." - } - ] - }, - "plans": { - "title": "Nos offres", - "description": "Choisissez la formule idéale pour votre établissement.", - "options": [ - { - "name": "Basic", - "price": "99 €/mois", - "features": [ - "Gestion des tables", - "Contrôle de stock basique" - ] - }, - { - "name": "Premium", - "price": "199 €/mois", - "features": [ - "Toutes les fonctionnalités Basic", - "Rapports avancés", - "Support prioritaire" - ] - } - ] - }, - "platformCarousel": { - "title": "Découvrez l'écosystème Boteco Pro en action", - "items": [ - { - "title": "Intégrations fluides", - "description": "Synchronisez POS, livraison et comptabilité avec suivi en temps réel.", - "ctaLabel": "Voir les intégrations", - "href": "/integracoes" - }, - { - "title": "Menu numérique inclusif", - "description": "Médias responsives, descriptions audio et promotions par service pour étonner vos clients.", - "ctaLabel": "Explorer le menu", - "href": "/menu-digital" - }, - { - "title": "Fidélité omnicanale", - "description": "Campagnes segmentées, cashback et automatisations pour booster la récurrence.", - "ctaLabel": "Créer la fidélité", - "href": "/fidelidade" - } - ] - }, - "testimonials": { - "title": "Ce que disent nos clients", - "quotes": [ - { - "text": "Boteco Pro a révolutionné la gestion de mon bar. Je recommande !", - "author": "Jean Dupont, Le Bar de Jean" - } - ] - }, - "faq": { - "title": "Questions fréquentes", - "items": [ - { - "question": "Le menu numérique s'intègre-t-il à mon POS ?", - "answer": "Oui. Boteco Pro synchronise menu, commandes et paiements pour mettre à jour stock et rapports automatiquement." - }, - { - "question": "Puis-je gérer fournisseurs et événements ensemble ?", - "answer": "Vous pilotez devis, livraisons, agenda et équipes dans des flux collaboratifs au sein de la plateforme." - }, - { - "question": "Disposez-vous d'un programme de fidélité prêt à l'emploi ?", - "answer": "Oui. Paramétrez points, cashback ou tampons avec notifications automatiques et analytics de rétention." - } - ] - }, - "ecosystemCta": { - "title": "Alliez hospitalité et technologie", - "description": "Échangez avec l'équipe Boteco Pro pour créer des parcours digitaux qui enchantent vos clients.", - "actions": [ - { - "label": "Parler à un expert", - "href": "/contact", - "variant": "default" - }, - { - "label": "Explorer les intégrations", - "href": "/integracoes", - "variant": "outline" - } - ] - }, - "finalCta": { - "title": "Prêt à transformer votre établissement ?", - "button": "Nous contacter" - } + "description": "Centralisez fournisseurs, contrats et livraisons avec des alertes automatiques." } diff --git a/src/content/fr/menu-digital.json b/src/content/fr/menu-digital.json index 6040e43..7824431 100644 --- a/src/content/fr/menu-digital.json +++ b/src/content/fr/menu-digital.json @@ -58,7 +58,7 @@ }, { "title": "Promotions par service", - "description": "Planifiez offres déjeuner, happy hour ou événements spéciaux sans double travail." + "description": "Planifiez offres déjeuner, happy hour ou services spéciaux sans double travail." } ] }, diff --git a/src/content/fr/realtime.json b/src/content/fr/realtime.json new file mode 100644 index 0000000..6b5889c --- /dev/null +++ b/src/content/fr/realtime.json @@ -0,0 +1,10 @@ +{ + "seo": {"title": "Synchronisation en Temps Réel | Boteco Pro"}, + "hero": { + "title": "Synchronisation et Broadcast en Temps Réel", + "description": "Mettez à jour commandes, tables et stock automatiquement entre appareils avec une faible latence.", + "cta": {"label": "Découvrir le temps réel", "href": "/contact"} + }, + "benefits": ["Mises à jour automatiques des commandes, tables et stocks", "Indicateurs d'activité et statut opérationnel", "Broadcast entre appareils"], + "cta": {"label": "Demander une démo", "href": "/contact"} +} diff --git a/src/content/pt/blog.json b/src/content/pt/blog.json index 4c071b9..226567b 100644 --- a/src/content/pt/blog.json +++ b/src/content/pt/blog.json @@ -43,7 +43,7 @@ "date": "2023-10-15", "cover": "/images/blog/product-updates.svg", "tags": ["Produto", "Roadmap"], - "content": "# Em Breve: Novas Funcionalidades no Boteco Pro\n\nEstamos preparando melhorias que deixarão a operação diária ainda mais inteligente. Confira um resumo do que vem por aí.\n\n## Painéis mais inteligentes\n\nEm breve será possível cruzar dados de vendas, reservas e fidelidade em uma única visão para acelerar decisões.\n\n## Experimentos de cardápio\n\nCrie menus sazonais e teste preços sem sair da plataforma. O retorno em tempo real ajuda a descobrir campeões de venda rapidamente.\n\n## Suporte integrado\n\nO novo centro de suporte reúne tutoriais, webinars e chat direto com o nosso time.\n\nEstamos ansiosos para compartilhar essas novidades. Acompanhe o blog e seja o primeiro a testar." + "content": "# Em Breve: Novas Funcionalidades no Boteco Pro\n\nEstamos preparando melhorias que deixarão a operação diária ainda mais inteligente. Confira um resumo do que vem por aí.\n\n## Painéis mais inteligentes\n\nEm breve será possível cruzar dados de vendas, reservas e operações em uma única visão para acelerar decisões.\n\n## Experimentos de cardápio\n\nCrie menus sazonais e teste preços sem sair da plataforma. O retorno em tempo real ajuda a descobrir campeões de venda rapidamente.\n\n## Suporte integrado\n\nO novo centro de suporte reúne tutoriais, webinars e chat direto com o nosso time.\n\nEstamos ansiosos para compartilhar essas novidades. Acompanhe o blog e seja o primeiro a testar." } ] } diff --git a/src/content/pt/eventos.json b/src/content/pt/eventos.json index 13e5b64..bb584d8 100644 --- a/src/content/pt/eventos.json +++ b/src/content/pt/eventos.json @@ -11,42 +11,11 @@ "href": "/contato" } }, - "benefits": { - "title": "Organização completa para festivais, shows e ativações", - "items": [ - { - "title": "Agenda inteligente", - "description": "Sincronize reservas, montagem e desmontagem com visões por equipe e fornecedor." - }, - { - "title": "Checklist colaborativo", - "description": "Distribua tarefas com responsáveis, prazos e anexos compartilhados em tempo real." - }, - { - "title": "Relatório pós-evento", - "description": "Capture feedback, vendas e custos para replicar o que funciona e corrigir rapidamente." - } - ] - }, - "workflow": { - "title": "Do convite à fidelização", - "steps": [ - { - "title": "Desenhe a experiência", - "description": "Monte cronogramas, mapinhas de mesa e playlists em um ambiente visual." - }, - { - "title": "Coordene a operação", - "description": "Atribua responsáveis, notifique parceiros e acompanhe status em dashboards ao vivo." - }, - { - "title": "Analise resultados", - "description": "Compare ticket médio, ocupação e satisfação para planejar o próximo evento." - } - ] - }, - "highlights": { - "title": "Recursos que garantem eventos memoráveis", + { + "archived": true, + "redirect": "/gestao-estoque", + "note": "Funcionalidade de eventos foi removida — veja /gestao-estoque para operações e gestão de stock." + } "items": [ { "title": "Reservas integradas", diff --git a/src/content/pt/fidelidade.json b/src/content/pt/fidelidade.json deleted file mode 100644 index dcd5ae1..0000000 --- a/src/content/pt/fidelidade.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "seo": { - "title": "Programa de Fidelidade Omnicanal | Boteco Pro", - "description": "Crie campanhas segmentadas com recompensas automáticas e mensure o impacto em recorrência e ticket médio." - }, - "hero": { - "title": "Fidelize fãs da sua marca com experiências memoráveis", - "subtitle": "Lance clubes, cashback e desafios personalizados com insights de consumo em tempo real.", - "cta": { - "label": "Construir programa", - "href": "/contato" - } - }, - "benefits": { - "title": "Retenção previsível com jornadas personalizadas", - "items": [ - { - "title": "Segmentação dinâmica", - "description": "Crie regras por frequência, ticket ou preferência e envie benefícios automaticamente." - }, - { - "title": "Wallet digital", - "description": "Clientes acumulam pontos, selos ou créditos em um app pronto para uso, integrado ao PDV." - }, - { - "title": "Relatórios de retenção", - "description": "Visualize cohorts, churn e tempo médio entre visitas para ajustar campanhas." - } - ] - }, - "workflow": { - "title": "Como lançar campanhas de fidelidade", - "steps": [ - { - "title": "Defina objetivos", - "description": "Escolha metas de consumo, recorrência ou ticket e selecione públicos-alvo." - }, - { - "title": "Ative recompensas", - "description": "Configure selos, vouchers ou experiências VIP com notificações automáticas." - }, - { - "title": "Avalie resultados", - "description": "Acompanhe métricas de adesão, resgate e impacto financeiro para otimizar rapidamente." - } - ] - }, - "highlights": { - "title": "Funcionalidades para encantar clientes", - "items": [ - { - "title": "Gamificação inclusiva", - "description": "Desafios acessíveis com leitura de tela, textos alternativos e progressos sincronizados." - }, - { - "title": "Comunicação omnicanal", - "description": "Envie push, e-mail ou SMS com templates traduzidos automaticamente." - }, - { - "title": "Integração com pagamentos", - "description": "Resgate direto no caixa com validação antifraude e auditoria." - } - ] - }, - "cta": { - "title": "Crie fãs que retornam toda semana", - "description": "Personalize jornadas de fidelidade sem complicar a operação.", - "button": { - "label": "Agendar consultoria", - "href": "/contato" - } - } -} diff --git a/src/content/pt/gestao-estoque.json b/src/content/pt/gestao-estoque.json new file mode 100644 index 0000000..1a23a18 --- /dev/null +++ b/src/content/pt/gestao-estoque.json @@ -0,0 +1,10 @@ +{ + "seo": {"title": "Gestão de Estoque & Operações | Boteco Pro"}, + "hero": { + "title": "Gestão de Stock, Pedidos e Vendas", + "description": "Controle inventário, movimentações de stock e registros de vendas com atualizações automáticas.", + "cta": {"label": "Conhecer Gestão de Estoque", "href": "/contato"} + }, + "benefits": ["Controle de inventário", "Movimentações de stock", "Registros de vendas e relatórios do dia"], + "cta": {"label": "Solicitar demonstração", "href": "/contato"} +} diff --git a/src/content/pt/home.json b/src/content/pt/home.json index 8320435..46935f7 100644 --- a/src/content/pt/home.json +++ b/src/content/pt/home.json @@ -16,13 +16,13 @@ "description": "Centralize fornecedores, contratos e entregas com alertas automáticos." }, { - "title": "Fidelização e Insights", - "description": "Lance campanhas personalizadas e monitore resultados com dashboards completos." + "title": "Gestão de Stock, Pedidos e Vendas", + "description": "Controle inventário, movimentações de stock e registros de vendas com atualizações automáticas." } ], "solutions": { "title": "Soluções conectadas para a sua operação", - "subtitle": "Combine menu digital, fornecedores, fidelidade, eventos e integrações em um único ecossistema.", + "subtitle": "Combine menu digital, fornecedores, sincronização em tempo real e gestão de estoque em um único ecossistema.", "items": [ { "title": "Menu Digital", @@ -38,16 +38,16 @@ "ctaLabel": "Centralizar compras" }, { - "title": "Programa de Fidelidade", - "description": "Wallet digital, campanhas segmentadas e métricas de retenção em tempo real.", - "href": "/fidelidade", - "ctaLabel": "Engajar clientes" + "title": "Sincronização em Tempo Real", + "description": "Sincronize pedidos, mesas e estoque entre dispositivos com broadcast e baixa latência.", + "href": "/realtime", + "ctaLabel": "Conhecer sincronização" }, { - "title": "Eventos e Experiências", - "description": "Checklists colaborativos, reservas integradas e relatórios pós-evento.", - "href": "/eventos", - "ctaLabel": "Planejar agenda" + "title": "Gestão de Estoque & Operações", + "description": "Controle itens, movimentações e vendas com relatórios simples do dia.", + "href": "/gestao-estoque", + "ctaLabel": "Gerenciar estoque" }, { "title": "Integrações Nativas", @@ -113,10 +113,10 @@ "href": "/menu-digital" }, { - "title": "Fidelidade omnicanal", - "description": "Campanhas segmentadas, cashback e automações para aumentar recorrência.", - "ctaLabel": "Criar fidelidade", - "href": "/fidelidade" + "title": "Sincronização e operações", + "description": "Atualizações automáticas de pedidos, mesas e estoque com indicadores de atividade.", + "ctaLabel": "Conhecer sincronização", + "href": "/realtime" } ] }, @@ -137,12 +137,12 @@ "answer": "Sim. O Boteco Pro conecta cardápio, pedidos e pagamentos para atualizar estoque e relatórios automaticamente." }, { - "question": "Consigo controlar fornecedores e eventos no mesmo painel?", - "answer": "Você gerencia cotações, entregas, agenda de eventos e equipe em fluxos colaborativos dentro da plataforma." + "question": "Consigo controlar fornecedores e operações no mesmo painel?", + "answer": "Você gerencia cotações, entregas, inventário e equipe em fluxos colaborativos dentro da plataforma." }, { - "question": "Existe programa de fidelidade pronto para usar?", - "answer": "Sim. Crie regras de pontos, cashback ou selos com notificações automáticas e métricas de retenção." + "question": "Existe controle de stock pronto para usar?", + "answer": "Sim. Controle itens, movimentações e relatórios simples do dia para manter a operação em dia." } ] }, diff --git a/src/content/pt/integracoes.json b/src/content/pt/integracoes.json index 7bd33e1..fe665aa 100644 --- a/src/content/pt/integracoes.json +++ b/src/content/pt/integracoes.json @@ -50,7 +50,7 @@ "items": [ { "title": "Webhooks e API GraphQL", - "description": "Acesse eventos em tempo real e construa integrações personalizadas com segurança." + "description": "Acesse sincronização em tempo real e construa integrações personalizadas com segurança." }, { "title": "Biblioteca de conectores", diff --git a/src/content/pt/menu-digital.json b/src/content/pt/menu-digital.json index d541bf6..1d0db91 100644 --- a/src/content/pt/menu-digital.json +++ b/src/content/pt/menu-digital.json @@ -58,7 +58,7 @@ }, { "title": "Promoções por turno", - "description": "Agende ofertas diferentes para almoço, happy hour ou eventos especiais sem duplicar trabalho." + "description": "Agende ofertas diferentes para almoço, happy hour ou turnos especiais sem duplicar trabalho." } ] }, diff --git a/src/content/pt/painel.json b/src/content/pt/painel.json index af7519f..a662dc2 100644 --- a/src/content/pt/painel.json +++ b/src/content/pt/painel.json @@ -45,7 +45,7 @@ "web-form": "Formulário do site", "instagram": "Instagram", "referral": "Indicação", - "events": "Eventos", + "events": "Operações", "partnership": "Parcerias" } }, diff --git a/src/content/pt/realtime.json b/src/content/pt/realtime.json new file mode 100644 index 0000000..9642302 --- /dev/null +++ b/src/content/pt/realtime.json @@ -0,0 +1,10 @@ +{ + "seo": {"title": "Sincronização em Tempo Real | Boteco Pro"}, + "hero": { + "title": "Sincronização e Broadcast em Tempo Real", + "description": "Atualize pedidos, mesas e estoque automaticamente entre dispositivos com baixa latência.", + "cta": {"label": "Conhecer Sincronização", "href": "/contato"} + }, + "benefits": ["Atualização automática de pedidos, mesas e estoque", "Indicadores de atividade e status operacional", "Broadcast entre dispositivos"], + "cta": {"label": "Solicitar demonstração", "href": "/contato"} +} diff --git a/src/globals.css b/src/globals.css index d953815..e659d8a 100644 --- a/src/globals.css +++ b/src/globals.css @@ -1,7 +1,7 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - +@tailwind base; +@tailwind components; +@tailwind utilities; + @layer base { :root { --boteco-primary: 341.8 64.5% 33.1%; @@ -121,8 +121,8 @@ --sidebar-ring: var(--boteco-secondary); } } - -@layer base { + +@layer base { * { @apply border-border; } diff --git a/src/pages/Eventos.tsx b/src/pages/Eventos.tsx index 7d3d50f..b654c2f 100644 --- a/src/pages/Eventos.tsx +++ b/src/pages/Eventos.tsx @@ -1,8 +1,10 @@ import React from 'react'; -import MarketingPageTemplate from '@/components/templates/MarketingPageTemplate'; +import { useParams, Navigate } from 'react-router-dom'; const Eventos: React.FC = () => { - return ; + const { locale } = useParams(); + const target = `/${locale ?? 'pt'}/gestao-estoque`; + return ; }; export default Eventos; diff --git a/src/pages/Fidelidade.tsx b/src/pages/Fidelidade.tsx deleted file mode 100644 index a4743f6..0000000 --- a/src/pages/Fidelidade.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import MarketingPageTemplate from '@/components/templates/MarketingPageTemplate'; - -const Fidelidade: React.FC = () => { - return ; -}; - -export default Fidelidade; diff --git a/src/pages/GestaoEstoque.tsx b/src/pages/GestaoEstoque.tsx new file mode 100644 index 0000000..689c0ae --- /dev/null +++ b/src/pages/GestaoEstoque.tsx @@ -0,0 +1,8 @@ +import React from 'react'; +import MarketingPageTemplate from '@/components/templates/MarketingPageTemplate'; + +const GestaoEstoque: React.FC = () => { + return ; +}; + +export default GestaoEstoque; diff --git a/src/pages/Realtime.tsx b/src/pages/Realtime.tsx new file mode 100644 index 0000000..39e990c --- /dev/null +++ b/src/pages/Realtime.tsx @@ -0,0 +1,8 @@ +import React from 'react'; +import MarketingPageTemplate from '@/components/templates/MarketingPageTemplate'; + +const Realtime: React.FC = () => { + return ; +}; + +export default Realtime; From 7f941f3fc72cb9e2e3a8c02592b794b2330033b2 Mon Sep 17 00:00:00 2001 From: Marcelo Santos Date: Sat, 15 Nov 2025 21:20:34 +0000 Subject: [PATCH 2/7] chore: remove obsolete Lighthouse and Visual Regression workflows; update Playwright config and add new TypeScript configuration files --- .github/workflows/ci.yml | 107 ++++++------------------ .github/workflows/lighthouse.yml | 106 ----------------------- .github/workflows/visual-regression.yml | 72 ---------------- playwright.config.ts | 2 +- tsconfig copy.json | 19 +++++ tsconfig.app copy.json | 31 +++++++ 6 files changed, 77 insertions(+), 260 deletions(-) delete mode 100644 .github/workflows/lighthouse.yml delete mode 100644 .github/workflows/visual-regression.yml create mode 100644 tsconfig copy.json create mode 100644 tsconfig.app copy.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c895c2b..1e9a10f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: name: Lint Code runs-on: ubuntu-latest timeout-minutes: 10 - + steps: - name: Checkout code uses: actions/checkout@v4 @@ -28,73 +28,28 @@ jobs: with: node-version: '20' - - name: Install pnpm - uses: pnpm/action-setup@v3 - with: - version: 10 - - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + - name: Install bun + run: npm install -g bun - - name: Setup pnpm cache - uses: actions/cache@v4 + - name: Cache dependencies + uses: actions/cache@v3 with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ~/.bun + key: ${{ runner.os }}-bun-${{ hashFiles('**/package.json') }} restore-keys: | - ${{ runner.os }}-pnpm-store- + ${{ runner.os }}-bun- - - name: Install dependencies - run: pnpm install --frozen-lockfile + - name: Run bun install + run: bun install - name: Run linter - run: pnpm lint + run: bun lint test: name: Run Tests runs-on: ubuntu-latest - timeout-minutes: 10 - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Install pnpm - uses: pnpm/action-setup@v3 - with: - version: 10 - - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - name: Setup pnpm cache - uses: actions/cache@v4 - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Run tests - run: pnpm test - - build: - name: Build Application - runs-on: ubuntu-latest timeout-minutes: 15 - + steps: - name: Checkout code uses: actions/checkout@v4 @@ -104,33 +59,23 @@ jobs: with: node-version: '20' - - name: Install pnpm - uses: pnpm/action-setup@v3 - with: - version: 10 - - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + - name: Install bun + run: npm install -g bun - - name: Setup pnpm cache - uses: actions/cache@v4 + - name: Cache dependencies + uses: actions/cache@v3 with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ~/.bun + key: ${{ runner.os }}-bun-${{ hashFiles('**/package.json') }} restore-keys: | - ${{ runner.os }}-pnpm-store- + ${{ runner.os }}-bun- - - name: Install dependencies - run: pnpm install --frozen-lockfile + - name: Run bun install + run: bun install - - name: Build application - run: pnpm build + - name: Run unit tests + run: bun test + + - name: Run visual tests + run: bun test:visual - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - with: - name: build-artifacts - path: dist/ - retention-days: 7 diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml deleted file mode 100644 index 2040672..0000000 --- a/.github/workflows/lighthouse.yml +++ /dev/null @@ -1,106 +0,0 @@ -name: Lighthouse CI - -on: - pull_request: - branches: [main, dev] - push: - branches: [main, dev] - -permissions: - contents: read - actions: read - pull-requests: write # For commenting on PRs - -jobs: - lighthouse: - name: Run Lighthouse Audits - runs-on: ubuntu-latest - timeout-minutes: 20 - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Install pnpm - uses: pnpm/action-setup@v3 - with: - version: 10 - - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - name: Setup pnpm cache - uses: actions/cache@v4 - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build application - run: pnpm run build - - - name: Run Lighthouse CI - run: npx --yes @lhci/cli@0.13.x autorun - env: - LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }} - continue-on-error: true - - - name: Upload Lighthouse results - uses: actions/upload-artifact@v4 - if: always() - with: - name: lighthouse-reports - path: .lighthouseci/ - retention-days: 30 - - - name: Comment PR with Lighthouse results - if: github.event_name == 'pull_request' - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - const path = require('path'); - - // Find the latest manifest - const lhciDir = '.lighthouseci'; - if (fs.existsSync(lhciDir)) { - const files = fs.readdirSync(lhciDir); - const manifestFile = files.find(f => f.startsWith('manifest')); - - if (manifestFile) { - const manifest = JSON.parse(fs.readFileSync(path.join(lhciDir, manifestFile), 'utf8')); - - let comment = '## 🔦 Lighthouse CI Results\n\n'; - - for (const result of manifest) { - const url = result.url; - const summary = result.summary; - - comment += `### ${url}\n`; - comment += `- **Accessibility**: ${Math.round(summary.accessibility * 100)}/100\n`; - comment += `- **Performance**: ${Math.round(summary.performance * 100)}/100\n`; - comment += `- **Best Practices**: ${Math.round(summary['best-practices'] * 100)}/100\n`; - comment += `- **SEO**: ${Math.round(summary.seo * 100)}/100\n\n`; - } - - comment += '✅ **Target Met**: Accessibility ≥ 90\n'; - - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: comment - }); - } - } diff --git a/.github/workflows/visual-regression.yml b/.github/workflows/visual-regression.yml deleted file mode 100644 index a3886ea..0000000 --- a/.github/workflows/visual-regression.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Visual Regression Tests - -on: - pull_request: - branches: [main, dev] - push: - branches: [main, dev] - -permissions: - contents: read - actions: read - -jobs: - visual-tests: - name: Run Visual Regression Tests - runs-on: ubuntu-latest - timeout-minutes: 30 - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Install pnpm - uses: pnpm/action-setup@v3 - with: - version: 10 - - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - name: Setup pnpm cache - uses: actions/cache@v4 - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Install Playwright browsers - run: pnpm exec playwright install --with-deps chromium firefox webkit - - - name: Run Playwright visual tests - run: pnpm exec playwright test - env: - CI: true - continue-on-error: true - - - name: Upload test results - uses: actions/upload-artifact@v4 - if: always() - with: - name: playwright-report - path: playwright-report/ - retention-days: 30 - - - name: Upload screenshots - uses: actions/upload-artifact@v4 - if: always() - with: - name: playwright-screenshots - path: test-results/ - retention-days: 7 diff --git a/playwright.config.ts b/playwright.config.ts index 7274cea..9cae42b 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -53,7 +53,7 @@ export default defineConfig({ // Run your local dev server before starting the tests webServer: { - command: 'pnpm run preview --port 8080', + command: 'bun run preview --port 8080', url: 'http://localhost:8080', reuseExistingServer: !process.env.CI, timeout: 120 * 1000, diff --git a/tsconfig copy.json b/tsconfig copy.json new file mode 100644 index 0000000..129b1a3 --- /dev/null +++ b/tsconfig copy.json @@ -0,0 +1,19 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ], + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + "noImplicitAny": false, + "noUnusedParameters": false, + "skipLibCheck": true, + "allowJs": true, + "noUnusedLocals": false, + "strictNullChecks": false + } +} diff --git a/tsconfig.app copy.json b/tsconfig.app copy.json new file mode 100644 index 0000000..f175f32 --- /dev/null +++ b/tsconfig.app copy.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + "resolveJsonModule": true, + + /* Linting */ + "strict": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitAny": false, + "noFallthroughCasesInSwitch": false, + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"] +} From 277b451fc4bb3871a679c51153db20142a67ea87 Mon Sep 17 00:00:00 2001 From: Marcelo Santos Date: Sat, 15 Nov 2025 21:24:26 +0000 Subject: [PATCH 3/7] Refactor documentation and remove obsolete files; update environment setup for bun; enhance main entry point with optimized QueryClient and Clerk integration. --- docs/DOCKER_DEPLOYMENT.md | 330 --------------------------------- docs/DOCKER_QUICK_REF.md | 220 ---------------------- docs/DOCKER_SETUP.md | 291 ----------------------------- docs/DOCKER_TROUBLESHOOTING.md | 294 ----------------------------- docs/ENVIRONMENT_SETUP.md | 2 +- docs/PERFORMANCE_SUMMARY.md | 116 ------------ docs/README.md | 259 -------------------------- docs/VISUAL_TESTING.md | 243 ------------------------ src/main copy.tsx | 64 +++++++ 9 files changed, 65 insertions(+), 1754 deletions(-) delete mode 100644 docs/DOCKER_DEPLOYMENT.md delete mode 100644 docs/DOCKER_QUICK_REF.md delete mode 100644 docs/DOCKER_SETUP.md delete mode 100644 docs/DOCKER_TROUBLESHOOTING.md delete mode 100644 docs/PERFORMANCE_SUMMARY.md delete mode 100644 docs/README.md delete mode 100644 docs/VISUAL_TESTING.md create mode 100644 src/main copy.tsx diff --git a/docs/DOCKER_DEPLOYMENT.md b/docs/DOCKER_DEPLOYMENT.md deleted file mode 100644 index de3f1f5..0000000 --- a/docs/DOCKER_DEPLOYMENT.md +++ /dev/null @@ -1,330 +0,0 @@ -# Docker Deployment Guide - -## Overview - -This project uses a multi-stage Docker build for optimal production deployment: -- **Stage 1 (Builder)**: Builds the React application using Node.js 20 and pnpm -- **Stage 2 (Production)**: Serves the static files using nginx Alpine (minimal footprint) - -## Quick Start - -### Option 1: Docker Compose (Recommended) - -```bash -# Build and start the container -docker-compose up -d - -# View logs -docker-compose logs -f - -# Stop the container -docker-compose down -``` - -Access the application at: http://localhost - -### Option 2: Docker CLI - -```bash -# Build the image -docker build -t boteco-pt:latest . - -# Run the container -docker run -d \ - --name boteco-pt \ - -p 80:80 \ - --restart unless-stopped \ - boteco-pt:latest - -# View logs -docker logs -f boteco-pt - -# Stop and remove -docker stop boteco-pt -docker rm boteco-pt -``` - -## Production Deployment - -### Environment Variables - -For production, you can inject environment variables at build time: - -```bash -docker build \ - --build-arg VITE_CLERK_PUBLISHABLE_KEY=your_key \ - --build-arg VITE_CLERK_FRONTEND_API_URL=your_url \ - -t boteco-pt:latest . -``` - -### Port Configuration - -By default, the container exposes port 80. To use a different port: - -```bash -# Run on port 8080 instead of 80 -docker run -d -p 8080:80 boteco-pt:latest -``` - -### Docker Hub Deployment - -```bash -# Tag the image -docker tag boteco-pt:latest your-username/boteco-pt:latest -docker tag boteco-pt:latest your-username/boteco-pt:1.0.0 - -# Push to Docker Hub -docker push your-username/boteco-pt:latest -docker push your-username/boteco-pt:1.0.0 -``` - -## Image Optimization - -The production image is optimized with: -- ✅ **Multi-stage build** (only production assets in final image) -- ✅ **Alpine Linux** (minimal base image ~5MB) -- ✅ **nginx** (efficient static file serving) -- ✅ **Gzip compression** (reduced bandwidth) -- ✅ **Cache headers** (optimal browser caching) -- ✅ **Health checks** (container orchestration support) - -### Image Size -- Builder stage: ~900MB (discarded) -- Final image: ~25-30MB (nginx + built assets) - -## Configuration Files - -### Dockerfile -Multi-stage build configuration with builder and production stages. - -### nginx.conf -Production-ready nginx configuration with: -- SPA routing support (all routes → index.html) -- Static asset caching (1 year for immutable assets) -- Security headers (XSS, frame options, etc.) -- Gzip compression -- Health check endpoint at `/health` - -### .dockerignore -Excludes unnecessary files from Docker context: -- node_modules -- Development files -- Test files -- Documentation -- Git files - -## Testing - -### Build Test - -```bash -# Build the image -docker build -t boteco-pt:test . - -# Check image size -docker images boteco-pt:test - -# Inspect the image -docker inspect boteco-pt:test -``` - -### Runtime Test - -```bash -# Start the container -docker run -d -p 3000:80 --name boteco-test boteco-pt:test - -# Test the application -curl http://localhost:3000/health -curl -I http://localhost:3000/pt - -# Check logs -docker logs boteco-test - -# Cleanup -docker stop boteco-test -docker rm boteco-test -``` - -### Health Check - -```bash -# Check container health status -docker ps --filter name=boteco-pt - -# Manual health check -docker exec boteco-pt wget -qO- http://localhost/health -``` - -## Troubleshooting - -### Container won't start - -```bash -# Check logs -docker logs boteco-pt - -# Check nginx configuration -docker exec -it boteco-pt nginx -t -``` - -### Build fails - -```bash -# Build with verbose output -docker build --progress=plain -t boteco-pt:latest . - -# Check Docker context size -docker build --no-cache -t boteco-pt:debug . -``` - -### Routes not working (404 errors) - -The nginx configuration should handle SPA routing. Verify: -```bash -# Check nginx config in container -docker exec -it boteco-pt cat /etc/nginx/nginx.conf - -# Restart nginx -docker exec -it boteco-pt nginx -s reload -``` - -## Production Best Practices - -1. **Use specific image tags** (not just `latest`) - ```bash - docker build -t boteco-pt:1.0.0 . - ``` - -2. **Scan for vulnerabilities** - ```bash - docker scan boteco-pt:latest - ``` - -3. **Use Docker secrets** for sensitive data (in orchestration) - ```yaml - # docker-compose with secrets - secrets: - - clerk_key - ``` - -4. **Set resource limits** - ```bash - docker run -d \ - --cpus="0.5" \ - --memory="512m" \ - -p 80:80 \ - boteco-pt:latest - ``` - -5. **Enable logging drivers** - ```bash - docker run -d \ - --log-driver=json-file \ - --log-opt max-size=10m \ - --log-opt max-file=3 \ - boteco-pt:latest - ``` - -## Kubernetes Deployment - -Example Kubernetes deployment: - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: boteco-pt -spec: - replicas: 3 - selector: - matchLabels: - app: boteco-pt - template: - metadata: - labels: - app: boteco-pt - spec: - containers: - - name: boteco-pt - image: your-username/boteco-pt:1.0.0 - ports: - - containerPort: 80 - resources: - requests: - memory: "256Mi" - cpu: "250m" - limits: - memory: "512Mi" - cpu: "500m" - livenessProbe: - httpGet: - path: /health - port: 80 - initialDelaySeconds: 10 - periodSeconds: 30 ---- -apiVersion: v1 -kind: Service -metadata: - name: boteco-pt -spec: - selector: - app: boteco-pt - ports: - - port: 80 - targetPort: 80 - type: LoadBalancer -``` - -## CI/CD Integration - -### GitHub Actions Example - -```yaml -name: Docker Build & Push - -on: - push: - tags: - - 'v*' - -jobs: - docker: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Build Docker image - run: docker build -t boteco-pt:${{ github.ref_name }} . - - - name: Push to registry - run: | - echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin - docker push boteco-pt:${{ github.ref_name }} -``` - -## Monitoring - -Monitor container health: - -```bash -# Container stats -docker stats boteco-pt - -# Resource usage -docker exec boteco-pt top - -# Nginx access logs -docker logs -f boteco-pt - -# Nginx error logs -docker exec boteco-pt tail -f /var/log/nginx/error.log -``` - ---- - -**Image**: `boteco-pt:latest` -**Base**: `nginx:alpine` -**Exposed Port**: `80` -**Health Endpoint**: `/health` diff --git a/docs/DOCKER_QUICK_REF.md b/docs/DOCKER_QUICK_REF.md deleted file mode 100644 index c12a6af..0000000 --- a/docs/DOCKER_QUICK_REF.md +++ /dev/null @@ -1,220 +0,0 @@ -# Docker Quick Reference - -## Build Commands - -```bash -# Basic build -docker build -t boteco-pt:latest . - -# Build with environment variables -docker build \ - --build-arg VITE_CLERK_PUBLISHABLE_KEY=your_key \ - --build-arg VITE_CLERK_FRONTEND_API_URL=your_url \ - -t boteco-pt:latest . - -# Build with version tag -docker build -t boteco-pt:1.0.0 . -docker tag boteco-pt:1.0.0 boteco-pt:latest -``` - -## Run Commands - -```bash -# Run on port 3000 -docker run -d -p 3000:80 --name boteco-pt boteco-pt:latest - -# Run on port 80 -docker run -d -p 80:80 --name boteco-pt boteco-pt:latest - -# Run with auto-restart -docker run -d \ - --name boteco-pt \ - -p 3000:80 \ - --restart unless-stopped \ - boteco-pt:latest -``` - -## Management Commands - -```bash -# View logs -docker logs -f boteco-pt - -# View container stats -docker stats boteco-pt - -# Stop container -docker stop boteco-pt - -# Start container -docker start boteco-pt - -# Restart container -docker restart boteco-pt - -# Remove container -docker rm boteco-pt - -# Remove container (force) -docker rm -f boteco-pt - -# Execute command in container -docker exec -it boteco-pt sh - -# Inspect container -docker inspect boteco-pt - -# View nginx config -docker exec boteco-pt cat /etc/nginx/nginx.conf -``` - -## Docker Compose Commands - -```bash -# Start services -docker-compose up -d - -# View logs -docker-compose logs -f - -# Stop services -docker-compose down - -# Rebuild and restart -docker-compose up -d --build - -# Stop and remove volumes -docker-compose down -v -``` - -## Health Checks - -```bash -# Check health status -docker ps --filter name=boteco-pt - -# Manual health check -curl http://localhost:3000/health - -# Health check from inside container -docker exec boteco-pt wget -qO- http://localhost/health -``` - -## Cleanup Commands - -```bash -# Remove image -docker rmi boteco-pt:latest - -# Remove all unused images -docker image prune -a - -# Remove all stopped containers -docker container prune - -# Complete cleanup (use with caution!) -docker system prune -a --volumes -``` - -## Testing - -```bash -# Test the application -curl http://localhost:3000/pt -curl -I http://localhost:3000/pt -curl http://localhost:3000/health - -# Test gzip compression -curl -H "Accept-Encoding: gzip" -I http://localhost:3000/pt - -# Test different locales -curl http://localhost:3000/en -curl http://localhost:3000/es -curl http://localhost:3000/fr -``` - -## Automated Scripts - -### Windows (PowerShell) -```powershell -.\docker-build.ps1 -``` - -### Linux/Mac (Bash) -```bash -chmod +x docker-build.sh -./docker-build.sh -``` - -## Common Issues - -### Container won't start -```bash -# Check logs for errors -docker logs boteco-pt - -# Test nginx configuration -docker exec boteco-pt nginx -t -``` - -### Port already in use -```bash -# Find what's using the port -# Windows -netstat -ano | findstr :3000 - -# Linux/Mac -lsof -i :3000 - -# Use different port -docker run -d -p 8080:80 --name boteco-pt boteco-pt:latest -``` - -### Image too large -```bash -# Check image size -docker images boteco-pt:latest - -# View image layers -docker history boteco-pt:latest - -# Use multi-stage build (already configured) -``` - -## Production Deployment - -### Push to Docker Hub -```bash -# Login -docker login - -# Tag image -docker tag boteco-pt:latest username/boteco-pt:latest -docker tag boteco-pt:latest username/boteco-pt:1.0.0 - -# Push -docker push username/boteco-pt:latest -docker push username/boteco-pt:1.0.0 -``` - -### Pull and Run -```bash -# Pull image -docker pull username/boteco-pt:latest - -# Run -docker run -d -p 80:80 --name boteco-pt username/boteco-pt:latest -``` - -## URLs - -- Local: http://localhost:3000 -- Portuguese: http://localhost:3000/pt -- English: http://localhost:3000/en -- Spanish: http://localhost:3000/es -- French: http://localhost:3000/fr -- Health: http://localhost:3000/health - ---- - -**See also**: `docs/DOCKER_DEPLOYMENT.md` for comprehensive guide diff --git a/docs/DOCKER_SETUP.md b/docs/DOCKER_SETUP.md deleted file mode 100644 index 4c7f2cc..0000000 --- a/docs/DOCKER_SETUP.md +++ /dev/null @@ -1,291 +0,0 @@ -# Docker Setup Summary - -## ✅ Files Created - -### Core Docker Files -1. **Dockerfile** - Multi-stage production build - - Stage 1: Build with Node.js 20 Alpine + pnpm - - Stage 2: Serve with nginx Alpine - - Supports build-time environment variables - - Optimized for minimal image size (~25-30MB final) - -2. **nginx.conf** - Production nginx configuration - - SPA routing (all routes → index.html) - - Gzip compression enabled - - Security headers (XSS, frame options, etc.) - - Optimized caching strategies: - - Static assets: 1 year cache - - JSON data: 5 minutes cache - - index.html: no cache - - Health check endpoint at `/health` - -3. **docker-compose.yml** - Easy orchestration - - Exposes port 80 - - Auto-restart enabled - - Health checks configured - - Resource limits ready (commented out) - -4. **.dockerignore** - Build optimization - - Excludes node_modules, tests, docs - - Reduces Docker context size - - Faster builds - -### Helper Scripts -5. **docker-build.ps1** - Windows PowerShell script - - Interactive build and run - - Docker status checks - - Health endpoint testing - - Container log viewing - -6. **docker-build.sh** - Linux/Mac bash script - - Same functionality as PowerShell version - - Colored output - - Executable with `chmod +x` - -### Documentation -7. **docs/DOCKER_DEPLOYMENT.md** - Comprehensive guide - - Quick start instructions - - Production deployment strategies - - Kubernetes examples - - CI/CD integration - - Troubleshooting guide - - Monitoring commands - -8. **DOCKER_QUICK_REF.md** - Quick reference - - Common commands - - Testing procedures - - Cleanup commands - - URL reference - -## 🏗️ Architecture - -### Multi-Stage Build -``` -┌─────────────────────────────────────┐ -│ Stage 1: Builder │ -│ - Base: node:20-alpine │ -│ - Install pnpm │ -│ - Install dependencies │ -│ - Build React app │ -│ - Size: ~900MB (discarded) │ -└─────────────────────────────────────┘ - ↓ -┌─────────────────────────────────────┐ -│ Stage 2: Production │ -│ - Base: nginx:alpine │ -│ - Copy built assets from Stage 1 │ -│ - Copy nginx configuration │ -│ - Size: ~25-30MB (final) │ -└─────────────────────────────────────┘ -``` - -### Image Optimization -- ✅ Alpine Linux base (minimal footprint) -- ✅ Multi-stage build (only production files) -- ✅ .dockerignore (reduced build context) -- ✅ Layer caching (faster rebuilds) -- ✅ No dev dependencies in final image - -## 📋 Docker Configuration Features - -### Nginx Features -- ✅ SPA routing support -- ✅ Gzip compression (6x compression level) -- ✅ Security headers -- ✅ Optimized caching -- ✅ Health check endpoint -- ✅ Custom error pages ready - -### Container Features -- ✅ Health checks (30s interval) -- ✅ Auto-restart on failure -- ✅ Resource limits ready -- ✅ Logging configured -- ✅ Port 80 exposed - -### Environment Variables -- ✅ Build-time ARG support -- ✅ VITE_ prefix required -- ✅ Optional Clerk auth -- ✅ Secure defaults - -## 🚀 Usage - -### Quick Start (Automated) - -**Windows**: -```powershell -.\docker-build.ps1 -``` - -**Linux/Mac**: -```bash -chmod +x docker-build.sh -./docker-build.sh -``` - -### Manual Build & Run - -```bash -# Build -docker build -t boteco-pt:latest . - -# Run on port 3000 -docker run -d -p 3000:80 --name boteco-pt boteco-pt:latest - -# View logs -docker logs -f boteco-pt - -# Test health -curl http://localhost:3000/health - -# Access app -http://localhost:3000/pt -``` - -### Docker Compose - -```bash -# Start -docker-compose up -d - -# Stop -docker-compose down - -# Logs -docker-compose logs -f -``` - -## 🧪 Testing Checklist - -Before deployment, verify: - -- [ ] Docker build completes successfully -- [ ] Image size is reasonable (~25-30MB) -- [ ] Container starts without errors -- [ ] Health check passes: `curl http://localhost:3000/health` -- [ ] Homepage loads: `curl http://localhost:3000/pt` -- [ ] Locale routing works: `/en`, `/es`, `/fr` -- [ ] Static assets load correctly -- [ ] Gzip compression works: `curl -H "Accept-Encoding: gzip" -I http://localhost:3000/` -- [ ] Container auto-restarts on failure -- [ ] Logs are accessible: `docker logs boteco-pt` - -## 📊 Performance Metrics - -### Expected Results -- **Image Size**: ~25-30MB -- **Build Time**: - - First build: 5-10 minutes - - Cached rebuild: 30-60 seconds -- **Container Memory**: ~10-20MB -- **Container CPU**: Minimal (static serving) -- **Startup Time**: < 5 seconds -- **Response Time**: < 50ms (local) - -### Compression Ratios -- Gzip level 6: ~70-80% reduction -- Typical bundle: 242KB → ~77KB gzipped - -## 🔒 Security Features - -- ✅ Non-root nginx user -- ✅ Alpine base (minimal attack surface) -- ✅ Security headers (XSS, CSRF, etc.) -- ✅ No sensitive data in image -- ✅ Health check endpoint -- ✅ Hidden files blocked - -## 🌐 Production Deployment - -### Docker Hub -```bash -docker tag boteco-pt:latest username/boteco-pt:1.0.0 -docker push username/boteco-pt:1.0.0 -``` - -### AWS ECS/Fargate -- Use task definition with image: `username/boteco-pt:1.0.0` -- Configure ALB on port 80 -- Set health check path: `/health` - -### Kubernetes -- See `docs/DOCKER_DEPLOYMENT.md` for k8s manifests -- Use 3+ replicas for HA -- Configure HPA based on CPU/memory -- Use Ingress for SSL termination - -### Google Cloud Run -```bash -gcloud run deploy boteco-pt \ - --image username/boteco-pt:1.0.0 \ - --platform managed \ - --port 80 -``` - -## 📝 Next Steps - -1. **Test locally**: - ```bash - .\docker-build.ps1 # or ./docker-build.sh - ``` - -2. **Verify all routes work**: - - http://localhost:3000/pt - - http://localhost:3000/en - - http://localhost:3000/es - - http://localhost:3000/fr - -3. **Check health endpoint**: - ```bash - curl http://localhost:3000/health - ``` - -4. **Push to registry** (if ready for production) - -5. **Deploy to cloud** (AWS, GCP, Azure, etc.) - -## 🆘 Troubleshooting - -### Issue: Docker not running -**Solution**: Start Docker Desktop and wait for it to fully initialize - -### Issue: Port already in use -**Solution**: Use different port: -```bash -docker run -d -p 8080:80 --name boteco-pt boteco-pt:latest -``` - -### Issue: Build fails -**Solution**: -- Check Docker has enough disk space -- Clear Docker cache: `docker system prune -a` -- Rebuild with no cache: `docker build --no-cache -t boteco-pt:latest .` - -### Issue: Container stops immediately -**Solution**: -```bash -# Check logs for errors -docker logs boteco-pt - -# Test nginx config -docker exec boteco-pt nginx -t -``` - -### Issue: 404 on routes -**Solution**: Check nginx config is properly copying SPA routing rules - -## 📚 Documentation Reference - -- **Quick Reference**: `DOCKER_QUICK_REF.md` -- **Full Guide**: `docs/DOCKER_DEPLOYMENT.md` -- **Copilot Instructions**: `.github/copilot-instructions.md` -- **Main README**: `README.md` - ---- - -**Status**: ✅ **READY FOR PRODUCTION** -**Image**: `boteco-pt:latest` -**Port**: `80` (container) → `3000` (host) -**Health**: `/health` endpoint -**Docs**: Complete diff --git a/docs/DOCKER_TROUBLESHOOTING.md b/docs/DOCKER_TROUBLESHOOTING.md deleted file mode 100644 index d9b1424..0000000 --- a/docs/DOCKER_TROUBLESHOOTING.md +++ /dev/null @@ -1,294 +0,0 @@ -# Docker Build Troubleshooting - -## Issue: Build Failed - Missing Module Resolution - -### Error Message -``` -[vite]: Rollup failed to resolve import "@/components/ui/toaster" from "/app/src/App.tsx". -``` - -### Root Cause -The `.dockerignore` file was excluding TypeScript and Vite configuration files that are required for the build process. - -### Solution Applied -Updated `.dockerignore` to include necessary build configuration files: -- `tsconfig*.json` - TypeScript configuration -- `vite.config.ts` - Vite bundler configuration -- `tailwind.config.ts` - Tailwind CSS configuration -- `postcss.config.js` - PostCSS configuration -- `components.json` - shadcn/ui component registry - -### Files Modified -✅ `.dockerignore` - Removed exclusions for build-critical config files - -## Docker Desktop Not Running - -### Error Message -``` -ERROR: error during connect: open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified. -``` - -### Solution -1. **Start Docker Desktop** - - Windows: Search for "Docker Desktop" in Start Menu - - Mac: Open Docker Desktop from Applications - - Linux: Run `sudo systemctl start docker` - -2. **Wait for Docker to fully initialize** - - Look for the Docker whale icon in system tray - - Icon should be static (not animated) - - May take 30-60 seconds - -3. **Verify Docker is running** - ```powershell - docker ps - ``` - Should return a list of containers (may be empty) - -## Build Process - -Once Docker Desktop is running: - -### Option 1: Automated Script (Recommended) -```powershell -.\docker-build.ps1 -``` - -This script will: -- ✅ Check Docker status -- ✅ Build the image -- ✅ Optionally run the container -- ✅ Test health endpoint -- ✅ Display logs - -### Option 2: Manual Build -```bash -# Build the image -docker build -t boteco-pt:latest . - -# Expected output: -# - [builder 1/7] FROM node:20-alpine -# - [builder 2/7] RUN npm install -g pnpm@10 -# - [builder 3/7] WORKDIR /app -# - [builder 4/7] COPY package.json pnpm-lock.yaml ./ -# - [builder 5/7] RUN pnpm install --frozen-lockfile -# - [builder 6/7] COPY . . -# - [builder 7/7] RUN pnpm build -# - [production 1/3] FROM nginx:alpine -# - [production 2/3] COPY nginx.conf /etc/nginx/nginx.conf -# - [production 3/3] COPY --from=builder /app/dist /usr/share/nginx/html -# - Successfully built [image-id] -# - Successfully tagged boteco-pt:latest - -# Run the container -docker run -d -p 3000:80 --name boteco-pt boteco-pt:latest - -# Verify it's running -docker ps - -# Test the application -curl http://localhost:3000/health -curl http://localhost:3000/pt -``` - -## Common Build Issues - -### Issue 1: Build fails with "ELIFECYCLE Command failed" - -**Cause**: Missing dependencies or configuration files - -**Solution**: -1. Verify local build works: `pnpm build` -2. Check `.dockerignore` isn't excluding needed files -3. Ensure all config files are present: - - `package.json` - - `pnpm-lock.yaml` - - `tsconfig.json` - - `vite.config.ts` - - `tailwind.config.ts` - -### Issue 2: "node_modules not found" during build - -**Cause**: `.dockerignore` is correct (it should exclude node_modules) - -**Solution**: This is expected. Docker installs dependencies in the container with `RUN pnpm install` - -### Issue 3: Build is very slow - -**Cause**: First build or no Docker layer caching - -**Solution**: -- First build: 5-10 minutes (normal) -- Subsequent builds: 30-60 seconds (with cache) -- To clear cache: `docker build --no-cache -t boteco-pt:latest .` - -### Issue 4: "COPY failed: file not found" - -**Cause**: File is excluded in `.dockerignore` - -**Solution**: Review `.dockerignore` and remove exclusion if file is needed for build - -### Issue 5: Port already in use - -**Error**: `Bind for 0.0.0.0:3000 failed: port is already allocated` - -**Solution**: -```bash -# Find what's using the port -netstat -ano | findstr :3000 - -# Use a different port -docker run -d -p 8080:80 --name boteco-pt boteco-pt:latest - -# Or stop the existing container -docker stop boteco-pt -docker rm boteco-pt -``` - -## Verification Steps - -After successful build: - -### 1. Check Image -```bash -# List images -docker images boteco-pt:latest - -# Expected: -# REPOSITORY TAG IMAGE ID CREATED SIZE -# boteco-pt latest [hash] [time] ~25-30MB -``` - -### 2. Run Container -```bash -# Start container -docker run -d -p 3000:80 --name boteco-pt boteco-pt:latest - -# Check status -docker ps - -# Expected: -# CONTAINER ID IMAGE STATUS PORTS NAMES -# [hash] boteco-pt:latest Up [time] 0.0.0.0:3000->80/tcp boteco-pt -``` - -### 3. Test Endpoints -```bash -# Health check -curl http://localhost:3000/health -# Expected: "healthy" - -# Homepage -curl http://localhost:3000/pt -# Expected: HTML content - -# Check response headers -curl -I http://localhost:3000/pt -# Expected: -# HTTP/1.1 200 OK -# Content-Type: text/html -# X-Frame-Options: SAMEORIGIN -# X-Content-Type-Options: nosniff -``` - -### 4. View Logs -```bash -# Follow logs -docker logs -f boteco-pt - -# Expected: -# [nginx startup messages] -# No errors -``` - -## Build Performance - -### Typical Build Times -- **First build**: 5-10 minutes - - Download base images - - Install all dependencies - - Build application - -- **Cached build**: 30-60 seconds - - Reuse cached layers - - Only rebuild changed parts - -### Optimizing Build Time -1. **Don't change `package.json` frequently** - - Dependencies layer is cached - - Changing forces reinstall - -2. **Use `.dockerignore` wisely** - - Smaller context = faster transfer - - Already optimized in this project - -3. **Multi-stage build benefits** - - Build stage discarded - - Only final artifacts in image - - Smaller image = faster deployment - -## Next Steps - -Once build succeeds: - -1. ✅ **Test locally** - ```bash - docker run -d -p 3000:80 --name boteco-pt boteco-pt:latest - ``` - -2. ✅ **Verify all routes** - - http://localhost:3000/pt (Portuguese) - - http://localhost:3000/en (English) - - http://localhost:3000/es (Spanish) - - http://localhost:3000/fr (French) - -3. ✅ **Test theme switching** - - Dark/light mode should work - - No theme flash on load - -4. ✅ **Check health endpoint** - ```bash - curl http://localhost:3000/health - ``` - -5. ✅ **Review logs** - ```bash - docker logs boteco-pt - ``` - -6. ✅ **Push to registry** (when ready) - ```bash - docker tag boteco-pt:latest username/boteco-pt:1.0.0 - docker push username/boteco-pt:1.0.0 - ``` - -## Getting Help - -If issues persist: - -1. **Check Docker logs**: - ```bash - docker logs boteco-pt - ``` - -2. **Check build logs**: - ```bash - docker build --progress=plain -t boteco-pt:latest . - ``` - -3. **Inspect container**: - ```bash - docker exec -it boteco-pt sh - ls -la /usr/share/nginx/html - cat /etc/nginx/nginx.conf - ``` - -4. **Clean Docker cache**: - ```bash - docker system prune -a - docker build --no-cache -t boteco-pt:latest . - ``` - ---- - -**Status**: ✅ `.dockerignore` fixed - Ready to build when Docker Desktop starts diff --git a/docs/ENVIRONMENT_SETUP.md b/docs/ENVIRONMENT_SETUP.md index 665a81e..0c52c2f 100644 --- a/docs/ENVIRONMENT_SETUP.md +++ b/docs/ENVIRONMENT_SETUP.md @@ -45,7 +45,7 @@ To verify your environment is set up correctly: ```bash # Start dev server -pnpm dev +bun dev # Check browser console - should see i18n loaded, no Clerk errors ``` diff --git a/docs/PERFORMANCE_SUMMARY.md b/docs/PERFORMANCE_SUMMARY.md deleted file mode 100644 index 34cbe82..0000000 --- a/docs/PERFORMANCE_SUMMARY.md +++ /dev/null @@ -1,116 +0,0 @@ -# Performance Optimization Summary - -## Overview -This document provides a concise summary of the performance optimizations implemented for the Boteco.pt application. - -## Problem Statement -The application was identified to have slow and inefficient code, particularly: -- Large bundle size (973KB minified) -- No code splitting or lazy loading -- Duplicate service instances -- Unnecessary re-renders -- Debug mode enabled in production - -## Solution Implemented -Comprehensive performance optimizations focusing on: -1. Code splitting and lazy loading -2. Component memoization -3. Build configuration optimization -4. Production-ready configurations - -## Key Metrics - -### Bundle Size -- **Before**: 973.29 kB (minified, single file) -- **After**: 244.18 kB (minified, main bundle) -- **Improvement**: 75% reduction - -### Code Splitting -- **Before**: 1 monolithic JavaScript file -- **After**: 40+ optimized chunks - - 6 vendor chunks (cached independently) - - Page-specific chunks (lazy loaded) - - Home section chunks (progressively loaded) - -### Home Page Initial Load -- **Before**: 12.95 kB -- **After**: 6.20 kB -- **Improvement**: 52% reduction - -## Changes Made - -### 1. Lazy Loading (src/App.tsx, src/pages/Home.tsx) -- All route components lazy loaded with React.lazy() -- Home page sections split into 3 progressive loading groups -- Suspense boundaries with loading indicators - -### 2. Code Splitting (vite.config.ts) -- Manual vendor chunks configuration -- Separated: React, UI libraries, i18n, animations, utils, Clerk -- Optimized chunk size warning limit - -### 3. Component Memoization -- Added React.memo to: Header, Footer, Layout -- Added useMemo/useCallback where appropriate -- Optimized hook implementations - -### 4. Production Configurations -- i18n debug mode disabled in production (src/i18n.ts) -- Optimized QueryClient defaults (src/main.tsx) -- Removed duplicate QueryClient instance - -### 5. Resource Optimization (index.html) -- Added preconnect hints for Google Fonts -- Proper crossorigin attributes - -### 6. Bug Fixes -- Fixed useIsMobile double state update (src/hooks/use-mobile.tsx) -- Removed unnecessary useMemo in Header - -## Testing Results -- **Unit Tests**: 15/15 passing ✅ -- **Linting**: No errors (only pre-existing shadcn warnings) -- **Security**: No CodeQL alerts ✅ -- **Build**: Successful with optimized output - -## Documentation -Comprehensive documentation created in: -- `docs/PERFORMANCE_OPTIMIZATIONS.md` - Detailed technical documentation -- `docs/PERFORMANCE_SUMMARY.md` - This executive summary - -## Impact - -### Developer Experience -- Faster development builds -- Better hot module replacement -- Clearer code organization - -### User Experience -- **75% faster initial load** (based on bundle size reduction) -- Progressive content loading -- Better caching strategy -- Improved perceived performance - -### Business Impact -- Lower bandwidth costs -- Better SEO (improved Core Web Vitals) -- Higher conversion rates (faster load = better UX) -- Reduced bounce rates - -## Future Recommendations -See `docs/PERFORMANCE_OPTIMIZATIONS.md` section "Future Optimization Opportunities" for: -- Image optimization strategies -- Font optimization -- Service worker implementation -- i18n namespace lazy loading -- CSS optimization - -## Conclusion -The implemented optimizations significantly improved application performance with: -- **75% bundle size reduction** -- **52% Home page reduction** -- **40+ optimized chunks** -- **Zero security issues** -- **All tests passing** - -These changes maintain code quality while providing a vastly improved user experience, especially for users on slower connections or devices. diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index ea39470..0000000 --- a/docs/README.md +++ /dev/null @@ -1,259 +0,0 @@ -# Boteco.pt Technical Documentation - -> **Version**: 1.0.0 -> **Last Updated**: November 7, 2025 -> **Project**: Boteco.pt - Multilingual Restaurant Management Platform - -## 📚 Documentation Overview - -This directory contains comprehensive technical documentation for the Boteco.pt project. The documentation is organized into the following categories: - -### Quick Links - -- 🚀 [Getting Started](#getting-started) -- 🔧 [Development Guides](#development-guides) -- 🐳 [Deployment](#deployment) -- 📊 [Performance](#development-guides) -- ✅ [Testing](#testing) - ---- - -## Getting Started - -### 1. [Environment Setup](./ENVIRONMENT_SETUP.md) - -Essential for all developers. - -Learn how to configure your development environment, including: - -- Environment variables configuration -- Clerk authentication setup (optional) -- Variable naming conventions (`VITE_` prefix) -- Verification steps - -**When to read**: First time setting up the project - ---- - -## Development Guides - -### 2. [Performance Optimizations](./PERFORMANCE_OPTIMIZATIONS.md) - -For understanding application architecture. - -Comprehensive guide to performance improvements: - -- Code splitting strategies -- Bundle size optimization (75% reduction) -- React optimization patterns -- Production configuration -- Lazy loading implementation - -**When to read**: When working on performance-critical features - -### 3. [Performance Summary](./PERFORMANCE_SUMMARY.md) - -Executive overview. - -High-level summary of performance metrics: - -- Before/after comparisons -- Key metrics and improvements -- Business impact analysis -- Quick reference for stakeholders - -**When to read**: Need quick performance metrics or presenting to stakeholders - ---- - -## Deployment - -### 4. [Docker Deployment](./DOCKER_DEPLOYMENT.md) - -Complete deployment guide. - -Full Docker deployment documentation: - -- Multi-stage build configuration -- Production deployment strategies -- Kubernetes deployment examples -- CI/CD integration -- Monitoring and troubleshooting - -**When to read**: Setting up production deployment - -### 5. [Docker Quick Reference](./DOCKER_QUICK_REF.md) - -Command cheat sheet. - -Quick reference for common Docker operations: - -- Build commands -- Run commands -- Management commands -- Troubleshooting tips -- Common issues and solutions - -**When to read**: Daily Docker operations - -### 6. [Docker Setup](./DOCKER_SETUP.md) - -Setup summary. - -Overview of Docker configuration: - -- Files created -- Architecture overview -- Usage instructions -- Testing checklist -- Production best practices - -**When to read**: Understanding Docker setup - -### 7. [Docker Troubleshooting](./DOCKER_TROUBLESHOOTING.md) - -Problem solving. - -Comprehensive troubleshooting guide: - -- Common build issues -- Runtime problems -- Health check failures -- Performance optimization -- Debugging techniques - -**When to read**: Encountering Docker-related issues - ---- - -## Testing - -### 8. [Visual Testing](./VISUAL_TESTING.md) - -Quality assurance guide. - -Visual regression testing documentation: - -- Playwright setup and configuration -- Lighthouse CI integration -- Accessibility testing -- Test structure and examples -- CI/CD integration - -**When to read**: Writing or debugging visual tests - ---- - -## Documentation Standards - -All documentation in this directory follows these standards: - -### Structure - -1. **Overview** - What the document covers -2. **Quick Start** - Get up and running fast -3. **Detailed Guide** - Comprehensive information -4. **Reference** - Command/API reference -5. **Troubleshooting** - Common issues and solutions - -### Formatting Conventions - -- **Code blocks**: Include language identifier -- **Commands**: Show expected output when relevant -- **Paths**: Use absolute paths from project root -- **Links**: Use relative links between docs -- **Examples**: Provide working, tested examples - -### Maintenance - -- Review quarterly or when major changes occur -- Update version number when content changes -- Keep "Last Updated" date current -- Test all code examples before committing - ---- - -## Related Documentation - -### In Project Root - -- [`README.md`](../README.md) - Project overview and quick start -- [`AGENTS.md`](../AGENTS.md) - Comprehensive AI agent instructions -- [`.github/copilot-instructions.md`](../.github/copilot-instructions.md) - Concise AI coding guidelines - -### External Resources - -- [Vite Documentation](https://vitejs.dev/) -- [React Documentation](https://react.dev/) -- [Tailwind CSS](https://tailwindcss.com/) -- [shadcn/ui](https://ui.shadcn.com/) -- [Playwright](https://playwright.dev/) -- [Docker Documentation](https://docs.docker.com/) - ---- - -## Contributing to Documentation - -### Adding New Documentation - -1. Follow the standard structure template -2. Update this index file -3. Add cross-references where appropriate -4. Test all code examples -5. Submit PR with documentation changes - -### Updating Existing Documentation - -1. Update "Last Updated" date -2. Increment version if major changes -3. Maintain backward compatibility in examples -4. Update index if title/scope changes - -### Documentation Checklist - -- [ ] Clear title and purpose -- [ ] Table of contents for long documents -- [ ] Code examples tested -- [ ] Cross-references added -- [ ] No broken links -- [ ] Proper formatting -- [ ] Updated index - ---- - -## Support - -### Getting Help - -- **Issues**: Check troubleshooting guides first -- **Questions**: Review relevant documentation section -- **Bugs**: Include steps to reproduce with documentation reference -- **Improvements**: Submit PR with proposed changes - -### Documentation Feedback - -If you find any issues with the documentation: - -1. Check if information is outdated -2. Verify code examples still work -3. Submit issue with specific section reference -4. Suggest improvements via PR - ---- - -## Version History - -| Version | Date | Changes | -|---------|------|---------| -| 1.0.0 | 2025-11-07 | Initial comprehensive documentation release | -| | | - Environment setup guide | -| | | - Performance documentation (2 files) | -| | | - Docker deployment (4 files) | -| | | - Visual testing guide | -| | | - Documentation index (this file) | - ---- - -**Maintained by**: Monynha Softwares -**Project**: Boteco.pt -**Repository**: [Monynha-Softwares/boteco.pt](https://github.com/Monynha-Softwares/boteco.pt) diff --git a/docs/VISUAL_TESTING.md b/docs/VISUAL_TESTING.md deleted file mode 100644 index 13512a1..0000000 --- a/docs/VISUAL_TESTING.md +++ /dev/null @@ -1,243 +0,0 @@ -# Visual Regression Testing Guide - -This document describes the visual regression testing setup for Boteco.pt, implemented as part of the UI/UX Correction Plan. - -## Overview - -Visual regression testing ensures that UI changes don't introduce unintended visual bugs. This setup uses: - -- **Playwright** for browser automation and screenshot capture -- **Lighthouse CI** for accessibility scoring and performance metrics -- **GitHub Actions** for automated CI/CD testing - -## Quick Start - -### Installation - -```bash -# Install all dependencies including Playwright -pnpm install - -# Install Playwright browsers -pnpm exec playwright install -``` - -### Running Tests Locally - -```bash -# Run all visual tests -pnpm test:visual - -# Run tests in UI mode (interactive) -pnpm test:visual:ui - -# Update baseline screenshots -pnpm test:visual:update -``` - -### Running Lighthouse Audits Locally - -```bash -# Build the application first -pnpm build - -# Run Lighthouse CI -npx lhci autorun -``` - -## Test Structure - -### Visual Tests (`tests/visual/`) - -1. **homepage.spec.ts** - Tests home page layout and grid alignment - - Full page screenshots - - Individual section screenshots - - Multi-breakpoint tests (mobile, tablet, desktop) - -2. **sidebar.spec.ts** - Tests sidebar toggle behavior - - No layout shifts during toggle - - Rapid toggle stability - - Performance metrics (CLS) - -3. **accessibility.spec.ts** - Tests WCAG compliance - - Keyboard navigation - - ARIA labels coverage - - Heading hierarchy - - Color contrast - - Touch target sizes - -## Configuration Files - -### playwright.config.ts - -Configures test execution, browsers, and viewports: - -- **Browsers**: Chrome, Firefox, Safari (Desktop & Mobile) -- **Base URL**: http://localhost:8080 -- **Retries**: 2 on CI, 0 locally -- **Screenshots**: On failure -- **Video**: Retained on failure - -### .lighthouserc.json - -Configures Lighthouse audits and assertions: - -- **URLs Tested**: Home, About, Blog, Contact -- **Runs**: 3 per URL (for statistical accuracy) -- **Assertions**: - - Accessibility ≥ 90 (ERROR) - - Performance ≥ 80 (WARN) - - Best Practices ≥ 90 (WARN) - - SEO ≥ 90 (WARN) - - CLS < 0.1 (ERROR) - -## CI/CD Integration - -### GitHub Actions Workflows - -#### Visual Regression Workflow (`.github/workflows/visual-regression.yml`) - -Triggers on: -- Pull requests to `main` or `dev` -- Pushes to `main` or `dev` - -Steps: -1. Checkout code -2. Install dependencies -3. Install Playwright browsers -4. Run visual tests -5. Upload test reports and screenshots as artifacts - -#### Lighthouse CI Workflow (`.github/workflows/lighthouse.yml`) - -Triggers on: -- Pull requests to `main` or `dev` -- Pushes to `main` or `dev` - -Steps: -1. Checkout code -2. Install dependencies -3. Build application -4. Run Lighthouse CI -5. Upload reports -6. Comment PR with results - -## Acceptance Criteria - -### Visual Regression - -✅ **Passed if:** -- All screenshots match baseline (or differences are intentional) -- No layout shifts detected (CLS < 0.1) -- Grid alignment consistent across breakpoints - -### Accessibility - -✅ **Passed if:** -- Lighthouse Accessibility score ≥ 90 -- All interactive elements have ARIA labels -- Keyboard navigation works without traps -- Touch targets meet 44×44px minimum on mobile - -## Troubleshooting - -### Tests Failing Locally - -**Issue**: Screenshots don't match baseline - -**Solution**: -1. Verify the UI changes are intentional -2. If intentional, update baselines: `pnpm test:visual:update` -3. Review the updated screenshots in `test-results/` - -**Issue**: Tests timeout - -**Solution**: -1. Ensure dev server is running: `pnpm dev` -2. Increase timeout in `playwright.config.ts` -3. Check for JavaScript errors in console - -### CI Tests Failing - -**Issue**: Visual tests fail in CI but pass locally - -**Solution**: -- Font rendering differences between OS -- Use `maxDiffPixels` or `maxDiffPixelRatio` in test config -- Generate baselines in CI environment - -**Issue**: Lighthouse scores vary - -**Solution**: -- Lighthouse scores can vary ±5 points due to system load -- Review trends over multiple runs -- Focus on consistent patterns, not single values - -## Best Practices - -### Writing Visual Tests - -1. **Wait for stability**: Use `page.waitForLoadState('networkidle')` -2. **Consistent viewports**: Define in `playwright.config.ts` -3. **Meaningful names**: Use descriptive test and screenshot names -4. **Test in isolation**: Don't rely on previous test state - -### Updating Baselines - -1. **Review changes**: Always review diff reports before accepting -2. **Update selectively**: Update only screenshots for your changes -3. **Document reasons**: Add comment in PR explaining visual changes -4. **Cross-browser check**: Verify updates across all browser projects - -### Lighthouse Optimization - -1. **Build for production**: Always test production builds -2. **Minimize network**: Use local server or staging environment -3. **Consistent hardware**: CI environment should match production specs -4. **Multiple runs**: Average 3+ runs for accurate scores - -## Maintenance - -### Updating Playwright - -```bash -# Update Playwright -pnpm update @playwright/test - -# Reinstall browsers -pnpm exec playwright install -``` - -### Updating Lighthouse CI - -```bash -# Update Lighthouse CLI -pnpm update -D @lhci/cli -``` - -### Reviewing Test Coverage - -Periodically review: -- Are all critical user paths tested? -- Do tests cover all breakpoints? -- Are new components included in visual tests? - -## References - -- [Playwright Documentation](https://playwright.dev) -- [Lighthouse CI Documentation](https://github.com/GoogleChrome/lighthouse-ci) -- [UI/UX Correction Plan](../UI_UX_CORRECTION_PLAN.md) -- [Implementation Summary](../UI_UX_FIXES_IMPLEMENTATION_SUMMARY.md) - -## Support - -For questions or issues: -1. Check this guide first -2. Review Playwright/Lighthouse documentation -3. Check GitHub Actions logs for CI failures -4. Open an issue with test failure details - ---- - -**Last Updated**: November 2025 -**Maintained by**: Boteco.pt Development Team diff --git a/src/main copy.tsx b/src/main copy.tsx new file mode 100644 index 0000000..ff04552 --- /dev/null +++ b/src/main copy.tsx @@ -0,0 +1,64 @@ +import type { ReactNode } from "react"; +import { createRoot } from "react-dom/client"; +import App from "./App.tsx"; +import "./globals.css"; +import "./i18n"; // Importar a configuração do i18n +import { I18nextProvider } from "react-i18next"; +import i18n from "./i18n"; +import { ClerkProvider } from "@clerk/clerk-react"; +import { HelmetProvider } from "react-helmet-async"; +import { ThemeProvider } from "./components/ThemeProvider.tsx"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +// Obtenha a chave pública do Clerk do ambiente +const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY; + +// Configure QueryClient with optimized defaults +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + // Cache data for 5 minutes by default + staleTime: 5 * 60 * 1000, + // Keep unused data in cache for 10 minutes + gcTime: 10 * 60 * 1000, + // Retry failed requests once + retry: 1, + // Don't refetch on window focus in development + refetchOnWindowFocus: !import.meta.env.DEV, + }, + }, +}); + +const wrapWithProviders = (node: ReactNode) => ( + + + + + {node} + + + + +); + +const rootElement = document.getElementById("root"); + +if (!rootElement) { + throw new Error("Root element not found"); +} + +const root = createRoot(rootElement); +const appTree = wrapWithProviders(); + +if (PUBLISHABLE_KEY) { + root.render( + + {appTree} + , + ); +} else { + console.warn( + "Missing Publishable Key from Clerk. Rendering without authentication.", + ); + root.render(appTree); +} From cc004d49fd7f2abcc00842663420e388dca59183 Mon Sep 17 00:00:00 2001 From: Marcelo Santos Date: Sat, 15 Nov 2025 21:31:56 +0000 Subject: [PATCH 4/7] chore: update CI workflow to use pnpm; add tabWidth and useTabs to Prettier config; modify Playwright command for preview; clean up visual tests and remove obsolete test files --- .github/workflows/ci.yml | 38 ++--- .prettierrc | 8 ++ playwright.config.ts | 2 +- src/components/ui/chart.tsx | 2 +- src/lib/storage/index.ts | 4 + tests/blogPosts.test.mjs | 50 ------- tests/contactContent.test.mjs | 52 ------- tests/contactRequests.test.mjs | 80 ----------- tests/homeSections.test.mjs | 83 ----------- tests/theme.test.mjs | 64 --------- tests/visual/accessibility.spec.ts | 221 ----------------------------- tests/visual/homepage.spec.ts | 119 ---------------- tests/visual/sidebar.spec.ts | 203 -------------------------- 13 files changed, 25 insertions(+), 901 deletions(-) create mode 100644 src/lib/storage/index.ts delete mode 100644 tests/blogPosts.test.mjs delete mode 100644 tests/contactContent.test.mjs delete mode 100644 tests/contactRequests.test.mjs delete mode 100644 tests/homeSections.test.mjs delete mode 100644 tests/theme.test.mjs delete mode 100644 tests/visual/accessibility.spec.ts delete mode 100644 tests/visual/homepage.spec.ts delete mode 100644 tests/visual/sidebar.spec.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e9a10f..e4ed817 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,22 +28,14 @@ jobs: with: node-version: '20' - - name: Install bun - run: npm install -g bun + - name: Setup pnpm + run: npm install -g pnpm@latest - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: ~/.bun - key: ${{ runner.os }}-bun-${{ hashFiles('**/package.json') }} - restore-keys: | - ${{ runner.os }}-bun- - - - name: Run bun install - run: bun install + - name: Install dependencies + run: pnpm install --frozen-lockfile - name: Run linter - run: bun lint + run: pnpm lint test: name: Run Tests @@ -59,23 +51,15 @@ jobs: with: node-version: '20' - - name: Install bun - run: npm install -g bun - - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: ~/.bun - key: ${{ runner.os }}-bun-${{ hashFiles('**/package.json') }} - restore-keys: | - ${{ runner.os }}-bun- + - name: Setup pnpm + run: npm install -g pnpm@latest - - name: Run bun install - run: bun install + - name: Install dependencies + run: pnpm install --frozen-lockfile - name: Run unit tests - run: bun test + run: pnpm test - name: Run visual tests - run: bun test:visual + run: pnpm test:visual diff --git a/.prettierrc b/.prettierrc index e69de29..6b8ac64 100644 --- a/.prettierrc +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 2, + "useTabs": false +} diff --git a/playwright.config.ts b/playwright.config.ts index 9cae42b..3c12e21 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -53,7 +53,7 @@ export default defineConfig({ // Run your local dev server before starting the tests webServer: { - command: 'bun run preview --port 8080', + command: process.env.PREVIEW_CMD || 'pnpm preview -- --port 8080', url: 'http://localhost:8080', reuseExistingServer: !process.env.CI, timeout: 120 * 1000, diff --git a/src/components/ui/chart.tsx b/src/components/ui/chart.tsx index 8c11d15..dda35e0 100644 --- a/src/components/ui/chart.tsx +++ b/src/components/ui/chart.tsx @@ -50,7 +50,7 @@ const ChartContainer = React.forwardRef< data-chart={chartId} ref={ref} className={cn( - "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none", + "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_]:stroke-border [&_.recharts-sector]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none", className, )} {...props} diff --git a/src/lib/storage/index.ts b/src/lib/storage/index.ts new file mode 100644 index 0000000..e0fd12c --- /dev/null +++ b/src/lib/storage/index.ts @@ -0,0 +1,4 @@ +export * from './contactRequests'; + +// Barrel file for storage utilities. Add additional exports here as new +// storage modules are added (e.g., users.ts, settings.ts). diff --git a/tests/blogPosts.test.mjs b/tests/blogPosts.test.mjs deleted file mode 100644 index 1fb2d1e..0000000 --- a/tests/blogPosts.test.mjs +++ /dev/null @@ -1,50 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { readFileSync } from 'node:fs'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const repoRoot = path.resolve(__dirname, '..'); - -const loadBlog = (locale) => { - const filePath = path.join(repoRoot, `src/content/${locale}/blog.json`); - return JSON.parse(readFileSync(filePath, 'utf-8')); -}; - -const localesToCheck = ['pt', 'en']; - -const expectedKeys = ['content', 'cover', 'date', 'excerpt', 'id', 'slug', 'tags', 'title']; - -localesToCheck.forEach((locale) => { - test(`blog posts for ${locale} include required fields`, () => { - const blog = loadBlog(locale); - assert.ok(Array.isArray(blog.posts), 'posts array should exist'); - assert.ok(blog.posts.length > 0, 'posts array should not be empty'); - - blog.posts.forEach((post) => { - const keys = Object.keys(post).sort(); - assert.deepStrictEqual(keys, expectedKeys, `${locale} post keys should match expected structure`); - assert.ok(post.slug.length > 0, `${locale} post should have slug`); - assert.ok(post.cover.startsWith('/images/blog/'), `${locale} post should include cover path`); - assert.ok(post.tags.length > 0, `${locale} post should list at least one tag`); - assert.ok(post.content.length > 50, `${locale} post should include markdown content`); - }); - }); -}); - -test('blog fallback metadata is present and missing posts return undefined', () => { - const ptBlog = loadBlog('pt'); - const enBlog = loadBlog('en'); - - const findPost = (blog, slug) => blog.posts.find((post) => post.slug === slug); - - assert.strictEqual(findPost(ptBlog, 'nao-existe'), undefined, 'PT should return undefined for missing slug'); - assert.strictEqual(findPost(enBlog, 'does-not-exist'), undefined, 'EN should return undefined for missing slug'); - - ['title', 'message', 'cta'].forEach((key) => { - assert.ok(ptBlog.notFound?.[key], `PT notFound.${key} should exist`); - assert.ok(enBlog.notFound?.[key], `EN notFound.${key} should exist`); - }); -}); diff --git a/tests/contactContent.test.mjs b/tests/contactContent.test.mjs deleted file mode 100644 index 49353a1..0000000 --- a/tests/contactContent.test.mjs +++ /dev/null @@ -1,52 +0,0 @@ -import assert from 'node:assert/strict'; -import test from 'node:test'; - -import { createRequire } from 'node:module'; - -const require = createRequire(import.meta.url); - -const ptContact = require('../src/content/pt/contact.json'); -const enContact = require('../src/content/en/contact.json'); -const esContact = require('../src/content/es/contact.json'); -const frContact = require('../src/content/fr/contact.json'); - -const locales = { - pt: ptContact, - en: enContact, - es: esContact, - fr: frContact, -}; - -const requiredFormKeys = ['successDescription', 'errorDescription', 'submitting']; -const validationFields = { - name: ['min', 'max'], - email: ['invalid'], - message: ['min', 'max'], -}; - -test('contact form translations expose complete validation messages', () => { - for (const [locale, content] of Object.entries(locales)) { - assert.ok(content?.form, `form block missing for locale ${locale}`); - const { form } = content; - - for (const key of requiredFormKeys) { - const value = form[key]; - assert.equal(typeof value, 'string', `${key} must be a string for locale ${locale}`); - assert.ok(value.trim().length > 0, `${key} cannot be empty for locale ${locale}`); - } - - const validation = form.validation; - assert.ok(validation, `validation block missing for locale ${locale}`); - - for (const [field, rules] of Object.entries(validationFields)) { - const fieldMessages = validation[field]; - assert.ok(fieldMessages, `validation messages missing for field ${field} in locale ${locale}`); - - for (const rule of rules) { - const message = fieldMessages[rule]; - assert.equal(typeof message, 'string', `validation message for ${field}.${rule} must be string in locale ${locale}`); - assert.ok(message.trim().length > 0, `validation message for ${field}.${rule} cannot be empty in locale ${locale}`); - } - } - } -}); diff --git a/tests/contactRequests.test.mjs b/tests/contactRequests.test.mjs deleted file mode 100644 index 8e85882..0000000 --- a/tests/contactRequests.test.mjs +++ /dev/null @@ -1,80 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { readFileSync } from 'node:fs'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const repoRoot = path.resolve(__dirname, '..'); - -const loadJson = (relativePath) => { - const filePath = path.join(repoRoot, relativePath); - return JSON.parse(readFileSync(filePath, 'utf-8')); -}; - -const locales = ['pt', 'en', 'es', 'fr']; -const painelContent = Object.fromEntries(locales.map((locale) => [locale, loadJson(`src/content/${locale}/painel.json`)])); -const contactRequests = loadJson('public/data/contact-requests.json'); - -const uniqueChannels = new Set(contactRequests.map((request) => request.channel)); -const uniqueStatuses = new Set(contactRequests.map((request) => request.status)); - -const isValidIsoDate = (value) => { - if (typeof value !== 'string') { - return false; - } - - const timestamp = Date.parse(value); - return Number.isFinite(timestamp); -}; - -test('contact requests mock contains structured entries', () => { - assert.ok(Array.isArray(contactRequests), 'contact requests should be an array'); - assert.ok(contactRequests.length > 0, 'contact requests array should not be empty'); - - contactRequests.forEach((request, index) => { - assert.ok(typeof request.id === 'string' && request.id.length > 0, `request ${index} should have an id`); - assert.ok(typeof request.name === 'string' && request.name.length > 0, `request ${index} should have a name`); - assert.ok(typeof request.email === 'string' && request.email.includes('@'), `request ${index} should have an email`); - assert.ok(typeof request.channel === 'string' && request.channel.length > 0, `request ${index} should have a channel`); - assert.ok(typeof request.status === 'string' && request.status.length > 0, `request ${index} should have a status`); - assert.ok(isValidIsoDate(request.createdAt), `request ${index} should have a valid createdAt date`); - - if (request.respondedAt) { - assert.ok(isValidIsoDate(request.respondedAt), `request ${index} should have a valid respondedAt date when present`); - } - }); -}); - -test('painel cards stay aligned across locales', () => { - const referenceCards = painelContent.pt.cards; - locales.forEach((locale) => { - const cards = painelContent[locale].cards; - assert.ok(Array.isArray(cards), `${locale} cards should be an array`); - assert.strictEqual(cards.length, referenceCards.length, `${locale} should have ${referenceCards.length} cards`); - - cards.forEach((card, index) => { - assert.ok(card.id, `${locale} card ${index} should declare an id`); - assert.ok(card.title, `${locale} card ${card.id} should have a title`); - assert.ok(card.description, `${locale} card ${card.id} should have a description`); - assert.strictEqual(card.id, referenceCards[index].id, `${locale} card order should match reference`); - }); - }); -}); - -test('painel translations cover contact request channels and statuses', () => { - locales.forEach((locale) => { - const { leadInsights } = painelContent[locale]; - const channelLabels = leadInsights?.channels?.labels ?? {}; - const statusLabels = leadInsights?.status?.labels ?? {}; - - uniqueChannels.forEach((channel) => { - assert.ok(channelLabels[channel], `${locale} should translate channel ${channel}`); - }); - - uniqueStatuses.forEach((status) => { - assert.ok(statusLabels[status], `${locale} should translate status ${status}`); - }); - }); -}); diff --git a/tests/homeSections.test.mjs b/tests/homeSections.test.mjs deleted file mode 100644 index f050d0c..0000000 --- a/tests/homeSections.test.mjs +++ /dev/null @@ -1,83 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { readFileSync } from 'node:fs'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const repoRoot = path.resolve(__dirname, '..'); - -const loadJson = (relativePath) => { - const filePath = path.join(repoRoot, relativePath); - return JSON.parse(readFileSync(filePath, 'utf-8')); -}; - -const readSource = (relativePath) => { - const filePath = path.join(repoRoot, relativePath); - return readFileSync(filePath, 'utf-8'); -}; - -const ptHome = loadJson('src/content/pt/home.json'); -const enHome = loadJson('src/content/en/home.json'); - -const sectionsDepthExpectations = [ - ['src/components/home/HeroSection.tsx', 'Hero', 'depth="overlay"'], - ['src/components/home/FeaturesSection.tsx', 'FeatureGrid', 'depth="surface"'], - ['src/components/home/HowItWorksSection.tsx', 'Stepper', 'depth="overlay"'], - ['src/components/home/PlansSection.tsx', 'PricingTable', 'depth="surface"'], - ['src/components/home/TestimonialsSection.tsx', 'TestimonialCarousel', 'depth="surface"'], - ['src/components/home/FaqSection.tsx', 'Faq', 'depth="overlay"'], - ['src/components/home/FinalCtaSection.tsx', 'AnimatedSection', 'depth="overlay"'], -]; - -test('home content has hero translations for pt and en', () => { - assert.ok(ptHome.hero?.title?.length > 0, 'PT hero title should exist'); - assert.ok(enHome.hero?.title?.length > 0, 'EN hero title should exist'); - assert.notStrictEqual(ptHome.hero.title, enHome.hero.title, 'Hero titles should be localized'); - assert.ok(ptHome.hero?.cta, 'PT hero CTA exists'); - assert.ok(enHome.hero?.cta, 'EN hero CTA exists'); -}); - -test('feature lists stay in sync across locales', () => { - assert.strictEqual(ptHome.features?.length, enHome.features?.length, 'Feature arrays should match length'); - ptHome.features.forEach((feature, index) => { - assert.ok(feature.title, `PT feature ${index} has title`); - assert.ok(enHome.features[index].title, `EN feature ${index} has title`); - }); -}); - -test('plans options stay in sync across locales', () => { - assert.strictEqual(ptHome.plans?.options?.length, enHome.plans?.options?.length, 'Plan counts should match'); - ptHome.plans.options.forEach((plan, index) => { - assert.ok(plan.features?.length > 0, `PT plan ${plan.name} has features`); - assert.strictEqual( - plan.features.length, - enHome.plans.options[index].features.length, - `Plan ${plan.name} should match feature count` - ); - }); -}); - -test('Reactbits sections apply expected depth variants', () => { - sectionsDepthExpectations.forEach(([relativePath, componentName, expectedDepth]) => { - const source = readSource(relativePath); - assert.match( - source, - new RegExp(expectedDepth.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')), - `${componentName} should include ${expectedDepth}` - ); - }); -}); - -test('Reactbits components are used in each section', () => { - // Exclude FinalCtaSection (AnimatedSection) as it uses a custom animated wrapper instead of a direct reactbits component - sectionsDepthExpectations.slice(0, -1).forEach(([relativePath, componentName]) => { - const source = readSource(relativePath); - assert.match( - source, - new RegExp(`<${componentName}[^>]*>`), - `${relativePath} should render ${componentName}` - ); - }); -}); diff --git a/tests/theme.test.mjs b/tests/theme.test.mjs deleted file mode 100644 index 8d3af83..0000000 --- a/tests/theme.test.mjs +++ /dev/null @@ -1,64 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { readFileSync } from 'node:fs'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const repoRoot = path.resolve(__dirname, '..'); - -const readSource = (relativePath) => { - const filePath = path.join(repoRoot, relativePath); - return readFileSync(filePath, 'utf-8'); -}; - -const themeProviderSource = readSource('src/components/ThemeProvider.tsx'); -const themeToggleSource = readSource('src/components/ThemeToggle.tsx'); -const globalsCss = readSource('src/globals.css'); - -test('theme provider defaults to class-based theming with transitions', () => { - assert.match( - themeProviderSource, - /attribute\s*=\s*"class"/, - 'ThemeProvider should default to using the class attribute', - ); - assert.match( - themeProviderSource, - /disableTransitionOnChange\s*=\s*true/, - 'ThemeProvider should disable transition flashes when switching', - ); - assert.match( - themeProviderSource, - /enableColorScheme\s*=\s*true/, - 'ThemeProvider should expose the active color scheme to the browser', - ); -}); - -test('theme toggle exposes radio options for light, dark and system', () => { - assert.match( - themeToggleSource, - /DropdownMenuRadioGroup/, - 'ThemeToggle should group the theme options in a radio group', - ); - ['light', 'dark', 'system'].forEach((option) => { - assert.match( - themeToggleSource, - new RegExp(`DropdownMenuRadioItem\\s+value=\\"${option}\\"`), - `ThemeToggle should include a radio item for ${option}`, - ); - }); -}); - -test('global body styles animate background and foreground changes', () => { - assert.match( - globalsCss, - /body\s*\{[^}]*transition-colors[^}]*\}/s, - 'Body styles should include a transition for color changes', - ); - assert.match( - globalsCss, - /body\s*\{[^}]*min-h-screen[^}]*\}/s, - 'Body styles should ensure the viewport stays filled in both themes', - ); -}); diff --git a/tests/visual/accessibility.spec.ts b/tests/visual/accessibility.spec.ts deleted file mode 100644 index 2be7366..0000000 --- a/tests/visual/accessibility.spec.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { test, expect } from '@playwright/test'; - -// Constants for accessibility testing -const MAX_TAB_COUNT = 50; // Maximum tabs to prevent infinite loops - -/** - * Accessibility Tests - * Validates WCAG compliance and accessibility features - */ -test.describe('Accessibility - Keyboard Navigation', () => { - test('can navigate entire site with keyboard', async ({ page }) => { - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - // Tab through all interactive elements - let tabCount = 0; - - while (tabCount < MAX_TAB_COUNT) { // Limit to prevent infinite loop - await page.keyboard.press('Tab'); - tabCount++; - - // Check if we've trapped in a focus loop - const focusedElement = await page.evaluate(() => { - const el = document.activeElement; - return { - tagName: el?.tagName, - role: el?.getAttribute('role'), - ariaLabel: el?.getAttribute('aria-label'), - }; - }); - - // If we hit a link and press Enter, we should navigate - if (focusedElement.tagName === 'A') { - // Found a link, continue tabbing - continue; - } - } - - // Should have successfully tabbed through elements - expect(tabCount).toBeGreaterThan(5); - }); - - test('sidebar trigger is keyboard accessible', async ({ page }) => { - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - const trigger = page.locator('[data-sidebar="trigger"]'); - - if (await trigger.count() === 0) { - test.skip(true, 'Sidebar trigger not found'); - return; - } - - // Focus the trigger - await trigger.focus(); - - // Check it has visible focus indicator - const hasFocusRing = await trigger.evaluate((el) => { - const styles = window.getComputedStyle(el); - return styles.outline !== 'none' || styles.boxShadow !== 'none'; - }); - - expect(hasFocusRing).toBeTruthy(); - - // Press Enter to toggle - await page.keyboard.press('Enter'); - await page.waitForTimeout(300); - - // Should have toggled - const isToggled = await page.evaluate(() => { - return document.querySelector('[data-sidebar]')?.getAttribute('data-state') === 'collapsed'; - }); - - // Should respond to keyboard activation (true or false, just checking it responded) - expect(typeof isToggled).toBe('boolean'); - }); -}); - -test.describe('Accessibility - ARIA Labels', () => { - test('all icon-only buttons have ARIA labels', async ({ page }) => { - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - // Find all buttons with only icons (no visible text) - const iconButtons = await page.locator('button').evaluateAll((buttons) => { - return buttons.filter((btn) => { - const hasVisibleText = (btn.textContent?.trim().length ?? 0) > 0; - const hasAriaLabel = btn.getAttribute('aria-label'); - const hasSrOnly = btn.querySelector('.sr-only'); - - // Consider it an icon-only button if it has no visible text - // but should have either aria-label or sr-only text - if (!hasVisibleText && !hasAriaLabel && !hasSrOnly) { - return true; // This is a problem button - } - return false; - }).length; - }); - - // All icon-only buttons should have labels - expect(iconButtons).toBe(0); - }); - - test('language switcher has ARIA label', async ({ page }) => { - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - const languageSwitcher = page.locator('[aria-label="Select language"]'); - await expect(languageSwitcher).toBeVisible(); - }); - - test('theme toggle has screen reader text', async ({ page }) => { - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - const themeToggle = page.locator('button').filter({ has: page.locator('.sr-only') }); - const count = await themeToggle.count(); - - // Should have at least one button with sr-only text (theme toggle) - expect(count).toBeGreaterThan(0); - }); -}); - -test.describe('Accessibility - Heading Hierarchy', () => { - test('home page has proper heading hierarchy', async ({ page }) => { - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - const headings = await page.evaluate(() => { - const h1s = Array.from(document.querySelectorAll('h1')).map(h => h.textContent?.trim()); - const h2s = Array.from(document.querySelectorAll('h2')).map(h => h.textContent?.trim()); - const h3s = Array.from(document.querySelectorAll('h3')).map(h => h.textContent?.trim()); - - return { h1s, h2s, h3s }; - }); - - // Should have exactly one H1 - expect(headings.h1s.length).toBe(1); - - // Should have H2s - expect(headings.h2s.length).toBeGreaterThan(0); - - // H1 should not be empty - expect(headings.h1s[0]).toBeTruthy(); - }); - - test('blog page has proper heading hierarchy', async ({ page }) => { - await page.goto('/pt/blog'); - await page.waitForLoadState('networkidle'); - - const h1Count = await page.locator('h1').count(); - expect(h1Count).toBe(1); - }); - - test('about page has proper heading hierarchy', async ({ page }) => { - await page.goto('/pt/sobre'); - await page.waitForLoadState('networkidle'); - - const h1Count = await page.locator('h1').count(); - expect(h1Count).toBe(1); - }); -}); - -test.describe('Accessibility - Color Contrast', () => { - test('text elements have sufficient color contrast', async ({ page }) => { - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - // Sample key text elements - const textElements = [ - page.locator('h1').first(), - page.locator('p').first(), - page.locator('a').first(), - ]; - - for (const element of textElements) { - if (await element.count() === 0) continue; - - const contrastInfo = await element.evaluate((el) => { - const styles = window.getComputedStyle(el); - const color = styles.color; - const backgroundColor = styles.backgroundColor; - const fontSize = parseFloat(styles.fontSize); - - return { color, backgroundColor, fontSize }; - }); - - // Basic check - elements should have defined colors - expect(contrastInfo.color).toBeTruthy(); - expect(contrastInfo.backgroundColor).toBeTruthy(); - } - }); -}); - -test.describe('Accessibility - Touch Targets', () => { - test('mobile interactive elements meet minimum size', async ({ page }) => { - await page.setViewportSize({ width: 375, height: 667 }); - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - const buttons = await page.locator('button:visible, a:visible').evaluateAll((elements) => { - return elements.map((el) => { - const rect = el.getBoundingClientRect(); - return { - width: rect.width, - height: rect.height, - meets44x44: rect.width >= 44 && rect.height >= 44, - meets40x40: rect.width >= 40 && rect.height >= 40, - }; - }).filter(size => size.width > 0 && size.height > 0); - }); - - // At least 80% of interactive elements should meet practical minimum (40x40) - // Note: WCAG 2.5.5 recommends 44x44, but 40x40 is acceptable for most elements - const passing = buttons.filter(b => b.meets40x40).length; - const total = buttons.length; - const percentage = (passing / total) * 100; - - expect(percentage).toBeGreaterThan(80); - }); -}); diff --git a/tests/visual/homepage.spec.ts b/tests/visual/homepage.spec.ts deleted file mode 100644 index 4790b09..0000000 --- a/tests/visual/homepage.spec.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { test, expect } from '@playwright/test'; - -/** - * Visual Regression Tests for Home Page - * Tests the layout and grid alignment at different breakpoints - */ -test.describe('Home Page Visual Regression', () => { - test.beforeEach(async ({ page }) => { - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - }); - - test('desktop layout full page', async ({ page }) => { - await expect(page).toHaveScreenshot('home-desktop-full.png', { - fullPage: true, - }); - }); - - test('hero section renders correctly', async ({ page }) => { - const hero = page.locator('section').first(); - await hero.waitFor({ state: 'visible' }); - await expect(hero).toHaveScreenshot('hero-section.png'); - }); - - test('features grid alignment', async ({ page }) => { - // Scroll to features section - await page.evaluate(() => { - const sections = document.querySelectorAll('section'); - if (sections[1]) { - sections[1].scrollIntoView({ behavior: 'instant', block: 'center' }); - } - }); - - // Wait for scroll position to stabilize - const featuresSection = page.locator('section').nth(1); - await featuresSection.waitFor({ state: 'visible' }); - - await expect(featuresSection).toHaveScreenshot('features-grid.png'); - }); - - test('solutions grid alignment', async ({ page }) => { - // Scroll to solutions section - await page.evaluate(() => { - const sections = document.querySelectorAll('section'); - if (sections[2]) { - sections[2].scrollIntoView({ behavior: 'instant', block: 'center' }); - } - }); - - // Wait for scroll position to stabilize - const solutionsSection = page.locator('section').nth(2); - await solutionsSection.waitFor({ state: 'visible' }); - - await expect(solutionsSection).toHaveScreenshot('solutions-grid.png'); - }); -}); - -test.describe('Grid Alignment at Multiple Breakpoints', () => { - const breakpoints = [ - { width: 375, height: 667, name: 'mobile' }, - { width: 768, height: 1024, name: 'tablet' }, - { width: 1024, height: 768, name: 'desktop-small' }, - { width: 1440, height: 900, name: 'desktop-large' }, - ]; - - for (const bp of breakpoints) { - test(`grid alignment at ${bp.name} (${bp.width}x${bp.height})`, async ({ page }) => { - await page.setViewportSize({ width: bp.width, height: bp.height }); - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - // Scroll through key sections - await page.evaluate(() => { - const sections = document.querySelectorAll('section'); - if (sections[1]) { - sections[1].scrollIntoView({ behavior: 'instant', block: 'center' }); - } - }); - - // Wait for the section to be visible and stable - await page.locator('section').nth(1).waitFor({ state: 'visible' }); - - await expect(page).toHaveScreenshot(`home-${bp.name}.png`, { - fullPage: true, - }); - }); - } -}); - -test.describe('Blog Page Grid Consistency', () => { - test('blog grid layout', async ({ page }) => { - await page.goto('/pt/blog'); - await page.waitForLoadState('networkidle'); - - const blogGrid = page.locator('.grid').first(); - await expect(blogGrid).toHaveScreenshot('blog-grid.png'); - }); -}); - -test.describe('About Page Grid Consistency', () => { - test('about values grid', async ({ page }) => { - await page.goto('/pt/sobre'); - await page.waitForLoadState('networkidle'); - - // Scroll to values section - await page.evaluate(() => { - const grids = document.querySelectorAll('.grid'); - if (grids[0]) { - grids[0].scrollIntoView({ behavior: 'instant', block: 'center' }); - } - }); - - // Wait for the grid to be visible and stable - const valuesGrid = page.locator('.grid').first(); - await valuesGrid.waitFor({ state: 'visible' }); - - await expect(valuesGrid).toHaveScreenshot('about-values-grid.png'); - }); -}); diff --git a/tests/visual/sidebar.spec.ts b/tests/visual/sidebar.spec.ts deleted file mode 100644 index 09c90a2..0000000 --- a/tests/visual/sidebar.spec.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { test, expect } from '@playwright/test'; - -/** - * Visual Regression Tests for Sidebar - * Validates no layout shifts during toggle - */ - -// Type definition for Layout Shift Performance Entry -interface LayoutShiftEntry extends PerformanceEntry { - value: number; - hadRecentInput: boolean; -} - -test.describe('Sidebar Toggle Animation', () => { - test.beforeEach(async ({ page }) => { - // Navigate to a page with sidebar (assuming /pt/painel or similar) - // Adjust path based on actual sidebar implementation - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - }); - - test('sidebar toggle does not cause layout shifts', async ({ page }) => { - // Find the sidebar trigger button - const trigger = page.locator('[data-sidebar="trigger"]'); - - if (await trigger.count() === 0) { - test.skip(true, 'Sidebar trigger not found on this page'); - return; - } - - const sidebar = page.locator('[data-sidebar="sidebar"]'); - - // Capture before toggle - await expect(page).toHaveScreenshot('sidebar-before-toggle.png'); - - // Toggle sidebar - await trigger.click(); - - // Wait for transition to complete by checking when the element becomes stable - await page.evaluate(() => - new Promise((resolve) => { - const sidebarEl = document.querySelector('[data-sidebar="sidebar"]'); - if (!sidebarEl) { - resolve(); - return; - } - const handler = () => { - sidebarEl.removeEventListener('transitionend', handler); - resolve(); - }; - sidebarEl.addEventListener('transitionend', handler); - // Fallback timeout in case transitionend doesn't fire - setTimeout(() => { - sidebarEl.removeEventListener('transitionend', handler); - resolve(); - }, 500); - }) - ); - - // Capture after toggle - await expect(page).toHaveScreenshot('sidebar-after-toggle.png'); - - // Toggle back - await trigger.click(); - - // Wait for transition to complete - await page.evaluate(() => - new Promise((resolve) => { - const sidebarEl = document.querySelector('[data-sidebar="sidebar"]'); - if (!sidebarEl) { - resolve(); - return; - } - const handler = () => { - sidebarEl.removeEventListener('transitionend', handler); - resolve(); - }; - sidebarEl.addEventListener('transitionend', handler); - // Fallback timeout - setTimeout(() => { - sidebarEl.removeEventListener('transitionend', handler); - resolve(); - }, 500); - }) - ); - - // Should match the original state - await expect(page).toHaveScreenshot('sidebar-toggled-back.png'); - }); - - test('rapid sidebar toggles remain stable', async ({ page }) => { - const trigger = page.locator('[data-sidebar="trigger"]'); - - if (await trigger.count() === 0) { - test.skip(true, 'Sidebar trigger not found on this page'); - return; - } - - // Perform rapid toggles - for (let i = 0; i < 5; i++) { - await trigger.click(); - // Wait briefly between clicks to ensure click is registered - await page.waitForTimeout(50); - } - - // Wait for all animations to settle by checking when sidebar transitions complete - await page.evaluate(() => - new Promise((resolve) => { - const sidebarEl = document.querySelector('[data-sidebar="sidebar"]'); - if (!sidebarEl) { - resolve(); - return; - } - let timeoutId: number; - const handler = () => { - // Clear existing timeout and set a new one to ensure all transitions are done - clearTimeout(timeoutId); - timeoutId = window.setTimeout(() => { - sidebarEl.removeEventListener('transitionend', handler); - resolve(); - }, 100); - }; - sidebarEl.addEventListener('transitionend', handler); - // Initial timeout to start the check - timeoutId = window.setTimeout(() => { - sidebarEl.removeEventListener('transitionend', handler); - resolve(); - }, 1000); - }) - ); - - // Check final state is stable - await expect(page).toHaveScreenshot('sidebar-after-rapid-toggles.png'); - }); -}); - -test.describe('Sidebar Performance', () => { - test('sidebar toggle has no layout shifts', async ({ page }) => { - // Start measuring layout shifts - await page.goto('/pt'); - await page.waitForLoadState('networkidle'); - - const trigger = page.locator('[data-sidebar="trigger"]'); - - if (await trigger.count() === 0) { - test.skip(true, 'Sidebar trigger not found on this page'); - return; - } - - // Measure layout shifts during toggle - const layoutShifts = await page.evaluate(() => { - return new Promise((resolve) => { - let cumulativeShift = 0; - const observer = new PerformanceObserver((list) => { - for (const entry of list.getEntries()) { - if (entry.entryType === 'layout-shift') { - // Check for user input using the PerformanceEntry properties - const hasRecentInput = 'hadRecentInput' in entry ? (entry as Record).hadRecentInput : false; - if (!hasRecentInput) { - const value = 'value' in entry ? (entry as Record).value as number : 0; - cumulativeShift += value; - } - } - } - }); - observer.observe({ type: 'layout-shift', buffered: true }); - - setTimeout(() => { - observer.disconnect(); - resolve(cumulativeShift); - }, 1000); - }); - }); - - // Trigger sidebar toggle - await trigger.click(); - - // Wait for transition to complete before checking layout shifts - await page.evaluate(() => - new Promise((resolve) => { - const sidebarEl = document.querySelector('[data-sidebar="sidebar"]'); - if (!sidebarEl) { - resolve(); - return; - } - const handler = () => { - sidebarEl.removeEventListener('transitionend', handler); - resolve(); - }; - sidebarEl.addEventListener('transitionend', handler); - // Fallback timeout - setTimeout(() => { - sidebarEl.removeEventListener('transitionend', handler); - resolve(); - }, 500); - }) - ); - - // Layout shift score should be 0 or very close to 0 - // Good: < 0.1, Needs improvement: 0.1-0.25, Poor: > 0.25 - expect(layoutShifts).toBeLessThan(0.1); - }); -}); From 756225f0d50a278de85450b8c38500450f0e5b45 Mon Sep 17 00:00:00 2001 From: Marcelo Santos Date: Sat, 15 Nov 2025 21:43:37 +0000 Subject: [PATCH 5/7] refactor: remove unused TypeScript configuration files and add comprehensive tests - Deleted obsolete TypeScript configuration files: `tsconfig copy.json` and `tsconfig.app copy.json`. - Introduced new test files for various components and functionalities: - `blogPosts.test.mjs`: Validates structure and content of blog posts across locales. - `contactContent.test.mjs`: Ensures contact form translations are complete and validation messages are present. - `contactRequests.test.mjs`: Tests structure and data integrity of contact requests. - `homeSections.test.mjs`: Confirms home page sections have consistent translations and expected components. - `theme.test.mjs`: Validates theme provider and toggle functionality. - `accessibility.spec.ts`: Conducts accessibility tests for keyboard navigation, ARIA labels, heading hierarchy, color contrast, and touch targets. - `homepage.spec.ts`: Performs visual regression tests for the home page layout and grid alignment. - `sidebar.spec.ts`: Tests sidebar toggle animations and performance to ensure no layout shifts occur. --- pnpm-lock.yaml | 3053 ++++++++++++++-------------- tests/blogPosts.test.mjs | 50 + tests/contactContent.test.mjs | 52 + tests/contactRequests.test.mjs | 80 + tests/homeSections.test.mjs | 83 + tests/theme.test.mjs | 64 + tests/visual/accessibility.spec.ts | 221 ++ tests/visual/homepage.spec.ts | 119 ++ tests/visual/sidebar.spec.ts | 203 ++ tsconfig copy.json | 19 - tsconfig.app copy.json | 31 - 11 files changed, 2423 insertions(+), 1552 deletions(-) create mode 100644 tests/blogPosts.test.mjs create mode 100644 tests/contactContent.test.mjs create mode 100644 tests/contactRequests.test.mjs create mode 100644 tests/homeSections.test.mjs create mode 100644 tests/theme.test.mjs create mode 100644 tests/visual/accessibility.spec.ts create mode 100644 tests/visual/homepage.spec.ts create mode 100644 tests/visual/sidebar.spec.ts delete mode 100644 tsconfig copy.json delete mode 100644 tsconfig.app copy.json diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d639aec..c0faf2d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,94 +10,94 @@ importers: dependencies: '@clerk/clerk-react': specifier: ^5.53.4 - version: 5.53.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 5.55.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@hookform/resolvers': specifier: ^3.9.0 - version: 3.10.0(react-hook-form@7.55.0(react@18.3.1)) + version: 3.10.0(react-hook-form@7.66.0(react@18.3.1)) '@radix-ui/react-accordion': specifier: ^1.2.0 - version: 1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.2.12(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-alert-dialog': specifier: ^1.1.1 - version: 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-aspect-ratio': specifier: ^1.1.0 - version: 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-avatar': specifier: ^1.1.0 - version: 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-checkbox': specifier: ^1.1.1 - version: 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.3.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-collapsible': specifier: ^1.1.0 - version: 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-context-menu': specifier: ^2.2.1 - version: 2.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.2.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dialog': specifier: ^1.1.2 - version: 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dropdown-menu': specifier: ^2.1.1 - version: 2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.1.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-hover-card': specifier: ^1.1.1 - version: 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-label': specifier: ^2.1.0 - version: 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.1.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-menubar': specifier: ^1.1.1 - version: 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-navigation-menu': specifier: ^1.2.0 - version: 1.2.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.2.14(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': specifier: ^1.1.1 - version: 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-progress': specifier: ^1.1.0 - version: 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-radio-group': specifier: ^1.2.0 - version: 1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.3.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-scroll-area': specifier: ^1.1.0 - version: 1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.2.10(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-select': specifier: ^2.1.1 - version: 2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.2.6(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-separator': specifier: ^1.1.0 - version: 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slider': specifier: ^1.2.0 - version: 1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.3.6(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': specifier: ^1.1.0 - version: 1.2.0(@types/react@18.3.20)(react@18.3.1) + version: 1.2.4(@types/react@18.3.26)(react@18.3.1) '@radix-ui/react-switch': specifier: ^1.1.0 - version: 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.2.6(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tabs': specifier: ^1.1.0 - version: 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-toast': specifier: ^1.2.1 - version: 1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.2.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-toggle': specifier: ^1.1.0 - version: 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-toggle-group': specifier: ^1.1.0 - version: 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tooltip': specifier: ^1.1.4 - version: 1.2.0(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tanstack/react-query': specifier: ^5.56.2 - version: 5.74.4(react@18.3.1) + version: 5.90.9(react@18.3.1) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -106,7 +106,7 @@ importers: version: 2.1.1 cmdk: specifier: ^1.0.0 - version: 1.1.1(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.1.1(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) date-fns: specifier: ^3.6.0 version: 3.6.0 @@ -118,7 +118,7 @@ importers: version: 12.23.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) i18next: specifier: ^25.6.0 - version: 25.6.0(typescript@5.8.3) + version: 25.6.2(typescript@5.9.3) i18next-browser-languagedetector: specifier: ^8.2.0 version: 8.2.0 @@ -145,19 +145,19 @@ importers: version: 2.0.5(react@18.3.1) react-hook-form: specifier: ^7.53.0 - version: 7.55.0(react@18.3.1) + version: 7.66.0(react@18.3.1) react-i18next: specifier: ^16.2.3 - version: 16.2.3(i18next@25.6.0(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3) + version: 16.3.3(i18next@25.6.2(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) react-resizable-panels: specifier: ^2.1.3 - version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router-dom: specifier: ^6.26.2 - version: 6.30.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 6.30.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) recharts: specifier: ^2.12.7 - version: 2.15.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.15.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) sonner: specifier: ^1.5.0 version: 1.7.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -166,20 +166,20 @@ importers: version: 2.6.0 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.17) + version: 1.0.7(tailwindcss@3.4.18) vaul: specifier: ^0.9.3 - version: 0.9.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.9.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) zod: specifier: ^3.23.8 - version: 3.24.3 + version: 3.25.76 devDependencies: '@dyad-sh/react-vite-component-tagger': specifier: ^0.8.0 - version: 0.8.0(vite@6.3.4(@types/node@22.14.1)(jiti@1.21.7)(yaml@2.7.1)) + version: 0.8.0(vite@6.4.1(@types/node@22.19.1)(jiti@1.21.7)) '@eslint/js': specifier: ^9.9.0 - version: 9.24.0 + version: 9.39.1 '@lhci/cli': specifier: ^0.13.0 version: 0.13.0 @@ -188,52 +188,52 @@ importers: version: 1.56.1 '@tailwindcss/typography': specifier: ^0.5.15 - version: 0.5.16(tailwindcss@3.4.17) + version: 0.5.19(tailwindcss@3.4.18) '@types/node': specifier: ^22.5.5 - version: 22.14.1 + version: 22.19.1 '@types/react': specifier: ^18.3.3 - version: 18.3.20 + version: 18.3.26 '@types/react-dom': specifier: ^18.3.0 - version: 18.3.6(@types/react@18.3.20) + version: 18.3.7(@types/react@18.3.26) '@vitejs/plugin-react-swc': specifier: ^3.9.0 - version: 3.9.0(vite@6.3.4(@types/node@22.14.1)(jiti@1.21.7)(yaml@2.7.1)) + version: 3.11.0(vite@6.4.1(@types/node@22.19.1)(jiti@1.21.7)) autoprefixer: specifier: ^10.4.20 - version: 10.4.21(postcss@8.5.3) + version: 10.4.22(postcss@8.5.6) eslint: specifier: ^9.9.0 - version: 9.24.0(jiti@1.21.7) + version: 9.39.1(jiti@1.21.7) eslint-plugin-react-hooks: specifier: ^5.1.0-rc.0 - version: 5.2.0(eslint@9.24.0(jiti@1.21.7)) + version: 5.2.0(eslint@9.39.1(jiti@1.21.7)) eslint-plugin-react-refresh: specifier: ^0.4.9 - version: 0.4.19(eslint@9.24.0(jiti@1.21.7)) + version: 0.4.24(eslint@9.39.1(jiti@1.21.7)) globals: specifier: ^15.9.0 version: 15.15.0 postcss: specifier: ^8.4.47 - version: 8.5.3 + version: 8.5.6 shadcn: specifier: ^3.5.0 - version: 3.5.0(@types/node@22.14.1)(typescript@5.8.3) + version: 3.5.0(@types/node@22.19.1)(typescript@5.9.3) tailwindcss: specifier: ^3.4.11 - version: 3.4.17 + version: 3.4.18 typescript: specifier: ^5.5.3 - version: 5.8.3 + version: 5.9.3 typescript-eslint: specifier: ^8.0.1 - version: 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) + version: 8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3) vite: specifier: ^6.3.4 - version: 6.3.4(@types/node@22.14.1)(jiti@1.21.7)(yaml@2.7.1) + version: 6.4.1(@types/node@22.19.1)(jiti@1.21.7) packages: @@ -315,10 +315,6 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} @@ -331,11 +327,6 @@ packages: resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} - '@babel/parser@7.27.5': - resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} - engines: {node: '>=6.0.0'} - hasBin: true - '@babel/parser@7.28.5': resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} @@ -371,10 +362,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.27.0': - resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} - engines: {node: '>=6.9.0'} - '@babel/runtime@7.28.4': resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} @@ -387,23 +374,19 @@ packages: resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.27.6': - resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} - engines: {node: '>=6.9.0'} - '@babel/types@7.28.5': resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - '@clerk/clerk-react@5.53.4': - resolution: {integrity: sha512-Ozl+5QxIGiH4dbzPpCIUmooSj+5R5hCVWwH+FLrgUrtZNV6Nu2XpjkwAL2gursfQjElWtOqBxfG5spThHiWRbg==} + '@clerk/clerk-react@5.55.0': + resolution: {integrity: sha512-CWLV0f87utJY2tS40n7imCPJHP2+DPwhoZhCRS2dtYd/c29kLAR5rgydBAy4KkvzZLCPG3Hyt4Vlw1EuMLTq1A==} engines: {node: '>=18.17.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 || ^19.0.0-0 react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-0 - '@clerk/shared@3.29.0': - resolution: {integrity: sha512-gwPInODY+Gp02UQcLN5FBP8MetT3LWR7mkkOX7zNM3U34WgGbs2qkQEOrY1BuHxIo/iFvkvZiXkH0oCXqto+Kw==} + '@clerk/shared@3.34.0': + resolution: {integrity: sha512-ZuruC+VtvejdnNj+e1sI5JK8tRdOc9wsMWyLNeumXrsZGh92DHTT+FGxCSDPJcmro0iIYw8ZiZqjHT9Fb2gMTg==} engines: {node: '>=18.17.0'} peerDependencies: react: ^18.0.0 || ^19.0.0 || ^19.0.0-0 @@ -414,12 +397,8 @@ packages: react-dom: optional: true - '@clerk/types@4.96.0': - resolution: {integrity: sha512-07AoSkx6CF1YjjRFa75HtrmZuVe+8X9WskWZJ6bC1juxYKf0RQfVbNHoEjMuJMh2+Ao6LYrNcrTu8gNwB2O4MA==} - engines: {node: '>=18.17.0'} - - '@dotenvx/dotenvx@1.51.0': - resolution: {integrity: sha512-CbMGzyOYSyFF7d4uaeYwO9gpSBzLTnMmSmTVpCZjvpJFV69qYbjYPpzNnCz1mb2wIvEhjWjRwQWuBzTO0jITww==} + '@dotenvx/dotenvx@1.51.1': + resolution: {integrity: sha512-fqcQxcxC4LOaUlW8IkyWw8x0yirlLUkbxohz9OnWvVWjf73J5yyw7jxWnkOJaUKXZotcGEScDox9MU6rSkcDgg==} hasBin: true '@dyad-sh/react-vite-component-tagger@0.8.0': @@ -427,218 +406,220 @@ packages: peerDependencies: vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 - '@ecies/ciphers@0.2.4': - resolution: {integrity: sha512-t+iX+Wf5nRKyNzk8dviW3Ikb/280+aEJAnw9YXvCp2tYGPSkMki+NRY+8aNLmVFv3eNtMdvViPNOPxS8SZNP+w==} + '@ecies/ciphers@0.2.5': + resolution: {integrity: sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A==} engines: {bun: '>=1', deno: '>=2', node: '>=16'} peerDependencies: '@noble/ciphers': ^1.0.0 - '@esbuild/aix-ppc64@0.25.3': - resolution: {integrity: sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.3': - resolution: {integrity: sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==} + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.3': - resolution: {integrity: sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==} + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.3': - resolution: {integrity: sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==} + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.3': - resolution: {integrity: sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==} + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.3': - resolution: {integrity: sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==} + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.3': - resolution: {integrity: sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==} + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.3': - resolution: {integrity: sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==} + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.3': - resolution: {integrity: sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==} + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.3': - resolution: {integrity: sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==} + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.3': - resolution: {integrity: sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==} + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.3': - resolution: {integrity: sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==} + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.3': - resolution: {integrity: sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==} + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.3': - resolution: {integrity: sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==} + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.3': - resolution: {integrity: sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==} + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.3': - resolution: {integrity: sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==} + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.3': - resolution: {integrity: sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==} + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.3': - resolution: {integrity: sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==} + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.3': - resolution: {integrity: sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==} + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.3': - resolution: {integrity: sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==} + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.3': - resolution: {integrity: sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==} + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.25.3': - resolution: {integrity: sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==} + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.3': - resolution: {integrity: sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==} + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.3': - resolution: {integrity: sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==} + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.3': - resolution: {integrity: sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==} + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.6.1': - resolution: {integrity: sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==} + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.20.0': - resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/config-helpers@0.2.1': - resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.12.0': - resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.13.0': - resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.24.0': - resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==} + '@eslint/js@9.39.1': + resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.6': - resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.2.8': - resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@floating-ui/core@1.6.9': - resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} + '@floating-ui/core@1.7.3': + resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} - '@floating-ui/dom@1.6.13': - resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==} + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} - '@floating-ui/react-dom@2.1.2': - resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} + '@floating-ui/react-dom@2.1.6': + resolution: {integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' - '@floating-ui/utils@0.2.9': - resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} '@formatjs/ecma402-abstract@2.3.6': resolution: {integrity: sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==} @@ -664,28 +645,24 @@ packages: resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@humanwhocodes/retry@0.4.2': - resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} - engines: {node: '>=18.18'} - - '@inquirer/ansi@1.0.1': - resolution: {integrity: sha512-yqq0aJW/5XPhi5xOAL1xRCpe1eh8UFVgYFpFsjEqmIR8rKLyP+HINvFXwUaxYICflJrVlxnp7lLN6As735kVpw==} + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} engines: {node: '>=18'} - '@inquirer/confirm@5.1.19': - resolution: {integrity: sha512-wQNz9cfcxrtEnUyG5PndC8g3gZ7lGDBzmWiXZkX8ot3vfZ+/BLjR8EvyGX4YzQLeVqtAlY/YScZpW7CW8qMoDQ==} + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -693,8 +670,8 @@ packages: '@types/node': optional: true - '@inquirer/core@10.3.0': - resolution: {integrity: sha512-Uv2aPPPSK5jeCplQmQ9xadnFx2Zhj9b5Dj7bU6ZeCdDNNY11nhYy4btcSdtDguHqCT2h5oNeQTcUNSGGLA7NTA==} + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -702,12 +679,12 @@ packages: '@types/node': optional: true - '@inquirer/figures@1.0.14': - resolution: {integrity: sha512-DbFgdt+9/OZYFM+19dbpXOSeAstPy884FPy1KjDu4anWwymZeOYhMY1mdFri172htv6mvc/uvIAAi7b7tvjJBQ==} + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} engines: {node: '>=18'} - '@inquirer/type@3.0.9': - resolution: {integrity: sha512-QPaNt/nmE2bLGQa9b7wwyRJoLZ7pN6rcyXvzU0YCmivmJyq1BVo94G98tStRWkoD1RgDX5C+dPlhhHzNdu/W/w==} + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -730,10 +707,6 @@ packages: '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} - '@jridgewell/remapping@2.3.5': resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} @@ -741,15 +714,8 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} @@ -761,9 +727,14 @@ packages: '@lhci/utils@0.13.0': resolution: {integrity: sha512-QkICuVx9rwP8cw0KIV7nEqMldKCddGwYVHal3NnvXl1dGkGJn+0kHZeN8RYZ6aBbLnjTqTCnK0KNAiVxIpD4cw==} - '@modelcontextprotocol/sdk@1.20.2': - resolution: {integrity: sha512-6rqTdFt67AAAzln3NOKsXRmv5ZzPkgbfaebKBqUbts7vK1GZudqnrun5a8d3M/h955cam9RHZ6Jb4Y1XhnmFPg==} + '@modelcontextprotocol/sdk@1.22.0': + resolution: {integrity: sha512-VUpl106XVTCpDmTBil2ehgJZjhyLY2QZikzF8NvTXtLRF1CvO5iEE2UNZdVIUer35vFOwMKYeUGbjJtvPWan3g==} engines: {node: '>=18'} + peerDependencies: + '@cfworker/json-schema': ^4.1.1 + peerDependenciesMeta: + '@cfworker/json-schema': + optional: true '@mswjs/interceptors@0.40.0': resolution: {integrity: sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==} @@ -819,11 +790,11 @@ packages: '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} - '@radix-ui/primitive@1.1.2': - resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==} + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} - '@radix-ui/react-accordion@1.2.4': - resolution: {integrity: sha512-SGCxlSBaMvEzDROzyZjsVNzu9XY5E28B3k8jOENyrz6csOv/pG1eHyYfLJai1n9tRjwG61coXDhfpgtxKxUv5g==} + '@radix-ui/react-accordion@1.2.12': + resolution: {integrity: sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -835,8 +806,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-alert-dialog@1.1.7': - resolution: {integrity: sha512-7Gx1gcoltd0VxKoR8mc+TAVbzvChJyZryZsTam0UhoL92z0L+W8ovxvcgvd+nkz24y7Qc51JQKBAGe4+825tYw==} + '@radix-ui/react-alert-dialog@1.1.15': + resolution: {integrity: sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -848,8 +819,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-arrow@1.1.3': - resolution: {integrity: sha512-2dvVU4jva0qkNZH6HHWuSz5FN5GeU5tymvCgutF8WaXz9WnD1NgUhy73cqzkjkN4Zkn8lfTPv5JIfrC221W+Nw==} + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -861,8 +832,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-aspect-ratio@1.1.3': - resolution: {integrity: sha512-yIrYZUc2e/JtRkDpuJCmaR6kj/jzekDfQLcPFdEWzSOygCPy8poR4YcszaHP5A7mh25ncofHEpeTwfhxEuBv8Q==} + '@radix-ui/react-aspect-ratio@1.1.8': + resolution: {integrity: sha512-5nZrJTF7gH+e0nZS7/QxFz6tJV4VimhQb1avEgtsJxvvIp5JilL+c58HICsKzPxghdwaDt48hEfPM1au4zGy+w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -874,8 +845,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-avatar@1.1.4': - resolution: {integrity: sha512-+kBesLBzwqyDiYCtYFK+6Ktf+N7+Y6QOTUueLGLIbLZ/YeyFW6bsBGDsN+5HxHpM55C90u5fxsg0ErxzXTcwKA==} + '@radix-ui/react-avatar@1.1.11': + resolution: {integrity: sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -887,8 +858,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-checkbox@1.1.5': - resolution: {integrity: sha512-B0gYIVxl77KYDR25AY9EGe/G//ef85RVBIxQvK+m5pxAC7XihAc/8leMHhDvjvhDu02SBSb6BuytlWr/G7F3+g==} + '@radix-ui/react-checkbox@1.3.3': + resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -900,8 +871,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collapsible@1.1.4': - resolution: {integrity: sha512-u7LCw1EYInQtBNLGjm9nZ89S/4GcvX1UR5XbekEgnQae2Hkpq39ycJ1OhdeN1/JDfVNG91kWaWoest127TaEKQ==} + '@radix-ui/react-collapsible@1.1.12': + resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -913,8 +884,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collection@1.1.3': - resolution: {integrity: sha512-mM2pxoQw5HJ49rkzwOs7Y6J4oYH22wS8BfK2/bBxROlI4xuR0c4jEenQP63LlTlDkO6Buj2Vt+QYAYcOgqtrXA==} + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -935,8 +906,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-context-menu@2.2.7': - resolution: {integrity: sha512-EwO3tyyqwGaLPg0P64jmIKJnBywD0yjiL1eRuMPyhUXPkWWpa5JPDS+oyeIWHy2JbhF+NUlfUPVq6vE7OqgZww==} + '@radix-ui/react-context-menu@2.2.16': + resolution: {integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -957,8 +928,17 @@ packages: '@types/react': optional: true - '@radix-ui/react-dialog@1.1.7': - resolution: {integrity: sha512-EIdma8C0C/I6kL6sO02avaCRqi3fmWJpxH6mqbVScorW6nNktzKJT/le7VPho3o/7wCsyRg3z0+Q+Obr0Gy/VQ==} + '@radix-ui/react-context@1.1.3': + resolution: {integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dialog@1.1.15': + resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -979,8 +959,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-dismissable-layer@1.1.6': - resolution: {integrity: sha512-7gpgMT2gyKym9Jz2ZhlRXSg2y6cNQIK8d/cqBZ0RBCaps8pFryCWXiUKI+uHGFrhMrbGUP7U6PWgiXzIxoyF3Q==} + '@radix-ui/react-dismissable-layer@1.1.11': + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -992,8 +972,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dropdown-menu@2.1.7': - resolution: {integrity: sha512-7/1LiuNZuCQE3IzdicGoHdQOHkS2Q08+7p8w6TXZ6ZjgAULaCI85ZY15yPl4o4FVgoKLRT43/rsfNVN8osClQQ==} + '@radix-ui/react-dropdown-menu@2.1.16': + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1005,8 +985,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-focus-guards@1.1.2': - resolution: {integrity: sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==} + '@radix-ui/react-focus-guards@1.1.3': + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1014,8 +994,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-focus-scope@1.1.3': - resolution: {integrity: sha512-4XaDlq0bPt7oJwR+0k0clCiCO/7lO7NKZTAaJBYxDNQT/vj4ig0/UvctrRscZaFREpRvUTkpKR96ov1e6jptQg==} + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1027,8 +1007,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-hover-card@1.1.7': - resolution: {integrity: sha512-HwM03kP8psrv21J1+9T/hhxi0f5rARVbqIZl9+IAq13l4j4fX+oGIuxisukZZmebO7J35w9gpoILvtG8bbph0w==} + '@radix-ui/react-hover-card@1.1.15': + resolution: {integrity: sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1049,8 +1029,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-label@2.1.3': - resolution: {integrity: sha512-zwSQ1NzSKG95yA0tvBMgv6XPHoqapJCcg9nsUBaQQ66iRBhZNhlpaQG2ERYYX4O4stkYFK5rxj5NsWfO9CS+Hg==} + '@radix-ui/react-label@2.1.8': + resolution: {integrity: sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1062,8 +1042,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-menu@2.1.7': - resolution: {integrity: sha512-tBODsrk68rOi1/iQzbM54toFF+gSw/y+eQgttFflqlGekuSebNqvFNHjJgjqPhiMb4Fw9A0zNFly1QT6ZFdQ+Q==} + '@radix-ui/react-menu@2.1.16': + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1075,8 +1055,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-menubar@1.1.7': - resolution: {integrity: sha512-YB2zFhGdZ5SWEgRS+PgrF7EkwpsjEHntIFB/LRbT49LJdnIeK/xQQyuwLiRcOCgTDN+ALlPXQ08f0P0+TfR41g==} + '@radix-ui/react-menubar@1.1.16': + resolution: {integrity: sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1088,8 +1068,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-navigation-menu@1.2.6': - resolution: {integrity: sha512-HJqyzqG74Lj7KV58rk73i/B1nnopVyCfUmKgeGWWrZZiCuMNcY0KKugTrmqMbIeMliUnkBUDKCy9J6Mzl6xeWw==} + '@radix-ui/react-navigation-menu@1.2.14': + resolution: {integrity: sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1101,8 +1081,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popover@1.1.7': - resolution: {integrity: sha512-I38OYWDmJF2kbO74LX8UsFydSHWOJuQ7LxPnTefjxxvdvPLempvAnmsyX9UsBlywcbSGpRH7oMLfkUf+ij4nrw==} + '@radix-ui/react-popover@1.1.15': + resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1114,8 +1094,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popper@1.2.3': - resolution: {integrity: sha512-iNb9LYUMkne9zIahukgQmHlSBp9XWGeQQ7FvUGNk45ywzOb6kQa+Ca38OphXlWDiKvyneo9S+KSJsLfLt8812A==} + '@radix-ui/react-popper@1.2.8': + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1127,8 +1107,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-portal@1.1.5': - resolution: {integrity: sha512-ps/67ZqsFm+Mb6lSPJpfhRLrVL2i2fntgCmGMqqth4eaGUf+knAuuRtWVJrNjUhExgmdRqftSgzpf0DF0n6yXA==} + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1140,8 +1120,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-presence@1.1.3': - resolution: {integrity: sha512-IrVLIhskYhH3nLvtcBLQFZr61tBG7wx7O3kEmdzcYwRGAEBmBicGGL7ATzNgruYJ3xBTbuzEEq9OXJM3PAX3tA==} + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1153,8 +1133,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-primitive@2.0.3': - resolution: {integrity: sha512-Pf/t/GkndH7CQ8wE2hbkXA+WyZ83fhQQn5DDmwDiDo6AwN/fhaH8oqZ0jRjMrO2iaMhDi6P1HRx6AZwyMinY1g==} + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1166,8 +1146,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-progress@1.1.3': - resolution: {integrity: sha512-F56aZPGTPb4qJQ/vDjnAq63oTu/DRoIG/Asb5XKOWj8rpefNLtUllR969j5QDN2sRrTk9VXIqQDRj5VvAuquaw==} + '@radix-ui/react-primitive@2.1.4': + resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1179,8 +1159,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-radio-group@1.2.4': - resolution: {integrity: sha512-oLz7ATfKgVTUbpr5OBu6Q7hQcnV22uPT306bmG0QwgnKqBStR98RfWfJGCfW/MmhL4ISmrmmBPBW+c77SDwV9g==} + '@radix-ui/react-progress@1.1.8': + resolution: {integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1192,8 +1172,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-roving-focus@1.1.3': - resolution: {integrity: sha512-ufbpLUjZiOg4iYgb2hQrWXEPYX6jOLBbR27bDyAff5GYMRrCzcze8lukjuXVUQvJ6HZe8+oL+hhswDcjmcgVyg==} + '@radix-ui/react-radio-group@1.3.8': + resolution: {integrity: sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1205,8 +1185,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-scroll-area@1.2.4': - resolution: {integrity: sha512-G9rdWTQjOR4sk76HwSdROhPU0jZWpfozn9skU1v4N0/g9k7TmswrJn8W8WMU+aYktnLLpk5LX6fofj2bGe5NFQ==} + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1218,8 +1198,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-select@2.1.7': - resolution: {integrity: sha512-exzGIRtc7S8EIM2KjFg+7lJZsH7O7tpaBaJbBNVDnOZNhtoQ2iV+iSNfi2Wth0m6h3trJkMVvzAehB3c6xj/3Q==} + '@radix-ui/react-scroll-area@1.2.10': + resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1231,8 +1211,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-separator@1.1.3': - resolution: {integrity: sha512-2omrWKJvxR0U/tkIXezcc1nFMwtLU0+b/rDK40gnzJqTLWQ/TD/D5IYVefp9sC3QWfeQbpSbEA6op9MQKyaALQ==} + '@radix-ui/react-select@2.2.6': + resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1244,8 +1224,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-slider@1.2.4': - resolution: {integrity: sha512-Vr/OgNejNJPAghIhjS7Mf/2F/EXGDT0qgtiHf2BHz71+KqgN+jndFLKq5xAB9JOGejGzejfJLIvT04Do+yzhcg==} + '@radix-ui/react-separator@1.1.8': + resolution: {integrity: sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1257,8 +1237,30 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-slot@1.2.0': - resolution: {integrity: sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==} + '@radix-ui/react-slider@1.3.6': + resolution: {integrity: sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-slot@1.2.4': + resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1266,8 +1268,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-switch@1.1.4': - resolution: {integrity: sha512-zGP6W8plLeogoeGMiTHJ/uvf+TE1C2chVsEwfP8YlvpQKJHktG+iCkUtCLGPAuDV8/qDSmIRPm4NggaTxFMVBQ==} + '@radix-ui/react-switch@1.2.6': + resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1279,8 +1281,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-tabs@1.1.4': - resolution: {integrity: sha512-fuHMHWSf5SRhXke+DbHXj2wVMo+ghVH30vhX3XVacdXqDl+J4XWafMIGOOER861QpBx1jxgwKXL2dQnfrsd8MQ==} + '@radix-ui/react-tabs@1.1.13': + resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1292,8 +1294,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-toast@1.2.7': - resolution: {integrity: sha512-0IWTbAUKvzdpOaWDMZisXZvScXzF0phaQjWspK8RUMEUxjLbli+886mB/kXTIC3F+t5vQ0n0vYn+dsX8s+WdfA==} + '@radix-ui/react-toast@1.2.15': + resolution: {integrity: sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1305,8 +1307,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-toggle-group@1.1.3': - resolution: {integrity: sha512-khTzdGIxy8WurYUEUrapvj5aOev/tUA8TDEFi1D0Dn3yX+KR5AqjX0b7E5sL9ngRRpxDN2RRJdn5siasu5jtcg==} + '@radix-ui/react-toggle-group@1.1.11': + resolution: {integrity: sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1318,8 +1320,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-toggle@1.1.3': - resolution: {integrity: sha512-Za5HHd9nvsiZ2t3EI/dVd4Bm/JydK+D22uHKk46fPtvuPxVCJBUo5mQybN+g5sZe35y7I6GDTTfdkVv5SnxlFg==} + '@radix-ui/react-toggle@1.1.10': + resolution: {integrity: sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1331,8 +1333,8 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-tooltip@1.2.0': - resolution: {integrity: sha512-b1Sdc75s7zN9B8ONQTGBSHL3XS8+IcjcOIY51fhM4R1Hx8s0YbgqgyNZiri4qcYMVZK8hfCZVBiyCm7N9rs0rw==} + '@radix-ui/react-tooltip@1.2.8': + resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1353,8 +1355,17 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-controllable-state@1.1.1': - resolution: {integrity: sha512-YnEXIy8/ga01Y1PN0VfaNH//MhA91JlEGVBDxDzROqwrAtG5Yr2QGEPz8A/rJA3C7ZAHryOYGaUv8fLSW2H/mg==} + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} peerDependencies: '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc @@ -1371,6 +1382,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-is-hydrated@0.1.0': + resolution: {integrity: sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-layout-effect@1.1.1': resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} peerDependencies: @@ -1407,8 +1427,8 @@ packages: '@types/react': optional: true - '@radix-ui/react-visually-hidden@1.1.3': - resolution: {integrity: sha512-oXSF3ZQRd5fvomd9hmUCb2EHSZbPp3ZSHAHJJU/DlF9XoFkJBBW8RHU/E8WEH+RbSfJd/QFA0sl8ClJXknBwHQ==} + '@radix-ui/react-visually-hidden@1.2.3': + resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} peerDependencies: '@types/react': '*' '@types/react-dom': '*' @@ -1423,107 +1443,120 @@ packages: '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} - '@remix-run/router@1.23.0': - resolution: {integrity: sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==} + '@remix-run/router@1.23.1': + resolution: {integrity: sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ==} engines: {node: '>=14.0.0'} - '@rollup/rollup-android-arm-eabi@4.40.0': - resolution: {integrity: sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==} + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + + '@rollup/rollup-android-arm-eabi@4.53.2': + resolution: {integrity: sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.40.0': - resolution: {integrity: sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==} + '@rollup/rollup-android-arm64@4.53.2': + resolution: {integrity: sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.40.0': - resolution: {integrity: sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==} + '@rollup/rollup-darwin-arm64@4.53.2': + resolution: {integrity: sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.40.0': - resolution: {integrity: sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==} + '@rollup/rollup-darwin-x64@4.53.2': + resolution: {integrity: sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.40.0': - resolution: {integrity: sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==} + '@rollup/rollup-freebsd-arm64@4.53.2': + resolution: {integrity: sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.40.0': - resolution: {integrity: sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==} + '@rollup/rollup-freebsd-x64@4.53.2': + resolution: {integrity: sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.40.0': - resolution: {integrity: sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==} + '@rollup/rollup-linux-arm-gnueabihf@4.53.2': + resolution: {integrity: sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.40.0': - resolution: {integrity: sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==} + '@rollup/rollup-linux-arm-musleabihf@4.53.2': + resolution: {integrity: sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.40.0': - resolution: {integrity: sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==} + '@rollup/rollup-linux-arm64-gnu@4.53.2': + resolution: {integrity: sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.40.0': - resolution: {integrity: sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==} + '@rollup/rollup-linux-arm64-musl@4.53.2': + resolution: {integrity: sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.40.0': - resolution: {integrity: sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==} + '@rollup/rollup-linux-loong64-gnu@4.53.2': + resolution: {integrity: sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': - resolution: {integrity: sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==} + '@rollup/rollup-linux-ppc64-gnu@4.53.2': + resolution: {integrity: sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.40.0': - resolution: {integrity: sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==} + '@rollup/rollup-linux-riscv64-gnu@4.53.2': + resolution: {integrity: sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.40.0': - resolution: {integrity: sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==} + '@rollup/rollup-linux-riscv64-musl@4.53.2': + resolution: {integrity: sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.40.0': - resolution: {integrity: sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==} + '@rollup/rollup-linux-s390x-gnu@4.53.2': + resolution: {integrity: sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.40.0': - resolution: {integrity: sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==} + '@rollup/rollup-linux-x64-gnu@4.53.2': + resolution: {integrity: sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.40.0': - resolution: {integrity: sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==} + '@rollup/rollup-linux-x64-musl@4.53.2': + resolution: {integrity: sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.40.0': - resolution: {integrity: sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==} + '@rollup/rollup-openharmony-arm64@4.53.2': + resolution: {integrity: sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.53.2': + resolution: {integrity: sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.40.0': - resolution: {integrity: sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==} + '@rollup/rollup-win32-ia32-msvc@4.53.2': + resolution: {integrity: sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.40.0': - resolution: {integrity: sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==} + '@rollup/rollup-win32-x64-gnu@4.53.2': + resolution: {integrity: sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.53.2': + resolution: {integrity: sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==} cpu: [x64] os: [win32] @@ -1558,68 +1591,68 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} - '@swc/core-darwin-arm64@1.11.21': - resolution: {integrity: sha512-v6gjw9YFWvKulCw3ZA1dY+LGMafYzJksm1mD4UZFZ9b36CyHFowYVYug1ajYRIRqEvvfIhHUNV660zTLoVFR8g==} + '@swc/core-darwin-arm64@1.15.2': + resolution: {integrity: sha512-Ghyz4RJv4zyXzrUC1B2MLQBbppIB5c4jMZJybX2ebdEQAvryEKp3gq1kBksCNsatKGmEgXul88SETU19sMWcrw==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.11.21': - resolution: {integrity: sha512-CUiTiqKlzskwswrx9Ve5NhNoab30L1/ScOfQwr1duvNlFvarC8fvQSgdtpw2Zh3MfnfNPpyLZnYg7ah4kbT9JQ==} + '@swc/core-darwin-x64@1.15.2': + resolution: {integrity: sha512-7n/PGJOcL2QoptzL42L5xFFfXY5rFxLHnuz1foU+4ruUTG8x2IebGhtwVTpaDN8ShEv2UZObBlT1rrXTba15Zw==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.11.21': - resolution: {integrity: sha512-YyBTAFM/QPqt1PscD8hDmCLnqPGKmUZpqeE25HXY8OLjl2MUs8+O4KjwPZZ+OGxpdTbwuWFyMoxjcLy80JODvg==} + '@swc/core-linux-arm-gnueabihf@1.15.2': + resolution: {integrity: sha512-ZUQVCfRJ9wimuxkStRSlLwqX4TEDmv6/J+E6FicGkQ6ssLMWoKDy0cAo93HiWt/TWEee5vFhFaSQYzCuBEGO6A==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.11.21': - resolution: {integrity: sha512-DQD+ooJmwpNsh4acrftdkuwl5LNxxg8U4+C/RJNDd7m5FP9Wo4c0URi5U0a9Vk/6sQNh9aSGcYChDpqCDWEcBw==} + '@swc/core-linux-arm64-gnu@1.15.2': + resolution: {integrity: sha512-GZh3pYBmfnpQ+JIg+TqLuz+pM+Mjsk5VOzi8nwKn/m+GvQBsxD5ectRtxuWUxMGNG8h0lMy4SnHRqdK3/iJl7A==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.11.21': - resolution: {integrity: sha512-y1L49+snt1a1gLTYPY641slqy55QotPdtRK9Y6jMi4JBQyZwxC8swWYlQWb+MyILwxA614fi62SCNZNznB3XSA==} + '@swc/core-linux-arm64-musl@1.15.2': + resolution: {integrity: sha512-5av6VYZZeneiYIodwzGMlnyVakpuYZryGzFIbgu1XP8wVylZxduEzup4eP8atiMDFmIm+s4wn8GySJmYqeJC0A==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.11.21': - resolution: {integrity: sha512-NesdBXv4CvVEaFUlqKj+GA4jJMNUzK2NtKOrUNEtTbXaVyNiXjFCSaDajMTedEB0jTAd9ybB0aBvwhgkJUWkWA==} + '@swc/core-linux-x64-gnu@1.15.2': + resolution: {integrity: sha512-1nO/UfdCLuT/uE/7oB3EZgTeZDCIa6nL72cFEpdegnqpJVNDI6Qb8U4g/4lfVPkmHq2lvxQ0L+n+JdgaZLhrRA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.11.21': - resolution: {integrity: sha512-qFV60pwpKVOdmX67wqQzgtSrUGWX9Cibnp1CXyqZ9Mmt8UyYGvmGu7p6PMbTyX7vdpVUvWVRf8DzrW2//wmVHg==} + '@swc/core-linux-x64-musl@1.15.2': + resolution: {integrity: sha512-Ksfrb0Tx310kr+TLiUOvB/I80lyZ3lSOp6cM18zmNRT/92NB4mW8oX2Jo7K4eVEI2JWyaQUAFubDSha2Q+439A==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.11.21': - resolution: {integrity: sha512-DJJe9k6gXR/15ZZVLv1SKhXkFst8lYCeZRNHH99SlBodvu4slhh/MKQ6YCixINRhCwliHrpXPym8/5fOq8b7Ig==} + '@swc/core-win32-arm64-msvc@1.15.2': + resolution: {integrity: sha512-IzUb5RlMUY0r1A9IuJrQ7Tbts1wWb73/zXVXT8VhewbHGoNlBKE0qUhKMED6Tv4wDF+pmbtUJmKXDthytAvLmg==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.11.21': - resolution: {integrity: sha512-TqEXuy6wedId7bMwLIr9byds+mKsaXVHctTN88R1UIBPwJA92Pdk0uxDgip0pEFzHB/ugU27g6d8cwUH3h2eIw==} + '@swc/core-win32-ia32-msvc@1.15.2': + resolution: {integrity: sha512-kCATEzuY2LP9AlbU2uScjcVhgnCAkRdu62vbce17Ro5kxEHxYWcugkveyBRS3AqZGtwAKYbMAuNloer9LS/hpw==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.11.21': - resolution: {integrity: sha512-BT9BNNbMxdpUM1PPAkYtviaV0A8QcXttjs2MDtOeSqqvSJaPtyM+Fof2/+xSwQDmDEFzbGCcn75M5+xy3lGqpA==} + '@swc/core-win32-x64-msvc@1.15.2': + resolution: {integrity: sha512-iJaHeYCF4jTn7OEKSa3KRiuVFIVYts8jYjNmCdyz1u5g8HRyTDISD76r8+ljEOgm36oviRQvcXaw6LFp1m0yyA==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.11.21': - resolution: {integrity: sha512-/Y3BJLcwd40pExmdar8MH2UGGvCBrqNN7hauOMckrEX2Ivcbv3IMhrbGX4od1dnF880Ed8y/E9aStZCIQi0EGw==} + '@swc/core@1.15.2': + resolution: {integrity: sha512-OQm+yJdXxvSjqGeaWhP6Ia264ogifwAO7Q12uTDVYj/Ks4jBTI4JknlcjDRAXtRhqbWsfbZyK/5RtuIPyptk3w==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -1630,19 +1663,19 @@ packages: '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - '@swc/types@0.1.21': - resolution: {integrity: sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==} + '@swc/types@0.1.25': + resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==} - '@tailwindcss/typography@0.5.16': - resolution: {integrity: sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==} + '@tailwindcss/typography@0.5.19': + resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==} peerDependencies: tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' - '@tanstack/query-core@5.74.4': - resolution: {integrity: sha512-YuG0A0+3i9b2Gfo9fkmNnkUWh5+5cFhWBN0pJAHkHilTx6A0nv8kepkk4T4GRt4e5ahbtFj2eTtkiPcVU1xO4A==} + '@tanstack/query-core@5.90.9': + resolution: {integrity: sha512-UFOCQzi6pRGeVTVlPNwNdnAvT35zugcIydqjvFUzG62dvz2iVjElmNp/hJkUoM5eqbUPfSU/GJIr/wbvD8bTUw==} - '@tanstack/react-query@5.74.4': - resolution: {integrity: sha512-mAbxw60d4ffQ4qmRYfkO1xzRBPUEf/72Dgo3qqea0J66nIKuDTLEqQt0ku++SDFlMGMnB6uKDnEG1xD/TDse4Q==} + '@tanstack/react-query@5.90.9': + resolution: {integrity: sha512-Zke2AaXiaSfnG8jqPZR52m8SsclKT2d9//AgE/QIzyNvbpj/Q2ln+FsZjb1j69bJZUouBvX2tg9PHirkTm8arw==} peerDependencies: react: ^18 || ^19 @@ -1652,8 +1685,8 @@ packages: '@ts-morph/common@0.27.0': resolution: {integrity: sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==} - '@types/d3-array@3.2.1': - resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} + '@types/d3-array@3.2.2': + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} '@types/d3-color@3.1.3': resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} @@ -1679,25 +1712,25 @@ packages: '@types/d3-timer@3.0.2': resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} - '@types/estree@1.0.7': - resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@22.14.1': - resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==} + '@types/node@22.19.1': + resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==} - '@types/prop-types@15.7.14': - resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} + '@types/prop-types@15.7.15': + resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - '@types/react-dom@18.3.6': - resolution: {integrity: sha512-nf22//wEbKXusP6E9pfOCDwFdHAX4u172eaJI4YkDRQEZiorm6KfYnSC2SWLDMVWUOWPERmJnN0ujeAfTBLvrw==} + '@types/react-dom@18.3.7': + resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} peerDependencies: '@types/react': ^18.0.0 - '@types/react@18.3.20': - resolution: {integrity: sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==} + '@types/react@18.3.26': + resolution: {integrity: sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==} '@types/statuses@2.0.6': resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} @@ -1705,57 +1738,69 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.30.1': - resolution: {integrity: sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==} + '@typescript-eslint/eslint-plugin@8.46.4': + resolution: {integrity: sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + '@typescript-eslint/parser': ^8.46.4 eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.30.1': - resolution: {integrity: sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==} + '@typescript-eslint/parser@8.46.4': + resolution: {integrity: sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.46.4': + resolution: {integrity: sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.46.4': + resolution: {integrity: sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.30.1': - resolution: {integrity: sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==} + '@typescript-eslint/tsconfig-utils@8.46.4': + resolution: {integrity: sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.30.1': - resolution: {integrity: sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==} + '@typescript-eslint/type-utils@8.46.4': + resolution: {integrity: sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.30.1': - resolution: {integrity: sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==} + '@typescript-eslint/types@8.46.4': + resolution: {integrity: sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.30.1': - resolution: {integrity: sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==} + '@typescript-eslint/typescript-estree@8.46.4': + resolution: {integrity: sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.30.1': - resolution: {integrity: sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==} + '@typescript-eslint/utils@8.46.4': + resolution: {integrity: sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.30.1': - resolution: {integrity: sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==} + '@typescript-eslint/visitor-keys@8.46.4': + resolution: {integrity: sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitejs/plugin-react-swc@3.9.0': - resolution: {integrity: sha512-jYFUSXhwMCYsh/aQTgSGLIN3Foz5wMbH9ahb0Zva//UzwZYbMiZd7oT3AU9jHT9DLswYDswsRwPU9jVF3yA48Q==} + '@vitejs/plugin-react-swc@3.11.0': + resolution: {integrity: sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w==} peerDependencies: - vite: ^4 || ^5 || ^6 + vite: ^4 || ^5 || ^6 || ^7 accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} @@ -1770,8 +1815,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.14.1: - resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} hasBin: true @@ -1783,9 +1828,20 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -1806,8 +1862,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} ansi-styles@3.2.1: @@ -1818,8 +1874,8 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} ansis@4.2.0: @@ -1842,8 +1898,8 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-hidden@1.2.4: - resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} array-flatten@1.1.1: @@ -1857,8 +1913,8 @@ packages: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} - autoprefixer@10.4.21: - resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} + autoprefixer@10.4.22: + resolution: {integrity: sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: @@ -1879,8 +1935,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - bare-events@2.8.1: - resolution: {integrity: sha512-oxSAxTS1hRfnyit2CL5QpAOS5ixfBjj6ex3yTNvXyY/kE719jQ/IjuESJBK2w5v4wwQRAHGseVJXx9QBYOtFGQ==} + bare-events@2.8.2: + resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} peerDependencies: bare-abort-controller: '*' peerDependenciesMeta: @@ -1890,8 +1946,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.22: - resolution: {integrity: sha512-/tk9kky/d8T8CTXIQYASLyhAxR5VwL3zct1oAoVTaOUHwrmsGnfbRwNdEq+vOl2BN8i3PcDdP0o4Q+jjKQoFbQ==} + baseline-browser-mapping@2.8.28: + resolution: {integrity: sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==} hasBin: true basic-ftp@5.0.5: @@ -1910,23 +1966,18 @@ packages: resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} engines: {node: '>=18'} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.24.4: - resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - browserslist@4.27.0: - resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} + browserslist@4.28.0: + resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1960,11 +2011,8 @@ packages: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} - caniuse-lite@1.0.30001714: - resolution: {integrity: sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg==} - - caniuse-lite@1.0.30001752: - resolution: {integrity: sha512-vKUk7beoukxE47P5gcVNKkDRzXdVofotshHwfR9vmpeFKxmI5PBpgOMC18LUJUA/DvJ70Y7RveasIBraqsyO/g==} + caniuse-lite@1.0.30001754: + resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -2153,6 +2201,9 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csstype@3.2.1: + resolution: {integrity: sha512-98XGutrXoh75MlgLihlNxAGbUuFQc7l1cqcnEZlLNKc0UrVdPndgmaDmYTDDh929VS/eqTZV0rozmhu2qqT1/g==} + d3-array@3.2.4: resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} engines: {node: '>=12'} @@ -2225,15 +2276,6 @@ packages: supports-color: optional: true - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -2332,11 +2374,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.138: - resolution: {integrity: sha512-FWlQc52z1dXqm+9cCJ2uyFgJkESd+16j6dBEjsgDNuHjBpuIzL8/lRc0uvh1k8RNI6waGo6tcy2DvwkTBJOLDg==} - - electron-to-chromium@1.5.244: - resolution: {integrity: sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw==} + electron-to-chromium@1.5.253: + resolution: {integrity: sha512-O0tpQ/35rrgdiGQ0/OFWhy1itmd9A6TY9uQzlqj3hKSu/aYpe7UIn5d7CU2N9myH6biZiWF3VMZVuup8pw5U9w==} embla-carousel-react@8.6.0: resolution: {integrity: sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==} @@ -2394,8 +2433,8 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} - esbuild@0.25.3: - resolution: {integrity: sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==} + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} hasBin: true @@ -2425,25 +2464,25 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - eslint-plugin-react-refresh@0.4.19: - resolution: {integrity: sha512-eyy8pcr/YxSYjBoqIFSrlbn9i/xvxUFa8CjzAYo9cFjgGXqq1hyjihcpZvxRLalpaWmueWR81xn7vuKmAFijDQ==} + eslint-plugin-react-refresh@0.4.24: + resolution: {integrity: sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==} peerDependencies: eslint: '>=8.40' - eslint-scope@8.3.0: - resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.24.0: - resolution: {integrity: sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==} + eslint@9.39.1: + resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -2452,8 +2491,8 @@ packages: jiti: optional: true - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esprima@4.0.1: @@ -2532,8 +2571,8 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-equals@5.2.2: - resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==} + fast-equals@5.3.3: + resolution: {integrity: sha512-/boTcHZeIAQ2r/tL11voclBHDeP9WPxLt+tyAbVSyyXuUFyh0Tne7gJZTqGbxnvj79TjLdCXLOY7UIPhyG5MTw==} engines: {node: '>=6.0.0'} fast-fifo@1.3.2: @@ -2549,14 +2588,18 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - fdir@6.4.4: - resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -2618,8 +2661,8 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} framer-motion@12.23.24: resolution: {integrity: sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==} @@ -2750,8 +2793,8 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - graphql@16.11.0: - resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==} + graphql@16.12.0: + resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} has-flag@3.0.0: @@ -2807,8 +2850,8 @@ packages: i18next-browser-languagedetector@8.2.0: resolution: {integrity: sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==} - i18next@25.6.0: - resolution: {integrity: sha512-tTn8fLrwBYtnclpL5aPXK/tAYBLWVvoHM1zdfXoRNLcI+RvtMsoZRV98ePlaW3khHYKuNh/Q65W/+NVFUeIwVw==} + i18next@25.6.2: + resolution: {integrity: sha512-0GawNyVUw0yvJoOEBq1VHMAsqdM23XrHkMtl2gKEjviJQSLVXsrPqsoYAxBEugW5AB96I2pZkwRxyl8WZVoWdw==} peerDependencies: typescript: ^5 peerDependenciesMeta: @@ -2834,6 +2877,10 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + image-ssim@0.2.0: resolution: {integrity: sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg==} @@ -2872,8 +2919,8 @@ packages: invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - ip-address@10.0.1: - resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==} + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} engines: {node: '>= 12'} ipaddr.js@1.9.1: @@ -2996,12 +3043,12 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true jsesc@3.1.0: @@ -3018,6 +3065,9 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -3073,12 +3123,6 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash.castarray@4.4.0: - resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} - - lodash.isplainobject@4.0.6: - resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -3114,8 +3158,8 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc - magic-string@0.30.17: - resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} @@ -3237,8 +3281,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msw@2.11.6: - resolution: {integrity: sha512-MCYMykvmiYScyUm7I6y0VCxpNq1rgd5v7kG8ks5dKtvmxRUUPjribX6mUoUNBbM5/3PhUyoelEWiKXGOz84c+w==} + msw@2.12.2: + resolution: {integrity: sha512-Fsr8AR5Yu6C0thoWa1Z8qGBFQLDvLsWlAn/v3CNLiUizoRqBYArK3Ex3thXpMWRr1Li5/MKLOEZ5mLygUmWi1A==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -3305,9 +3349,6 @@ packages: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} @@ -3487,8 +3528,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} pify@2.3.0: @@ -3519,22 +3560,28 @@ packages: peerDependencies: postcss: ^8.0.0 - postcss-js@4.0.1: - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + postcss-js@4.1.0: + resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 - postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} peerDependencies: + jiti: '>=1.21.0' postcss: '>=8.0.9' - ts-node: '>=9.0.0' + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: + jiti: + optional: true postcss: optional: true - ts-node: + tsx: + optional: true + yaml: optional: true postcss-nested@6.2.0: @@ -3554,10 +3601,6 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.3: - resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -3649,16 +3692,16 @@ packages: peerDependencies: react: ^16.6.0 || ^17.0.0 || ^18.0.0 - react-hook-form@7.55.0: - resolution: {integrity: sha512-XRnjsH3GVMQz1moZTW53MxfoWN7aDpUg/GpVNc4A3eXRVNdGXfbzJ4vM4aLQ8g6XCUh1nIbx70aaNCl7kxnjog==} + react-hook-form@7.66.0: + resolution: {integrity: sha512-xXBqsWGKrY46ZqaHDo+ZUYiMUgi8suYu5kdrS20EG8KiL7VRQitEbNjm+UcrDYrNi1YLyfpmAeGjCZYXLT9YBw==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - react-i18next@16.2.3: - resolution: {integrity: sha512-O0t2zvmIz7nHWKNfIL+O/NTIbpTaOPY0vZov779hegbep3IZ+xcqkeVPKWBSXwzdkiv77q8zmq9toKIUys1x3A==} + react-i18next@16.3.3: + resolution: {integrity: sha512-IaY2W+ueVd/fe7H6Wj2S4bTuLNChnajFUlZFfCTrTHWzGcOrUHlVzW55oXRSl+J51U8Onn6EvIhQ+Bar9FUcjw==} peerDependencies: - i18next: '>= 25.5.2' + i18next: '>= 25.6.2' react: '>= 16.8.0' react-dom: '*' react-native: '*' @@ -3687,8 +3730,8 @@ packages: '@types/react': optional: true - react-remove-scroll@2.6.3: - resolution: {integrity: sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==} + react-remove-scroll@2.7.1: + resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==} engines: {node: '>=10'} peerDependencies: '@types/react': '*' @@ -3697,21 +3740,21 @@ packages: '@types/react': optional: true - react-resizable-panels@2.1.7: - resolution: {integrity: sha512-JtT6gI+nURzhMYQYsx8DKkx6bSoOGFp7A3CwMrOb8y5jFHFyqwo9m68UhmXRw57fRVJksFn1TSlm3ywEQ9vMgA==} + react-resizable-panels@2.1.9: + resolution: {integrity: sha512-z77+X08YDIrgAes4jl8xhnUu1LNIRp4+E7cv4xHmLOxxUPO/ML7PSrE813b90vj7xvQ1lcf7g2uA9GeMZonjhQ==} peerDependencies: react: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - react-router-dom@6.30.0: - resolution: {integrity: sha512-x30B78HV5tFk8ex0ITwzC9TTZMua4jGyA9IUlH1JLQYQTFyxr/ZxwOJq7evg1JX1qGVUcvhsmQSKdPncQrjTgA==} + react-router-dom@6.30.2: + resolution: {integrity: sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' - react-router@6.30.0: - resolution: {integrity: sha512-D3X8FyH9nBcTSHGdEKurK7r8OYE1kKFn3d/CF+CoxbSHkxU7o37+Uh7eAHRXr6k2tSExXYO++07PeXJtA/dEhQ==} + react-router@6.30.2: + resolution: {integrity: sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' @@ -3756,20 +3799,21 @@ packages: recharts-scale@0.4.5: resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==} - recharts@2.15.2: - resolution: {integrity: sha512-xv9lVztv3ingk7V3Jf05wfAZbM9Q2umJzu5t/cfnAK7LUslNrGT7LPBr74G+ok8kSCeFMaePmWMg0rcYOnczTw==} + recharts@2.15.4: + resolution: {integrity: sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==} engines: {node: '>=14'} peerDependencies: react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} @@ -3777,8 +3821,8 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} hasBin: true @@ -3811,8 +3855,8 @@ packages: resolution: {integrity: sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ==} engines: {node: '>=10.0.0'} - rollup@4.40.0: - resolution: {integrity: sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==} + rollup@4.53.2: + resolution: {integrity: sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -3848,8 +3892,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.1: - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true @@ -4002,8 +4046,8 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} strip-bom@3.0.0: @@ -4052,8 +4096,8 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@3.4.17: - resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} + tailwindcss@3.4.18: + resolution: {integrity: sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==} engines: {node: '>=14.0.0'} hasBin: true @@ -4082,11 +4126,12 @@ packages: tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - tinyexec@1.0.1: - resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} - tinyglobby@0.2.13: - resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} tldts-core@6.1.86: @@ -4170,15 +4215,15 @@ packages: typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - typescript-eslint@8.30.1: - resolution: {integrity: sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==} + typescript-eslint@8.46.4: + resolution: {integrity: sha512-KALyxkpYV5Ix7UhvjTwJXZv76VWsHG+NjNlt/z+a17SOQSiOcBdUXdbJdyXi7RPxrBFECtFOiPwUJQusJuCqrg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + typescript: '>=4.8.4 <6.0.0' - typescript@5.8.3: - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true @@ -4207,12 +4252,6 @@ packages: until-async@3.0.2: resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - update-browserslist-db@1.1.4: resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true @@ -4274,8 +4313,8 @@ packages: victory-vendor@36.9.2: resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==} - vite@6.3.4: - resolution: {integrity: sha512-BiReIiMS2fyFqbqNT/Qqt4CVITDU9M9vE+DKcVAsB+ZV0wvTKd+3hMbkpxz1b+NmEDMegpVbisKiAZOnvO92Sw==} + vite@6.4.1: + resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -4404,11 +4443,6 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@2.7.1: - resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} - engines: {node: '>= 14'} - hasBin: true - yargs-parser@13.1.2: resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==} @@ -4448,8 +4482,8 @@ packages: peerDependencies: zod: ^3.24.1 - zod@3.24.3: - resolution: {integrity: sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==} + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} snapshots: @@ -4460,7 +4494,7 @@ snapshots: ansis: 4.2.0 fzf: 0.5.2 package-manager-detector: 1.5.0 - tinyexec: 1.0.1 + tinyexec: 1.0.2 '@babel/code-frame@7.27.1': dependencies: @@ -4483,7 +4517,7 @@ snapshots: '@babel/types': 7.28.5 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.0 + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -4506,7 +4540,7 @@ snapshots: dependencies: '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.27.0 + browserslist: 4.28.0 lru-cache: 5.1.1 semver: 6.3.1 @@ -4572,8 +4606,6 @@ snapshots: '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.27.1': {} - '@babel/helper-validator-identifier@7.28.5': {} '@babel/helper-validator-option@7.27.1': {} @@ -4583,10 +4615,6 @@ snapshots: '@babel/template': 7.27.2 '@babel/types': 7.28.5 - '@babel/parser@7.27.5': - dependencies: - '@babel/types': 7.27.6 - '@babel/parser@7.28.5': dependencies: '@babel/types': 7.28.5 @@ -4631,10 +4659,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/runtime@7.27.0': - dependencies: - regenerator-runtime: 0.14.1 - '@babel/runtime@7.28.4': {} '@babel/template@7.27.2': @@ -4651,31 +4675,25 @@ snapshots: '@babel/parser': 7.28.5 '@babel/template': 7.27.2 '@babel/types': 7.28.5 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.27.6': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@clerk/clerk-react@5.53.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@clerk/clerk-react@5.55.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@clerk/shared': 3.29.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@clerk/types': 4.96.0 + '@clerk/shared': 3.34.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.8.1 - '@clerk/shared@3.29.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@clerk/shared@3.34.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@clerk/types': 4.96.0 + csstype: 3.1.3 dequal: 2.0.3 glob-to-regexp: 0.4.1 js-cookie: 3.0.5 @@ -4685,172 +4703,169 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@clerk/types@4.96.0': - dependencies: - csstype: 3.1.3 - - '@dotenvx/dotenvx@1.51.0': + '@dotenvx/dotenvx@1.51.1': dependencies: commander: 11.1.0 dotenv: 17.2.3 eciesjs: 0.4.16 execa: 5.1.1 - fdir: 6.4.4(picomatch@4.0.2) + fdir: 6.5.0(picomatch@4.0.3) ignore: 5.3.2 object-treeify: 1.1.33 - picomatch: 4.0.2 + picomatch: 4.0.3 which: 4.0.0 - '@dyad-sh/react-vite-component-tagger@0.8.0(vite@6.3.4(@types/node@22.14.1)(jiti@1.21.7)(yaml@2.7.1))': + '@dyad-sh/react-vite-component-tagger@0.8.0(vite@6.4.1(@types/node@22.19.1)(jiti@1.21.7))': dependencies: - '@babel/parser': 7.27.5 + '@babel/parser': 7.28.5 estree-walker: 2.0.2 - magic-string: 0.30.17 - vite: 6.3.4(@types/node@22.14.1)(jiti@1.21.7)(yaml@2.7.1) + magic-string: 0.30.21 + vite: 6.4.1(@types/node@22.19.1)(jiti@1.21.7) - '@ecies/ciphers@0.2.4(@noble/ciphers@1.3.0)': + '@ecies/ciphers@0.2.5(@noble/ciphers@1.3.0)': dependencies: '@noble/ciphers': 1.3.0 - '@esbuild/aix-ppc64@0.25.3': + '@esbuild/aix-ppc64@0.25.12': optional: true - '@esbuild/android-arm64@0.25.3': + '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm@0.25.3': + '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-x64@0.25.3': + '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.25.3': + '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-x64@0.25.3': + '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.25.3': + '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.25.3': + '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/linux-arm64@0.25.3': + '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm@0.25.3': + '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-ia32@0.25.3': + '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-loong64@0.25.3': + '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-mips64el@0.25.3': + '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-ppc64@0.25.3': + '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.25.3': + '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-s390x@0.25.3': + '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-x64@0.25.3': + '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.25.3': + '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.25.3': + '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.25.3': + '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.25.3': + '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/sunos-x64@0.25.3': + '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/win32-arm64@0.25.3': + '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/win32-ia32@0.25.3': + '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-x64@0.25.3': + '@esbuild/win32-ia32@0.25.12': optional: true - '@eslint-community/eslint-utils@4.6.1(eslint@9.24.0(jiti@1.21.7))': + '@esbuild/win32-x64@0.25.12': + optional: true + + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@1.21.7))': dependencies: - eslint: 9.24.0(jiti@1.21.7) + eslint: 9.39.1(jiti@1.21.7) eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.1': {} + '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.20.0': + '@eslint/config-array@0.21.1': dependencies: - '@eslint/object-schema': 2.1.6 - debug: 4.4.0 + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.2.1': {} - - '@eslint/core@0.12.0': + '@eslint/config-helpers@0.4.2': dependencies: - '@types/json-schema': 7.0.15 + '@eslint/core': 0.17.0 - '@eslint/core@0.13.0': + '@eslint/core@0.17.0': dependencies: '@types/json-schema': 7.0.15 '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.0 - espree: 10.3.0 + debug: 4.4.3 + espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.1.0 + js-yaml: 4.1.1 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@9.24.0': {} + '@eslint/js@9.39.1': {} - '@eslint/object-schema@2.1.6': {} + '@eslint/object-schema@2.1.7': {} - '@eslint/plugin-kit@0.2.8': + '@eslint/plugin-kit@0.4.1': dependencies: - '@eslint/core': 0.13.0 + '@eslint/core': 0.17.0 levn: 0.4.1 - '@floating-ui/core@1.6.9': + '@floating-ui/core@1.7.3': dependencies: - '@floating-ui/utils': 0.2.9 + '@floating-ui/utils': 0.2.10 - '@floating-ui/dom@1.6.13': + '@floating-ui/dom@1.7.4': dependencies: - '@floating-ui/core': 1.6.9 - '@floating-ui/utils': 0.2.9 + '@floating-ui/core': 1.7.3 + '@floating-ui/utils': 0.2.10 - '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@floating-ui/react-dom@2.1.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/dom': 1.6.13 + '@floating-ui/dom': 1.7.4 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@floating-ui/utils@0.2.9': {} + '@floating-ui/utils@0.2.10': {} '@formatjs/ecma402-abstract@2.3.6': dependencies: @@ -4878,50 +4893,48 @@ snapshots: dependencies: tslib: 2.8.1 - '@hookform/resolvers@3.10.0(react-hook-form@7.55.0(react@18.3.1))': + '@hookform/resolvers@3.10.0(react-hook-form@7.66.0(react@18.3.1))': dependencies: - react-hook-form: 7.55.0(react@18.3.1) + react-hook-form: 7.66.0(react@18.3.1) '@humanfs/core@0.19.1': {} - '@humanfs/node@0.16.6': + '@humanfs/node@0.16.7': dependencies: '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 + '@humanwhocodes/retry': 0.4.3 '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/retry@0.3.1': {} + '@humanwhocodes/retry@0.4.3': {} - '@humanwhocodes/retry@0.4.2': {} + '@inquirer/ansi@1.0.2': {} - '@inquirer/ansi@1.0.1': {} - - '@inquirer/confirm@5.1.19(@types/node@22.14.1)': + '@inquirer/confirm@5.1.21(@types/node@22.19.1)': dependencies: - '@inquirer/core': 10.3.0(@types/node@22.14.1) - '@inquirer/type': 3.0.9(@types/node@22.14.1) + '@inquirer/core': 10.3.2(@types/node@22.19.1) + '@inquirer/type': 3.0.10(@types/node@22.19.1) optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.19.1 - '@inquirer/core@10.3.0(@types/node@22.14.1)': + '@inquirer/core@10.3.2(@types/node@22.19.1)': dependencies: - '@inquirer/ansi': 1.0.1 - '@inquirer/figures': 1.0.14 - '@inquirer/type': 3.0.9(@types/node@22.14.1) + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@22.19.1) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.19.1 - '@inquirer/figures@1.0.14': {} + '@inquirer/figures@1.0.15': {} - '@inquirer/type@3.0.9(@types/node@22.14.1)': + '@inquirer/type@3.0.10(@types/node@22.19.1)': optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.19.1 '@isaacs/balanced-match@4.0.1': {} @@ -4933,22 +4946,16 @@ snapshots: dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/gen-mapping@0.3.8': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/remapping@2.3.5': dependencies: '@jridgewell/gen-mapping': 0.3.13 @@ -4956,26 +4963,19 @@ snapshots: '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec@1.5.5': {} '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@lhci/cli@0.13.0': dependencies: '@lhci/utils': 0.13.0 chrome-launcher: 0.13.4 compression: 1.8.1 - debug: 4.4.0 + debug: 4.4.3 express: 4.21.2 https-proxy-agent: 5.0.1 inquirer: 6.5.2 @@ -4997,9 +4997,9 @@ snapshots: '@lhci/utils@0.13.0': dependencies: - debug: 4.4.0 + debug: 4.4.3 isomorphic-fetch: 3.0.0 - js-yaml: 3.14.1 + js-yaml: 3.14.2 lighthouse: 11.4.0 tree-kill: 1.2.2 transitivePeerDependencies: @@ -5010,9 +5010,10 @@ snapshots: - supports-color - utf-8-validate - '@modelcontextprotocol/sdk@1.20.2': + '@modelcontextprotocol/sdk@1.22.0': dependencies: - ajv: 6.12.6 + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) content-type: 1.0.5 cors: 2.8.5 cross-spawn: 7.0.6 @@ -5022,8 +5023,8 @@ snapshots: express-rate-limit: 7.5.1(express@5.1.0) pkce-challenge: 5.0.0 raw-body: 3.0.1 - zod: 3.24.3 - zod-to-json-schema: 3.24.6(zod@3.24.3) + zod: 3.25.76 + zod-to-json-schema: 3.24.6(zod@3.25.76) transitivePeerDependencies: - supports-color @@ -5088,721 +5089,767 @@ snapshots: '@radix-ui/number@1.1.1': {} - '@radix-ui/primitive@1.1.2': {} + '@radix-ui/primitive@1.1.3': {} - '@radix-ui/react-accordion@1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-accordion@1.2.12(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collapsible': 1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-collection': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-alert-dialog@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dialog': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.0(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-arrow@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-aspect-ratio@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-aspect-ratio@1.1.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-avatar@1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-avatar@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-context': 1.1.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-checkbox@1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-checkbox@1.3.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-collapsible@1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-collapsible@1.1.12(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-collection@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-collection@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.0(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.26)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-context-menu@2.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-context-menu@2.2.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-menu': 2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-context@1.1.2(@types/react@18.3.26)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.26 - '@radix-ui/react-context@1.1.2(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-context@1.1.3(@types/react@18.3.26)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 - - '@radix-ui/react-dialog@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-portal': 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.0(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - aria-hidden: 1.2.4 + '@types/react': 18.3.26 + + '@radix-ui/react-dialog@1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.6.3(@types/react@18.3.20)(react@18.3.1) + react-remove-scroll: 2.7.1(@types/react@18.3.26)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-direction@1.1.1(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-direction@1.1.1(@types/react@18.3.26)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-dismissable-layer@1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-dropdown-menu@2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-menu': 2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-focus-guards@1.1.2(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-focus-guards@1.1.3(@types/react@18.3.26)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-focus-scope@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-hover-card@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-popper': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-hover-card@1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-id@1.1.1(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-id@1.1.1(@types/react@18.3.26)(react@18.3.1)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-label@2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-label@2.1.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-menu@2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-popper': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.0(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - aria-hidden: 1.2.4 + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-menu@2.1.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.6.3(@types/react@18.3.20)(react@18.3.1) + react-remove-scroll: 2.7.1(@types/react@18.3.26)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-menubar@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-menu': 2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-menubar@1.1.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-navigation-menu@1.2.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-popover@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-popper': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.0(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - aria-hidden: 1.2.4 + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-popover@1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.6.3(@types/react@18.3.20)(react@18.3.1) + react-remove-scroll: 2.7.1(@types/react@18.3.26)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-popper@1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-arrow': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-popper@1.2.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.26)(react@18.3.1) '@radix-ui/rect': 1.1.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-portal@1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-portal@1.1.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-presence@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-presence@1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-primitive@2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-primitive@2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-slot': 1.2.0(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-progress@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-primitive@2.1.4(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.4(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-radio-group@1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-progress@1.1.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-context': 1.1.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-radio-group@1.3.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-roving-focus@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-scroll-area@1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-select@2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-select@2.2.6(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-popper': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.0(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - aria-hidden: 1.2.4 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + aria-hidden: 1.2.6 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.6.3(@types/react@18.3.20)(react@18.3.1) + react-remove-scroll: 2.7.1(@types/react@18.3.26)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-separator@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-separator@1.1.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-slider@1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-slider@1.3.6(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-slot@1.2.3(@types/react@18.3.26)(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.26 - '@radix-ui/react-slot@1.2.0(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-slot@1.2.4(@types/react@18.3.26)(react@18.3.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-switch@1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-switch@1.2.6(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-tabs@1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-tabs@1.1.13(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-toast@1.2.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-toast@1.2.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-toggle-group@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-toggle': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-toggle-group@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-toggle': 1.1.10(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) - '@radix-ui/react-toggle@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-toggle@1.1.10(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-tooltip@1.2.0(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-popper': 1.2.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.0(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-tooltip@1.2.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) + + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.26)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.26 + + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.26)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.26 - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.26)(react@18.3.1)': dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-use-controllable-state@1.1.1(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.26)(react@18.3.1)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@18.3.26)(react@18.3.1)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) react: 18.3.1 + use-sync-external-store: 1.6.0(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.26)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-use-previous@1.1.1(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-use-previous@1.1.1(@types/react@18.3.26)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-use-rect@1.1.1(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-use-rect@1.1.1(@types/react@18.3.26)(react@18.3.1)': dependencies: '@radix-ui/rect': 1.1.1 react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-use-size@1.1.1(@types/react@18.3.20)(react@18.3.1)': + '@radix-ui/react-use-size@1.1.1(@types/react@18.3.26)(react@18.3.1)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.26)(react@18.3.1) react: 18.3.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@radix-ui/react-visually-hidden@1.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@types/react': 18.3.26 + '@types/react-dom': 18.3.7(@types/react@18.3.26) '@radix-ui/rect@1.1.1': {} - '@remix-run/router@1.23.0': {} + '@remix-run/router@1.23.1': {} + + '@rolldown/pluginutils@1.0.0-beta.27': {} + + '@rollup/rollup-android-arm-eabi@4.53.2': + optional: true + + '@rollup/rollup-android-arm64@4.53.2': + optional: true - '@rollup/rollup-android-arm-eabi@4.40.0': + '@rollup/rollup-darwin-arm64@4.53.2': optional: true - '@rollup/rollup-android-arm64@4.40.0': + '@rollup/rollup-darwin-x64@4.53.2': optional: true - '@rollup/rollup-darwin-arm64@4.40.0': + '@rollup/rollup-freebsd-arm64@4.53.2': optional: true - '@rollup/rollup-darwin-x64@4.40.0': + '@rollup/rollup-freebsd-x64@4.53.2': optional: true - '@rollup/rollup-freebsd-arm64@4.40.0': + '@rollup/rollup-linux-arm-gnueabihf@4.53.2': optional: true - '@rollup/rollup-freebsd-x64@4.40.0': + '@rollup/rollup-linux-arm-musleabihf@4.53.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.40.0': + '@rollup/rollup-linux-arm64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.40.0': + '@rollup/rollup-linux-arm64-musl@4.53.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.40.0': + '@rollup/rollup-linux-loong64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.40.0': + '@rollup/rollup-linux-ppc64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.40.0': + '@rollup/rollup-linux-riscv64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': + '@rollup/rollup-linux-riscv64-musl@4.53.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.40.0': + '@rollup/rollup-linux-s390x-gnu@4.53.2': optional: true - '@rollup/rollup-linux-riscv64-musl@4.40.0': + '@rollup/rollup-linux-x64-gnu@4.53.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.40.0': + '@rollup/rollup-linux-x64-musl@4.53.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.40.0': + '@rollup/rollup-openharmony-arm64@4.53.2': optional: true - '@rollup/rollup-linux-x64-musl@4.40.0': + '@rollup/rollup-win32-arm64-msvc@4.53.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.40.0': + '@rollup/rollup-win32-ia32-msvc@4.53.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.40.0': + '@rollup/rollup-win32-x64-gnu@4.53.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.40.0': + '@rollup/rollup-win32-x64-msvc@4.53.2': optional: true '@sec-ant/readable-stream@0.4.1': {} @@ -5849,71 +5896,68 @@ snapshots: '@sindresorhus/merge-streams@4.0.0': {} - '@swc/core-darwin-arm64@1.11.21': + '@swc/core-darwin-arm64@1.15.2': optional: true - '@swc/core-darwin-x64@1.11.21': + '@swc/core-darwin-x64@1.15.2': optional: true - '@swc/core-linux-arm-gnueabihf@1.11.21': + '@swc/core-linux-arm-gnueabihf@1.15.2': optional: true - '@swc/core-linux-arm64-gnu@1.11.21': + '@swc/core-linux-arm64-gnu@1.15.2': optional: true - '@swc/core-linux-arm64-musl@1.11.21': + '@swc/core-linux-arm64-musl@1.15.2': optional: true - '@swc/core-linux-x64-gnu@1.11.21': + '@swc/core-linux-x64-gnu@1.15.2': optional: true - '@swc/core-linux-x64-musl@1.11.21': + '@swc/core-linux-x64-musl@1.15.2': optional: true - '@swc/core-win32-arm64-msvc@1.11.21': + '@swc/core-win32-arm64-msvc@1.15.2': optional: true - '@swc/core-win32-ia32-msvc@1.11.21': + '@swc/core-win32-ia32-msvc@1.15.2': optional: true - '@swc/core-win32-x64-msvc@1.11.21': + '@swc/core-win32-x64-msvc@1.15.2': optional: true - '@swc/core@1.11.21': + '@swc/core@1.15.2': dependencies: '@swc/counter': 0.1.3 - '@swc/types': 0.1.21 + '@swc/types': 0.1.25 optionalDependencies: - '@swc/core-darwin-arm64': 1.11.21 - '@swc/core-darwin-x64': 1.11.21 - '@swc/core-linux-arm-gnueabihf': 1.11.21 - '@swc/core-linux-arm64-gnu': 1.11.21 - '@swc/core-linux-arm64-musl': 1.11.21 - '@swc/core-linux-x64-gnu': 1.11.21 - '@swc/core-linux-x64-musl': 1.11.21 - '@swc/core-win32-arm64-msvc': 1.11.21 - '@swc/core-win32-ia32-msvc': 1.11.21 - '@swc/core-win32-x64-msvc': 1.11.21 + '@swc/core-darwin-arm64': 1.15.2 + '@swc/core-darwin-x64': 1.15.2 + '@swc/core-linux-arm-gnueabihf': 1.15.2 + '@swc/core-linux-arm64-gnu': 1.15.2 + '@swc/core-linux-arm64-musl': 1.15.2 + '@swc/core-linux-x64-gnu': 1.15.2 + '@swc/core-linux-x64-musl': 1.15.2 + '@swc/core-win32-arm64-msvc': 1.15.2 + '@swc/core-win32-ia32-msvc': 1.15.2 + '@swc/core-win32-x64-msvc': 1.15.2 '@swc/counter@0.1.3': {} - '@swc/types@0.1.21': + '@swc/types@0.1.25': dependencies: '@swc/counter': 0.1.3 - '@tailwindcss/typography@0.5.16(tailwindcss@3.4.17)': + '@tailwindcss/typography@0.5.19(tailwindcss@3.4.18)': dependencies: - lodash.castarray: 4.4.0 - lodash.isplainobject: 4.0.6 - lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 - tailwindcss: 3.4.17 + tailwindcss: 3.4.18 - '@tanstack/query-core@5.74.4': {} + '@tanstack/query-core@5.90.9': {} - '@tanstack/react-query@5.74.4(react@18.3.1)': + '@tanstack/react-query@5.90.9(react@18.3.1)': dependencies: - '@tanstack/query-core': 5.74.4 + '@tanstack/query-core': 5.90.9 react: 18.3.1 '@tootallnate/quickjs-emscripten@0.23.0': {} @@ -5924,7 +5968,7 @@ snapshots: minimatch: 10.1.1 path-browserify: 1.0.1 - '@types/d3-array@3.2.1': {} + '@types/d3-array@3.2.2': {} '@types/d3-color@3.1.3': {} @@ -5948,113 +5992,130 @@ snapshots: '@types/d3-timer@3.0.2': {} - '@types/estree@1.0.7': {} + '@types/estree@1.0.8': {} '@types/json-schema@7.0.15': {} - '@types/node@22.14.1': + '@types/node@22.19.1': dependencies: undici-types: 6.21.0 - '@types/prop-types@15.7.14': {} + '@types/prop-types@15.7.15': {} - '@types/react-dom@18.3.6(@types/react@18.3.20)': + '@types/react-dom@18.3.7(@types/react@18.3.26)': dependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - '@types/react@18.3.20': + '@types/react@18.3.26': dependencies: - '@types/prop-types': 15.7.14 - csstype: 3.1.3 + '@types/prop-types': 15.7.15 + csstype: 3.2.1 '@types/statuses@2.0.6': {} '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.14.1 + '@types/node': 22.19.1 optional: true - '@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.46.4(@typescript-eslint/parser@8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.30.1 - '@typescript-eslint/type-utils': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/utils': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.30.1 - eslint: 9.24.0(jiti@1.21.7) + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.4 + '@typescript-eslint/type-utils': 8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.4 + eslint: 9.39.1(jiti@1.21.7) graphemer: 1.4.0 - ignore: 5.3.2 + ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.8.3) - typescript: 5.8.3 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.46.4 + '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.4 + debug: 4.4.3 + eslint: 9.39.1(jiti@1.21.7) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/project-service@8.46.4(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.30.1 - '@typescript-eslint/types': 8.30.1 - '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.30.1 - debug: 4.4.0 - eslint: 9.24.0(jiti@1.21.7) - typescript: 5.8.3 + '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3) + '@typescript-eslint/types': 8.46.4 + debug: 4.4.3 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.30.1': + '@typescript-eslint/scope-manager@8.46.4': dependencies: - '@typescript-eslint/types': 8.30.1 - '@typescript-eslint/visitor-keys': 8.30.1 + '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/visitor-keys': 8.46.4 - '@typescript-eslint/type-utils@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/tsconfig-utils@8.46.4(typescript@5.9.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) - '@typescript-eslint/utils': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) - debug: 4.4.0 - eslint: 9.24.0(jiti@1.21.7) - ts-api-utils: 2.1.0(typescript@5.8.3) - typescript: 5.8.3 + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.1(jiti@1.21.7) + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.30.1': {} + '@typescript-eslint/types@8.46.4': {} - '@typescript-eslint/typescript-estree@8.30.1(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.46.4(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.30.1 - '@typescript-eslint/visitor-keys': 8.30.1 - debug: 4.4.0 + '@typescript-eslint/project-service': 8.46.4(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3) + '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/visitor-keys': 8.46.4 + debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.7.1 - ts-api-utils: 2.1.0(typescript@5.8.3) - typescript: 5.8.3 + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3)': + '@typescript-eslint/utils@8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.6.1(eslint@9.24.0(jiti@1.21.7)) - '@typescript-eslint/scope-manager': 8.30.1 - '@typescript-eslint/types': 8.30.1 - '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) - eslint: 9.24.0(jiti@1.21.7) - typescript: 5.8.3 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7)) + '@typescript-eslint/scope-manager': 8.46.4 + '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) + eslint: 9.39.1(jiti@1.21.7) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.30.1': + '@typescript-eslint/visitor-keys@8.46.4': dependencies: - '@typescript-eslint/types': 8.30.1 - eslint-visitor-keys: 4.2.0 + '@typescript-eslint/types': 8.46.4 + eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react-swc@3.9.0(vite@6.3.4(@types/node@22.14.1)(jiti@1.21.7)(yaml@2.7.1))': + '@vitejs/plugin-react-swc@3.11.0(vite@6.4.1(@types/node@22.19.1)(jiti@1.21.7))': dependencies: - '@swc/core': 1.11.21 - vite: 6.3.4(@types/node@22.14.1)(jiti@1.21.7)(yaml@2.7.1) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@swc/core': 1.15.2 + vite: 6.4.1(@types/node@22.19.1)(jiti@1.21.7) transitivePeerDependencies: - '@swc/helpers' @@ -6068,20 +6129,24 @@ snapshots: mime-types: 3.0.1 negotiator: 1.0.0 - acorn-jsx@5.3.2(acorn@8.14.1): + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: - acorn: 8.14.1 + acorn: 8.15.0 - acorn@8.14.1: {} + acorn@8.15.0: {} agent-base@6.0.2: dependencies: - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color agent-base@7.1.4: {} + ajv-formats@3.0.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -6089,6 +6154,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-colors@4.1.3: {} ansi-escapes@3.2.0: {} @@ -6099,7 +6171,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.1.0: {} + ansi-regex@6.2.2: {} ansi-styles@3.2.1: dependencies: @@ -6109,7 +6181,7 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.1: {} + ansi-styles@6.2.3: {} ansis@4.2.0: {} @@ -6128,7 +6200,7 @@ snapshots: argparse@2.0.1: {} - aria-hidden@1.2.4: + aria-hidden@1.2.6: dependencies: tslib: 2.8.1 @@ -6142,14 +6214,14 @@ snapshots: dependencies: tslib: 2.8.1 - autoprefixer@10.4.21(postcss@8.5.3): + autoprefixer@10.4.22(postcss@8.5.6): dependencies: - browserslist: 4.24.4 - caniuse-lite: 1.0.30001714 - fraction.js: 4.3.7 + browserslist: 4.28.0 + caniuse-lite: 1.0.30001754 + fraction.js: 5.3.4 normalize-range: 0.1.2 picocolors: 1.1.1 - postcss: 8.5.3 + postcss: 8.5.6 postcss-value-parser: 4.2.0 axe-core@4.11.0: {} @@ -6158,11 +6230,11 @@ snapshots: balanced-match@1.0.2: {} - bare-events@2.8.1: {} + bare-events@2.8.2: {} base64-js@1.5.1: {} - baseline-browser-mapping@2.8.22: {} + baseline-browser-mapping@2.8.28: {} basic-ftp@5.0.5: {} @@ -6189,7 +6261,7 @@ snapshots: dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 4.4.0 + debug: 4.4.3 http-errors: 2.0.0 iconv-lite: 0.6.3 on-finished: 2.4.1 @@ -6199,12 +6271,12 @@ snapshots: transitivePeerDependencies: - supports-color - brace-expansion@1.1.11: + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.1: + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -6212,20 +6284,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.24.4: + browserslist@4.28.0: dependencies: - caniuse-lite: 1.0.30001714 - electron-to-chromium: 1.5.138 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.24.4) - - browserslist@4.27.0: - dependencies: - baseline-browser-mapping: 2.8.22 - caniuse-lite: 1.0.30001752 - electron-to-chromium: 1.5.244 + baseline-browser-mapping: 2.8.28 + caniuse-lite: 1.0.30001754 + electron-to-chromium: 1.5.253 node-releases: 2.0.27 - update-browserslist-db: 1.1.4(browserslist@4.27.0) + update-browserslist-db: 1.1.4(browserslist@4.28.0) buffer-crc32@0.2.13: {} @@ -6252,9 +6317,7 @@ snapshots: camelcase@5.3.1: {} - caniuse-lite@1.0.30001714: {} - - caniuse-lite@1.0.30001752: {} + caniuse-lite@1.0.30001754: {} chalk@2.4.2: dependencies: @@ -6285,7 +6348,7 @@ snapshots: chrome-launcher@0.13.4: dependencies: - '@types/node': 22.14.1 + '@types/node': 22.19.1 escape-string-regexp: 1.0.5 is-wsl: 2.2.0 lighthouse-logger: 1.2.0 @@ -6296,7 +6359,7 @@ snapshots: chrome-launcher@1.2.1: dependencies: - '@types/node': 22.14.1 + '@types/node': 22.19.1 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.2 @@ -6341,12 +6404,12 @@ snapshots: clsx@2.1.1: {} - cmdk@1.1.1(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + cmdk@1.1.1(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dialog': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.26)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -6429,14 +6492,14 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cosmiconfig@9.0.0(typescript@5.8.3): + cosmiconfig@9.0.0(typescript@5.9.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 - js-yaml: 4.1.0 + js-yaml: 4.1.1 parse-json: 5.2.0 optionalDependencies: - typescript: 5.8.3 + typescript: 5.9.3 cross-fetch@4.0.0: dependencies: @@ -6458,6 +6521,8 @@ snapshots: csstype@3.1.3: {} + csstype@3.2.1: {} + d3-array@3.2.4: dependencies: internmap: 2.0.3 @@ -6510,10 +6575,6 @@ snapshots: dependencies: ms: 2.1.2 - debug@4.4.0: - dependencies: - ms: 2.1.3 - debug@4.4.3: dependencies: ms: 2.1.3 @@ -6558,8 +6619,8 @@ snapshots: dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.27.0 - csstype: 3.1.3 + '@babel/runtime': 7.28.4 + csstype: 3.2.1 dot-prop@5.3.0: dependencies: @@ -6577,16 +6638,14 @@ snapshots: eciesjs@0.4.16: dependencies: - '@ecies/ciphers': 0.2.4(@noble/ciphers@1.3.0) + '@ecies/ciphers': 0.2.5(@noble/ciphers@1.3.0) '@noble/ciphers': 1.3.0 '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 ee-first@1.1.1: {} - electron-to-chromium@1.5.138: {} - - electron-to-chromium@1.5.244: {} + electron-to-chromium@1.5.253: {} embla-carousel-react@8.6.0(react@18.3.1): dependencies: @@ -6633,33 +6692,34 @@ snapshots: dependencies: es-errors: 1.3.0 - esbuild@0.25.3: + esbuild@0.25.12: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.3 - '@esbuild/android-arm': 0.25.3 - '@esbuild/android-arm64': 0.25.3 - '@esbuild/android-x64': 0.25.3 - '@esbuild/darwin-arm64': 0.25.3 - '@esbuild/darwin-x64': 0.25.3 - '@esbuild/freebsd-arm64': 0.25.3 - '@esbuild/freebsd-x64': 0.25.3 - '@esbuild/linux-arm': 0.25.3 - '@esbuild/linux-arm64': 0.25.3 - '@esbuild/linux-ia32': 0.25.3 - '@esbuild/linux-loong64': 0.25.3 - '@esbuild/linux-mips64el': 0.25.3 - '@esbuild/linux-ppc64': 0.25.3 - '@esbuild/linux-riscv64': 0.25.3 - '@esbuild/linux-s390x': 0.25.3 - '@esbuild/linux-x64': 0.25.3 - '@esbuild/netbsd-arm64': 0.25.3 - '@esbuild/netbsd-x64': 0.25.3 - '@esbuild/openbsd-arm64': 0.25.3 - '@esbuild/openbsd-x64': 0.25.3 - '@esbuild/sunos-x64': 0.25.3 - '@esbuild/win32-arm64': 0.25.3 - '@esbuild/win32-ia32': 0.25.3 - '@esbuild/win32-x64': 0.25.3 + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 escalade@3.2.0: {} @@ -6677,46 +6737,45 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-plugin-react-hooks@5.2.0(eslint@9.24.0(jiti@1.21.7)): + eslint-plugin-react-hooks@5.2.0(eslint@9.39.1(jiti@1.21.7)): dependencies: - eslint: 9.24.0(jiti@1.21.7) + eslint: 9.39.1(jiti@1.21.7) - eslint-plugin-react-refresh@0.4.19(eslint@9.24.0(jiti@1.21.7)): + eslint-plugin-react-refresh@0.4.24(eslint@9.39.1(jiti@1.21.7)): dependencies: - eslint: 9.24.0(jiti@1.21.7) + eslint: 9.39.1(jiti@1.21.7) - eslint-scope@8.3.0: + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.2.0: {} + eslint-visitor-keys@4.2.1: {} - eslint@9.24.0(jiti@1.21.7): + eslint@9.39.1(jiti@1.21.7): dependencies: - '@eslint-community/eslint-utils': 4.6.1(eslint@9.24.0(jiti@1.21.7)) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.20.0 - '@eslint/config-helpers': 0.2.1 - '@eslint/core': 0.12.0 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@1.21.7)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.24.0 - '@eslint/plugin-kit': 0.2.8 - '@humanfs/node': 0.16.6 + '@eslint/js': 9.39.1 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.2 - '@types/estree': 1.0.7 - '@types/json-schema': 7.0.15 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.0 + debug: 4.4.3 escape-string-regexp: 4.0.0 - eslint-scope: 8.3.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -6736,11 +6795,11 @@ snapshots: transitivePeerDependencies: - supports-color - espree@10.3.0: + espree@10.4.0: dependencies: - acorn: 8.14.1 - acorn-jsx: 5.3.2(acorn@8.14.1) - eslint-visitor-keys: 4.2.0 + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 esprima@4.0.1: {} @@ -6764,7 +6823,7 @@ snapshots: events-universal@1.0.1: dependencies: - bare-events: 2.8.1 + bare-events: 2.8.2 transitivePeerDependencies: - bare-abort-controller @@ -6849,7 +6908,7 @@ snapshots: content-type: 1.0.5 cookie: 0.7.2 cookie-signature: 1.2.2 - debug: 4.4.0 + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -6881,7 +6940,7 @@ snapshots: extract-zip@2.0.1: dependencies: - debug: 4.4.0 + debug: 4.4.3 get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -6891,7 +6950,7 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-equals@5.2.2: {} + fast-equals@5.3.3: {} fast-fifo@1.3.2: {} @@ -6907,6 +6966,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-uri@3.1.0: {} + fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -6915,9 +6976,9 @@ snapshots: dependencies: pend: 1.2.0 - fdir@6.4.4(picomatch@4.0.2): + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: - picomatch: 4.0.2 + picomatch: 4.0.3 fetch-blob@3.2.0: dependencies: @@ -6954,7 +7015,7 @@ snapshots: finalhandler@2.1.0: dependencies: - debug: 4.4.0 + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -6991,7 +7052,7 @@ snapshots: forwarded@0.2.0: {} - fraction.js@4.3.7: {} + fraction.js@5.3.4: {} framer-motion@12.23.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: @@ -7069,7 +7130,7 @@ snapshots: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -7111,7 +7172,7 @@ snapshots: graphemer@1.4.0: {} - graphql@16.11.0: {} + graphql@16.12.0: {} has-flag@3.0.0: {} @@ -7142,21 +7203,21 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -7166,13 +7227,13 @@ snapshots: i18next-browser-languagedetector@8.2.0: dependencies: - '@babel/runtime': 7.27.0 + '@babel/runtime': 7.28.4 - i18next@25.6.0(typescript@5.8.3): + i18next@25.6.2(typescript@5.9.3): dependencies: '@babel/runtime': 7.28.4 optionalDependencies: - typescript: 5.8.3 + typescript: 5.9.3 iconv-lite@0.4.24: dependencies: @@ -7190,6 +7251,8 @@ snapshots: ignore@5.3.2: {} + ignore@7.0.5: {} + image-ssim@0.2.0: {} import-fresh@3.3.1: @@ -7240,7 +7303,7 @@ snapshots: dependencies: loose-envify: 1.4.0 - ip-address@10.0.1: {} + ip-address@10.1.0: {} ipaddr.js@1.9.1: {} @@ -7323,12 +7386,12 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@3.14.1: + js-yaml@3.14.2: dependencies: argparse: 1.0.10 esprima: 4.0.1 - js-yaml@4.1.0: + js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -7340,6 +7403,8 @@ snapshots: json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} @@ -7429,10 +7494,6 @@ snapshots: dependencies: p-locate: 5.0.0 - lodash.castarray@4.4.0: {} - - lodash.isplainobject@4.0.6: {} - lodash.merge@4.6.2: {} lodash@4.17.21: {} @@ -7462,9 +7523,9 @@ snapshots: dependencies: react: 18.3.1 - magic-string@0.30.17: + magic-string@0.30.21: dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 make-dir@3.1.0: dependencies: @@ -7521,11 +7582,11 @@ snapshots: minimatch@3.1.2: dependencies: - brace-expansion: 1.1.11 + brace-expansion: 1.1.12 minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 minimist@1.2.8: {} @@ -7551,14 +7612,14 @@ snapshots: ms@2.1.3: {} - msw@2.11.6(@types/node@22.14.1)(typescript@5.8.3): + msw@2.12.2(@types/node@22.19.1)(typescript@5.9.3): dependencies: - '@inquirer/confirm': 5.1.19(@types/node@22.14.1) + '@inquirer/confirm': 5.1.21(@types/node@22.19.1) '@mswjs/interceptors': 0.40.0 '@open-draft/deferred-promise': 2.2.0 '@types/statuses': 2.0.6 cookie: 1.0.2 - graphql: 16.11.0 + graphql: 16.12.0 headers-polyfill: 4.0.3 is-node-process: 1.2.0 outvariant: 1.4.3 @@ -7572,7 +7633,7 @@ snapshots: until-async: 3.0.2 yargs: 17.7.2 optionalDependencies: - typescript: 5.8.3 + typescript: 5.9.3 transitivePeerDependencies: - '@types/node' @@ -7615,8 +7676,6 @@ snapshots: fetch-blob: 3.2.0 formdata-polyfill: 4.0.10 - node-releases@2.0.19: {} - node-releases@2.0.27: {} normalize-path@3.0.0: {} @@ -7692,7 +7751,7 @@ snapshots: log-symbols: 6.0.0 stdin-discarder: 0.2.2 string-width: 7.2.0 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 os-tmpdir@1.0.2: {} @@ -7720,7 +7779,7 @@ snapshots: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.4 - debug: 4.4.0 + debug: 4.4.3 get-uri: 6.0.5 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 @@ -7784,7 +7843,7 @@ snapshots: picomatch@2.3.1: {} - picomatch@4.0.2: {} + picomatch@4.0.3: {} pify@2.3.0: {} @@ -7800,28 +7859,28 @@ snapshots: optionalDependencies: fsevents: 2.3.2 - postcss-import@15.1.0(postcss@8.5.3): + postcss-import@15.1.0(postcss@8.5.6): dependencies: - postcss: 8.5.3 + postcss: 8.5.6 postcss-value-parser: 4.2.0 read-cache: 1.0.0 - resolve: 1.22.10 + resolve: 1.22.11 - postcss-js@4.0.1(postcss@8.5.3): + postcss-js@4.1.0(postcss@8.5.6): dependencies: camelcase-css: 2.0.1 - postcss: 8.5.3 + postcss: 8.5.6 - postcss-load-config@4.0.2(postcss@8.5.3): + postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6): dependencies: lilconfig: 3.1.3 - yaml: 2.7.1 optionalDependencies: - postcss: 8.5.3 + jiti: 1.21.7 + postcss: 8.5.6 - postcss-nested@6.2.0(postcss@8.5.3): + postcss-nested@6.2.0(postcss@8.5.6): dependencies: - postcss: 8.5.3 + postcss: 8.5.6 postcss-selector-parser: 6.1.2 postcss-selector-parser@6.0.10: @@ -7836,12 +7895,6 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.5.3: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -7875,7 +7928,7 @@ snapshots: proxy-agent@6.3.1: dependencies: agent-base: 7.1.4 - debug: 4.4.0 + debug: 4.4.3 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 lru-cache: 7.18.3 @@ -7958,80 +8011,80 @@ snapshots: react-fast-compare: 3.2.2 shallowequal: 1.1.0 - react-hook-form@7.55.0(react@18.3.1): + react-hook-form@7.66.0(react@18.3.1): dependencies: react: 18.3.1 - react-i18next@16.2.3(i18next@25.6.0(typescript@5.8.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3): + react-i18next@16.3.3(i18next@25.6.2(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3): dependencies: '@babel/runtime': 7.28.4 html-parse-stringify: 3.0.1 - i18next: 25.6.0(typescript@5.8.3) + i18next: 25.6.2(typescript@5.9.3) react: 18.3.1 use-sync-external-store: 1.6.0(react@18.3.1) optionalDependencies: react-dom: 18.3.1(react@18.3.1) - typescript: 5.8.3 + typescript: 5.9.3 react-is@16.13.1: {} react-is@18.3.1: {} - react-remove-scroll-bar@2.3.8(@types/react@18.3.20)(react@18.3.1): + react-remove-scroll-bar@2.3.8(@types/react@18.3.26)(react@18.3.1): dependencies: react: 18.3.1 - react-style-singleton: 2.2.3(@types/react@18.3.20)(react@18.3.1) + react-style-singleton: 2.2.3(@types/react@18.3.26)(react@18.3.1) tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - react-remove-scroll@2.6.3(@types/react@18.3.20)(react@18.3.1): + react-remove-scroll@2.7.1(@types/react@18.3.26)(react@18.3.1): dependencies: react: 18.3.1 - react-remove-scroll-bar: 2.3.8(@types/react@18.3.20)(react@18.3.1) - react-style-singleton: 2.2.3(@types/react@18.3.20)(react@18.3.1) + react-remove-scroll-bar: 2.3.8(@types/react@18.3.26)(react@18.3.1) + react-style-singleton: 2.2.3(@types/react@18.3.26)(react@18.3.1) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@18.3.20)(react@18.3.1) - use-sidecar: 1.1.3(@types/react@18.3.20)(react@18.3.1) + use-callback-ref: 1.3.3(@types/react@18.3.26)(react@18.3.1) + use-sidecar: 1.1.3(@types/react@18.3.26)(react@18.3.1) optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - react-resizable-panels@2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-resizable-panels@2.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-router-dom@6.30.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-router-dom@6.30.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@remix-run/router': 1.23.0 + '@remix-run/router': 1.23.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-router: 6.30.0(react@18.3.1) + react-router: 6.30.2(react@18.3.1) - react-router@6.30.0(react@18.3.1): + react-router@6.30.2(react@18.3.1): dependencies: - '@remix-run/router': 1.23.0 + '@remix-run/router': 1.23.1 react: 18.3.1 react-smooth@4.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - fast-equals: 5.2.2 + fast-equals: 5.3.3 prop-types: 15.8.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-style-singleton@2.2.3(@types/react@18.3.20)(react@18.3.1): + react-style-singleton@2.2.3(@types/react@18.3.26)(react@18.3.1): dependencies: get-nonce: 1.0.1 react: 18.3.1 tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.27.0 + '@babel/runtime': 7.28.4 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -8062,7 +8115,7 @@ snapshots: dependencies: decimal.js-light: 2.5.1 - recharts@2.15.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + recharts@2.15.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: clsx: 2.1.1 eventemitter3: 4.0.7 @@ -8075,15 +8128,15 @@ snapshots: tiny-invariant: 1.3.3 victory-vendor: 36.9.2 - regenerator-runtime@0.14.1: {} - require-directory@2.1.1: {} + require-from-string@2.0.2: {} + require-main-filename@2.0.0: {} resolve-from@4.0.0: {} - resolve@1.22.10: + resolve@1.22.11: dependencies: is-core-module: 2.16.1 path-parse: 1.0.7 @@ -8113,35 +8166,37 @@ snapshots: robots-parser@3.0.1: {} - rollup@4.40.0: + rollup@4.53.2: dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.40.0 - '@rollup/rollup-android-arm64': 4.40.0 - '@rollup/rollup-darwin-arm64': 4.40.0 - '@rollup/rollup-darwin-x64': 4.40.0 - '@rollup/rollup-freebsd-arm64': 4.40.0 - '@rollup/rollup-freebsd-x64': 4.40.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.40.0 - '@rollup/rollup-linux-arm-musleabihf': 4.40.0 - '@rollup/rollup-linux-arm64-gnu': 4.40.0 - '@rollup/rollup-linux-arm64-musl': 4.40.0 - '@rollup/rollup-linux-loongarch64-gnu': 4.40.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.40.0 - '@rollup/rollup-linux-riscv64-gnu': 4.40.0 - '@rollup/rollup-linux-riscv64-musl': 4.40.0 - '@rollup/rollup-linux-s390x-gnu': 4.40.0 - '@rollup/rollup-linux-x64-gnu': 4.40.0 - '@rollup/rollup-linux-x64-musl': 4.40.0 - '@rollup/rollup-win32-arm64-msvc': 4.40.0 - '@rollup/rollup-win32-ia32-msvc': 4.40.0 - '@rollup/rollup-win32-x64-msvc': 4.40.0 + '@rollup/rollup-android-arm-eabi': 4.53.2 + '@rollup/rollup-android-arm64': 4.53.2 + '@rollup/rollup-darwin-arm64': 4.53.2 + '@rollup/rollup-darwin-x64': 4.53.2 + '@rollup/rollup-freebsd-arm64': 4.53.2 + '@rollup/rollup-freebsd-x64': 4.53.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.2 + '@rollup/rollup-linux-arm-musleabihf': 4.53.2 + '@rollup/rollup-linux-arm64-gnu': 4.53.2 + '@rollup/rollup-linux-arm64-musl': 4.53.2 + '@rollup/rollup-linux-loong64-gnu': 4.53.2 + '@rollup/rollup-linux-ppc64-gnu': 4.53.2 + '@rollup/rollup-linux-riscv64-gnu': 4.53.2 + '@rollup/rollup-linux-riscv64-musl': 4.53.2 + '@rollup/rollup-linux-s390x-gnu': 4.53.2 + '@rollup/rollup-linux-x64-gnu': 4.53.2 + '@rollup/rollup-linux-x64-musl': 4.53.2 + '@rollup/rollup-openharmony-arm64': 4.53.2 + '@rollup/rollup-win32-arm64-msvc': 4.53.2 + '@rollup/rollup-win32-ia32-msvc': 4.53.2 + '@rollup/rollup-win32-x64-gnu': 4.53.2 + '@rollup/rollup-win32-x64-msvc': 4.53.2 fsevents: 2.3.3 router@2.2.0: dependencies: - debug: 4.4.0 + debug: 4.4.3 depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 @@ -8171,7 +8226,7 @@ snapshots: semver@6.3.1: {} - semver@7.7.1: {} + semver@7.7.3: {} send@0.19.0: dependencies: @@ -8193,7 +8248,7 @@ snapshots: send@1.2.0: dependencies: - debug: 4.4.0 + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -8229,18 +8284,18 @@ snapshots: setprototypeof@1.2.0: {} - shadcn@3.5.0(@types/node@22.14.1)(typescript@5.8.3): + shadcn@3.5.0(@types/node@22.19.1)(typescript@5.9.3): dependencies: '@antfu/ni': 25.0.0 '@babel/core': 7.28.5 '@babel/parser': 7.28.5 '@babel/plugin-transform-typescript': 7.28.5(@babel/core@7.28.5) '@babel/preset-typescript': 7.28.5(@babel/core@7.28.5) - '@dotenvx/dotenvx': 1.51.0 - '@modelcontextprotocol/sdk': 1.20.2 - browserslist: 4.27.0 + '@dotenvx/dotenvx': 1.51.1 + '@modelcontextprotocol/sdk': 1.22.0 + browserslist: 4.28.0 commander: 14.0.2 - cosmiconfig: 9.0.0(typescript@5.8.3) + cosmiconfig: 9.0.0(typescript@5.9.3) dedent: 1.7.0 deepmerge: 4.3.1 diff: 8.0.2 @@ -8250,7 +8305,7 @@ snapshots: fuzzysort: 3.1.0 https-proxy-agent: 7.0.6 kleur: 4.1.5 - msw: 2.11.6(@types/node@22.14.1)(typescript@5.8.3) + msw: 2.12.2(@types/node@22.19.1)(typescript@5.9.3) node-fetch: 3.3.2 ora: 8.2.0 postcss: 8.5.6 @@ -8259,9 +8314,10 @@ snapshots: stringify-object: 5.0.0 ts-morph: 26.0.0 tsconfig-paths: 4.2.0 - zod: 3.24.3 - zod-to-json-schema: 3.24.6(zod@3.24.3) + zod: 3.25.76 + zod-to-json-schema: 3.24.6(zod@3.25.76) transitivePeerDependencies: + - '@cfworker/json-schema' - '@types/node' - babel-plugin-macros - supports-color @@ -8314,14 +8370,14 @@ snapshots: socks-proxy-agent@8.0.5: dependencies: agent-base: 7.1.4 - debug: 4.4.0 + debug: 4.4.3 socks: 2.8.7 transitivePeerDependencies: - supports-color socks@2.8.7: dependencies: - ip-address: 10.0.1 + ip-address: 10.1.0 smart-buffer: 4.2.0 sonner@1.7.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -8335,7 +8391,7 @@ snapshots: speedline-core@1.4.3: dependencies: - '@types/node': 22.14.1 + '@types/node': 22.19.1 image-ssim: 0.2.0 jpeg-js: 0.4.4 @@ -8375,13 +8431,13 @@ snapshots: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 string-width@7.2.0: dependencies: emoji-regex: 10.6.0 get-east-asian-width: 1.4.0 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 stringify-object@5.0.0: dependencies: @@ -8401,9 +8457,9 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: + strip-ansi@7.1.2: dependencies: - ansi-regex: 6.1.0 + ansi-regex: 6.2.2 strip-bom@3.0.0: {} @@ -8415,7 +8471,7 @@ snapshots: sucrase@3.35.0: dependencies: - '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 glob: 10.4.5 lines-and-columns: 1.2.4 @@ -8441,11 +8497,11 @@ snapshots: tailwind-merge@2.6.0: {} - tailwindcss-animate@1.0.7(tailwindcss@3.4.17): + tailwindcss-animate@1.0.7(tailwindcss@3.4.18): dependencies: - tailwindcss: 3.4.17 + tailwindcss: 3.4.18 - tailwindcss@3.4.17: + tailwindcss@3.4.18: dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -8461,16 +8517,17 @@ snapshots: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.1.1 - postcss: 8.5.3 - postcss-import: 15.1.0(postcss@8.5.3) - postcss-js: 4.0.1(postcss@8.5.3) - postcss-load-config: 4.0.2(postcss@8.5.3) - postcss-nested: 6.2.0(postcss@8.5.3) + postcss: 8.5.6 + postcss-import: 15.1.0(postcss@8.5.6) + postcss-js: 4.1.0(postcss@8.5.6) + postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6) + postcss-nested: 6.2.0(postcss@8.5.6) postcss-selector-parser: 6.1.2 - resolve: 1.22.10 + resolve: 1.22.11 sucrase: 3.35.0 transitivePeerDependencies: - - ts-node + - tsx + - yaml tar-fs@3.0.4: dependencies: @@ -8510,12 +8567,12 @@ snapshots: tiny-invariant@1.3.3: {} - tinyexec@1.0.1: {} + tinyexec@1.0.2: {} - tinyglobby@0.2.13: + tinyglobby@0.2.15: dependencies: - fdir: 6.4.4(picomatch@4.0.2) - picomatch: 4.0.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 tldts-core@6.1.86: {} @@ -8551,9 +8608,9 @@ snapshots: tree-kill@1.2.2: {} - ts-api-utils@2.1.0(typescript@5.8.3): + ts-api-utils@2.1.0(typescript@5.9.3): dependencies: - typescript: 5.8.3 + typescript: 5.9.3 ts-interface-checker@0.1.13: {} @@ -8593,17 +8650,18 @@ snapshots: dependencies: is-typedarray: 1.0.0 - typescript-eslint@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3): + typescript-eslint@8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/parser': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) - '@typescript-eslint/utils': 8.30.1(eslint@9.24.0(jiti@1.21.7))(typescript@5.8.3) - eslint: 9.24.0(jiti@1.21.7) - typescript: 5.8.3 + '@typescript-eslint/eslint-plugin': 8.46.4(@typescript-eslint/parser@8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.4(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3) + eslint: 9.39.1(jiti@1.21.7) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - typescript@5.8.3: {} + typescript@5.9.3: {} unbzip2-stream@1.4.3: dependencies: @@ -8624,15 +8682,9 @@ snapshots: until-async@3.0.2: {} - update-browserslist-db@1.1.3(browserslist@4.24.4): - dependencies: - browserslist: 4.24.4 - escalade: 3.2.0 - picocolors: 1.1.1 - - update-browserslist-db@1.1.4(browserslist@4.27.0): + update-browserslist-db@1.1.4(browserslist@4.28.0): dependencies: - browserslist: 4.27.0 + browserslist: 4.28.0 escalade: 3.2.0 picocolors: 1.1.1 @@ -8642,20 +8694,20 @@ snapshots: urlpattern-polyfill@10.0.0: {} - use-callback-ref@1.3.3(@types/react@18.3.20)(react@18.3.1): + use-callback-ref@1.3.3(@types/react@18.3.26)(react@18.3.1): dependencies: react: 18.3.1 tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 - use-sidecar@1.1.3(@types/react@18.3.20)(react@18.3.1): + use-sidecar@1.1.3(@types/react@18.3.26)(react@18.3.1): dependencies: detect-node-es: 1.1.0 react: 18.3.1 tslib: 2.8.1 optionalDependencies: - '@types/react': 18.3.20 + '@types/react': 18.3.26 use-sync-external-store@1.6.0(react@18.3.1): dependencies: @@ -8669,9 +8721,9 @@ snapshots: vary@1.1.2: {} - vaul@0.9.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + vaul@0.9.9(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@radix-ui/react-dialog': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.26))(@types/react@18.3.26)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: @@ -8680,7 +8732,7 @@ snapshots: victory-vendor@36.9.2: dependencies: - '@types/d3-array': 3.2.1 + '@types/d3-array': 3.2.2 '@types/d3-ease': 3.0.2 '@types/d3-interpolate': 3.0.4 '@types/d3-scale': 4.0.9 @@ -8695,19 +8747,18 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@6.3.4(@types/node@22.14.1)(jiti@1.21.7)(yaml@2.7.1): + vite@6.4.1(@types/node@22.19.1)(jiti@1.21.7): dependencies: - esbuild: 0.25.3 - fdir: 6.4.4(picomatch@4.0.2) - picomatch: 4.0.2 - postcss: 8.5.3 - rollup: 4.40.0 - tinyglobby: 0.2.13 + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.53.2 + tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 22.14.1 + '@types/node': 22.19.1 fsevents: 2.3.3 jiti: 1.21.7 - yaml: 2.7.1 void-elements@3.1.0: {} @@ -8748,9 +8799,9 @@ snapshots: wrap-ansi@8.1.0: dependencies: - ansi-styles: 6.2.1 + ansi-styles: 6.2.3 string-width: 5.1.2 - strip-ansi: 7.1.0 + strip-ansi: 7.1.2 wrappy@1.0.2: {} @@ -8773,8 +8824,6 @@ snapshots: yallist@3.1.1: {} - yaml@2.7.1: {} - yargs-parser@13.1.2: dependencies: camelcase: 5.3.1 @@ -8822,8 +8871,8 @@ snapshots: yoctocolors@2.1.2: {} - zod-to-json-schema@3.24.6(zod@3.24.3): + zod-to-json-schema@3.24.6(zod@3.25.76): dependencies: - zod: 3.24.3 + zod: 3.25.76 - zod@3.24.3: {} + zod@3.25.76: {} diff --git a/tests/blogPosts.test.mjs b/tests/blogPosts.test.mjs new file mode 100644 index 0000000..1fb2d1e --- /dev/null +++ b/tests/blogPosts.test.mjs @@ -0,0 +1,50 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const repoRoot = path.resolve(__dirname, '..'); + +const loadBlog = (locale) => { + const filePath = path.join(repoRoot, `src/content/${locale}/blog.json`); + return JSON.parse(readFileSync(filePath, 'utf-8')); +}; + +const localesToCheck = ['pt', 'en']; + +const expectedKeys = ['content', 'cover', 'date', 'excerpt', 'id', 'slug', 'tags', 'title']; + +localesToCheck.forEach((locale) => { + test(`blog posts for ${locale} include required fields`, () => { + const blog = loadBlog(locale); + assert.ok(Array.isArray(blog.posts), 'posts array should exist'); + assert.ok(blog.posts.length > 0, 'posts array should not be empty'); + + blog.posts.forEach((post) => { + const keys = Object.keys(post).sort(); + assert.deepStrictEqual(keys, expectedKeys, `${locale} post keys should match expected structure`); + assert.ok(post.slug.length > 0, `${locale} post should have slug`); + assert.ok(post.cover.startsWith('/images/blog/'), `${locale} post should include cover path`); + assert.ok(post.tags.length > 0, `${locale} post should list at least one tag`); + assert.ok(post.content.length > 50, `${locale} post should include markdown content`); + }); + }); +}); + +test('blog fallback metadata is present and missing posts return undefined', () => { + const ptBlog = loadBlog('pt'); + const enBlog = loadBlog('en'); + + const findPost = (blog, slug) => blog.posts.find((post) => post.slug === slug); + + assert.strictEqual(findPost(ptBlog, 'nao-existe'), undefined, 'PT should return undefined for missing slug'); + assert.strictEqual(findPost(enBlog, 'does-not-exist'), undefined, 'EN should return undefined for missing slug'); + + ['title', 'message', 'cta'].forEach((key) => { + assert.ok(ptBlog.notFound?.[key], `PT notFound.${key} should exist`); + assert.ok(enBlog.notFound?.[key], `EN notFound.${key} should exist`); + }); +}); diff --git a/tests/contactContent.test.mjs b/tests/contactContent.test.mjs new file mode 100644 index 0000000..49353a1 --- /dev/null +++ b/tests/contactContent.test.mjs @@ -0,0 +1,52 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; + +import { createRequire } from 'node:module'; + +const require = createRequire(import.meta.url); + +const ptContact = require('../src/content/pt/contact.json'); +const enContact = require('../src/content/en/contact.json'); +const esContact = require('../src/content/es/contact.json'); +const frContact = require('../src/content/fr/contact.json'); + +const locales = { + pt: ptContact, + en: enContact, + es: esContact, + fr: frContact, +}; + +const requiredFormKeys = ['successDescription', 'errorDescription', 'submitting']; +const validationFields = { + name: ['min', 'max'], + email: ['invalid'], + message: ['min', 'max'], +}; + +test('contact form translations expose complete validation messages', () => { + for (const [locale, content] of Object.entries(locales)) { + assert.ok(content?.form, `form block missing for locale ${locale}`); + const { form } = content; + + for (const key of requiredFormKeys) { + const value = form[key]; + assert.equal(typeof value, 'string', `${key} must be a string for locale ${locale}`); + assert.ok(value.trim().length > 0, `${key} cannot be empty for locale ${locale}`); + } + + const validation = form.validation; + assert.ok(validation, `validation block missing for locale ${locale}`); + + for (const [field, rules] of Object.entries(validationFields)) { + const fieldMessages = validation[field]; + assert.ok(fieldMessages, `validation messages missing for field ${field} in locale ${locale}`); + + for (const rule of rules) { + const message = fieldMessages[rule]; + assert.equal(typeof message, 'string', `validation message for ${field}.${rule} must be string in locale ${locale}`); + assert.ok(message.trim().length > 0, `validation message for ${field}.${rule} cannot be empty in locale ${locale}`); + } + } + } +}); diff --git a/tests/contactRequests.test.mjs b/tests/contactRequests.test.mjs new file mode 100644 index 0000000..8e85882 --- /dev/null +++ b/tests/contactRequests.test.mjs @@ -0,0 +1,80 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const repoRoot = path.resolve(__dirname, '..'); + +const loadJson = (relativePath) => { + const filePath = path.join(repoRoot, relativePath); + return JSON.parse(readFileSync(filePath, 'utf-8')); +}; + +const locales = ['pt', 'en', 'es', 'fr']; +const painelContent = Object.fromEntries(locales.map((locale) => [locale, loadJson(`src/content/${locale}/painel.json`)])); +const contactRequests = loadJson('public/data/contact-requests.json'); + +const uniqueChannels = new Set(contactRequests.map((request) => request.channel)); +const uniqueStatuses = new Set(contactRequests.map((request) => request.status)); + +const isValidIsoDate = (value) => { + if (typeof value !== 'string') { + return false; + } + + const timestamp = Date.parse(value); + return Number.isFinite(timestamp); +}; + +test('contact requests mock contains structured entries', () => { + assert.ok(Array.isArray(contactRequests), 'contact requests should be an array'); + assert.ok(contactRequests.length > 0, 'contact requests array should not be empty'); + + contactRequests.forEach((request, index) => { + assert.ok(typeof request.id === 'string' && request.id.length > 0, `request ${index} should have an id`); + assert.ok(typeof request.name === 'string' && request.name.length > 0, `request ${index} should have a name`); + assert.ok(typeof request.email === 'string' && request.email.includes('@'), `request ${index} should have an email`); + assert.ok(typeof request.channel === 'string' && request.channel.length > 0, `request ${index} should have a channel`); + assert.ok(typeof request.status === 'string' && request.status.length > 0, `request ${index} should have a status`); + assert.ok(isValidIsoDate(request.createdAt), `request ${index} should have a valid createdAt date`); + + if (request.respondedAt) { + assert.ok(isValidIsoDate(request.respondedAt), `request ${index} should have a valid respondedAt date when present`); + } + }); +}); + +test('painel cards stay aligned across locales', () => { + const referenceCards = painelContent.pt.cards; + locales.forEach((locale) => { + const cards = painelContent[locale].cards; + assert.ok(Array.isArray(cards), `${locale} cards should be an array`); + assert.strictEqual(cards.length, referenceCards.length, `${locale} should have ${referenceCards.length} cards`); + + cards.forEach((card, index) => { + assert.ok(card.id, `${locale} card ${index} should declare an id`); + assert.ok(card.title, `${locale} card ${card.id} should have a title`); + assert.ok(card.description, `${locale} card ${card.id} should have a description`); + assert.strictEqual(card.id, referenceCards[index].id, `${locale} card order should match reference`); + }); + }); +}); + +test('painel translations cover contact request channels and statuses', () => { + locales.forEach((locale) => { + const { leadInsights } = painelContent[locale]; + const channelLabels = leadInsights?.channels?.labels ?? {}; + const statusLabels = leadInsights?.status?.labels ?? {}; + + uniqueChannels.forEach((channel) => { + assert.ok(channelLabels[channel], `${locale} should translate channel ${channel}`); + }); + + uniqueStatuses.forEach((status) => { + assert.ok(statusLabels[status], `${locale} should translate status ${status}`); + }); + }); +}); diff --git a/tests/homeSections.test.mjs b/tests/homeSections.test.mjs new file mode 100644 index 0000000..f050d0c --- /dev/null +++ b/tests/homeSections.test.mjs @@ -0,0 +1,83 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const repoRoot = path.resolve(__dirname, '..'); + +const loadJson = (relativePath) => { + const filePath = path.join(repoRoot, relativePath); + return JSON.parse(readFileSync(filePath, 'utf-8')); +}; + +const readSource = (relativePath) => { + const filePath = path.join(repoRoot, relativePath); + return readFileSync(filePath, 'utf-8'); +}; + +const ptHome = loadJson('src/content/pt/home.json'); +const enHome = loadJson('src/content/en/home.json'); + +const sectionsDepthExpectations = [ + ['src/components/home/HeroSection.tsx', 'Hero', 'depth="overlay"'], + ['src/components/home/FeaturesSection.tsx', 'FeatureGrid', 'depth="surface"'], + ['src/components/home/HowItWorksSection.tsx', 'Stepper', 'depth="overlay"'], + ['src/components/home/PlansSection.tsx', 'PricingTable', 'depth="surface"'], + ['src/components/home/TestimonialsSection.tsx', 'TestimonialCarousel', 'depth="surface"'], + ['src/components/home/FaqSection.tsx', 'Faq', 'depth="overlay"'], + ['src/components/home/FinalCtaSection.tsx', 'AnimatedSection', 'depth="overlay"'], +]; + +test('home content has hero translations for pt and en', () => { + assert.ok(ptHome.hero?.title?.length > 0, 'PT hero title should exist'); + assert.ok(enHome.hero?.title?.length > 0, 'EN hero title should exist'); + assert.notStrictEqual(ptHome.hero.title, enHome.hero.title, 'Hero titles should be localized'); + assert.ok(ptHome.hero?.cta, 'PT hero CTA exists'); + assert.ok(enHome.hero?.cta, 'EN hero CTA exists'); +}); + +test('feature lists stay in sync across locales', () => { + assert.strictEqual(ptHome.features?.length, enHome.features?.length, 'Feature arrays should match length'); + ptHome.features.forEach((feature, index) => { + assert.ok(feature.title, `PT feature ${index} has title`); + assert.ok(enHome.features[index].title, `EN feature ${index} has title`); + }); +}); + +test('plans options stay in sync across locales', () => { + assert.strictEqual(ptHome.plans?.options?.length, enHome.plans?.options?.length, 'Plan counts should match'); + ptHome.plans.options.forEach((plan, index) => { + assert.ok(plan.features?.length > 0, `PT plan ${plan.name} has features`); + assert.strictEqual( + plan.features.length, + enHome.plans.options[index].features.length, + `Plan ${plan.name} should match feature count` + ); + }); +}); + +test('Reactbits sections apply expected depth variants', () => { + sectionsDepthExpectations.forEach(([relativePath, componentName, expectedDepth]) => { + const source = readSource(relativePath); + assert.match( + source, + new RegExp(expectedDepth.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')), + `${componentName} should include ${expectedDepth}` + ); + }); +}); + +test('Reactbits components are used in each section', () => { + // Exclude FinalCtaSection (AnimatedSection) as it uses a custom animated wrapper instead of a direct reactbits component + sectionsDepthExpectations.slice(0, -1).forEach(([relativePath, componentName]) => { + const source = readSource(relativePath); + assert.match( + source, + new RegExp(`<${componentName}[^>]*>`), + `${relativePath} should render ${componentName}` + ); + }); +}); diff --git a/tests/theme.test.mjs b/tests/theme.test.mjs new file mode 100644 index 0000000..8d3af83 --- /dev/null +++ b/tests/theme.test.mjs @@ -0,0 +1,64 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const repoRoot = path.resolve(__dirname, '..'); + +const readSource = (relativePath) => { + const filePath = path.join(repoRoot, relativePath); + return readFileSync(filePath, 'utf-8'); +}; + +const themeProviderSource = readSource('src/components/ThemeProvider.tsx'); +const themeToggleSource = readSource('src/components/ThemeToggle.tsx'); +const globalsCss = readSource('src/globals.css'); + +test('theme provider defaults to class-based theming with transitions', () => { + assert.match( + themeProviderSource, + /attribute\s*=\s*"class"/, + 'ThemeProvider should default to using the class attribute', + ); + assert.match( + themeProviderSource, + /disableTransitionOnChange\s*=\s*true/, + 'ThemeProvider should disable transition flashes when switching', + ); + assert.match( + themeProviderSource, + /enableColorScheme\s*=\s*true/, + 'ThemeProvider should expose the active color scheme to the browser', + ); +}); + +test('theme toggle exposes radio options for light, dark and system', () => { + assert.match( + themeToggleSource, + /DropdownMenuRadioGroup/, + 'ThemeToggle should group the theme options in a radio group', + ); + ['light', 'dark', 'system'].forEach((option) => { + assert.match( + themeToggleSource, + new RegExp(`DropdownMenuRadioItem\\s+value=\\"${option}\\"`), + `ThemeToggle should include a radio item for ${option}`, + ); + }); +}); + +test('global body styles animate background and foreground changes', () => { + assert.match( + globalsCss, + /body\s*\{[^}]*transition-colors[^}]*\}/s, + 'Body styles should include a transition for color changes', + ); + assert.match( + globalsCss, + /body\s*\{[^}]*min-h-screen[^}]*\}/s, + 'Body styles should ensure the viewport stays filled in both themes', + ); +}); diff --git a/tests/visual/accessibility.spec.ts b/tests/visual/accessibility.spec.ts new file mode 100644 index 0000000..2be7366 --- /dev/null +++ b/tests/visual/accessibility.spec.ts @@ -0,0 +1,221 @@ +import { test, expect } from '@playwright/test'; + +// Constants for accessibility testing +const MAX_TAB_COUNT = 50; // Maximum tabs to prevent infinite loops + +/** + * Accessibility Tests + * Validates WCAG compliance and accessibility features + */ +test.describe('Accessibility - Keyboard Navigation', () => { + test('can navigate entire site with keyboard', async ({ page }) => { + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + // Tab through all interactive elements + let tabCount = 0; + + while (tabCount < MAX_TAB_COUNT) { // Limit to prevent infinite loop + await page.keyboard.press('Tab'); + tabCount++; + + // Check if we've trapped in a focus loop + const focusedElement = await page.evaluate(() => { + const el = document.activeElement; + return { + tagName: el?.tagName, + role: el?.getAttribute('role'), + ariaLabel: el?.getAttribute('aria-label'), + }; + }); + + // If we hit a link and press Enter, we should navigate + if (focusedElement.tagName === 'A') { + // Found a link, continue tabbing + continue; + } + } + + // Should have successfully tabbed through elements + expect(tabCount).toBeGreaterThan(5); + }); + + test('sidebar trigger is keyboard accessible', async ({ page }) => { + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + const trigger = page.locator('[data-sidebar="trigger"]'); + + if (await trigger.count() === 0) { + test.skip(true, 'Sidebar trigger not found'); + return; + } + + // Focus the trigger + await trigger.focus(); + + // Check it has visible focus indicator + const hasFocusRing = await trigger.evaluate((el) => { + const styles = window.getComputedStyle(el); + return styles.outline !== 'none' || styles.boxShadow !== 'none'; + }); + + expect(hasFocusRing).toBeTruthy(); + + // Press Enter to toggle + await page.keyboard.press('Enter'); + await page.waitForTimeout(300); + + // Should have toggled + const isToggled = await page.evaluate(() => { + return document.querySelector('[data-sidebar]')?.getAttribute('data-state') === 'collapsed'; + }); + + // Should respond to keyboard activation (true or false, just checking it responded) + expect(typeof isToggled).toBe('boolean'); + }); +}); + +test.describe('Accessibility - ARIA Labels', () => { + test('all icon-only buttons have ARIA labels', async ({ page }) => { + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + // Find all buttons with only icons (no visible text) + const iconButtons = await page.locator('button').evaluateAll((buttons) => { + return buttons.filter((btn) => { + const hasVisibleText = (btn.textContent?.trim().length ?? 0) > 0; + const hasAriaLabel = btn.getAttribute('aria-label'); + const hasSrOnly = btn.querySelector('.sr-only'); + + // Consider it an icon-only button if it has no visible text + // but should have either aria-label or sr-only text + if (!hasVisibleText && !hasAriaLabel && !hasSrOnly) { + return true; // This is a problem button + } + return false; + }).length; + }); + + // All icon-only buttons should have labels + expect(iconButtons).toBe(0); + }); + + test('language switcher has ARIA label', async ({ page }) => { + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + const languageSwitcher = page.locator('[aria-label="Select language"]'); + await expect(languageSwitcher).toBeVisible(); + }); + + test('theme toggle has screen reader text', async ({ page }) => { + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + const themeToggle = page.locator('button').filter({ has: page.locator('.sr-only') }); + const count = await themeToggle.count(); + + // Should have at least one button with sr-only text (theme toggle) + expect(count).toBeGreaterThan(0); + }); +}); + +test.describe('Accessibility - Heading Hierarchy', () => { + test('home page has proper heading hierarchy', async ({ page }) => { + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + const headings = await page.evaluate(() => { + const h1s = Array.from(document.querySelectorAll('h1')).map(h => h.textContent?.trim()); + const h2s = Array.from(document.querySelectorAll('h2')).map(h => h.textContent?.trim()); + const h3s = Array.from(document.querySelectorAll('h3')).map(h => h.textContent?.trim()); + + return { h1s, h2s, h3s }; + }); + + // Should have exactly one H1 + expect(headings.h1s.length).toBe(1); + + // Should have H2s + expect(headings.h2s.length).toBeGreaterThan(0); + + // H1 should not be empty + expect(headings.h1s[0]).toBeTruthy(); + }); + + test('blog page has proper heading hierarchy', async ({ page }) => { + await page.goto('/pt/blog'); + await page.waitForLoadState('networkidle'); + + const h1Count = await page.locator('h1').count(); + expect(h1Count).toBe(1); + }); + + test('about page has proper heading hierarchy', async ({ page }) => { + await page.goto('/pt/sobre'); + await page.waitForLoadState('networkidle'); + + const h1Count = await page.locator('h1').count(); + expect(h1Count).toBe(1); + }); +}); + +test.describe('Accessibility - Color Contrast', () => { + test('text elements have sufficient color contrast', async ({ page }) => { + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + // Sample key text elements + const textElements = [ + page.locator('h1').first(), + page.locator('p').first(), + page.locator('a').first(), + ]; + + for (const element of textElements) { + if (await element.count() === 0) continue; + + const contrastInfo = await element.evaluate((el) => { + const styles = window.getComputedStyle(el); + const color = styles.color; + const backgroundColor = styles.backgroundColor; + const fontSize = parseFloat(styles.fontSize); + + return { color, backgroundColor, fontSize }; + }); + + // Basic check - elements should have defined colors + expect(contrastInfo.color).toBeTruthy(); + expect(contrastInfo.backgroundColor).toBeTruthy(); + } + }); +}); + +test.describe('Accessibility - Touch Targets', () => { + test('mobile interactive elements meet minimum size', async ({ page }) => { + await page.setViewportSize({ width: 375, height: 667 }); + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + const buttons = await page.locator('button:visible, a:visible').evaluateAll((elements) => { + return elements.map((el) => { + const rect = el.getBoundingClientRect(); + return { + width: rect.width, + height: rect.height, + meets44x44: rect.width >= 44 && rect.height >= 44, + meets40x40: rect.width >= 40 && rect.height >= 40, + }; + }).filter(size => size.width > 0 && size.height > 0); + }); + + // At least 80% of interactive elements should meet practical minimum (40x40) + // Note: WCAG 2.5.5 recommends 44x44, but 40x40 is acceptable for most elements + const passing = buttons.filter(b => b.meets40x40).length; + const total = buttons.length; + const percentage = (passing / total) * 100; + + expect(percentage).toBeGreaterThan(80); + }); +}); diff --git a/tests/visual/homepage.spec.ts b/tests/visual/homepage.spec.ts new file mode 100644 index 0000000..4790b09 --- /dev/null +++ b/tests/visual/homepage.spec.ts @@ -0,0 +1,119 @@ +import { test, expect } from '@playwright/test'; + +/** + * Visual Regression Tests for Home Page + * Tests the layout and grid alignment at different breakpoints + */ +test.describe('Home Page Visual Regression', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + }); + + test('desktop layout full page', async ({ page }) => { + await expect(page).toHaveScreenshot('home-desktop-full.png', { + fullPage: true, + }); + }); + + test('hero section renders correctly', async ({ page }) => { + const hero = page.locator('section').first(); + await hero.waitFor({ state: 'visible' }); + await expect(hero).toHaveScreenshot('hero-section.png'); + }); + + test('features grid alignment', async ({ page }) => { + // Scroll to features section + await page.evaluate(() => { + const sections = document.querySelectorAll('section'); + if (sections[1]) { + sections[1].scrollIntoView({ behavior: 'instant', block: 'center' }); + } + }); + + // Wait for scroll position to stabilize + const featuresSection = page.locator('section').nth(1); + await featuresSection.waitFor({ state: 'visible' }); + + await expect(featuresSection).toHaveScreenshot('features-grid.png'); + }); + + test('solutions grid alignment', async ({ page }) => { + // Scroll to solutions section + await page.evaluate(() => { + const sections = document.querySelectorAll('section'); + if (sections[2]) { + sections[2].scrollIntoView({ behavior: 'instant', block: 'center' }); + } + }); + + // Wait for scroll position to stabilize + const solutionsSection = page.locator('section').nth(2); + await solutionsSection.waitFor({ state: 'visible' }); + + await expect(solutionsSection).toHaveScreenshot('solutions-grid.png'); + }); +}); + +test.describe('Grid Alignment at Multiple Breakpoints', () => { + const breakpoints = [ + { width: 375, height: 667, name: 'mobile' }, + { width: 768, height: 1024, name: 'tablet' }, + { width: 1024, height: 768, name: 'desktop-small' }, + { width: 1440, height: 900, name: 'desktop-large' }, + ]; + + for (const bp of breakpoints) { + test(`grid alignment at ${bp.name} (${bp.width}x${bp.height})`, async ({ page }) => { + await page.setViewportSize({ width: bp.width, height: bp.height }); + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + // Scroll through key sections + await page.evaluate(() => { + const sections = document.querySelectorAll('section'); + if (sections[1]) { + sections[1].scrollIntoView({ behavior: 'instant', block: 'center' }); + } + }); + + // Wait for the section to be visible and stable + await page.locator('section').nth(1).waitFor({ state: 'visible' }); + + await expect(page).toHaveScreenshot(`home-${bp.name}.png`, { + fullPage: true, + }); + }); + } +}); + +test.describe('Blog Page Grid Consistency', () => { + test('blog grid layout', async ({ page }) => { + await page.goto('/pt/blog'); + await page.waitForLoadState('networkidle'); + + const blogGrid = page.locator('.grid').first(); + await expect(blogGrid).toHaveScreenshot('blog-grid.png'); + }); +}); + +test.describe('About Page Grid Consistency', () => { + test('about values grid', async ({ page }) => { + await page.goto('/pt/sobre'); + await page.waitForLoadState('networkidle'); + + // Scroll to values section + await page.evaluate(() => { + const grids = document.querySelectorAll('.grid'); + if (grids[0]) { + grids[0].scrollIntoView({ behavior: 'instant', block: 'center' }); + } + }); + + // Wait for the grid to be visible and stable + const valuesGrid = page.locator('.grid').first(); + await valuesGrid.waitFor({ state: 'visible' }); + + await expect(valuesGrid).toHaveScreenshot('about-values-grid.png'); + }); +}); diff --git a/tests/visual/sidebar.spec.ts b/tests/visual/sidebar.spec.ts new file mode 100644 index 0000000..09c90a2 --- /dev/null +++ b/tests/visual/sidebar.spec.ts @@ -0,0 +1,203 @@ +import { test, expect } from '@playwright/test'; + +/** + * Visual Regression Tests for Sidebar + * Validates no layout shifts during toggle + */ + +// Type definition for Layout Shift Performance Entry +interface LayoutShiftEntry extends PerformanceEntry { + value: number; + hadRecentInput: boolean; +} + +test.describe('Sidebar Toggle Animation', () => { + test.beforeEach(async ({ page }) => { + // Navigate to a page with sidebar (assuming /pt/painel or similar) + // Adjust path based on actual sidebar implementation + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + }); + + test('sidebar toggle does not cause layout shifts', async ({ page }) => { + // Find the sidebar trigger button + const trigger = page.locator('[data-sidebar="trigger"]'); + + if (await trigger.count() === 0) { + test.skip(true, 'Sidebar trigger not found on this page'); + return; + } + + const sidebar = page.locator('[data-sidebar="sidebar"]'); + + // Capture before toggle + await expect(page).toHaveScreenshot('sidebar-before-toggle.png'); + + // Toggle sidebar + await trigger.click(); + + // Wait for transition to complete by checking when the element becomes stable + await page.evaluate(() => + new Promise((resolve) => { + const sidebarEl = document.querySelector('[data-sidebar="sidebar"]'); + if (!sidebarEl) { + resolve(); + return; + } + const handler = () => { + sidebarEl.removeEventListener('transitionend', handler); + resolve(); + }; + sidebarEl.addEventListener('transitionend', handler); + // Fallback timeout in case transitionend doesn't fire + setTimeout(() => { + sidebarEl.removeEventListener('transitionend', handler); + resolve(); + }, 500); + }) + ); + + // Capture after toggle + await expect(page).toHaveScreenshot('sidebar-after-toggle.png'); + + // Toggle back + await trigger.click(); + + // Wait for transition to complete + await page.evaluate(() => + new Promise((resolve) => { + const sidebarEl = document.querySelector('[data-sidebar="sidebar"]'); + if (!sidebarEl) { + resolve(); + return; + } + const handler = () => { + sidebarEl.removeEventListener('transitionend', handler); + resolve(); + }; + sidebarEl.addEventListener('transitionend', handler); + // Fallback timeout + setTimeout(() => { + sidebarEl.removeEventListener('transitionend', handler); + resolve(); + }, 500); + }) + ); + + // Should match the original state + await expect(page).toHaveScreenshot('sidebar-toggled-back.png'); + }); + + test('rapid sidebar toggles remain stable', async ({ page }) => { + const trigger = page.locator('[data-sidebar="trigger"]'); + + if (await trigger.count() === 0) { + test.skip(true, 'Sidebar trigger not found on this page'); + return; + } + + // Perform rapid toggles + for (let i = 0; i < 5; i++) { + await trigger.click(); + // Wait briefly between clicks to ensure click is registered + await page.waitForTimeout(50); + } + + // Wait for all animations to settle by checking when sidebar transitions complete + await page.evaluate(() => + new Promise((resolve) => { + const sidebarEl = document.querySelector('[data-sidebar="sidebar"]'); + if (!sidebarEl) { + resolve(); + return; + } + let timeoutId: number; + const handler = () => { + // Clear existing timeout and set a new one to ensure all transitions are done + clearTimeout(timeoutId); + timeoutId = window.setTimeout(() => { + sidebarEl.removeEventListener('transitionend', handler); + resolve(); + }, 100); + }; + sidebarEl.addEventListener('transitionend', handler); + // Initial timeout to start the check + timeoutId = window.setTimeout(() => { + sidebarEl.removeEventListener('transitionend', handler); + resolve(); + }, 1000); + }) + ); + + // Check final state is stable + await expect(page).toHaveScreenshot('sidebar-after-rapid-toggles.png'); + }); +}); + +test.describe('Sidebar Performance', () => { + test('sidebar toggle has no layout shifts', async ({ page }) => { + // Start measuring layout shifts + await page.goto('/pt'); + await page.waitForLoadState('networkidle'); + + const trigger = page.locator('[data-sidebar="trigger"]'); + + if (await trigger.count() === 0) { + test.skip(true, 'Sidebar trigger not found on this page'); + return; + } + + // Measure layout shifts during toggle + const layoutShifts = await page.evaluate(() => { + return new Promise((resolve) => { + let cumulativeShift = 0; + const observer = new PerformanceObserver((list) => { + for (const entry of list.getEntries()) { + if (entry.entryType === 'layout-shift') { + // Check for user input using the PerformanceEntry properties + const hasRecentInput = 'hadRecentInput' in entry ? (entry as Record).hadRecentInput : false; + if (!hasRecentInput) { + const value = 'value' in entry ? (entry as Record).value as number : 0; + cumulativeShift += value; + } + } + } + }); + observer.observe({ type: 'layout-shift', buffered: true }); + + setTimeout(() => { + observer.disconnect(); + resolve(cumulativeShift); + }, 1000); + }); + }); + + // Trigger sidebar toggle + await trigger.click(); + + // Wait for transition to complete before checking layout shifts + await page.evaluate(() => + new Promise((resolve) => { + const sidebarEl = document.querySelector('[data-sidebar="sidebar"]'); + if (!sidebarEl) { + resolve(); + return; + } + const handler = () => { + sidebarEl.removeEventListener('transitionend', handler); + resolve(); + }; + sidebarEl.addEventListener('transitionend', handler); + // Fallback timeout + setTimeout(() => { + sidebarEl.removeEventListener('transitionend', handler); + resolve(); + }, 500); + }) + ); + + // Layout shift score should be 0 or very close to 0 + // Good: < 0.1, Needs improvement: 0.1-0.25, Poor: > 0.25 + expect(layoutShifts).toBeLessThan(0.1); + }); +}); diff --git a/tsconfig copy.json b/tsconfig copy.json deleted file mode 100644 index 129b1a3..0000000 --- a/tsconfig copy.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "files": [], - "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } - ], - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - }, - "noImplicitAny": false, - "noUnusedParameters": false, - "skipLibCheck": true, - "allowJs": true, - "noUnusedLocals": false, - "strictNullChecks": false - } -} diff --git a/tsconfig.app copy.json b/tsconfig.app copy.json deleted file mode 100644 index f175f32..0000000 --- a/tsconfig.app copy.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - "resolveJsonModule": true, - - /* Linting */ - "strict": false, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noImplicitAny": false, - "noFallthroughCasesInSwitch": false, - - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - } - }, - "include": ["src"] -} From 5b63b953d5fd95d35d4638b8386ad4091ebe0a7d Mon Sep 17 00:00:00 2001 From: Marcelo Santos Date: Sat, 15 Nov 2025 22:03:56 +0000 Subject: [PATCH 6/7] feat: add loyalty program content for multiple languages and enhance eventos section with hero details --- src/content/en/eventos.json | 4 +- src/content/en/fidelidade.json | 14 +++++++ src/content/en/home.json | 14 +++++++ src/content/es/eventos.json | 74 +++++++++++++++++++++++++++++++++- src/content/es/fidelidade.json | 14 +++++++ src/content/fr/eventos.json | 4 +- src/content/fr/fidelidade.json | 14 +++++++ src/content/pt/eventos.json | 37 ++++++++--------- src/content/pt/fidelidade.json | 14 +++++++ 9 files changed, 164 insertions(+), 25 deletions(-) create mode 100644 src/content/en/fidelidade.json create mode 100644 src/content/es/fidelidade.json create mode 100644 src/content/fr/fidelidade.json create mode 100644 src/content/pt/fidelidade.json diff --git a/src/content/en/eventos.json b/src/content/en/eventos.json index e61ed21..ed8bd04 100644 --- a/src/content/en/eventos.json +++ b/src/content/en/eventos.json @@ -1,8 +1,8 @@ { "archived": true, "redirect": "/gestao-estoque", - "note": "This page was removed — see /gestao-estoque for inventory & operations features." -} + "note": "This page was removed — see /gestao-estoque for inventory & operations features.", + "hero": { "title": "Flawless events from kickoff to encore", "subtitle": "Manage reservations, production, and team communication through a collaborative visual board.", "cta": { diff --git a/src/content/en/fidelidade.json b/src/content/en/fidelidade.json new file mode 100644 index 0000000..12d3170 --- /dev/null +++ b/src/content/en/fidelidade.json @@ -0,0 +1,14 @@ +{ + "seo": { + "title": "Loyalty | Boteco Pro", + "description": "Create loyalty programs that keep guests coming back with simple rules and automation." + }, + "hero": { + "title": "Loyalty that drives repeat business", + "subtitle": "Points, cashback, and tier rules with automated notifications.", + "cta": { + "label": "Discover loyalty", + "href": "/contact" + } + } +} diff --git a/src/content/en/home.json b/src/content/en/home.json index c050610..65c25c0 100644 --- a/src/content/en/home.json +++ b/src/content/en/home.json @@ -6,6 +6,20 @@ "demoCta": "Try the demo", "demoCtaAria": "Try the Boteco Pro demo (opens in a new tab)" }, + "features": [ + { + "title": "Omnichannel Digital Menu", + "description": "Update your menu in real time and offer inclusive QR Code experiences." + }, + { + "title": "Smart Purchasing", + "description": "Centralize suppliers, contracts, and deliveries with automated alerts." + }, + { + "title": "Stock, Orders & Sales Management", + "description": "Control inventory, stock movements and sales records with automatic updates." + } + ], "faq": [ { "question": "Can I manage suppliers and operations together?", diff --git a/src/content/es/eventos.json b/src/content/es/eventos.json index 24d0246..c4bd4ed 100644 --- a/src/content/es/eventos.json +++ b/src/content/es/eventos.json @@ -1,8 +1,80 @@ { "archived": true, "redirect": "/gestao-estoque", - "note": "Este contenido fue eliminado — consulte /gestao-estoque para inventario y operaciones." + "note": "Este contenido fue eliminado — consulte /gestao-estoque para inventario y operaciones.", + "hero": { + "title": "Eventos impecables de principio a fin", + "subtitle": "Controla reservas, producción y comunicación del equipo en un tablero visual colaborativo.", + "cta": { + "label": "Planificar evento", + "href": "/contacto" + } + }, + "benefits": { + "title": "Organización total para festivales, shows y activaciones", + "items": [ + { + "title": "Agenda inteligente", + "description": "Sincroniza reservas, montaje y desmontaje con vistas por equipo y proveedor." + }, + { + "title": "Checklist colaborativo", + "description": "Asigna tareas con responsables, plazos y archivos compartidos en tiempo real." + }, + { + "title": "Reporte post-evento", + "description": "Registra feedback, ventas y costos para repetir lo que funciona y corregir rápido." + } + ] + }, + "workflow": { + "title": "Del convite a la fidelización", + "steps": [ + { + "title": "Diseña la experiencia", + "description": "Crea cronogramas, mapas de mesas y playlists en un espacio visual." + }, + { + "title": "Coordina la operación", + "description": "Asigna responsables, notifica socios y sigue el estado con dashboards en vivo." + }, + { + "title": "Analiza resultados", + "description": "Compara ticket promedio, ocupación y satisfacción para el próximo evento." + } + ] + }, + "highlights": { + "title": "Recursos para eventos memorables", + "items": [ + { + "title": "Reservas integradas", + "description": "Bloques conectados al menú digital para vender combos anticipados." + }, + { + "title": "Comunicación con invitados", + "description": "Envía invitaciones personalizadas, confirmaciones y recordatorios automáticos." + }, + { + "title": "Dashboard en tiempo real", + "description": "Monitorea consumo, filas y feedback instantáneo para ajustar sobre la marcha." + } + ] + }, + "cta": { + "title": "Encanta cada evento con precisión", + "description": "Simplifica la producción y entrega experiencias inolvidables.", + "button": { + "label": "Diseñar cronograma", + "href": "/contacto" + } + } } +{ + "archived": true, + "redirect": "/gestao-estoque", + "note": "Este contenido fue eliminado — consulte /gestao-estoque para inventario y operaciones.", + "hero": { "title": "Eventos impecables de principio a fin", "subtitle": "Controla reservas, producción y comunicación del equipo en un tablero visual colaborativo.", "cta": { diff --git a/src/content/es/fidelidade.json b/src/content/es/fidelidade.json new file mode 100644 index 0000000..0ad3f9b --- /dev/null +++ b/src/content/es/fidelidade.json @@ -0,0 +1,14 @@ +{ + "seo": { + "title": "Fidelidad | Boteco Pro", + "description": "Crea programas de fidelidad que retienen clientes con reglas sencillas y automatizaciones." + }, + "hero": { + "title": "Fidelidad que genera recurrencia", + "subtitle": "Puntos, cashback y reglas por nivel con notificaciones automáticas.", + "cta": { + "label": "Conocer fidelidad", + "href": "/contacto" + } + } +} diff --git a/src/content/fr/eventos.json b/src/content/fr/eventos.json index fbad851..192c3bb 100644 --- a/src/content/fr/eventos.json +++ b/src/content/fr/eventos.json @@ -1,8 +1,8 @@ { "archived": true, "redirect": "/gestao-estoque", - "note": "Ce contenu a été supprimé — voir /gestao-estoque pour inventaire et opérations." -} + "note": "Ce contenu a été supprimé — voir /gestao-estoque pour inventaire et opérations.", + "hero": { "title": "Des événements impeccables du brief au débrief", "subtitle": "Gérez réservations, production et communication d'équipe via un tableau visuel collaboratif.", "cta": { diff --git a/src/content/fr/fidelidade.json b/src/content/fr/fidelidade.json new file mode 100644 index 0000000..1d8259f --- /dev/null +++ b/src/content/fr/fidelidade.json @@ -0,0 +1,14 @@ +{ + "seo": { + "title": "Fidélité | Boteco Pro", + "description": "Créez des programmes de fidélité qui font revenir les clients avec des règles simples et des automatisations." + }, + "hero": { + "title": "Fidélité qui génère du retour", + "subtitle": "Points, cashback et règles de niveau avec notifications automatisées.", + "cta": { + "label": "Découvrir la fidélité", + "href": "/contact" + } + } +} diff --git a/src/content/pt/eventos.json b/src/content/pt/eventos.json index bb584d8..d098920 100644 --- a/src/content/pt/eventos.json +++ b/src/content/pt/eventos.json @@ -11,26 +11,23 @@ "href": "/contato" } }, - { - "archived": true, - "redirect": "/gestao-estoque", - "note": "Funcionalidade de eventos foi removida — veja /gestao-estoque para operações e gestão de stock." - } - "items": [ - { - "title": "Reservas integradas", - "description": "Blocos específicos conectados ao menu digital para venda antecipada de combos." - }, - { - "title": "Comunicação com convidados", - "description": "Envie convites personalizados, confirmações e lembretes automatizados." - }, - { - "title": "Dashboard em tempo real", - "description": "Monitore consumo, filas e feedback instantâneo para ajustar durante o evento." - } - ] - }, + "archived": true, + "redirect": "/gestao-estoque", + "note": "Funcionalidade de eventos foi removida — veja /gestao-estoque para operações e gestão de stock.", + "items": [ + { + "title": "Reservas integradas", + "description": "Blocos específicos conectados ao menu digital para venda antecipada de combos." + }, + { + "title": "Comunicação com convidados", + "description": "Envie convites personalizados, confirmações e lembretes automatizados." + }, + { + "title": "Dashboard em tempo real", + "description": "Monitore consumo, filas e feedback instantâneo para ajustar durante o evento." + } + ], "cta": { "title": "Encante cada evento com precisão", "description": "Simplifique a produção e entregue experiências inesquecíveis.", diff --git a/src/content/pt/fidelidade.json b/src/content/pt/fidelidade.json new file mode 100644 index 0000000..2b0d8e9 --- /dev/null +++ b/src/content/pt/fidelidade.json @@ -0,0 +1,14 @@ +{ + "seo": { + "title": "Fidelidade | Boteco Pro", + "description": "Crie programas de fidelidade que mantêm clientes voltando com regras simples e automações." + }, + "hero": { + "title": "Fidelidade que gera retorno", + "subtitle": "Pontos, cashback e regras por perfil com notificações automáticas.", + "cta": { + "label": "Conhecer fidelidade", + "href": "/contato" + } + } +} From 272abd8ca4c82d09729dc7d9921dc73323f83d30 Mon Sep 17 00:00:00 2001 From: Marcelo Santos Date: Sat, 15 Nov 2025 22:21:06 +0000 Subject: [PATCH 7/7] refactor: archive loyalty content and remove eventos feature; update related data structures --- AGENTS.md | 1 + public/data/contact-requests.json | 6 +++--- src/content/en/fidelidade.json | 14 +++++--------- src/content/es/fidelidade.json | 15 +++------------ src/content/fr/fidelidade.json | 14 +++++--------- src/content/pt/fidelidade.json | 14 +++++--------- src/i18n.ts | 18 ------------------ src/pages/Eventos.tsx | 11 +++++------ 8 files changed, 27 insertions(+), 66 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 976546f..3c85086 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -78,6 +78,7 @@ Pre-built marketing components from @react-bits registry: - **`BlogPost.tsx`** - Individual blog post - **`Painel.tsx`** - Dashboard (auth-protected if Clerk enabled) - **Solution Pages**: `MenuDigital.tsx`, `Fornecedores.tsx`, `Fidelidade.tsx`, `Eventos.tsx`, `Integracoes.tsx` +- **Solution Pages**: `MenuDigital.tsx`, `Fornecedores.tsx`, `Integracoes.tsx` - **Legal**: `legal/PrivacyPolicy.tsx`, `legal/TermsOfService.tsx` - **`NotFound.tsx`** - 404 page diff --git a/public/data/contact-requests.json b/public/data/contact-requests.json index 7c113ab..02bd75b 100644 --- a/public/data/contact-requests.json +++ b/public/data/contact-requests.json @@ -22,7 +22,7 @@ "status": "contacted", "createdAt": "2025-01-09T18:12:00.000Z", "respondedAt": "2025-01-10T09:40:00.000Z", - "tags": ["fidelidade"], + "tags": [], "estimatedValue": 540 }, { @@ -30,12 +30,12 @@ "name": "Ana Paula Souza", "email": "ana.souza@example.com", "phone": "+55 31 98765-0987", - "message": "Tenho interesse em automatizar o fluxo de eventos e reservas.", + "message": "Tenho interesse em automatizar o fluxo de reservas e operações.", "channel": "referral", "status": "qualified", "createdAt": "2025-01-06T12:45:00.000Z", "respondedAt": "2025-01-06T13:30:00.000Z", - "tags": ["eventos", "automacao"], + "tags": ["automacao"], "estimatedValue": 1120 }, { diff --git a/src/content/en/fidelidade.json b/src/content/en/fidelidade.json index 12d3170..a0e870e 100644 --- a/src/content/en/fidelidade.json +++ b/src/content/en/fidelidade.json @@ -2,13 +2,9 @@ "seo": { "title": "Loyalty | Boteco Pro", "description": "Create loyalty programs that keep guests coming back with simple rules and automation." - }, - "hero": { - "title": "Loyalty that drives repeat business", - "subtitle": "Points, cashback, and tier rules with automated notifications.", - "cta": { - "label": "Discover loyalty", - "href": "/contact" - } + { + "archived": true, + "note": "This content was removed — archived by code cleanup.", + "redirect": "/" } -} + "label": "Discover loyalty", diff --git a/src/content/es/fidelidade.json b/src/content/es/fidelidade.json index 0ad3f9b..f677ed2 100644 --- a/src/content/es/fidelidade.json +++ b/src/content/es/fidelidade.json @@ -1,14 +1,5 @@ { - "seo": { - "title": "Fidelidad | Boteco Pro", - "description": "Crea programas de fidelidad que retienen clientes con reglas sencillas y automatizaciones." - }, - "hero": { - "title": "Fidelidad que genera recurrencia", - "subtitle": "Puntos, cashback y reglas por nivel con notificaciones automáticas.", - "cta": { - "label": "Conocer fidelidad", - "href": "/contacto" - } - } + "archived": true, + "note": "Este contenido fue eliminado — archivado por limpieza de código.", + "redirect": "/" } diff --git a/src/content/fr/fidelidade.json b/src/content/fr/fidelidade.json index 1d8259f..1b83c6a 100644 --- a/src/content/fr/fidelidade.json +++ b/src/content/fr/fidelidade.json @@ -2,13 +2,9 @@ "seo": { "title": "Fidélité | Boteco Pro", "description": "Créez des programmes de fidélité qui font revenir les clients avec des règles simples et des automatisations." - }, - "hero": { - "title": "Fidélité qui génère du retour", - "subtitle": "Points, cashback et règles de niveau avec notifications automatisées.", - "cta": { - "label": "Découvrir la fidélité", - "href": "/contact" - } + { + "archived": true, + "note": "Ce contenu a été supprimé — archivé lors du nettoyage du code.", + "redirect": "/" } -} + "label": "Découvrir la fidélité", diff --git a/src/content/pt/fidelidade.json b/src/content/pt/fidelidade.json index 2b0d8e9..0cbb705 100644 --- a/src/content/pt/fidelidade.json +++ b/src/content/pt/fidelidade.json @@ -2,13 +2,9 @@ "seo": { "title": "Fidelidade | Boteco Pro", "description": "Crie programas de fidelidade que mantêm clientes voltando com regras simples e automações." - }, - "hero": { - "title": "Fidelidade que gera retorno", - "subtitle": "Pontos, cashback e regras por perfil com notificações automáticas.", - "cta": { - "label": "Conhecer fidelidade", - "href": "/contato" - } + { + "archived": true, + "note": "This content was removed — archived by code cleanup.", + "redirect": "/" } -} + "label": "Conhecer fidelidade", diff --git a/src/i18n.ts b/src/i18n.ts index d59c93c..2e59816 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -12,8 +12,6 @@ import ptTerms from './content/pt/legal/terms.json'; import ptPainel from './content/pt/painel.json'; import ptMenuDigital from './content/pt/menu-digital.json'; import ptFornecedores from './content/pt/fornecedores.json'; -import ptFidelidade from './content/pt/fidelidade.json'; -import ptEventos from './content/pt/eventos.json'; import ptIntegracoes from './content/pt/integracoes.json'; import ptCommon from './content/pt/common.json'; @@ -26,8 +24,6 @@ import enTerms from './content/en/legal/terms.json'; import enPainel from './content/en/painel.json'; import enMenuDigital from './content/en/menu-digital.json'; import enFornecedores from './content/en/fornecedores.json'; -import enFidelidade from './content/en/fidelidade.json'; -import enEventos from './content/en/eventos.json'; import enIntegracoes from './content/en/integracoes.json'; import enCommon from './content/en/common.json'; @@ -40,8 +36,6 @@ import esTerms from './content/es/legal/terms.json'; import esPainel from './content/es/painel.json'; import esMenuDigital from './content/es/menu-digital.json'; import esFornecedores from './content/es/fornecedores.json'; -import esFidelidade from './content/es/fidelidade.json'; -import esEventos from './content/es/eventos.json'; import esIntegracoes from './content/es/integracoes.json'; import esCommon from './content/es/common.json'; @@ -54,8 +48,6 @@ import frTerms from './content/fr/legal/terms.json'; import frPainel from './content/fr/painel.json'; import frMenuDigital from './content/fr/menu-digital.json'; import frFornecedores from './content/fr/fornecedores.json'; -import frFidelidade from './content/fr/fidelidade.json'; -import frEventos from './content/fr/eventos.json'; import frIntegracoes from './content/fr/integracoes.json'; import frCommon from './content/fr/common.json'; @@ -70,8 +62,6 @@ const resources = { painel: ptPainel, 'menu-digital': ptMenuDigital, fornecedores: ptFornecedores, - fidelidade: ptFidelidade, - eventos: ptEventos, integracoes: ptIntegracoes, common: ptCommon, }, @@ -85,8 +75,6 @@ const resources = { painel: enPainel, 'menu-digital': enMenuDigital, fornecedores: enFornecedores, - fidelidade: enFidelidade, - eventos: enEventos, integracoes: enIntegracoes, common: enCommon, }, @@ -100,8 +88,6 @@ const resources = { painel: esPainel, 'menu-digital': esMenuDigital, fornecedores: esFornecedores, - fidelidade: esFidelidade, - eventos: esEventos, integracoes: esIntegracoes, common: esCommon, }, @@ -115,8 +101,6 @@ const resources = { painel: frPainel, 'menu-digital': frMenuDigital, fornecedores: frFornecedores, - fidelidade: frFidelidade, - eventos: frEventos, integracoes: frIntegracoes, common: frCommon, }, @@ -142,8 +126,6 @@ i18n 'painel', 'menu-digital', 'fornecedores', - 'fidelidade', - 'eventos', 'integracoes', 'common', ], diff --git a/src/pages/Eventos.tsx b/src/pages/Eventos.tsx index b654c2f..42de5c2 100644 --- a/src/pages/Eventos.tsx +++ b/src/pages/Eventos.tsx @@ -1,10 +1,9 @@ +// This page was removed as part of the cleanup that deleted the "eventos" feature. +// Kept as a harmless placeholder to avoid accidental import failures during the transition. import React from 'react'; -import { useParams, Navigate } from 'react-router-dom'; -const Eventos: React.FC = () => { - const { locale } = useParams(); - const target = `/${locale ?? 'pt'}/gestao-estoque`; - return ; +const EventosRemoved: React.FC = () => { + return null; }; -export default Eventos; +export default EventosRemoved;