@kaufmann-lab/ui 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaufmann-lab/ui",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Shared Angular component library for the Kaufmann frontends",
5
5
  "license": "MIT",
6
6
  "author": "Kaufmann Lab",
@@ -206,7 +206,7 @@ declare class Avatar {
206
206
  * no existe un `-strong` para secondary todavía — usa el color base).
207
207
  */
208
208
  declare class Badge {
209
- readonly tone: _angular_core.InputSignal<"error" | "info" | "ok" | "warn" | "neutral" | "service">;
209
+ readonly tone: _angular_core.InputSignal<"info" | "ok" | "warn" | "error" | "neutral" | "service">;
210
210
  readonly dot: _angular_core.InputSignalWithTransform<boolean, unknown>;
211
211
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Badge, never>;
212
212
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<Badge, "kf-badge", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "dot": { "alias": "dot"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
@@ -393,7 +393,7 @@ declare class Checkbox implements ControlValueAccessor {
393
393
  * de superficie/borde/texto-muted más cercanos).
394
394
  */
395
395
  declare class Chip {
396
- readonly tone: _angular_core.InputSignal<"error" | "ok" | "warn" | "neutral">;
396
+ readonly tone: _angular_core.InputSignal<"ok" | "warn" | "error" | "neutral">;
397
397
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Chip, never>;
398
398
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<Chip, "kf-chip", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
399
399
  }
@@ -881,6 +881,21 @@ interface FolderTabOption {
881
881
  label: string;
882
882
  icon?: IconName;
883
883
  }
884
+ /**
885
+ * Marca el contenido que `kf-folder-tabs` debe proyectar dentro de su
886
+ * panel. Sin lógica propia — existe solo como token de tipo para que
887
+ * `contentChild(FolderTabsPanel)` pueda detectar si el consumidor proyectó
888
+ * algo (mismo mecanismo que `kf-dropdown` usa con `contentChild(DropdownPanel)`;
889
+ * acá no hace falta un componente completo, alcanza con una directiva de
890
+ * atributo porque el panel no necesita comportamiento propio, solo marcar
891
+ * su presencia).
892
+ *
893
+ * <div kf-folder-tabs-panel>...</div>
894
+ */
895
+ declare class FolderTabsPanel {
896
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FolderTabsPanel, never>;
897
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<FolderTabsPanel, "[kf-folder-tabs-panel]", never, {}, {}, never, never, true, never>;
898
+ }
884
899
  /**
885
900
  * Tabs con forma de "carpeta": el borde superior queda redondeado y el borde
886
901
  * inferior de la pestaña activa se funde visualmente con el panel de
@@ -891,20 +906,61 @@ interface FolderTabOption {
891
906
  * `--active` se mueve de un botón a otro, y eso vuelve a disparar el keyframe
892
907
  * sin tocar JS.
893
908
  *
894
- * El consumidor es responsable de renderizar el panel de contenido debajo;
895
- * este componente solo resuelve la fila de pestañas y emite `valueChange`.
896
- *
909
+ * El panel de contenido es un `<ng-content>` OPCIONAL — si el consumidor no
910
+ * proyecta nada, `kf-folder-tabs` renderiza solo la fila de pestañas (mismo
911
+ * comportamiento que antes de que existiera este slot, detectado con
912
+ * `contentChild()` sin `.required`, igual patrón que usa `kf-dropdown` para
913
+ * saber si hay un `kf-dropdown-panel` proyectado). Si SÍ proyecta contenido,
914
+ * se envuelve en un panel con la esquina superior-izquierda recta (nace ahí
915
+ * la primera pestaña, siempre pegada al borde izquierdo de la fila — un
916
+ * radio ahí competiría visualmente con el propio borde redondeado de esa
917
+ * pestaña) y las otras tres redondeadas. El `border-bottom` de 2px de la
918
+ * pestaña activa (ver `.kf-folder-tabs__tab--active` más abajo) es la señal
919
+ * visual de conexión con el panel para CUALQUIER pestaña activa, sin
920
+ * necesitar mover ni medir nada.
921
+ *
922
+ * El borde izquierdo de toda la fila (y por lo tanto de la esquina recta
923
+ * del panel) depende de que ninguna pestaña se corra al cambiar de estado
924
+ * — ver `transform-origin: bottom left` en `.kf-folder-tabs__tab`: con el
925
+ * origen centrado (como estaba antes), el `scale()` de la pestaña inactiva
926
+ * encogía el borde izquierdo unos px, y ese corrimiento sub-pixel es lo que
927
+ * hacía que este mismo diseño (esquina fija) se viera "roto" cuando la
928
+ * pestaña activa no era la primera. Con el origen anclado a la izquierda,
929
+ * el corrimiento desaparece y la esquina fija vuelve a ser una solución
930
+ * válida y simple — sin necesitar medir la pestaña activa por JS.
931
+ *
932
+ * Antes de este slot, el patrón era que el consumidor pusiera su propia
933
+ * card como HERMANO de `kf-folder-tabs` y anulara a mano el radio superior
934
+ * completo (`border-top-left-radius: 0`, `border-top-right-radius: 0` — ver
935
+ * el caso original de `web-portal-latam-frontend`). Encapsular esto acá
936
+ * evita que cada consumidor repita esas reglas a mano.
937
+ *
938
+ * <kf-folder-tabs [options]="tabs" [value]="active" (valueChange)="active = $event">
939
+ * <div kf-folder-tabs-panel>contenido de la pestaña activa</div>
940
+ * </kf-folder-tabs>
941
+ *
942
+ * <!-- o, sin contenido, como antes: -->
897
943
  * <kf-folder-tabs [options]="tabs" [value]="active" (valueChange)="active = $event" />
898
944
  */
899
945
  declare class FolderTabs {
900
946
  readonly options: _angular_core.InputSignal<FolderTabOption[]>;
901
947
  readonly value: _angular_core.InputSignal<string>;
902
948
  readonly valueChange: _angular_core.OutputEmitterRef<string>;
949
+ /**
950
+ * Detecta si el consumidor proyectó contenido marcado con
951
+ * `kf-folder-tabs-panel` — sin `.required`, así que es `undefined`
952
+ * cuando no hay nada proyectado (mismo patrón que usa `kf-dropdown` con
953
+ * `contentChild(DropdownPanel)` para saber si hay un panel que
954
+ * attachear). `hasPanel()` decide si el wrapper del panel participa del
955
+ * layout (`display: contents` si no).
956
+ */
957
+ private readonly projectedPanel;
958
+ protected readonly hasPanel: _angular_core.Signal<boolean>;
903
959
  select(value: string): void;
904
960
  /** Navegación estándar de ARIA tabs: flechas mueven el foco y activan la pestaña. */
905
961
  onKeydown(event: KeyboardEvent, currentValue: string): void;
906
962
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FolderTabs, never>;
907
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FolderTabs, "kf-folder-tabs", never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
963
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FolderTabs, "kf-folder-tabs", never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; }, { "valueChange": "valueChange"; }, ["projectedPanel"], ["[kf-folder-tabs-panel]"], true, never>;
908
964
  }
909
965
 
910
966
  /**
@@ -1258,12 +1314,29 @@ interface PortalHeaderAdminAction {
1258
1314
  * Es distinto de `kf-page-header`/`kf-page-head` (título de una vista
1259
1315
  * interna) — este es el chrome global del portal, se monta una sola vez.
1260
1316
  *
1317
+ * `:host` es `position: sticky; top: 0` — el header queda pegado arriba al
1318
+ * hacer scroll. No es `fixed`: como no se superpone al contenido en el
1319
+ * primer render, no hace falta que el consumidor compense con
1320
+ * `padding-top`.
1321
+ *
1322
+ * Bajo los 768px, el `<nav>` deja de mostrarse en línea junto al logo y
1323
+ * colapsa detrás de un botón de menú (ícono `menu`/`x`) que despliega un
1324
+ * drawer lateral (desde el borde derecho, `position: fixed` + overlay de
1325
+ * fondo) con los mismos `navItems` en columna. Ese drawer expone un slot
1326
+ * (`<ng-content select="[kf-portal-header-extra]">`) al final, pensado
1327
+ * para que el consumidor proyecte contenido propio que en escritorio vive
1328
+ * en otro lugar (ej. el menú de sesión) — `PortalHeader` no sabe qué es
1329
+ * ese contenido ni cómo se abre, solo le da un lugar dentro del drawer ya
1330
+ * desplegado. El overlay cierra el drawer al tocarlo, y `Escape` también.
1331
+ *
1261
1332
  * <kf-portal-header
1262
1333
  * [isAdmin]="true"
1263
1334
  * [adminActions]="[{ label: 'Consultar deuda clientes', href: '/deuda' }, { label: 'Cambiar DNI', href: '/dni' }]"
1264
1335
  * [navItems]="[{ label: 'Home', href: '/', active: true }, { label: 'Vehículos', href: '/vehiculos' }]"
1265
1336
  * userInitials="TS"
1266
- * />
1337
+ * >
1338
+ * <div kf-portal-header-extra>contenido propio, solo visible en el panel mobile</div>
1339
+ * </kf-portal-header>
1267
1340
  */
1268
1341
  declare class PortalHeader {
1269
1342
  readonly brand: _angular_core.InputSignal<string>;
@@ -1272,8 +1345,23 @@ declare class PortalHeader {
1272
1345
  readonly navItems: _angular_core.InputSignal<PortalHeaderNavItem[]>;
1273
1346
  readonly userInitials: _angular_core.InputSignal<string>;
1274
1347
  readonly sessionClick: _angular_core.OutputEmitterRef<void>;
1348
+ /** Visibilidad del drawer de navegación mobile (bajo los 768px). */
1349
+ protected readonly mobileMenuOpen: _angular_core.WritableSignal<boolean>;
1350
+ /** Cierra el drawer con Escape — mismo patrón que cualquier drawer/modal. */
1351
+ protected onEscape(): void;
1352
+ /**
1353
+ * `ElementRef` real del botón de sesión (el avatar en la esquina
1354
+ * derecha), no de todo el header. Pensado para anclar un `kf-dropdown`
1355
+ * externo — sin esto, el único `ElementRef` disponible desde afuera es el
1356
+ * del host de `PortalHeader`, que ocupa el ancho completo de la pantalla
1357
+ * (logo + nav + sesión), y el overlay del CDK termina "pegado" a la
1358
+ * esquina del header entero en vez de al botón que el usuario clickeó.
1359
+ *
1360
+ * <kf-dropdown [(open)]="menuOpen" [anchor]="header().sessionButtonRef()">
1361
+ */
1362
+ readonly sessionButtonRef: _angular_core.Signal<ElementRef<any>>;
1275
1363
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<PortalHeader, never>;
1276
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<PortalHeader, "kf-portal-header", never, { "brand": { "alias": "brand"; "required": false; "isSignal": true; }; "isAdmin": { "alias": "isAdmin"; "required": false; "isSignal": true; }; "adminActions": { "alias": "adminActions"; "required": false; "isSignal": true; }; "navItems": { "alias": "navItems"; "required": false; "isSignal": true; }; "userInitials": { "alias": "userInitials"; "required": true; "isSignal": true; }; }, { "sessionClick": "sessionClick"; }, never, never, true, never>;
1364
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<PortalHeader, "kf-portal-header", never, { "brand": { "alias": "brand"; "required": false; "isSignal": true; }; "isAdmin": { "alias": "isAdmin"; "required": false; "isSignal": true; }; "adminActions": { "alias": "adminActions"; "required": false; "isSignal": true; }; "navItems": { "alias": "navItems"; "required": false; "isSignal": true; }; "userInitials": { "alias": "userInitials"; "required": true; "isSignal": true; }; }, { "sessionClick": "sessionClick"; }, never, ["[kf-portal-header-extra]"], true, never>;
1277
1365
  }
1278
1366
 
1279
1367
  /**
@@ -1522,7 +1610,7 @@ declare class StatTile {
1522
1610
  * <kf-status-pill tone="error" dot>Fuera de servicio</kf-status-pill>
1523
1611
  */
1524
1612
  declare class StatusPill {
1525
- readonly tone: _angular_core.InputSignal<"error" | "ok" | "warn" | "blue">;
1613
+ readonly tone: _angular_core.InputSignal<"ok" | "warn" | "error" | "blue">;
1526
1614
  readonly dot: _angular_core.InputSignalWithTransform<boolean, unknown>;
1527
1615
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StatusPill, never>;
1528
1616
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<StatusPill, "kf-status-pill", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "dot": { "alias": "dot"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
@@ -1754,5 +1842,5 @@ declare class ViewToggle {
1754
1842
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ViewToggle, "kf-view-toggle", never, { "view": { "alias": "view"; "required": true; "isSignal": true; }; }, { "viewChange": "viewChange"; }, never, never, true, never>;
1755
1843
  }
1756
1844
 
1757
- export { ActionTile, AdminBadge, Alert, Avatar, Badge, Breadcrumb, Button, Card, Carousel, CarouselSlide, Checkbox, Chip, CompanySelector, ContentSlot, ContentState, DataTable, Divider, Dropdown, DropdownItem, DropdownPanel, EmptyState, FeatureCard, Field, FieldLabel, FilterChips, FolderTabs, Icon, Input, Link, MetricCard, Modal, MultiSelect, PageHeader, Pagination, Panel, PortalHeader, ReserveBlock, SectionHeader, Segmented, Select, Skeleton, Spinner, StatTile, StatusPill, Tabs, Text, ToastHost, ToastService, VehicleHeader, ViewToggle };
1845
+ export { ActionTile, AdminBadge, Alert, Avatar, Badge, Breadcrumb, Button, Card, Carousel, CarouselSlide, Checkbox, Chip, CompanySelector, ContentSlot, ContentState, DataTable, Divider, Dropdown, DropdownItem, DropdownPanel, EmptyState, FeatureCard, Field, FieldLabel, FilterChips, FolderTabs, FolderTabsPanel, Icon, Input, Link, MetricCard, Modal, MultiSelect, PageHeader, Pagination, Panel, PortalHeader, ReserveBlock, SectionHeader, Segmented, Select, Skeleton, Spinner, StatTile, StatusPill, Tabs, Text, ToastHost, ToastService, VehicleHeader, ViewToggle };
1758
1846
  export type { AlertTone, BreadcrumbItem, CompanySelectorMeta, ContentStateKind, ContentStateLoad, DataTableCardRole, DataTableColumn, DataTableView, DividerOrientation, DropdownItemTone, FolderTabOption, IconName, IconSize, LinkVariant, MultiSelectOption, PaginationItem, PortalHeaderAdminAction, PortalHeaderNavItem, SegmentedOption, SkeletonVariant, SpinnerSize, TabOption, TextAs, TextTone, TextVariant, ToastOptions, ToastPromiseMessages, ToastState, ToastTone, VehicleHeaderStatus, ViewToggleOption };