# ACHS Webkit UI

Conjunto de componentes de UI con el estilo del Sistema de Diseño ACHS (Asociación Chilena
de Seguridad), para reutilizar de forma transversal en las aplicaciones web de ACHS.
Construido con **React 19**, **TypeScript** y **Vite**, con soporte para las tres marcas
(Salud, Seguro y Servicios) vía theming por atributo `data-theme`.

## Requisitos

- **React 19** y **React DOM 19** (declarados como `peerDependencies`).
- Un **bundler que procese imports de CSS** (Vite, webpack, Next.js, Parcel, etc.). Los
  estilos de cada componente se distribuyen como archivos CSS que se importan junto con el
  componente; esto es lo que permite el _tree-shaking_ (ver más abajo). Cualquier app React
  moderna cumple este requisito por defecto.

## Instalación

```sh
npm install @achs/webkit
# o
pnpm add @achs/webkit
```

### Dependencia opcional: antd

Los componentes **`Flex`**, **`Row`/`Col`** (Grid), **`Layout`** y **`Menu`** están
construidos sobre [Ant Design](https://ant.design/) v5. `antd` es una `peerDependency`
**opcional**: solo necesitas instalarlo si usas alguno de esos cuatro componentes.

```sh
# Solo si usas Flex / Grid / Layout / Menu
npm install antd
```

El resto de los componentes no dependen de `antd` y no lo incluirán en tu bundle.

## Uso

```tsx
import { Button } from '@achs/webkit';

const App = () => (
  <div data-theme="salud">
    <h1>Bienvenido a ACHS Webkit UI</h1>
    <Button>Haz clic aquí</Button>
  </div>
);

export default App;
```

No es necesario importar hojas de estilo manualmente: el CSS de cada componente (y la
fuente/variables de tema) se incluye automáticamente al importar el componente.

## Theming (marcas ACHS)

El tema se controla con el atributo `data-theme` en cualquier contenedor. Todos los
componentes dentro de ese contenedor heredan la paleta correspondiente:

```tsx
<div data-theme="salud">    {/* azul   */} ... </div>
<div data-theme="seguro">   {/* verde  */} ... </div>
<div data-theme="servicios">{/* morado */} ... </div>
```

Si no se define `data-theme`, se aplica el tema por defecto (verde / seguro).

### Variables CSS de tema

Estas variables generales quedan disponibles globalmente y pueden usarse en tus propias
hojas de estilo SCSS/CSS:

```
--primary-color
--secondary-color
--complementary-color
--texto-color
--light
--dark
--disabled-color
```

Los colores se definen como **componentes RGB sin la función `rgb()`** (p. ej.
`--primary-color: 39, 147, 62;`) para poder aplicar transparencias en sombras y otras
propiedades. Por eso deben usarse envueltos en `rgb()` / `rgba()`:

```scss
.mi-elemento {
  background-color: rgb(var(--primary-color));
  box-shadow: 0 2px 8px rgba(var(--secondary-color), 0.5);
}
```

También se exponen tamaños de fuente como variables: `--font-xs` … `--font-5xl`.

## Componentes disponibles

**Átomos:** `Badge`, `Button`, `Checkbox`, `CheckItem`, `Chip`, `Icon`, `ImagePlaceholder`,
`Imagotipo`, `Input`, `Label`, `LoadingDots`, `MapPlaceholder`, `ModalContent`, `RadioButton`,
`SelectNavigation`, `Switch`, `Tab`, `Tag`, `Toast`, `ToggleSwitch`, `Tooltip`, `VideoPlayer`,
`CardContent`, `CardHeader`, `CardFooter`, `CardTitle`

**Moléculas:** `Accordion`, `Alert`, `Breadcrumbs`, `CaptchaField`, `Card`, `DatePicker`,
`Drawer`, `EmptyState`, `InputField`, `Menu`¹, `ModalButtons`, `MultiSelect`, `Paginate`,
`Progress`, `RadioGroup`, `Search`, `Select`, `StatusBar`, `Stepper`

**Organismos:** `Modal`, `Slider`, `Table`

**Layout:** `Layout`¹, `Flex`¹, `Row`¹, `Col`¹

**Providers / hooks:** `NotificationProvider`, `useNotification`

¹ Requieren `antd` instalado (ver [Dependencia opcional](#dependencia-opcional-antd)).

## Tree-shaking y tamaño

El paquete se publica con módulos preservados (un archivo por componente), `sideEffects`
acotado y un `exports` map, de modo que el **JavaScript** siempre tree-shakea: importar
`Button` no arrastra el código de `antd` ni de otros componentes.

### JS vs. CSS: usa _subpath imports_ para el CSS mínimo

El CSS de cada componente se inyecta como _side-effect_ (necesario para que los estilos
lleguen sin importar hojas de estilo a mano). Por eso, el **CSS no tree-shakea a través del
barrel**: como el punto de entrada raíz importa todos los componentes, importar desde
`'@achs/webkit'` incluye el CSS de **toda** la librería (~647 KB), aunque solo uses un botón.

Para el bundle más pequeño posible, importa cada componente por su **subpath**:

```tsx
// ✅ Recomendado si te importa el tamaño: solo trae el CSS de Button (~2.7 KB)
import { Button } from '@achs/webkit/Button';
import { Alert }  from '@achs/webkit/Alert';

// ⚠️ Cómodo pero trae el CSS de toda la librería (~647 KB de CSS)
import { Button, Alert } from '@achs/webkit';
```

Ambas formas funcionan y son equivalentes en runtime; la diferencia es solo cuánto CSS
termina en tu bundle. El barrel se mantiene por comodidad y retrocompatibilidad. Los subpaths
se generan automáticamente en cada build ([`scripts/gen-exports.mjs`](scripts/gen-exports.mjs)).

> `Flex`, `Row`/`Col` (Grid) no tienen subpath propio porque son _passthrough_ de `antd`;
> impórtalos desde el barrel.

### Limitación conocida: fuente de iconos (bootstrap-icons)

Los componentes con iconos (`Alert`, `Tag`, `Icon`, etc.) importan
`bootstrap-icons/font/bootstrap-icons.css`, que trae la **fuente de iconos embebida
(~500 KB)**. Ese CSS se incluye una vez en cuanto uses **cualquier** componente con iconos,
tanto por barrel como por subpath. Mejora futura evaluada: externalizar `bootstrap-icons`
como `peerDependency` para que la app la cargue una sola vez (implica que el consumidor
importe el CSS de bootstrap-icons manualmente). Pendiente de decisión.

## Desarrollo

Requiere **Node ≥ 22.13** y **pnpm**.

```sh
pnpm install            # instalar dependencias
pnpm dev                # entorno de desarrollo (Vite)
pnpm build              # compilar la librería a dist/
pnpm size               # verificar el presupuesto de tamaño del bundle
pnpm storybook          # catálogo de componentes (Storybook)
pnpm build-storybook    # build estático del catálogo
pnpm lint               # ESLint
```

### Publicación

```sh
pnpm pub                # build + check de tamaño + npm publish --access public
```

El script `pub` ejecuta `pnpm size` como _gate_: si el bundle supera el presupuesto
(o si `antd` quedara embebido, o si las fuentes se duplicaran), la publicación se aborta.
La configuración de presupuestos está en [`scripts/check-bundle-size.mjs`](scripts/check-bundle-size.mjs).

## Contribución

- El código fuente vive en `lib/` (entry principal: `lib/main.ts`).
- Cada componente sigue el patrón `lib/components/<nivel>/<Componente>/` con su `index.tsx`,
  su `*.module.scss` y su `*.stories.tsx`. Hay plantillas en `.vscode/__templates__/`.
- Los componentes consumen las variables CSS de tema (`var(--primary-color)`, etc.); evita
  hardcodear colores de marca.
