npm package: @squareetlabs/weekly-availability-picker
Description: Angular 20+ component to pick weekly availability (time slots per day)
Author: Squareetlabs
Latest version: 1.0.0

# @squareetlabs/weekly-availability-picker

Selector de disponibilidad semanal para Angular: cuadrícula días × horas, arrastre para marcar o quitar franjas y redimensionar bloques.

**Requisitos:** Angular ^20.0.0 · Node ^20.19.0 || ^22.12.0 || ^24.0.0

---

## Instalación

```bash
npm install @squareetlabs/weekly-availability-picker
```

## Uso

Importa el componente standalone e enlaza `slots` con `slotsChange`:

```typescript
import { WeeklyAvailabilityPickerComponent, type WeekSlot } from '@squareetlabs/weekly-availability-picker';

@Component({
  imports: [WeeklyAvailabilityPickerComponent],
  // ...
})
export class MyComponent {
  slots = signal<WeekSlot[]>([]);
}
```

```html
<ngx-weekly-availability-picker
  title="Unavailability"
  [days]="['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo']"
  [slots]="slots()"
  (slotsChange)="slots.set($event)"
  [startHour]="0"
  [endHour]="24"
  [stepMinutes]="15"
/>
```

## API

### Inputs

| Input | Tipo | Default | Descripción |
|-------|------|--------|-------------|
| `title` | `string` | `'Unavailability'` | Título del bloque |
| `days` | `string[]` | Lunes..Domingo (EN) | Nombres de los 7 días (orden de filas) |
| `slots` | `WeekSlot[]` | `[]` | Franjas actuales |
| `startHour` | `number` | `0` | Hora inicial (0–23) |
| `endHour` | `number` | `24` | Hora final (1–24) |
| `stepMinutes` | `number` | `15` | Paso en minutos (5, 10, 15, 30, 60…) |
| `readonly` | `boolean` | `false` | Desactiva arrastre y edición |
| `resizeDisabled` | `boolean` | `false` | Desactiva redimensionar por bordes |
| `minSlotMinutes` | `number` | `0` | Mínimo minutos por slot (0 = `stepMinutes`) |
| `maxSlotsPerDay` | `number` | `0` | Máximo slots por día (0 = sin límite) |
| `showInfoIcon` | `boolean` | `true` | Muestra icono de ayuda (?) |
| `infoTooltip` | `string` | (texto por defecto) | Tooltip del icono |
| `showSlotRemoveButton` | `boolean` | `true` | Botón quitar franja al hover |
| `timeFormat` | `'24h' \| '12h'` | `'24h'` | Formato de hora |
| `slotLabelSeparator` | `string` | `' – '` | Separador en etiqueta del bloque |
| `ariaLabel` | `string` | (por defecto) | Aria-label del componente |
| `infoAriaLabel` | `string` | (usa `infoTooltip`) | Aria-label del icono (?) |
| `hostClass` | `string` | `''` | Clases CSS adicionales en el host |
| `validate` | `(slots: WeekSlot[]) => boolean` | — | Si devuelve `false`, no se aplica el cambio |

### Outputs

| Output | Descripción |
|--------|-------------|
| `slotsChange` | Nuevo valor de franjas (formato listo para persistir) |
| `dragStart` | Inicio de arrastre (añadir/cortar) |
| `dragEnd` | Fin de arrastre |
| `resizeEnd` | Fin de redimensionado por borde |

### Tipo `WeekSlot`

```ts
interface WeekSlot {
  day: number;        // 0–6 (índice en `days`)
  time_start: string; // "HH:mm" o "HH:mm:ss"
  time_end: string;
}
```

### Comportamiento

- **Arrastre** en una fila: crea franja o la quita si se solapa con una existente (toggle).
- **Bordes del bloque**: arrastre para redimensionar (salvo `resizeDisabled`).
- **Botón quitar** (hover sobre el bloque): elimina esa franja.
- **Escape**: cancela arrastre o resize en curso.

## Theming

Variables CSS con prefijo `--wap-`. Las que terminan en `-px` aceptan número sin unidad (ej. `32` → `32px`).

| Variable | Default |
|----------|--------|
| `--wap-font-family` | system-ui, … |
| `--wap-picker-border-color` | #d8dee6 |
| `--wap-picker-border-radius-px` | 4 |
| `--wap-picker-bg-color` | #fff |
| `--wap-picker-padding-px` | 12 |
| `--wap-title-font-size-px` | 18 |
| `--wap-title-color` | #3a4452 |
| `--wap-info-size-px` | 16 |
| `--wap-info-bg-color` | #e9eef6 |
| `--wap-info-color` | #5b6b7d |
| `--wap-days-column-width-px` | 120 |
| `--wap-hour-font-size-px` | 12 |
| `--wap-hour-color` | #8794a6 |
| `--wap-row-min-height-px` | 42 |
| `--wap-day-label-font-size-px` | 13 |
| `--wap-day-label-color` | #5b6b7d |
| `--wap-track-height-px` | 24 |
| `--wap-track-bg-color` | #f4f7fb |
| `--wap-track-border-color` | #e6ebf2 |
| `--wap-block-bg-color` | #4bb5d1 |
| `--wap-block-color` | #fff |
| `--wap-block-font-size-px` | 12 |
| `--wap-block-preview-opacity` | 0.45 |
| `--wap-resize-edge-width-px` | 8 |
| `--wap-slot-remove-size-px` | 22 |
| `--wap-slot-remove-radius-px` | 4 |
| `--wap-slot-remove-bg` | #e67e22 |
| `--wap-slot-remove-color` | #fff |
| `--wap-slot-remove-hover-bg` | #d35400 |

Ejemplo:

```css
ngx-weekly-availability-picker {
  --wap-block-bg-color: #2c5282;
  --wap-track-height-px: 32;
  --wap-title-color: #1a202c;
}
```

## Desarrollo (contribuidores)

```bash
# Build
ng build weekly-availability-picker

# Tests
ng test weekly-availability-picker

# Publicar (desde raíz del repo)
npm run build && cd dist/weekly-availability-picker && npm publish --access public
```

---

**Autor:** [Jacobo Cantorna Cigarrán](https://github.com/jcancig) · [Squareet](https://squareet.com)  
**Licencia:** MIT