Skip to content

Commit 4950957

Browse files
committed
update instalation.ts with dateRangeOptions
1 parent 42ab211 commit 4950957

2 files changed

Lines changed: 37 additions & 18 deletions

File tree

CLAUDE.md

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,36 @@
11
# CLAUDE.md
22

3+
> **Regla para Claude: mantén este archivo al día.** Tras cualquier cambio relevante en el repo (rename de componentes/carpetas, cambios de selector o de API pública, nuevas demos, scripts, gotchas descubiertos, etc.), actualiza este `CLAUDE.md` en la misma tarea — no esperes a que el usuario lo pida explícitamente. Si detectas que algo aquí ya no coincide con el código (como pasó con el rename `date-picker``date-range-picker`), corrígelo de inmediato.
4+
35
Contexto para trabajar en este repo. Es un workspace de Angular con dos proyectos:
46

57
- **`date-range-picker`** (`src/app`) — la landing page/showcase de la librería. No es un producto real, no tiene backend.
6-
- **`@some-angular-utils/date-range-picker`** (`projects/some-angular-utils/date-picker`) — la librería Angular publicable de verdad (el componente `<date-range-input>`). El nombre de la carpeta en disco (`date-picker`) no coincide con el nombre del paquete publicado (`date-range-picker`) — es intencional, no lo renombres para "que coincida".
8+
- **`@some-angular-utils/date-range-picker`** (`projects/some-angular-utils/date-range-picker`) — la librería Angular publicable de verdad. El componente se selecciona como `<sau-date-range-picker>` y su clase TypeScript se llama, algo confusamente, `SAUDateRangePickerModule` (es un `@Component`, no un `NgModule`el sufijo "Module" es solo el nombre de la clase, no refleja su naturaleza).
79

810
Este repo es hermano de `c:\Users\ADMINISTRATOR\Desktop\table` (la librería `@some-angular-utils/table`) — ambas landing pages siguen exactamente el mismo patrón (mismo navbar/hero/features/demos/installation/footer, mismo mini editor de código). Si cambias algo estructural aquí, probablemente también aplique allí, y viceversa.
911

10-
Este repo es además una evolución de lo que antes era `@some-angular-utils/filter`: la librería original era un formulario de filtros genérico y configurable (`sau-filter`, con `custom-input`/`custom-select`/`date-range-input` como subcomponentes). Se hizo un pivote completo para publicar únicamente el `date-range-input` como librería independiente — `filter.ts`/`filter.html`/`filter.scss` y `custom-input`/`custom-select` se eliminaron porque solo los usaba el `sau-filter` original. Si encuentras referencias sueltas a "filter" en código, lockfiles o `dist/` antiguo que no se mencionen en este documento, son resquicios de esa migración, no parte del diseño actual.
12+
Este repo es además una evolución de lo que antes era `@some-angular-utils/filter`: la librería original era un formulario de filtros genérico y configurable (`sau-filter`, con `custom-input`/`custom-select`/`date-range-input` como subcomponentes). Se hizo un pivote completo para publicar únicamente el selector de rango de fechas como librería independiente — `filter.ts`/`filter.html`/`filter.scss` y `custom-input`/`custom-select` se eliminaron porque solo los usaba el `sau-filter` original. Si encuentras referencias sueltas a "filter" en código, lockfiles o `dist/` antiguo (p. ej. `dist/some-angular-utils/filter`, `dist/some-angular-utils/selector`) que no se mencionen en este documento, son resquicios de esa migración, no parte del diseño actual.
13+
14+
## ⚠️ El componente se llamaba `date-range-input` — ya no
15+
16+
La librería pasó por un rename que dejó residuos. El componente actual (`SAUDateRangePickerModule`, selector `sau-date-range-picker`, archivo `date-range-picker.component.ts`) antes se llamaba `DateRangeInputComponent` con selector `<date-range-input>`, y vivía en `projects/some-angular-utils/date-picker/.../components/date-range-input/`. El nombre de carpeta del proyecto Angular pasó de `date-picker` a `date-range-picker` (ahora sí coincide con el nombre del paquete npm), y la clase pasó de `date-range-input` a `date-range-picker`. Pero el rename quedó **incompleto**:
17+
18+
- `angular.json` (target de librería, líneas ~67-90) y `tsconfig.json` (`references`) todavía apuntan a `projects/some-angular-utils/date-picker/...`, una ruta que **ya no existe en disco** (ahora es `projects/some-angular-utils/date-range-picker/...`). El build real (`npm run build:lib`) no pasa por ahí — invoca `ng-packagr` directamente sobre `projects/some-angular-utils/date-range-picker/ng-package.json` — así que el build funciona a pesar de la referencia rota, pero cualquier tooling que sí use esas referencias (IDE, `ng test` del proyecto librería, etc.) puede fallar o resolver mal.
19+
- `src/app/components/installation/installation.ts` (snippet de uso) y `src/app/components/demos/demos.html` (texto de la sección "See it in action") todavía muestran/mencionan `<date-range-input>` y `DateRangeInputComponent` en vez del nombre real `<sau-date-range-picker>` / `SAUDateRangePickerModule`. Es texto de la showcase desactualizado, no refleja cómo se usa la librería realmente — si tocas esos archivos, vale la pena corregirlo de paso.
20+
21+
Si vuelves a encontrar `date-range-input`/`DateRangeInputComponent` en algún sitio no listado arriba, asume que es otro resquicio del mismo rename incompleto, no una API alternativa vigente.
1122

1223
## Árbol del código
1324

1425
```
1526
date-input/
1627
├── CLAUDE.md
1728
├── README.md
18-
├── angular.json
29+
├── angular.json # ⚠️ el target de librería referencia la ruta vieja "date-picker" (ver arriba)
1930
├── package.json
2031
├── .postcssrc.json # Tailwind v4 vía @tailwindcss/postcss
2132
├── tsconfig.json # mapea "@some-angular-utils/date-range-picker" -> dist/some-angular-utils/date-range-picker
33+
│ # (su "references" también apunta a la ruta vieja "date-picker", ver arriba)
2234
2335
├── src/ # app showcase (proyecto "date-range-picker")
2436
│ ├── index.html
@@ -28,58 +40,64 @@ date-input/
2840
│ ├── app.ts / app.html / app.scss / app.config.ts / app.routes.ts
2941
│ └── components/
3042
│ ├── navbar/ navbar.ts — barra superior fija
31-
│ ├── hero/ hero.ts, hero.html — portada con un date-range-input de ejemplo
43+
│ ├── hero/ hero.ts, hero.html — portada con un <sau-date-range-picker> de ejemplo
3244
│ ├── features/ features.ts, features.html — grid de características
3345
│ ├── demos/ demos.ts, demos.html — "See it in action": demos editables en vivo (basic, prefilled, compact, presets, validation, theme)
3446
│ ├── code-editor/ code-editor.ts/html/scss — mini editor de código reutilizable (usado por demos)
3547
│ ├── installation/ installation.ts, installation.html — instrucciones de instalación/uso
3648
│ └── footer/ footer.ts — pie de página
3749
38-
└── projects/some-angular-utils/date-picker/ # la librería publicable (nombre de paquete: date-range-picker)
50+
└── projects/some-angular-utils/date-range-picker/ # la librería publicable (nombre de paquete: date-range-picker)
3951
└── src/
40-
├── public-api.ts # exports públicos del paquete npm (solo DateRangeInputComponent)
52+
├── public-api.ts # exports públicos del paquete npm: SAUDateRangePickerModule + interfaz DateRangeOption
4153
└── lib/
42-
└── components/
43-
└── date-range-input/ # único componente publicado: selector de rango de fechas con presets (hoy, mes actual...)
54+
├── date-range-picker.component.ts # único componente publicado, todo en un archivo plano (sin subcarpeta components/)
55+
├── date-range-picker.component.html
56+
└── date-range-picker.component.scss
4457
```
4558

4659
## El orden de build importa
4760

48-
La app importa la librería como `@some-angular-utils/date-range-picker`, que `tsconfig.json` mapea a `./dist/some-angular-utils/date-range-picker`**no** al código fuente. Si editas algo dentro de `projects/some-angular-utils/date-picker/src`, hay que reconstruir antes de que la app lo vea:
61+
La app importa la librería como `@some-angular-utils/date-range-picker`, que `tsconfig.json` mapea a `./dist/some-angular-utils/date-range-picker`**no** al código fuente. Si editas algo dentro de `projects/some-angular-utils/date-range-picker/src`, hay que reconstruir antes de que la app lo vea:
4962

5063
```bash
51-
npm run build:lib # ng-packagr -> dist/some-angular-utils/date-range-picker
64+
npm run build:lib # ng-packagr -p projects/some-angular-utils/date-range-picker/ng-package.json -> dist/some-angular-utils/date-range-picker
65+
npm run dev # build:lib + ng serve, en un solo comando (útil para arrancar de cero)
5266
```
5367

54-
`ng serve` (usa Vite) pre-empaqueta dependencias y **no** recoge de forma confiable un `dist/` recién construido. Después de `build:lib`, mata y reinicia `ng serve` (o borra `.angular/cache` antes) — no asumas que el hot-reload lo detectó.
68+
`ng serve` (usa Vite) pre-empaqueta dependencias y **no** recoge de forma confiable un `dist/` recién construido. Si `ng serve` ya está corriendo y vuelves a correr `build:lib` por separado, mata y reinicia `ng serve` (o borra `.angular/cache` antes) — no asumas que el hot-reload lo detectó.
5569

5670
## Storybook fue eliminado
5771

58-
Storybook (`.storybook/` en la raíz y en la librería, `src/stories/`, los targets `storybook`/`build-storybook` en `angular.json`, las dependencias `@storybook/*`, el workflow `publishStorybook.yml` y `debug-storybook.log`) se eliminó a propósito en favor de la app showcase de `src/app`. No lo reintroduzcas a menos que se pida explícitamente.
72+
Storybook (`.storybook/` en la raíz y en la librería, `src/stories/`, los targets `storybook`/`build-storybook` en `angular.json`, las dependencias `@storybook/*`, el workflow `publishStorybook.yml` y `debug-storybook.log`) se eliminó a propósito en favor de la app showcase de `src/app`. No lo reintroduzcas a menos que se pida explícitamente. (Nota: el step de `publishInGithubPages.yml` todavía se llama `"Build Storybook"` aunque solo corre `build:lib && build` — es un nombre de step desactualizado, no un retorno de Storybook.)
5973

6074
## Gotcha de especificidad CSS al teñir en vivo (distinto del proyecto `table`)
6175

6276
La demo de "Theming" inyecta un `<style>` global de forma imperativa vía `Renderer2` + `DOCUMENT` (igual que en el proyecto `table`), porque Angular extrae las etiquetas `<style>` literales de las plantillas en tiempo de compilación y nunca llegan al DOM en tiempo de ejecución.
6377

64-
Pero a diferencia de `sau-table` (que usa `ViewEncapsulation.None`), **`DateRangeInputComponent` usa encapsulación Emulated por defecto**. Eso significa que la propia regla `.sau-date-range { ... }` de la librería se compila como `.sau-date-range[_ngcontent-xxx] { ... }` — una clase + un atributo, exactamente la misma especificidad que nuestro override `.theme-live .sau-date-range` (dos clases). Con especificidad empatada, gana el orden de inserción en el `<head>`, que no es fiable (depende de cuándo Angular registra el stylesheet del componente vs. cuándo se ejecuta nuestro constructor). La solución es añadir `!important` a cada declaración generada (función `withImportant()` en `demos.ts`) — confirmado con pruebas, no es una suposición. Si se porta este patrón a otra librería, comprobar primero qué `ViewEncapsulation` usa el componente raíz antes de asumir que la especificidad por selectores basta.
78+
Pero a diferencia de `sau-table` (que usa `ViewEncapsulation.None`), **`SAUDateRangePickerModule` usa encapsulación Emulated por defecto**. Eso significa que la propia regla `.sau-date-range { ... }` de la librería se compila como `.sau-date-range[_ngcontent-xxx] { ... }` — una clase + un atributo, exactamente la misma especificidad que nuestro override `.theme-live .sau-date-range` (dos clases). Con especificidad empatada, gana el orden de inserción en el `<head>`, que no es fiable (depende de cuándo Angular registra el stylesheet del componente vs. cuándo se ejecuta nuestro constructor). La solución es añadir `!important` a cada declaración generada (función `withImportant()` en `demos.ts`) — confirmado con pruebas, no es una suposición. Si se porta este patrón a otra librería, comprobar primero qué `ViewEncapsulation` usa el componente raíz antes de asumir que la especificidad por selectores basta.
6579

66-
Las variables CSS `--sau-color-primary`/`--sau-color-background` en `date-range-input.component.scss` no existían en el componente original — se añadieron expresamente para que la demo de Theming tuviera algo que tocar, siguiendo el mismo patrón que ya usaba `sau-filter`. Solo cubren el acento principal (texto "Rango personalizado...", botón Aplicar, día inicio/fin seleccionado) — los tonos secundarios del hover dentro del calendario quedaron hardcodeados a propósito, igual que en el `sau-filter` original.
80+
Las variables CSS `--sau-color-primary`/`--sau-color-background` en `date-range-picker.component.scss` no existían en el componente original — se añadieron expresamente para que la demo de Theming tuviera algo que tocar, siguiendo el mismo patrón que ya usaba `sau-filter`. Solo cubren el acento principal (texto "Rango personalizado...", botón Aplicar, día inicio/fin seleccionado) — los tonos secundarios del hover dentro del calendario quedaron hardcodeados a propósito, igual que en el `sau-filter` original.
6781

6882
## Cómo funciona el editor de las demos en vivo (`src/app/components/demos`)
6983

70-
Mismo patrón que en el proyecto `table`: cada pestaña tiene su propio mini editor de código (`src/app/components/code-editor`) enlazado a un string de configuración (`{ label, placeholder, initialValue?, required? }`, o CSS plano en la pestaña Theming). Al editar (debounce ~600ms), el texto se evalúa con `new Function('"use strict"; return (' + texto + ');')()` — evaluado en el propio navegador del visitante, sin ida y vuelta al servidor (mismo modelo de confianza que cualquier playground de JS).
84+
Mismo patrón que en el proyecto `table`: cada pestaña tiene su propio mini editor de código (`src/app/components/code-editor`) enlazado a un string de configuración (`{ label, placeholder, initialValue?, required?, dateRangeOptions? }`, o CSS plano en la pestaña Theming). Al editar (debounce ~600ms), el texto se evalúa con `new Function('"use strict"; return (' + texto + ');')()` — evaluado en el propio navegador del visitante, sin ida y vuelta al servidor (mismo modelo de confianza que cualquier playground de JS).
85+
86+
`dateRangeOptions` (los presets del dropdown) es un `@Input` del componente — antes era una lista fija interna. La demo "Custom presets" se apoya en esto para mostrar cómo reemplazar los presets en español por una lista propia en inglés (`{ label, value, getRange }`).
7187

72-
`DateRangeInputComponent` solo lee el valor inicial de su `formControlItem` dentro del propio setter del `@Input` (no tiene `ngOnChanges`), así que reescribir el valor del mismo `FormControl` con `setValue()` no resetea lo que se ve en pantalla (el calendario no "salta" al nuevo rango). Por eso cada demo sigue usando el mismo truco que `sau-filter`: `@for (cfg of [demo.config()]; track cfg)` — trackear por la referencia del objeto fuerza a Angular a destruir y recrear `<date-range-input>` cada vez que el evaluador produce un objeto nuevo, y el `FormControl` ya tiene el valor correcto seteado (vía `applyJsConfig()`) antes de que eso ocurra.
88+
`SAUDateRangePickerModule` solo lee el valor inicial de su `formControlItem` dentro del propio setter del `@Input` (no tiene `ngOnChanges`), así que reescribir el valor del mismo `FormControl` con `setValue()` no resetea lo que se ve en pantalla (el calendario no "salta" al nuevo rango). Por eso cada demo sigue usando el mismo truco que `sau-filter`: `@for (cfg of [demo.config()]; track cfg)` — trackear por la referencia del objeto fuerza a Angular a destruir y recrear `<sau-date-range-picker>` cada vez que el evaluador produce un objeto nuevo, y el `FormControl` ya tiene el valor correcto seteado (vía `applyJsConfig()`) antes de que eso ocurra.
7389

7490
El rango seleccionado se lee a través de `control.valueChanges` hacia señales (`selectedRange`, `canSubmit`) en vez de depender de que Angular vuelva a marcar el árbol de componentes como "dirty" tras un click dentro de un hijo `OnPush` — es más explícito y no depende de cómo Angular propague la detección de cambios por eventos.
7591

7692
## El texto en español dentro de la librería es intencional, no un bug
7793

78-
Los presets del dropdown ("Hoy", "Mañana", "Hace 3 días", "Mes actual", "Próximo mes", "Año actual", "Próximo año") y los textos de la UI ("Limpiar rango", "Rango personalizado...", "Aplicar Rango", "Volver") están hardcodeados en español dentro de `date-range-input.component.ts`/`.html`. No es algo que se pueda cambiar desde `label`/`placeholder` ni desde la app showcase — es el comportamiento real del componente. No "corregir" esto en las demos para que parezca todo en inglés; mostrarlo tal cual es lo correcto.
94+
Los presets del dropdown por defecto ("Hoy", "Ayer", "Hace 3 días", "Mes actual", "Mes anterior", "Año actual", "Año anterior") y los textos de la UI ("Limpiar rango", "Rango personalizado...", "Aplicar Rango", "Volver", "Limpiar") están hardcodeados en español dentro de `date-range-picker.component.ts`/`.html`. No es algo que se pueda cambiar desde `label`/`placeholder` ni desde la app showcase — es el comportamiento real del componente. No "corregir" esto en las demos para que parezca todo en inglés; mostrarlo tal cual es lo correcto. (Los presets sí se pueden *reemplazar* por completo pasando `dateRangeOptions`, como hace la demo "Custom presets" — pero los textos fijos del resto de la UI, sí o sí en español, no.)
95+
96+
Además del dropdown de presets y el calendario de doble mes, el input principal admite edición manual: doble click sobre el texto mostrado lo vuelve editable (`isEditingMainInput`, parseo `dd/mm/yyyy - dd/mm/yyyy` vía `onDisplayInputChange`), y el footer del calendario tiene dos `<input type="date">` nativos (`onStartDateInputChange`/`onEndDateInputChange`) para teclear las fechas en vez de hacer click día por día.
7997

8098
## Convenciones de este repo (`.github/copilot-instructions.md`)
8199

82-
Este repo tiene un archivo de instrucciones para agentes de IA que sí se respetó al escribir los componentes nuevos de `src/app`: `ChangeDetectionStrategy.OnPush` en todos los componentes, `input()`/`output()`/`model()` en vez de decoradores `@Input`/`@Output` donde tiene sentido, `@if`/`@for`/`@switch` nativos en vez de `*ngIf`/`*ngFor`, sin `ngClass`/`ngStyle` (usar `[class.x]`/`[style.x]`), sin arrow functions dentro de plantillas. La librería (`projects/some-angular-utils/date-picker`) en cambio es código preexistente y NO sigue estas convenciones (usa `@Input`/`@Output`, `@HostListener`) — no es necesario migrarla solo por consistencia.
100+
Este repo tiene un archivo de instrucciones para agentes de IA que sí se respetó al escribir los componentes nuevos de `src/app`: `ChangeDetectionStrategy.OnPush` en todos los componentes, `input()`/`output()`/`model()` en vez de decoradores `@Input`/`@Output` donde tiene sentido, `@if`/`@for`/`@switch` nativos en vez de `*ngIf`/`*ngFor`, sin `ngClass`/`ngStyle` (usar `[class.x]`/`[style.x]`), sin arrow functions dentro de plantillas. La librería (`projects/some-angular-utils/date-range-picker`) en cambio es código preexistente y NO sigue estas convenciones (usa `@Input`/`@Output`, `@HostListener`) — no es necesario migrarla solo por consistencia.
83101

84102
## Tailwind v4
85103

src/app/components/installation/installation.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ constructor() {
2626
templateSnippet = `<date-range-input
2727
label="Travel dates"
2828
placeholder="Select a date range"
29+
[dateRangeOptions]="dateRangeOptions"
2930
[formControlItem]="dateRange">
3031
</date-range-input>`;
3132
}

0 commit comments

Comments
 (0)