From c65e9f1cbd6e5217b3815cb376abd57aefa54b4a Mon Sep 17 00:00:00 2001 From: Josep Piguillem Date: Tue, 28 Jul 2026 00:09:15 +0200 Subject: [PATCH] docs: documenta la migracion y sus cambios de comportamiento --- libs/ui/README.md | 111 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 4 deletions(-) diff --git a/libs/ui/README.md b/libs/ui/README.md index 139ffca..8f4236d 100644 --- a/libs/ui/README.md +++ b/libs/ui/README.md @@ -1,7 +1,110 @@ -# ui +# @pi/ui -This library was generated with [Nx](https://nx.dev). +Librería de componentes Angular migrada desde `monorepo-nx-ddd-demo/libs/shared` +(Angular 14, NgModules, decoradores) a Angular 22 con componentes standalone y +señales. -## Running unit tests +``` +libs/ui/src/ + index.ts barrel público de @pi/ui + lib/styles/ antes shared/styles + lib/util// antes shared/util/ (24 libs) + lib/ui// antes shared/ui/ (29 libs) +``` -Run `nx test ui` to execute the unit tests. +Construir: `nx build ui` · Lint: `nx lint ui` + +## Qué se hizo + +| | | +|---|---| +| Prefijo | `Dl`→`Pi`, `dl-`→`pi-` (selectores, clases CSS, nombres de fichero), `@deale-workspace/…`→rutas relativas | +| NgModules | 41 → 4 (sólo quedan los que aportan providers: `icon-registry`, `loaders`, `router-store`, `scroll-to`) | +| Componentes | 70, **todos** con `ChangeDetectionStrategy.OnPush` | +| Decoradores | 0 restantes: 460 `input()`, 6 `model()`, 20 `output()`, 8 `viewChild()`, 2 `viewChildren()`, 17 `contentChild()`, 6 `contentChildren()` | + +Se usaron las migraciones oficiales de Angular (`@angular/core:standalone`, +`signal-input-migration`, `output-migration`, `signal-queries-migration`) y se +resolvió a mano lo que no cubren. + +## Decisiones que cambian comportamiento + +Revisar estos puntos antes de usar la librería en producción: + +**1. `input.required` no significa lo mismo que el antiguo `!`.** +La migración convierte `@Input() x!: T` en `input.required()`, pero en +Angular 14 no existían las entradas obligatorias: el `!` sólo era una aserción +de asignación definida. Se devolvieron a opcionales las que las propias +plantillas de la librería demostraban que no eran obligatorias (`allowPropagation`, +`flexDirection`, `value` de text-viewer, `gap`/`icon`/`label` de divider, +`link`/`gap` de headline, `device`/`justify`/`itemWidth` de carousel, las de +grid-item…). **Las `input.required` que quedan endurecen la API respecto al +original**; conviene repasarlas contra el uso real en las aplicaciones. + +**2. Entradas con accessor → `input()`/`model()` + `effect()`.** +Seis entradas tenían getter/setter con efectos secundarios. El efecto se ejecuta +durante la detección de cambios, no de forma síncrona en la asignación: + +- `PiTabComponent.defaultSelectedTab` — el `onTabChange()` del setter pasa a un `effect()`. +- `PiBaseFormFieldComponent.isDisabled` — pasa a `input()`; el estado efectivo a leer sigue siendo `disabled` (lo escriben también el CVA y el efecto). +- `PiSearchFieldComponent.isExpanded` — `model()`; la emisión de `isActive` pasa a un `effect()`. +- `PiSelectOptionComponent.isSelected` — `model()` (los selects padre lo asignan sobre las instancias hijas); su `markForCheck()` manual ya no hace falta. +- `PiBaseMenuComponent.menuItems` — el setter era un pass-through puro. +- `PiSelectMultipleComponent.selectedOptions` — sólo tenía getter, así que el `@Input()` nunca pudo asignarse desde fuera: era un valor derivado. + +**3. `PiAccordionComponent.expandedItemIndex` pasa a `model()`.** +Tenía un two-way binding hecho a mano (`expandedItemIndex` + `expandedItemIndexChange`). +`model()` genera el evento automáticamente. **Ojo:** el código original emitía el +valor *anterior* al plegar/desplegar (`emit(expandedItemIndex)` antes de reasignar); +`model()` emite el nuevo. Parece que el original tenía un bug. Su tipo pasa a +`number | null` porque `toggleState` asigna `null` al colapsar. + +**4. Suscripciones a `.changes` eliminadas.** +Las signal queries no exponen `QueryList.changes`. Donde sólo se usaba para +`markForCheck()` (accordion, tab, carousel) se eliminó: Angular ya reevalúa la +plantilla al cambiar la señal. En los 4 selects se sustituyó por `toObservable()`. + +**5. Salidas que emitían `any`.** +`changePage` y `toggledTo` eran `new EventEmitter()` sin genérico. Ahora son +`output()` y `output<'on' | 'off'>()`. + +**6. Aserciones `!` en plantillas.** +`*ngIf="icon()"` no estrecha el tipo (TypeScript no estrecha resultados de +llamada entre expresiones), así que hay `[svgIcon]="icon()!"` en ~30 sitios. +Mantiene el runtime idéntico al original. Se pueden eliminar migrando a +`@if (icon(); as icon)`. + +**7. Precedencia de pipes en select-multiple.** +`x | truncate : 33 || (placeholder() | translate)` se parseaba como +`truncate : (33 || …)`, así que el fallback nunca se aplicaba. Ahora está +parentizado como se pretendía. + +## Colisiones de nombres en el barrel + +El origen tiene símbolos duplicados. En `index.ts` gana el primero y el otro se +omite (queda anotado en el fichero). Siguen siendo accesibles por ruta directa: + +| Símbolo | Se exporta desde | Se omite de | +|---|---|---| +| `PiSlideToggleComponent` | `ui/form-field` | `ui/slide-toggle` | +| `PiDisabledDirective` | `util/status` | `ui/text` | +| `featureKey`, `getFeatureState`, `initialState` | `util/device-configs` | `util/list-configs` | + +## APIs de terceros actualizadas + +- **ngx-translate 18** — no hay `TranslateModule`. `PiSharedUtilTranslateModule` → `providePiTranslate()`; en plantillas se importa `TranslatePipe`/`TranslateDirective`. +- **apollo-angular 14** — no hay `ApolloModule`. `PiSharedUtilDatoCmsModule` → `providePiDatoCms()`. +- **ngx-currency 19** — `CurrencyMaskInputMode`→`NgxCurrencyInputMode`, `NgxCurrencyModule`→`NgxCurrencyDirective`. +- **chart.js 4** — `chart.js/dist/types/utils` no es importable; los tipos se derivan de `ChartOptions`. +- **Angular** — `TransferState`/`StateKey`/`makeStateKey` vienen de `@angular/core`. + +## Pendiente + +- **Tests**: no se copiaron los `*.spec.ts` del origen. +- **`Sector`** vivía en `deale-saas/util/models` (lib de aplicación, fuera de alcance); se trajo la interfaz a `util/models`. +- **ngrx 21 con Angular 22**: instalado con `--legacy-peer-deps` (aún no declara soporte para 22). +- **Lint**: `nx lint ui` falla con avisos heredados del código original — + `prefer-control-flow` (104: `*ngIf`/`*ngFor` en vez de `@if`/`@for`), + `directive-selector` (40), `prefer-inject` (33), a11y y `no-unused-vars`. + Nada bloquea el build. Hay migraciones oficiales para los dos primeros grupos: + `nx g @angular/core:control-flow-migration` y `nx g @angular/core:inject-migration`.