refactor: Migra todos los widgets nacionales a CSS Modules para encapsular estilos
Esta refactorización modifica la forma en que los widgets manejan sus estilos para prevenir conflictos con los CSS de los sitios anfitriones donde se incrustan. Se ha migrado el sistema de estilos de CSS global a CSS Modules para todos los componentes principales y sus hijos, asegurando que todas las clases sean únicas y estén aisladas. Cambios principales: - Se actualizan los componentes .tsx para importar y usar los módulos de estilos (`import styles from ...`). - Se renombran los archivos `.css` a `.module.css`. - Se añade una regla en cada módulo para proteger la `font-family` y el `box-sizing` del widget, evitando que sean sobreescritos por estilos externos. - Se ajustan los selectores para librerías de terceros (react-select, react-simple-maps) usando `:global()` para mantener la compatibilidad. - Se mueven las variables CSS de `:root` a las clases principales de cada widget para evitar colisiones en el scope global. Como resultado, los widgets (`HomeCarouselWidget`, `PanelNacionalWidget`, `ResultadosNacionalesCardsWidget`, `CongresoNacionalWidget`) son ahora más robustos, portátiles y visualmente consistentes en cualquier entorno.
This commit is contained in:
		| @@ -1,3 +1,4 @@ | ||||
| // src/features/legislativas/nacionales/components/MapaNacional.tsx | ||||
| import axios from 'axios'; | ||||
| import { Suspense, useState, useEffect, useCallback, useRef } from 'react'; | ||||
| import { useSuspenseQuery } from '@tanstack/react-query'; | ||||
| @@ -12,6 +13,8 @@ import { CabaLupa } from './CabaLupa'; | ||||
| import { BiZoomIn, BiZoomOut } from "react-icons/bi"; | ||||
| import toast from 'react-hot-toast'; | ||||
| import { useMediaQuery } from '../hooks/useMediaQuery'; | ||||
| // 1. Importamos el archivo de estilos como un módulo CSS | ||||
| import styles from '../PanelNacional.module.css'; | ||||
|  | ||||
| const DEFAULT_MAP_COLOR = '#E0E0E0'; | ||||
| const FADED_BACKGROUND_COLOR = '#F0F0F0'; | ||||
| @@ -52,7 +55,6 @@ interface MapaNacionalProps { | ||||
|   isMobileView: boolean; | ||||
| } | ||||
|  | ||||
| // --- CONFIGURACIONES DEL MAPA --- | ||||
| const desktopProjectionConfig = { scale: 700, center: [-65, -40] as [number, number] }; | ||||
| const mobileProjectionConfig = { scale: 1000, center: [-64, -43] as [number, number] }; | ||||
| const mobileSmallProjectionConfig = { scale: 750, center: [-64, -45] as [number, number] }; | ||||
| @@ -123,7 +125,6 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom | ||||
|     } | ||||
|   }, [nivel, nombreAmbito, geoDataNacional, isMobileView, isMobileSmall]); | ||||
|  | ||||
|  | ||||
|   const resultadosNacionalesPorNombre = new Map<string, ResultadoMapaDto>(mapaDataNacional.map(d => [normalizarTexto(d.ambitoNombre), d])); | ||||
|   const nombreMunicipioSeleccionado = nivel === 'municipio' ? nombreAmbito : null; | ||||
|   const handleCalculatedCenter = useCallback((center: PointTuple, zoom: number) => { setPosition({ center, zoom }); }, []); | ||||
| @@ -235,30 +236,31 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom | ||||
|   const isZoomOutDisabled = | ||||
|     (nivel === 'provincia' && initialProvincePositionRef.current && position.zoom <= initialProvincePositionRef.current.zoom) || | ||||
|     (nivel === 'pais' && position.zoom <= (isMobileView ? 1.4 : 1.05)); | ||||
|  | ||||
|   const mapContainerClasses = panEnabled ? 'mapa-componente-container map-pannable' : 'mapa-componente-container map-locked'; | ||||
|      | ||||
|   // 2. Todas las props 'className' ahora usan el objeto 'styles' | ||||
|   const mapContainerClasses = `${styles.mapaComponenteContainer} ${panEnabled ? styles.mapPannable : styles.mapLocked}`; | ||||
|  | ||||
|   return ( | ||||
|     <div className={mapContainerClasses} ref={containerRef}> | ||||
|       {showZoomControls && ( | ||||
|         <div className="zoom-controls-container"> | ||||
|           <button onClick={handleZoomIn} className="zoom-btn" title="Acercar"> | ||||
|             <span className="zoom-icon-wrapper"><BiZoomIn /></span> | ||||
|         <div className={styles.zoomControlsContainer}> | ||||
|           <button onClick={handleZoomIn} className={styles.zoomBtn} title="Acercar"> | ||||
|             <span className={styles.zoomIconWrapper}><BiZoomIn /></span> | ||||
|           </button> | ||||
|           <button | ||||
|             onClick={handleZoomOut} | ||||
|             className={`zoom-btn ${isZoomOutDisabled ? 'disabled' : ''}`} | ||||
|             className={`${styles.zoomBtn} ${isZoomOutDisabled ? styles.disabled : ''}`} | ||||
|             title="Alejar" | ||||
|             disabled={isZoomOutDisabled} | ||||
|           > | ||||
|             <span className="zoom-icon-wrapper"><BiZoomOut /></span> | ||||
|             <span className={styles.zoomIconWrapper}><BiZoomOut /></span> | ||||
|           </button> | ||||
|         </div> | ||||
|       )} | ||||
|  | ||||
|       {nivel !== 'pais' && <button onClick={onVolver} className="mapa-volver-btn">← Volver</button>} | ||||
|       {nivel !== 'pais' && <button onClick={onVolver} className={styles.mapaVolverBtn}>← Volver</button>} | ||||
|  | ||||
|       <div className="mapa-render-area"> | ||||
|       <div className={styles.mapaRenderArea}> | ||||
|         <ComposableMap | ||||
|           projection="geoMercator" | ||||
|           projectionConfig={isMobileSmall ? mobileSmallProjectionConfig : (isMobileView ? mobileProjectionConfig : desktopProjectionConfig)} | ||||
| @@ -270,7 +272,7 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom | ||||
|             onMoveStart={() => setIsPanning(true)} | ||||
|             onMoveEnd={handleMoveEnd} | ||||
|             filterZoomEvent={filterInteractionEvents} | ||||
|             className={isPanning ? 'panning' : ''} | ||||
|             className={isPanning ? styles.panning : ''} | ||||
|           > | ||||
|             <Geographies geography={geoDataNacional}> | ||||
|               {({ geographies }: { geographies: AmbitoGeography[] }) => geographies.map((geo) => { | ||||
| @@ -284,6 +286,8 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom | ||||
|                     key={geo.rsmKey} | ||||
|                     geography={geo} | ||||
|                     ref={esCABA ? cabaPathRef : undefined} | ||||
|                     // 3. Las clases de react-simple-maps ahora deben ser globales o no funcionarán | ||||
|                     // Como el CSS module ya las define con :global(), no necesitamos hacer nada aquí. | ||||
|                     className={`rsm-geography ${nivel !== 'pais' ? 'rsm-geography-faded' : ''}`} | ||||
|                     style={{ visibility: esCABA ? 'hidden' : (esProvinciaActiva ? 'hidden' : 'visible') }} | ||||
|                     fill={nivel === 'pais' ? (resultado?.colorGanador || DEFAULT_MAP_COLOR) : FADED_BACKGROUND_COLOR} | ||||
| @@ -314,7 +318,7 @@ export const MapaNacional = ({ eleccionId, categoriaId, nivel, nombreAmbito, nom | ||||
|       </div> | ||||
|  | ||||
|       {nivel === 'pais' && ( | ||||
|         <div id="caba-lupa-anchor" className="caba-magnifier-container" style={lupaStyle} ref={lupaRef}> | ||||
|         <div id="caba-lupa-anchor" className={styles.cabaMagnifierContainer} style={lupaStyle} ref={lupaRef}> | ||||
|           {(() => { | ||||
|             const resultadoCABA = resultadosNacionalesPorNombre.get("CIUDAD AUTONOMA DE BUENOS AIRES"); | ||||
|             const fillColor = resultadoCABA?.colorGanador || DEFAULT_MAP_COLOR; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user