sapenlinea-components 0.12.98 → 0.13.99

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { model, input, signal, computed, Component, Injectable, inject, ElementRef, NgZone, output, HostListener, ViewChild, ViewChildren, forwardRef, effect, booleanAttribute, DestroyRef, EventEmitter, Output, Input as Input$1, untracked, viewChildren, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
2
+ import { model, input, signal, computed, Component, Injectable, inject, ElementRef, NgZone, output, HostListener, ViewChild, ViewChildren, forwardRef, effect, booleanAttribute, DestroyRef, EventEmitter, Output, Input as Input$1, untracked, viewChildren, ChangeDetectionStrategy, ChangeDetectorRef, viewChild } from '@angular/core';
3
3
  import * as i1$2 from '@angular/common';
4
4
  import { CommonModule, DOCUMENT, NgStyle, UpperCasePipe, NgClass, DatePipe } from '@angular/common';
5
5
  import * as i1 from 'lucide-angular';
@@ -8556,6 +8556,237 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8556
8556
  }]
8557
8557
  }] });
8558
8558
 
8559
+ class BellWithBadge {
8560
+ count = input(0, ...(ngDevMode ? [{ debugName: "count" }] : []));
8561
+ active = input(false, ...(ngDevMode ? [{ debugName: "active", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
8562
+ ariaLabel = input('Notificaciones', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
8563
+ bellClick = output();
8564
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BellWithBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
8565
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: BellWithBadge, isStandalone: true, selector: "lib-bell-with-badge", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { bellClick: "bellClick" }, ngImport: i0, template: "<button\n class=\"lib-bell__btn\"\n [class.lib-bell__btn--active]=\"active()\"\n type=\"button\"\n [attr.aria-label]=\"ariaLabel()\"\n (click)=\"bellClick.emit()\"\n>\n <svg class=\"lib-bell__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"/>\n <path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>\n </svg>\n @if (count() > 0) {\n <span class=\"lib-bell__badge\">{{ count() > 99 ? '99+' : count() }}</span>\n }\n</button>\n", styles: [":host{--lib-bell-icon: #1c1c12;--lib-bell-badge-bg: #bfd100;--lib-bell-badge-text: #1c1c12}.lib-bell__btn{position:relative;background:none;border:none;cursor:pointer;padding:10px;width:44px;height:44px;border-radius:50%;color:var(--lib-bell-icon);transition:background-color .2s ease;display:inline-flex;align-items:center;justify-content:center}.lib-bell__btn:hover{background-color:#00000014}.lib-bell__btn--active{background-color:#0000001f}.lib-bell__icon{width:24px;height:24px}.lib-bell__badge{position:absolute;top:3px;right:3px;min-width:18px;height:18px;padding:0 4px;box-sizing:border-box;border-radius:9px;background-color:var(--lib-bell-badge-bg);color:var(--lib-bell-badge-text);font-family:Inter,sans-serif;font-size:12px;font-weight:600;line-height:1;display:inline-flex;align-items:center;justify-content:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
8566
+ }
8567
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BellWithBadge, decorators: [{
8568
+ type: Component,
8569
+ args: [{ selector: 'lib-bell-with-badge', standalone: true, imports: [CommonModule], template: "<button\n class=\"lib-bell__btn\"\n [class.lib-bell__btn--active]=\"active()\"\n type=\"button\"\n [attr.aria-label]=\"ariaLabel()\"\n (click)=\"bellClick.emit()\"\n>\n <svg class=\"lib-bell__icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"/>\n <path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>\n </svg>\n @if (count() > 0) {\n <span class=\"lib-bell__badge\">{{ count() > 99 ? '99+' : count() }}</span>\n }\n</button>\n", styles: [":host{--lib-bell-icon: #1c1c12;--lib-bell-badge-bg: #bfd100;--lib-bell-badge-text: #1c1c12}.lib-bell__btn{position:relative;background:none;border:none;cursor:pointer;padding:10px;width:44px;height:44px;border-radius:50%;color:var(--lib-bell-icon);transition:background-color .2s ease;display:inline-flex;align-items:center;justify-content:center}.lib-bell__btn:hover{background-color:#00000014}.lib-bell__btn--active{background-color:#0000001f}.lib-bell__icon{width:24px;height:24px}.lib-bell__badge{position:absolute;top:3px;right:3px;min-width:18px;height:18px;padding:0 4px;box-sizing:border-box;border-radius:9px;background-color:var(--lib-bell-badge-bg);color:var(--lib-bell-badge-text);font-family:Inter,sans-serif;font-size:12px;font-weight:600;line-height:1;display:inline-flex;align-items:center;justify-content:center}\n"] }]
8570
+ }], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], bellClick: [{ type: i0.Output, args: ["bellClick"] }] } });
8571
+
8572
+ class NotificationCenter {
8573
+ notifications = input([], ...(ngDevMode ? [{ debugName: "notifications" }] : []));
8574
+ isOpen = input(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
8575
+ /** Indica si hay una página de notificaciones cargándose en este momento. */
8576
+ loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
8577
+ /** Indica si quedan más notificaciones por cargar desde el origen. */
8578
+ hasMore = input(false, ...(ngDevMode ? [{ debugName: "hasMore" }] : []));
8579
+ markAllRead = output();
8580
+ notificationClick = output();
8581
+ close = output();
8582
+ /** Se emite cuando el usuario se acerca al final de la lista y debe cargarse la siguiente página. */
8583
+ loadMore = output();
8584
+ scrollContainer = viewChild('scrollContainer', ...(ngDevMode ? [{ debugName: "scrollContainer" }] : []));
8585
+ sentinel = viewChild('sentinel', ...(ngDevMode ? [{ debugName: "sentinel" }] : []));
8586
+ selectedCategory = signal('Todas', ...(ngDevMode ? [{ debugName: "selectedCategory" }] : []));
8587
+ categories = computed(() => {
8588
+ const cats = new Set(this.notifications().map((n) => n.category));
8589
+ return ['Todas', ...Array.from(cats)];
8590
+ }, ...(ngDevMode ? [{ debugName: "categories" }] : []));
8591
+ filteredNotifications = computed(() => {
8592
+ const cat = this.selectedCategory();
8593
+ if (cat === 'Todas')
8594
+ return this.notifications();
8595
+ return this.notifications().filter((n) => n.category === cat);
8596
+ }, ...(ngDevMode ? [{ debugName: "filteredNotifications" }] : []));
8597
+ unreadCount = computed(() => this.notifications().filter((n) => !n.isRead).length, ...(ngDevMode ? [{ debugName: "unreadCount" }] : []));
8598
+ lightColors = {
8599
+ acuerdos: '#9DAFD8',
8600
+ financiero: '#9ED89D',
8601
+ infracciones: '#D89D9D',
8602
+ sistema: '#BAC2BB',
8603
+ default: '#C7C7AD',
8604
+ };
8605
+ darkColors = {
8606
+ acuerdos: '#0746CF',
8607
+ financiero: '#006D2F',
8608
+ infracciones: '#CF0707',
8609
+ sistema: '#40484C',
8610
+ default: '#454733',
8611
+ };
8612
+ constructor() {
8613
+ // Carga progresiva: observamos un sentinel al final de la lista y pedimos
8614
+ // la siguiente página cuando entra en pantalla, evitando cargar todo de golpe.
8615
+ effect((onCleanup) => {
8616
+ const sentinel = this.sentinel();
8617
+ const root = this.scrollContainer();
8618
+ if (!sentinel || !root || typeof IntersectionObserver === 'undefined')
8619
+ return;
8620
+ const observer = new IntersectionObserver((entries) => {
8621
+ if (entries[0].isIntersecting &&
8622
+ this.isOpen() &&
8623
+ this.hasMore() &&
8624
+ !this.loading()) {
8625
+ this.loadMore.emit();
8626
+ }
8627
+ }, { root: root.nativeElement, rootMargin: '120px', threshold: 0 });
8628
+ observer.observe(sentinel.nativeElement);
8629
+ onCleanup(() => observer.disconnect());
8630
+ });
8631
+ }
8632
+ selectCategory(cat) {
8633
+ this.selectedCategory.set(cat);
8634
+ }
8635
+ onMarkAllRead() {
8636
+ if (this.unreadCount() === 0)
8637
+ return;
8638
+ this.markAllRead.emit();
8639
+ }
8640
+ onNotificationClick(n) {
8641
+ this.notificationClick.emit(n);
8642
+ }
8643
+ /** Etiqueta legible para una pestaña de categoría (ej. "ACUERDOS DE PAGO" -> "Acuerdos de pago"). */
8644
+ tabLabel(category) {
8645
+ if (category === 'Todas')
8646
+ return category;
8647
+ return category.charAt(0).toUpperCase() + category.slice(1).toLowerCase();
8648
+ }
8649
+ /** Normaliza una categoría a una de las claves conocidas para color e icono. */
8650
+ categoryKey(category) {
8651
+ const c = (category || '').toUpperCase();
8652
+ if (c.includes('ACUERDO'))
8653
+ return 'acuerdos';
8654
+ if (c.includes('FINAN'))
8655
+ return 'financiero';
8656
+ if (c.includes('INFRAC'))
8657
+ return 'infracciones';
8658
+ if (c.includes('SISTEMA'))
8659
+ return 'sistema';
8660
+ return 'default';
8661
+ }
8662
+ getCategoryLight(category) {
8663
+ return this.lightColors[this.categoryKey(category)];
8664
+ }
8665
+ getCategoryDark(category) {
8666
+ return this.darkColors[this.categoryKey(category)];
8667
+ }
8668
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationCenter, deps: [], target: i0.ɵɵFactoryTarget.Component });
8669
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: NotificationCenter, isStandalone: true, selector: "lib-notification-center", inputs: { notifications: { classPropertyName: "notifications", publicName: "notifications", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, hasMore: { classPropertyName: "hasMore", publicName: "hasMore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { markAllRead: "markAllRead", notificationClick: "notificationClick", close: "close", loadMore: "loadMore" }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }, { propertyName: "sentinel", first: true, predicate: ["sentinel"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (isOpen()) {\n<div class=\"lib-nc__overlay\" (click)=\"close.emit()\"></div>\n}\n\n<div class=\"lib-nc__panel\" [class.lib-nc__panel--open]=\"isOpen()\">\n <div class=\"lib-nc__header\">\n <div class=\"lib-nc__title-group\">\n <span class=\"lib-nc__title\">Notificaciones</span>\n <span class=\"lib-nc__counter\">({{ unreadCount() }} nuevas)</span>\n </div>\n <button\n class=\"lib-nc__mark-all\"\n type=\"button\"\n [disabled]=\"unreadCount() === 0\"\n (click)=\"onMarkAllRead()\"\n >\n Marcar todas como le\u00EDdas\n </button>\n </div>\n\n @if (notifications().length > 0) {\n <div class=\"lib-nc__tabs\">\n @for (cat of categories(); track cat) {\n <button\n class=\"lib-nc__tab\"\n [class.lib-nc__tab--active]=\"selectedCategory() === cat\"\n type=\"button\"\n (click)=\"selectCategory(cat)\"\n >\n {{ tabLabel(cat) }}\n </button>\n }\n </div>\n\n <div class=\"lib-nc__list\" #scrollContainer>\n @for (notification of filteredNotifications(); track notification.id) {\n <div class=\"lib-nc__item\" (click)=\"onNotificationClick(notification)\">\n <div\n class=\"lib-nc__item-icon\"\n [style.background-color]=\"getCategoryLight(notification.category)\"\n [style.color]=\"getCategoryDark(notification.category)\"\n >\n <svg class=\"lib-nc__item-icon-svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n @switch (categoryKey(notification.category)) {\n @case ('acuerdos') {\n <path d=\"m11 17 2 2a1 1 0 1 0 3-3\"/>\n <path d=\"m14 14 2.5 2.5a1 1 0 1 0 3-3l-3.88-3.88a3 3 0 0 0-4.24 0l-.88.88a1 1 0 1 1-3-3l2.81-2.81a5.79 5.79 0 0 1 7.06-.87l.47.28a2 2 0 0 0 1.42.25L21 4\"/>\n <path d=\"m21 3 1 11h-2\"/>\n <path d=\"M3 3 2 14l6.5 6.5a1 1 0 1 0 3-3\"/>\n <path d=\"M3 4h8\"/>\n }\n @case ('financiero') {\n <line x1=\"12\" x2=\"12\" y1=\"2\" y2=\"22\"/>\n <path d=\"M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6\"/>\n }\n @case ('infracciones') {\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/>\n <path d=\"M12 9v4\"/>\n <path d=\"M12 17h.01\"/>\n }\n @case ('sistema') {\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\" ry=\"2\"/>\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\" ry=\"2\"/>\n <line x1=\"6\" x2=\"6.01\" y1=\"6\" y2=\"6\"/>\n <line x1=\"6\" x2=\"6.01\" y1=\"18\" y2=\"18\"/>\n }\n @default {\n <path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"/>\n <path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>\n }\n }\n </svg>\n </div>\n\n <div class=\"lib-nc__item-content\">\n <div class=\"lib-nc__item-top\">\n <span class=\"lib-nc__item-title\">{{ notification.title }}</span>\n <span class=\"lib-nc__item-time\">{{ notification.timeAgo }}</span>\n </div>\n <p class=\"lib-nc__item-message\">{{ notification.description }}</p>\n <span\n class=\"lib-nc__item-chip\"\n [style.background-color]=\"getCategoryLight(notification.category)\"\n [style.color]=\"getCategoryDark(notification.category)\"\n >\n {{ notification.category }}\n </span>\n </div>\n\n @if (!notification.isRead) {\n <span class=\"lib-nc__item-dot\"></span>\n }\n </div>\n }\n\n @if (loading()) {\n <div class=\"lib-nc__loading\">\n <span class=\"lib-nc__spinner\" aria-label=\"Cargando notificaciones\"></span>\n </div>\n }\n\n <div class=\"lib-nc__sentinel\" #sentinel aria-hidden=\"true\"></div>\n </div>\n } @else {\n <div class=\"lib-nc__empty\">\n <svg class=\"lib-nc__empty-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M8.7 3A6 6 0 0 1 18 8a21.3 21.3 0 0 0 .6 5\"/>\n <path d=\"M17 17H3s3-2 3-9a4.67 4.67 0 0 1 .3-1.7\"/>\n <path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>\n <path d=\"m2 2 20 20\"/>\n </svg>\n <p class=\"lib-nc__empty-title\">Est\u00E1s al d\u00EDa</p>\n <p class=\"lib-nc__empty-message\">No tienes notificaciones por ahora.</p>\n </div>\n }\n</div>\n", styles: [":host{--lib-nc-width: 420px;--lib-nc-max-height: 560px;--lib-nc-bg: #f0f0db;--lib-nc-border: #d8d8c8;--lib-nc-text-strong: #1c1c12;--lib-nc-text: #454733;--lib-nc-text-muted: #7a7f52;--lib-nc-accent: #bfd100;--lib-nc-link: #596300}.lib-nc__overlay{position:fixed;inset:0;z-index:1090}.lib-nc__panel{position:absolute;top:calc(100% + 10px);right:0;width:var(--lib-nc-width);max-height:var(--lib-nc-max-height);max-width:calc(100vw - 24px);background:var(--lib-nc-bg);border:1px solid var(--lib-nc-border);border-radius:12px;box-shadow:5px 6px 5px -3px #0000005c;display:flex;flex-direction:column;z-index:1100;overflow:hidden;opacity:0;visibility:hidden;transform:translateY(-8px);transition:opacity .2s ease,transform .2s ease,visibility .2s ease;pointer-events:none;font-family:Inter,sans-serif}.lib-nc__panel--open{opacity:1;visibility:visible;transform:translateY(0);pointer-events:auto}.lib-nc__header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:16px 20px;border-bottom:1px solid var(--lib-nc-border);flex-shrink:0}.lib-nc__title-group{display:flex;align-items:center;gap:6px}.lib-nc__title{font-size:16px;font-weight:600;color:var(--lib-nc-text-strong);line-height:1.4}.lib-nc__counter{font-size:12px;color:var(--lib-nc-text);line-height:1.4}.lib-nc__mark-all{background:none;border:none;padding:0;color:var(--lib-nc-link);font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap;line-height:1.4}.lib-nc__mark-all:hover:not(:disabled){text-decoration:underline}.lib-nc__mark-all:disabled{color:var(--lib-nc-text-muted);cursor:default}.lib-nc__tabs{display:flex;align-items:flex-end;gap:4px;padding:0 16px;border-bottom:1px solid var(--lib-nc-border);overflow-x:auto;flex-shrink:0;scrollbar-width:none}.lib-nc__tabs::-webkit-scrollbar{display:none}.lib-nc__tab{background:none;border:none;border-bottom:2px solid transparent;padding:10px 8px;font-size:12px;font-weight:500;letter-spacing:.2px;line-height:1.4;color:var(--lib-nc-text-muted);cursor:pointer;white-space:nowrap;transition:color .15s ease,border-color .15s ease}.lib-nc__tab:hover{color:var(--lib-nc-text-strong)}.lib-nc__tab--active{color:var(--lib-nc-text-strong);font-weight:600;border-bottom-color:var(--lib-nc-accent)}.lib-nc__list{flex:1;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:#c4c4a8 transparent}.lib-nc__list::-webkit-scrollbar{width:10px}.lib-nc__list::-webkit-scrollbar-track{background:transparent}.lib-nc__list::-webkit-scrollbar-thumb{background-color:#c4c4a8;border-radius:999px;border:3px solid transparent;background-clip:padding-box}.lib-nc__list::-webkit-scrollbar-thumb:hover{background-color:#aeae90}.lib-nc__loading{display:flex;align-items:center;justify-content:center;padding:16px}.lib-nc__spinner{width:22px;height:22px;border-radius:50%;border:2.5px solid #d8d8c8;border-top-color:var(--lib-nc-accent);animation:lib-nc-spin .7s linear infinite}@keyframes lib-nc-spin{to{transform:rotate(360deg)}}.lib-nc__sentinel{width:100%;height:1px}.lib-nc__item{display:flex;align-items:center;gap:12px;padding:12px 20px;border-bottom:1px solid var(--lib-nc-border);cursor:pointer;transition:background-color .15s ease}.lib-nc__item:hover{background-color:#00000008}.lib-nc__item-icon{width:36px;height:36px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.lib-nc__item-icon-svg{width:18px;height:18px}.lib-nc__item-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}.lib-nc__item-top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.lib-nc__item-title{font-size:14px;font-weight:600;color:var(--lib-nc-text-strong);line-height:1.4}.lib-nc__item-time{font-size:12px;color:var(--lib-nc-text);line-height:1.4;white-space:nowrap;flex-shrink:0}.lib-nc__item-message{margin:0;font-size:14px;color:var(--lib-nc-text);line-height:1.4}.lib-nc__item-chip{align-self:flex-start;display:inline-flex;align-items:center;border-radius:12px;padding:4px 10px;font-size:11px;font-weight:600;letter-spacing:.4px;line-height:1.2;margin-top:2px}.lib-nc__item-dot{width:8px;height:8px;border-radius:50%;background-color:var(--lib-nc-accent);flex-shrink:0}.lib-nc__empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:24px;text-align:center}.lib-nc__empty-icon{width:64px;height:64px;color:#c7c7ad;margin-bottom:4px}.lib-nc__empty-title{margin:0;font-size:16px;font-weight:600;color:var(--lib-nc-text);line-height:1.4}.lib-nc__empty-message{margin:0;font-size:14px;color:var(--lib-nc-text-muted);line-height:1.4}@media (max-width: 480px){.lib-nc__panel{width:calc(100vw - 16px);right:-8px;max-height:calc(100vh - 90px)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
8670
+ }
8671
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationCenter, decorators: [{
8672
+ type: Component,
8673
+ args: [{ selector: 'lib-notification-center', standalone: true, imports: [CommonModule], template: "@if (isOpen()) {\n<div class=\"lib-nc__overlay\" (click)=\"close.emit()\"></div>\n}\n\n<div class=\"lib-nc__panel\" [class.lib-nc__panel--open]=\"isOpen()\">\n <div class=\"lib-nc__header\">\n <div class=\"lib-nc__title-group\">\n <span class=\"lib-nc__title\">Notificaciones</span>\n <span class=\"lib-nc__counter\">({{ unreadCount() }} nuevas)</span>\n </div>\n <button\n class=\"lib-nc__mark-all\"\n type=\"button\"\n [disabled]=\"unreadCount() === 0\"\n (click)=\"onMarkAllRead()\"\n >\n Marcar todas como le\u00EDdas\n </button>\n </div>\n\n @if (notifications().length > 0) {\n <div class=\"lib-nc__tabs\">\n @for (cat of categories(); track cat) {\n <button\n class=\"lib-nc__tab\"\n [class.lib-nc__tab--active]=\"selectedCategory() === cat\"\n type=\"button\"\n (click)=\"selectCategory(cat)\"\n >\n {{ tabLabel(cat) }}\n </button>\n }\n </div>\n\n <div class=\"lib-nc__list\" #scrollContainer>\n @for (notification of filteredNotifications(); track notification.id) {\n <div class=\"lib-nc__item\" (click)=\"onNotificationClick(notification)\">\n <div\n class=\"lib-nc__item-icon\"\n [style.background-color]=\"getCategoryLight(notification.category)\"\n [style.color]=\"getCategoryDark(notification.category)\"\n >\n <svg class=\"lib-nc__item-icon-svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n @switch (categoryKey(notification.category)) {\n @case ('acuerdos') {\n <path d=\"m11 17 2 2a1 1 0 1 0 3-3\"/>\n <path d=\"m14 14 2.5 2.5a1 1 0 1 0 3-3l-3.88-3.88a3 3 0 0 0-4.24 0l-.88.88a1 1 0 1 1-3-3l2.81-2.81a5.79 5.79 0 0 1 7.06-.87l.47.28a2 2 0 0 0 1.42.25L21 4\"/>\n <path d=\"m21 3 1 11h-2\"/>\n <path d=\"M3 3 2 14l6.5 6.5a1 1 0 1 0 3-3\"/>\n <path d=\"M3 4h8\"/>\n }\n @case ('financiero') {\n <line x1=\"12\" x2=\"12\" y1=\"2\" y2=\"22\"/>\n <path d=\"M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6\"/>\n }\n @case ('infracciones') {\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/>\n <path d=\"M12 9v4\"/>\n <path d=\"M12 17h.01\"/>\n }\n @case ('sistema') {\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\" ry=\"2\"/>\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\" ry=\"2\"/>\n <line x1=\"6\" x2=\"6.01\" y1=\"6\" y2=\"6\"/>\n <line x1=\"6\" x2=\"6.01\" y1=\"18\" y2=\"18\"/>\n }\n @default {\n <path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"/>\n <path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>\n }\n }\n </svg>\n </div>\n\n <div class=\"lib-nc__item-content\">\n <div class=\"lib-nc__item-top\">\n <span class=\"lib-nc__item-title\">{{ notification.title }}</span>\n <span class=\"lib-nc__item-time\">{{ notification.timeAgo }}</span>\n </div>\n <p class=\"lib-nc__item-message\">{{ notification.description }}</p>\n <span\n class=\"lib-nc__item-chip\"\n [style.background-color]=\"getCategoryLight(notification.category)\"\n [style.color]=\"getCategoryDark(notification.category)\"\n >\n {{ notification.category }}\n </span>\n </div>\n\n @if (!notification.isRead) {\n <span class=\"lib-nc__item-dot\"></span>\n }\n </div>\n }\n\n @if (loading()) {\n <div class=\"lib-nc__loading\">\n <span class=\"lib-nc__spinner\" aria-label=\"Cargando notificaciones\"></span>\n </div>\n }\n\n <div class=\"lib-nc__sentinel\" #sentinel aria-hidden=\"true\"></div>\n </div>\n } @else {\n <div class=\"lib-nc__empty\">\n <svg class=\"lib-nc__empty-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M8.7 3A6 6 0 0 1 18 8a21.3 21.3 0 0 0 .6 5\"/>\n <path d=\"M17 17H3s3-2 3-9a4.67 4.67 0 0 1 .3-1.7\"/>\n <path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>\n <path d=\"m2 2 20 20\"/>\n </svg>\n <p class=\"lib-nc__empty-title\">Est\u00E1s al d\u00EDa</p>\n <p class=\"lib-nc__empty-message\">No tienes notificaciones por ahora.</p>\n </div>\n }\n</div>\n", styles: [":host{--lib-nc-width: 420px;--lib-nc-max-height: 560px;--lib-nc-bg: #f0f0db;--lib-nc-border: #d8d8c8;--lib-nc-text-strong: #1c1c12;--lib-nc-text: #454733;--lib-nc-text-muted: #7a7f52;--lib-nc-accent: #bfd100;--lib-nc-link: #596300}.lib-nc__overlay{position:fixed;inset:0;z-index:1090}.lib-nc__panel{position:absolute;top:calc(100% + 10px);right:0;width:var(--lib-nc-width);max-height:var(--lib-nc-max-height);max-width:calc(100vw - 24px);background:var(--lib-nc-bg);border:1px solid var(--lib-nc-border);border-radius:12px;box-shadow:5px 6px 5px -3px #0000005c;display:flex;flex-direction:column;z-index:1100;overflow:hidden;opacity:0;visibility:hidden;transform:translateY(-8px);transition:opacity .2s ease,transform .2s ease,visibility .2s ease;pointer-events:none;font-family:Inter,sans-serif}.lib-nc__panel--open{opacity:1;visibility:visible;transform:translateY(0);pointer-events:auto}.lib-nc__header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:16px 20px;border-bottom:1px solid var(--lib-nc-border);flex-shrink:0}.lib-nc__title-group{display:flex;align-items:center;gap:6px}.lib-nc__title{font-size:16px;font-weight:600;color:var(--lib-nc-text-strong);line-height:1.4}.lib-nc__counter{font-size:12px;color:var(--lib-nc-text);line-height:1.4}.lib-nc__mark-all{background:none;border:none;padding:0;color:var(--lib-nc-link);font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap;line-height:1.4}.lib-nc__mark-all:hover:not(:disabled){text-decoration:underline}.lib-nc__mark-all:disabled{color:var(--lib-nc-text-muted);cursor:default}.lib-nc__tabs{display:flex;align-items:flex-end;gap:4px;padding:0 16px;border-bottom:1px solid var(--lib-nc-border);overflow-x:auto;flex-shrink:0;scrollbar-width:none}.lib-nc__tabs::-webkit-scrollbar{display:none}.lib-nc__tab{background:none;border:none;border-bottom:2px solid transparent;padding:10px 8px;font-size:12px;font-weight:500;letter-spacing:.2px;line-height:1.4;color:var(--lib-nc-text-muted);cursor:pointer;white-space:nowrap;transition:color .15s ease,border-color .15s ease}.lib-nc__tab:hover{color:var(--lib-nc-text-strong)}.lib-nc__tab--active{color:var(--lib-nc-text-strong);font-weight:600;border-bottom-color:var(--lib-nc-accent)}.lib-nc__list{flex:1;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:#c4c4a8 transparent}.lib-nc__list::-webkit-scrollbar{width:10px}.lib-nc__list::-webkit-scrollbar-track{background:transparent}.lib-nc__list::-webkit-scrollbar-thumb{background-color:#c4c4a8;border-radius:999px;border:3px solid transparent;background-clip:padding-box}.lib-nc__list::-webkit-scrollbar-thumb:hover{background-color:#aeae90}.lib-nc__loading{display:flex;align-items:center;justify-content:center;padding:16px}.lib-nc__spinner{width:22px;height:22px;border-radius:50%;border:2.5px solid #d8d8c8;border-top-color:var(--lib-nc-accent);animation:lib-nc-spin .7s linear infinite}@keyframes lib-nc-spin{to{transform:rotate(360deg)}}.lib-nc__sentinel{width:100%;height:1px}.lib-nc__item{display:flex;align-items:center;gap:12px;padding:12px 20px;border-bottom:1px solid var(--lib-nc-border);cursor:pointer;transition:background-color .15s ease}.lib-nc__item:hover{background-color:#00000008}.lib-nc__item-icon{width:36px;height:36px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.lib-nc__item-icon-svg{width:18px;height:18px}.lib-nc__item-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}.lib-nc__item-top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.lib-nc__item-title{font-size:14px;font-weight:600;color:var(--lib-nc-text-strong);line-height:1.4}.lib-nc__item-time{font-size:12px;color:var(--lib-nc-text);line-height:1.4;white-space:nowrap;flex-shrink:0}.lib-nc__item-message{margin:0;font-size:14px;color:var(--lib-nc-text);line-height:1.4}.lib-nc__item-chip{align-self:flex-start;display:inline-flex;align-items:center;border-radius:12px;padding:4px 10px;font-size:11px;font-weight:600;letter-spacing:.4px;line-height:1.2;margin-top:2px}.lib-nc__item-dot{width:8px;height:8px;border-radius:50%;background-color:var(--lib-nc-accent);flex-shrink:0}.lib-nc__empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:24px;text-align:center}.lib-nc__empty-icon{width:64px;height:64px;color:#c7c7ad;margin-bottom:4px}.lib-nc__empty-title{margin:0;font-size:16px;font-weight:600;color:var(--lib-nc-text);line-height:1.4}.lib-nc__empty-message{margin:0;font-size:14px;color:var(--lib-nc-text-muted);line-height:1.4}@media (max-width: 480px){.lib-nc__panel{width:calc(100vw - 16px);right:-8px;max-height:calc(100vh - 90px)}}\n"] }]
8674
+ }], ctorParameters: () => [], propDecorators: { notifications: [{ type: i0.Input, args: [{ isSignal: true, alias: "notifications", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], hasMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasMore", required: false }] }], markAllRead: [{ type: i0.Output, args: ["markAllRead"] }], notificationClick: [{ type: i0.Output, args: ["notificationClick"] }], close: [{ type: i0.Output, args: ["close"] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], scrollContainer: [{ type: i0.ViewChild, args: ['scrollContainer', { isSignal: true }] }], sentinel: [{ type: i0.ViewChild, args: ['sentinel', { isSignal: true }] }] } });
8675
+
8676
+ class Header {
8677
+ /**
8678
+ * Todas las entradas son opcionales para que el header funcione igual
8679
+ * como custom element, microfrontend con module-federation o dentro del
8680
+ * monolito, sin que el consumidor esté obligado a enlazar cada propiedad.
8681
+ */
8682
+ isExpanded = input(false, ...(ngDevMode ? [{ debugName: "isExpanded" }] : []));
8683
+ activeTitle = input('', ...(ngDevMode ? [{ debugName: "activeTitle" }] : []));
8684
+ mfId = input('', ...(ngDevMode ? [{ debugName: "mfId" }] : []));
8685
+ isMfFailed = input(false, ...(ngDevMode ? [{ debugName: "isMfFailed" }] : []));
8686
+ userRole = input('Administrador', ...(ngDevMode ? [{ debugName: "userRole" }] : []));
8687
+ /** Lista de notificaciones a mostrar en el centro de notificaciones. */
8688
+ notifications = input([], ...(ngDevMode ? [{ debugName: "notifications" }] : []));
8689
+ /** Indica si se está cargando una página de notificaciones. */
8690
+ notificationsLoading = input(false, ...(ngDevMode ? [{ debugName: "notificationsLoading" }] : []));
8691
+ /** Indica si quedan más notificaciones por cargar desde el origen. */
8692
+ notificationsHasMore = input(false, ...(ngDevMode ? [{ debugName: "notificationsHasMore" }] : []));
8693
+ navigateTo = output();
8694
+ menuClick = output();
8695
+ profileClick = output();
8696
+ logoutClick = output();
8697
+ actionClick = output();
8698
+ /** Eventos reenviados desde el centro de notificaciones. */
8699
+ markAllRead = output();
8700
+ notificationClick = output();
8701
+ /** Se emite cuando debe cargarse la siguiente página de notificaciones. */
8702
+ loadMoreNotifications = output();
8703
+ isDropdownOpen = signal(false, ...(ngDevMode ? [{ debugName: "isDropdownOpen" }] : []));
8704
+ isNotifOpen = signal(false, ...(ngDevMode ? [{ debugName: "isNotifOpen" }] : []));
8705
+ /** Cantidad de notificaciones no leídas, derivada de la lista. */
8706
+ unreadCount = computed(() => this.notifications().filter((n) => !n.isRead).length, ...(ngDevMode ? [{ debugName: "unreadCount" }] : []));
8707
+ onMenuClick() {
8708
+ this.menuClick.emit();
8709
+ }
8710
+ toggleDropdown() {
8711
+ this.isNotifOpen.set(false);
8712
+ this.isDropdownOpen.update((open) => !open);
8713
+ }
8714
+ toggleNotifications() {
8715
+ this.isDropdownOpen.set(false);
8716
+ this.isNotifOpen.update((open) => !open);
8717
+ }
8718
+ closeNotifications() {
8719
+ this.isNotifOpen.set(false);
8720
+ }
8721
+ userProfile() {
8722
+ this.isDropdownOpen.set(false);
8723
+ this.profileClick.emit();
8724
+ }
8725
+ logout() {
8726
+ this.isDropdownOpen.set(false);
8727
+ this.logoutClick.emit();
8728
+ }
8729
+ getMenuIcon() {
8730
+ return this.isExpanded() ? '✕' : '☰';
8731
+ }
8732
+ goToHome() {
8733
+ this.navigateTo.emit('/home');
8734
+ }
8735
+ onActionClick() {
8736
+ const id = this.mfId();
8737
+ const routeMap = {
8738
+ 'infractions': '/child/infractions/register',
8739
+ 'paymentAgreements': '/child/paymentAgreements/register',
8740
+ 'trainingCourses-programar': '/child/trainingCourses/programacion',
8741
+ };
8742
+ const eventMap = {
8743
+ 'paymentAgreementParameters': 'mf-action-register-parameter',
8744
+ 'trainingCourses-administrar': 'mf-action-training-course-nuevo',
8745
+ 'trainingCourses-catalogos-cia': 'mf-action-catalogo-cia-nuevo',
8746
+ 'trainingCourses-catalogos-salones': 'mf-action-catalogo-salon-nuevo',
8747
+ 'trainingCourses-catalogos-instructores': 'mf-action-catalogo-instructor-nuevo',
8748
+ };
8749
+ if (routeMap[id]) {
8750
+ this.navigateTo.emit(routeMap[id]);
8751
+ }
8752
+ else if (eventMap[id]) {
8753
+ window.dispatchEvent(new CustomEvent(eventMap[id]));
8754
+ }
8755
+ this.actionClick.emit(id);
8756
+ }
8757
+ getActionLabel() {
8758
+ const labels = {
8759
+ 'infractions': 'Nueva Infracción',
8760
+ 'paymentAgreements': 'Nuevo Acuerdo',
8761
+ 'paymentAgreementParameters': 'Nuevo Parámetro',
8762
+ 'trainingCourses-administrar': 'Nuevo Curso',
8763
+ 'trainingCourses-programar': 'Programar Curso',
8764
+ 'trainingCourses-catalogos-cia': 'Nueva CIA',
8765
+ 'trainingCourses-catalogos-salones': 'Nuevo salón',
8766
+ 'trainingCourses-catalogos-instructores': 'Nuevo instructor',
8767
+ };
8768
+ return labels[this.mfId()] || '';
8769
+ }
8770
+ hasAction() {
8771
+ return !!this.getActionLabel() && !this.isMfFailed();
8772
+ }
8773
+ onMarkAllRead() {
8774
+ this.markAllRead.emit();
8775
+ }
8776
+ onNotificationItemClick(notification) {
8777
+ this.notificationClick.emit(notification);
8778
+ }
8779
+ onLoadMoreNotifications() {
8780
+ this.loadMoreNotifications.emit();
8781
+ }
8782
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Header, deps: [], target: i0.ɵɵFactoryTarget.Component });
8783
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: Header, isStandalone: true, selector: "lib-header", inputs: { isExpanded: { classPropertyName: "isExpanded", publicName: "isExpanded", isSignal: true, isRequired: false, transformFunction: null }, activeTitle: { classPropertyName: "activeTitle", publicName: "activeTitle", isSignal: true, isRequired: false, transformFunction: null }, mfId: { classPropertyName: "mfId", publicName: "mfId", isSignal: true, isRequired: false, transformFunction: null }, isMfFailed: { classPropertyName: "isMfFailed", publicName: "isMfFailed", isSignal: true, isRequired: false, transformFunction: null }, userRole: { classPropertyName: "userRole", publicName: "userRole", isSignal: true, isRequired: false, transformFunction: null }, notifications: { classPropertyName: "notifications", publicName: "notifications", isSignal: true, isRequired: false, transformFunction: null }, notificationsLoading: { classPropertyName: "notificationsLoading", publicName: "notificationsLoading", isSignal: true, isRequired: false, transformFunction: null }, notificationsHasMore: { classPropertyName: "notificationsHasMore", publicName: "notificationsHasMore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { navigateTo: "navigateTo", menuClick: "menuClick", profileClick: "profileClick", logoutClick: "logoutClick", actionClick: "actionClick", markAllRead: "markAllRead", notificationClick: "notificationClick", loadMoreNotifications: "loadMoreNotifications" }, ngImport: i0, template: "<header class=\"lib-header\">\n <div class=\"lib-header__left\" (click)=\"goToHome()\">\n <button class=\"lib-header__menu-btn\" type=\"button\" (click)=\"$event.stopPropagation(); onMenuClick()\">\n <span class=\"lib-header__menu-icon\">{{ getMenuIcon() }}</span>\n </button>\n <div class=\"lib-header__section-icons\">\n <div class=\"lib-header__icon lib-header__icon--first\"></div>\n <div class=\"lib-header__divider\"></div>\n <div class=\"lib-header__icon lib-header__icon--second\"></div>\n </div>\n </div>\n\n <div class=\"lib-header__title-container\">\n <div class=\"lib-header__title\">{{ activeTitle() }}</div>\n </div>\n\n <div class=\"lib-header__right\">\n @if (hasAction()) {\n <button class=\"lib-header__action-btn\" type=\"button\" (click)=\"onActionClick()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M12 4a1 1 0 0 1 1 1v6h6a1 1 0 0 1 0 2h-6v6a1 1 0 0 1 -2 0v-6h-6a1 1 0 0 1 0 -2h6v-6a1 1 0 0 1 1 -1\"/>\n </svg>\n {{ getActionLabel() }}\n </button>\n }\n\n <div class=\"lib-header__notif-wrapper\">\n <lib-bell-with-badge\n [count]=\"unreadCount()\"\n [active]=\"isNotifOpen()\"\n (bellClick)=\"toggleNotifications()\"\n />\n\n <lib-notification-center\n [isOpen]=\"isNotifOpen()\"\n [notifications]=\"notifications()\"\n [loading]=\"notificationsLoading()\"\n [hasMore]=\"notificationsHasMore()\"\n (markAllRead)=\"onMarkAllRead()\"\n (notificationClick)=\"onNotificationItemClick($event)\"\n (loadMore)=\"onLoadMoreNotifications()\"\n (close)=\"closeNotifications()\"\n />\n </div>\n\n <div class=\"lib-header__user-info\" [class.lib-header__user-info--open]=\"isDropdownOpen()\" (click)=\"toggleDropdown()\">\n <div class=\"lib-header__user-avatar\">{{ userRole().charAt(0) }}</div>\n <svg class=\"lib-header__dropdown-arrow\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M4 6l4 4 4-4H4z\"/>\n </svg>\n\n <div class=\"lib-header__dropdown-menu\" [class.lib-header__dropdown-menu--show]=\"isDropdownOpen()\" (click)=\"$event.stopPropagation()\">\n <div class=\"lib-header__dropdown-header\">\n <div class=\"lib-header__dropdown-avatar\">{{ userRole().charAt(0) }}</div>\n <div class=\"lib-header__dropdown-user-info\">\n <div class=\"lib-header__dropdown-user-name\">{{ userRole() }}</div>\n <div class=\"lib-header__dropdown-user-role\">Administrador</div>\n </div>\n </div>\n <div class=\"lib-header__dropdown-item\" (click)=\"userProfile()\">\n <svg class=\"lib-header__dropdown-item-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"/>\n <circle cx=\"12\" cy=\"7\" r=\"4\"/>\n </svg>\n Perfil\n </div>\n <div class=\"lib-header__dropdown-item lib-header__dropdown-item--danger\" (click)=\"logout()\">\n <svg class=\"lib-header__dropdown-item-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\"/>\n <polyline points=\"16,17 21,12 16,7\"/>\n <line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\"/>\n </svg>\n Cerrar sesi\u00F3n\n </div>\n </div>\n </div>\n </div>\n</header>\n", styles: [":host{--lib-header-height: 75px;--lib-header-bg: #fafae8;--lib-header-text: #171c1f;--lib-header-accent: #bfd100;--lib-header-avatar-bg: #bfd100;--lib-header-user-chip-bg: #e3e3d1;--lib-header-divider: #d6d5d2}.lib-header{background-color:var(--lib-header-bg);height:var(--lib-header-height);display:flex;align-items:center;justify-content:space-between;padding:0 10px;position:fixed;top:0;left:0;right:0;z-index:200}.lib-header__left{display:flex;align-items:center;flex:1;justify-content:flex-start;cursor:pointer;gap:0}.lib-header__menu-btn{display:none;background:none;border:none;cursor:pointer;padding:8px;color:var(--lib-header-text);border-radius:4px;transition:background-color .2s ease}.lib-header__menu-btn:hover{background-color:#0000001a}.lib-header__menu-icon{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center}.lib-header__section-icons{display:flex;align-items:center;gap:3px}.lib-header__icon{background-size:contain;background-repeat:no-repeat;background-position:center;flex-shrink:0}.lib-header__icon--first{width:54px;height:44px;border-radius:8px;margin-right:6px;background-image:url(/logo.png)}.lib-header__icon--second{width:140px;height:60px;margin-left:10px;background-image:url(/logos-secretaria-alcaldia.svg)}.lib-header__divider{width:1px;height:30px;background-color:var(--lib-header-divider);border-radius:1px;flex-shrink:0}.lib-header__title-container{display:flex;align-items:center;justify-content:center}.lib-header__title{font-size:26px;font-weight:600;color:var(--lib-header-text)}.lib-header__right{display:flex;align-items:center;gap:15px;flex:1;justify-content:flex-end}.lib-header__action-btn{display:inline-flex;align-items:center;gap:8px;background-color:#596300;color:#fff;border:none;border-radius:6px;padding:8px 16px;font-size:14px;font-weight:500;cursor:pointer;transition:background-color .2s ease}.lib-header__action-btn:hover{background-color:#4a5200}.lib-header__notif-wrapper{position:relative;display:inline-flex;align-items:center}.lib-header__user-info{display:flex;align-items:center;gap:8px;background-color:var(--lib-header-user-chip-bg);padding:5px;border-radius:24px;cursor:pointer;transition:background-color .2s ease;position:relative;justify-content:space-between;width:80px}.lib-header__user-info:hover:not(.lib-header__user-info--open){background-color:#d4d8dc}.lib-header__user-info--open{background-color:#eaeef2}.lib-header__user-avatar,.lib-header__dropdown-avatar{width:40px;height:40px;background-color:var(--lib-header-avatar-bg);border-radius:50%;display:flex;align-items:center;justify-content:center;color:#111827;font-weight:600;font-size:16px;flex-shrink:0}.lib-header__dropdown-arrow{width:16px;height:16px;color:#666;flex-shrink:0;transition:transform .2s ease}.lib-header__user-info--open .lib-header__dropdown-arrow{transform:rotate(180deg)}.lib-header__dropdown-menu{position:absolute;top:100%;right:0;margin-top:8px;background-color:#fff;border-radius:12px;min-width:240px;overflow:hidden;opacity:0;visibility:hidden;transform:translateY(-10px);transition:all .2s ease;z-index:1001;box-shadow:5px 6px 5px -3px #0000005c}.lib-header__dropdown-menu--show{opacity:1;visibility:visible;transform:translateY(0)}.lib-header__dropdown-header{padding:16px 20px;border-bottom:2px solid #f0f0f0;display:flex;align-items:center;gap:12px}.lib-header__dropdown-user-info{flex:1}.lib-header__dropdown-user-name{font-size:16px;font-weight:600;color:var(--lib-header-text);margin-bottom:2px}.lib-header__dropdown-user-role{font-size:14px;color:#666}.lib-header__dropdown-item{display:flex;align-items:center;gap:12px;padding:12px 20px;color:var(--lib-header-text);font-size:14px;transition:background-color .2s ease;cursor:pointer}.lib-header__dropdown-item:hover{background-color:#f8f9fa}.lib-header__dropdown-item--danger{color:#dc3545}.lib-header__dropdown-item--danger:hover{background-color:#fff5f5;color:#a02834}.lib-header__dropdown-item-icon{width:15px;height:15px;flex-shrink:0}@media (max-width: 921px){.lib-header__title{display:none}}@media (max-width: 640px){.lib-header__section-icons{display:none}.lib-header__menu-btn{display:block}}@media (max-width: 480px){.lib-header{padding:0 8px}.lib-header__right{gap:10px}}@media (max-width: 360px){.lib-header{padding:0 6px}.lib-header__right{gap:8px}.lib-header__user-avatar{width:36px;height:36px;font-size:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BellWithBadge, selector: "lib-bell-with-badge", inputs: ["count", "active", "ariaLabel"], outputs: ["bellClick"] }, { kind: "component", type: NotificationCenter, selector: "lib-notification-center", inputs: ["notifications", "isOpen", "loading", "hasMore"], outputs: ["markAllRead", "notificationClick", "close", "loadMore"] }] });
8784
+ }
8785
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: Header, decorators: [{
8786
+ type: Component,
8787
+ args: [{ selector: 'lib-header', standalone: true, imports: [CommonModule, BellWithBadge, NotificationCenter], template: "<header class=\"lib-header\">\n <div class=\"lib-header__left\" (click)=\"goToHome()\">\n <button class=\"lib-header__menu-btn\" type=\"button\" (click)=\"$event.stopPropagation(); onMenuClick()\">\n <span class=\"lib-header__menu-icon\">{{ getMenuIcon() }}</span>\n </button>\n <div class=\"lib-header__section-icons\">\n <div class=\"lib-header__icon lib-header__icon--first\"></div>\n <div class=\"lib-header__divider\"></div>\n <div class=\"lib-header__icon lib-header__icon--second\"></div>\n </div>\n </div>\n\n <div class=\"lib-header__title-container\">\n <div class=\"lib-header__title\">{{ activeTitle() }}</div>\n </div>\n\n <div class=\"lib-header__right\">\n @if (hasAction()) {\n <button class=\"lib-header__action-btn\" type=\"button\" (click)=\"onActionClick()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M12 4a1 1 0 0 1 1 1v6h6a1 1 0 0 1 0 2h-6v6a1 1 0 0 1 -2 0v-6h-6a1 1 0 0 1 0 -2h6v-6a1 1 0 0 1 1 -1\"/>\n </svg>\n {{ getActionLabel() }}\n </button>\n }\n\n <div class=\"lib-header__notif-wrapper\">\n <lib-bell-with-badge\n [count]=\"unreadCount()\"\n [active]=\"isNotifOpen()\"\n (bellClick)=\"toggleNotifications()\"\n />\n\n <lib-notification-center\n [isOpen]=\"isNotifOpen()\"\n [notifications]=\"notifications()\"\n [loading]=\"notificationsLoading()\"\n [hasMore]=\"notificationsHasMore()\"\n (markAllRead)=\"onMarkAllRead()\"\n (notificationClick)=\"onNotificationItemClick($event)\"\n (loadMore)=\"onLoadMoreNotifications()\"\n (close)=\"closeNotifications()\"\n />\n </div>\n\n <div class=\"lib-header__user-info\" [class.lib-header__user-info--open]=\"isDropdownOpen()\" (click)=\"toggleDropdown()\">\n <div class=\"lib-header__user-avatar\">{{ userRole().charAt(0) }}</div>\n <svg class=\"lib-header__dropdown-arrow\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path d=\"M4 6l4 4 4-4H4z\"/>\n </svg>\n\n <div class=\"lib-header__dropdown-menu\" [class.lib-header__dropdown-menu--show]=\"isDropdownOpen()\" (click)=\"$event.stopPropagation()\">\n <div class=\"lib-header__dropdown-header\">\n <div class=\"lib-header__dropdown-avatar\">{{ userRole().charAt(0) }}</div>\n <div class=\"lib-header__dropdown-user-info\">\n <div class=\"lib-header__dropdown-user-name\">{{ userRole() }}</div>\n <div class=\"lib-header__dropdown-user-role\">Administrador</div>\n </div>\n </div>\n <div class=\"lib-header__dropdown-item\" (click)=\"userProfile()\">\n <svg class=\"lib-header__dropdown-item-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"/>\n <circle cx=\"12\" cy=\"7\" r=\"4\"/>\n </svg>\n Perfil\n </div>\n <div class=\"lib-header__dropdown-item lib-header__dropdown-item--danger\" (click)=\"logout()\">\n <svg class=\"lib-header__dropdown-item-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\"/>\n <polyline points=\"16,17 21,12 16,7\"/>\n <line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\"/>\n </svg>\n Cerrar sesi\u00F3n\n </div>\n </div>\n </div>\n </div>\n</header>\n", styles: [":host{--lib-header-height: 75px;--lib-header-bg: #fafae8;--lib-header-text: #171c1f;--lib-header-accent: #bfd100;--lib-header-avatar-bg: #bfd100;--lib-header-user-chip-bg: #e3e3d1;--lib-header-divider: #d6d5d2}.lib-header{background-color:var(--lib-header-bg);height:var(--lib-header-height);display:flex;align-items:center;justify-content:space-between;padding:0 10px;position:fixed;top:0;left:0;right:0;z-index:200}.lib-header__left{display:flex;align-items:center;flex:1;justify-content:flex-start;cursor:pointer;gap:0}.lib-header__menu-btn{display:none;background:none;border:none;cursor:pointer;padding:8px;color:var(--lib-header-text);border-radius:4px;transition:background-color .2s ease}.lib-header__menu-btn:hover{background-color:#0000001a}.lib-header__menu-icon{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center}.lib-header__section-icons{display:flex;align-items:center;gap:3px}.lib-header__icon{background-size:contain;background-repeat:no-repeat;background-position:center;flex-shrink:0}.lib-header__icon--first{width:54px;height:44px;border-radius:8px;margin-right:6px;background-image:url(/logo.png)}.lib-header__icon--second{width:140px;height:60px;margin-left:10px;background-image:url(/logos-secretaria-alcaldia.svg)}.lib-header__divider{width:1px;height:30px;background-color:var(--lib-header-divider);border-radius:1px;flex-shrink:0}.lib-header__title-container{display:flex;align-items:center;justify-content:center}.lib-header__title{font-size:26px;font-weight:600;color:var(--lib-header-text)}.lib-header__right{display:flex;align-items:center;gap:15px;flex:1;justify-content:flex-end}.lib-header__action-btn{display:inline-flex;align-items:center;gap:8px;background-color:#596300;color:#fff;border:none;border-radius:6px;padding:8px 16px;font-size:14px;font-weight:500;cursor:pointer;transition:background-color .2s ease}.lib-header__action-btn:hover{background-color:#4a5200}.lib-header__notif-wrapper{position:relative;display:inline-flex;align-items:center}.lib-header__user-info{display:flex;align-items:center;gap:8px;background-color:var(--lib-header-user-chip-bg);padding:5px;border-radius:24px;cursor:pointer;transition:background-color .2s ease;position:relative;justify-content:space-between;width:80px}.lib-header__user-info:hover:not(.lib-header__user-info--open){background-color:#d4d8dc}.lib-header__user-info--open{background-color:#eaeef2}.lib-header__user-avatar,.lib-header__dropdown-avatar{width:40px;height:40px;background-color:var(--lib-header-avatar-bg);border-radius:50%;display:flex;align-items:center;justify-content:center;color:#111827;font-weight:600;font-size:16px;flex-shrink:0}.lib-header__dropdown-arrow{width:16px;height:16px;color:#666;flex-shrink:0;transition:transform .2s ease}.lib-header__user-info--open .lib-header__dropdown-arrow{transform:rotate(180deg)}.lib-header__dropdown-menu{position:absolute;top:100%;right:0;margin-top:8px;background-color:#fff;border-radius:12px;min-width:240px;overflow:hidden;opacity:0;visibility:hidden;transform:translateY(-10px);transition:all .2s ease;z-index:1001;box-shadow:5px 6px 5px -3px #0000005c}.lib-header__dropdown-menu--show{opacity:1;visibility:visible;transform:translateY(0)}.lib-header__dropdown-header{padding:16px 20px;border-bottom:2px solid #f0f0f0;display:flex;align-items:center;gap:12px}.lib-header__dropdown-user-info{flex:1}.lib-header__dropdown-user-name{font-size:16px;font-weight:600;color:var(--lib-header-text);margin-bottom:2px}.lib-header__dropdown-user-role{font-size:14px;color:#666}.lib-header__dropdown-item{display:flex;align-items:center;gap:12px;padding:12px 20px;color:var(--lib-header-text);font-size:14px;transition:background-color .2s ease;cursor:pointer}.lib-header__dropdown-item:hover{background-color:#f8f9fa}.lib-header__dropdown-item--danger{color:#dc3545}.lib-header__dropdown-item--danger:hover{background-color:#fff5f5;color:#a02834}.lib-header__dropdown-item-icon{width:15px;height:15px;flex-shrink:0}@media (max-width: 921px){.lib-header__title{display:none}}@media (max-width: 640px){.lib-header__section-icons{display:none}.lib-header__menu-btn{display:block}}@media (max-width: 480px){.lib-header{padding:0 8px}.lib-header__right{gap:10px}}@media (max-width: 360px){.lib-header{padding:0 6px}.lib-header__right{gap:8px}.lib-header__user-avatar{width:36px;height:36px;font-size:12px}}\n"] }]
8788
+ }], propDecorators: { isExpanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "isExpanded", required: false }] }], activeTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTitle", required: false }] }], mfId: [{ type: i0.Input, args: [{ isSignal: true, alias: "mfId", required: false }] }], isMfFailed: [{ type: i0.Input, args: [{ isSignal: true, alias: "isMfFailed", required: false }] }], userRole: [{ type: i0.Input, args: [{ isSignal: true, alias: "userRole", required: false }] }], notifications: [{ type: i0.Input, args: [{ isSignal: true, alias: "notifications", required: false }] }], notificationsLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "notificationsLoading", required: false }] }], notificationsHasMore: [{ type: i0.Input, args: [{ isSignal: true, alias: "notificationsHasMore", required: false }] }], navigateTo: [{ type: i0.Output, args: ["navigateTo"] }], menuClick: [{ type: i0.Output, args: ["menuClick"] }], profileClick: [{ type: i0.Output, args: ["profileClick"] }], logoutClick: [{ type: i0.Output, args: ["logoutClick"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }], markAllRead: [{ type: i0.Output, args: ["markAllRead"] }], notificationClick: [{ type: i0.Output, args: ["notificationClick"] }], loadMoreNotifications: [{ type: i0.Output, args: ["loadMoreNotifications"] }] } });
8789
+
8559
8790
  // src/app/components/public-api.ts
8560
8791
  // Exportar los componentes
8561
8792
 
@@ -8563,5 +8794,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8563
8794
  * Generated bundle index. Do not edit.
8564
8795
  */
8565
8796
 
8566
- export { BarChart, BaseChart, Button, ButtonCards, CARD_BG, CSS_ICON_CATALOG, CardContent, CardHistory, ColorPicker, Colors, DEFAULT_ICON_PICKER_ICONS, DEFAULT_MODULE_ICONS, DEFAULT_ROLE_COLORS, DateTimeFilter, DateTimePicker, DevicesCarousel, DialogAlertComponent, DialogConfirmation, DocumentItem, DocumentUpload, DonutChart, DynamicFormFields, FeatureCard, Footer, GeoAPIMaps, Heatmap, IconPicker, InfoGroup, Input, InputNumberFilter, InputSelectFilter, InputTextFilter, InputTimeFilter, KpiCard, LUCIDE_ICON_CATALOG, LineChart, LoadImage, Loader, MapGeo, ModalForm, ModuleCard, ModuleCardList, NotFoundModal, NotFoundSection, NotificationModal, OptionCard, PaginationComponent, PdfViewer, PdfViewerService, ProcessingOverlay, ProgressBar, ProgressFormService, QuickAccessCards, RolCard, SelectCustomSearch, SideCard, SideCardDetail, Sidebar, SidebarService, Signature, TOAST_EVENTS, Table, TableChart, Tabs, TitleFilters, Toast, ToastHelper, ToastService, ToggleCustom, UI_CHART_TOKENS, WizardForm, buildChildGridTemplateColumns, filterVisibleSidebarItems, getCssIconClass, getIconPickerOptionLabel, getInitialOpenState, getLucideIconName, getModuleChildOrder, getTableMinWidth, isLucideIconValue, isMultilineHeaderLabel, mapModuleDataToSidebarItems, markActiveSidebarItems, parseIconPickerValue, resolveIconKind, resolveModuleChildren, resolveTableColumnLayout, submoduleOpenKey, toIconPickerStoredValue, toLucidePascalCase };
8797
+ export { BarChart, BaseChart, BellWithBadge, Button, ButtonCards, CARD_BG, CSS_ICON_CATALOG, CardContent, CardHistory, ColorPicker, Colors, DEFAULT_ICON_PICKER_ICONS, DEFAULT_MODULE_ICONS, DEFAULT_ROLE_COLORS, DateTimeFilter, DateTimePicker, DevicesCarousel, DialogAlertComponent, DialogConfirmation, DocumentItem, DocumentUpload, DonutChart, DynamicFormFields, FeatureCard, Footer, GeoAPIMaps, Header, Heatmap, IconPicker, InfoGroup, Input, InputNumberFilter, InputSelectFilter, InputTextFilter, InputTimeFilter, KpiCard, LUCIDE_ICON_CATALOG, LineChart, LoadImage, Loader, MapGeo, ModalForm, ModuleCard, ModuleCardList, NotFoundModal, NotFoundSection, NotificationCenter, NotificationModal, OptionCard, PaginationComponent, PdfViewer, PdfViewerService, ProcessingOverlay, ProgressBar, ProgressFormService, QuickAccessCards, RolCard, SelectCustomSearch, SideCard, SideCardDetail, Sidebar, SidebarService, Signature, TOAST_EVENTS, Table, TableChart, Tabs, TitleFilters, Toast, ToastHelper, ToastService, ToggleCustom, UI_CHART_TOKENS, WizardForm, buildChildGridTemplateColumns, filterVisibleSidebarItems, getCssIconClass, getIconPickerOptionLabel, getInitialOpenState, getLucideIconName, getModuleChildOrder, getTableMinWidth, isLucideIconValue, isMultilineHeaderLabel, mapModuleDataToSidebarItems, markActiveSidebarItems, parseIconPickerValue, resolveIconKind, resolveModuleChildren, resolveTableColumnLayout, submoduleOpenKey, toIconPickerStoredValue, toLucidePascalCase };
8567
8798
  //# sourceMappingURL=sapenlinea-components.mjs.map