layout-tsi 0.0.4 → 20.0.0-rc.0
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/README.md +30 -63
- package/fesm2022/layout-tsi.mjs +209 -209
- package/fesm2022/layout-tsi.mjs.map +1 -1
- package/index.d.ts +581 -5
- package/package.json +6 -5
- package/lib/models/general/app-tab.model.d.ts +0 -9
- package/lib/models/general/dashboard.model.d.ts +0 -15
- package/lib/models/general/route-info.model.d.ts +0 -16
- package/lib/models/general/session-data.model.d.ts +0 -8
- package/lib/service/detector.service.d.ts +0 -8
- package/lib/service/header-ui.service.d.ts +0 -9
- package/lib/service/menu.service.d.ts +0 -8
- package/lib/service/tabs.service.d.ts +0 -36
- package/lib/ui/bottom-navigation/bottom-navigation.component.d.ts +0 -31
- package/lib/ui/chatbot/chatbot.component.d.ts +0 -30
- package/lib/ui/chatbot/chatbot.model.d.ts +0 -28
- package/lib/ui/chatbot/chatbot.service.d.ts +0 -19
- package/lib/ui/dashboard/dashboard-chart-bars/dashboard-chart-bars.component.d.ts +0 -45
- package/lib/ui/dashboard/dashboard-chart-donut/dashboard-chart-donut.component.d.ts +0 -21
- package/lib/ui/dashboard/dashboard-view-switcher/dashboard-view-switcher.component.d.ts +0 -14
- package/lib/ui/dashboard/item-dashboard/item-dashboard.component.d.ts +0 -26
- package/lib/ui/dashboard/item-dashboard-group/item-dashboard-group.component.d.ts +0 -28
- package/lib/ui/full/full.component.d.ts +0 -48
- package/lib/ui/menu-item/menu-item.component.d.ts +0 -70
- package/lib/ui/not-found/not-found.component.d.ts +0 -7
- package/lib/ui/tab-bar/tab-bar.component.d.ts +0 -23
- package/lib/ui/vertical-header/vertical-header.component.d.ts +0 -96
- package/lib/utils/validaciones.d.ts +0 -1
- package/public-api.d.ts +0 -21
package/fesm2022/layout-tsi.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import { Subject, combineLatest, EMPTY, filter as filter$1, map as map$1, startW
|
|
|
9
9
|
import { filter, takeUntil, skip, debounceTime, map, distinctUntilChanged, switchMap, catchError } from 'rxjs/operators';
|
|
10
10
|
|
|
11
11
|
class MenuService {
|
|
12
|
-
_openMenus = signal(new Map());
|
|
12
|
+
_openMenus = signal(new Map(), ...(ngDevMode ? [{ debugName: "_openMenus" }] : []));
|
|
13
13
|
openMenus = this._openMenus.asReadonly();
|
|
14
14
|
setOpenMenu(level, id) {
|
|
15
15
|
const currentMap = new Map(this._openMenus());
|
|
@@ -21,10 +21,10 @@ class MenuService {
|
|
|
21
21
|
}
|
|
22
22
|
this._openMenus.set(currentMap);
|
|
23
23
|
}
|
|
24
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
25
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
24
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: MenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
25
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: MenuService, providedIn: 'root' });
|
|
26
26
|
}
|
|
27
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
27
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: MenuService, decorators: [{
|
|
28
28
|
type: Injectable,
|
|
29
29
|
args: [{
|
|
30
30
|
providedIn: 'root'
|
|
@@ -32,18 +32,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
32
32
|
}] });
|
|
33
33
|
|
|
34
34
|
class HeaderUiService {
|
|
35
|
-
typeDocumento = signal(null);
|
|
36
|
-
numintDocumento = signal(null);
|
|
35
|
+
typeDocumento = signal(null, ...(ngDevMode ? [{ debugName: "typeDocumento" }] : []));
|
|
36
|
+
numintDocumento = signal(null, ...(ngDevMode ? [{ debugName: "numintDocumento" }] : []));
|
|
37
37
|
setTypeDocumento(value) {
|
|
38
38
|
this.typeDocumento.set(value);
|
|
39
39
|
}
|
|
40
40
|
setNumintDocumento(value) {
|
|
41
41
|
this.numintDocumento.set(value);
|
|
42
42
|
}
|
|
43
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
44
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
43
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: HeaderUiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
44
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: HeaderUiService, providedIn: 'root' });
|
|
45
45
|
}
|
|
46
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
46
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: HeaderUiService, decorators: [{
|
|
47
47
|
type: Injectable,
|
|
48
48
|
args: [{
|
|
49
49
|
providedIn: 'root'
|
|
@@ -62,15 +62,15 @@ class TabsService {
|
|
|
62
62
|
syncProvider = inject(TABS_SYNC_PROVIDER, { optional: true });
|
|
63
63
|
destroyRef = inject(DestroyRef);
|
|
64
64
|
injector = inject(Injector);
|
|
65
|
-
tabs = signal([]);
|
|
66
|
-
activeId = signal(null);
|
|
67
|
-
visible = signal(true);
|
|
65
|
+
tabs = signal([], ...(ngDevMode ? [{ debugName: "tabs" }] : []));
|
|
66
|
+
activeId = signal(null, ...(ngDevMode ? [{ debugName: "activeId" }] : []));
|
|
67
|
+
visible = signal(true, ...(ngDevMode ? [{ debugName: "visible" }] : []));
|
|
68
68
|
// Corta la carga/sincronización en curso cuando clear() destruye la sesión (logout).
|
|
69
69
|
destroy$ = new Subject();
|
|
70
70
|
sortedTabs = computed(() => {
|
|
71
71
|
const ts = this.tabs();
|
|
72
72
|
return [...ts.filter(t => t.pinned), ...ts.filter(t => !t.pinned)];
|
|
73
|
-
});
|
|
73
|
+
}, ...(ngDevMode ? [{ debugName: "sortedTabs" }] : []));
|
|
74
74
|
toggleVisible() { this.visible.update(v => !v); }
|
|
75
75
|
constructor() {
|
|
76
76
|
this.loadFromStorage();
|
|
@@ -182,16 +182,16 @@ class TabsService {
|
|
|
182
182
|
event.stopPropagation();
|
|
183
183
|
this.tabs.update(ts => ts.map(t => t.id === id ? { ...t, pinned: !t.pinned } : t));
|
|
184
184
|
}
|
|
185
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
186
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
185
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: TabsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
186
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: TabsService, providedIn: 'root' });
|
|
187
187
|
}
|
|
188
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
188
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: TabsService, decorators: [{
|
|
189
189
|
type: Injectable,
|
|
190
190
|
args: [{ providedIn: 'root' }]
|
|
191
191
|
}], ctorParameters: () => [] });
|
|
192
192
|
|
|
193
|
-
const activeFlyoutKey = signal(null);
|
|
194
|
-
const activeTooltip = signal(null);
|
|
193
|
+
const activeFlyoutKey = signal(null, ...(ngDevMode ? [{ debugName: "activeFlyoutKey" }] : []));
|
|
194
|
+
const activeTooltip = signal(null, ...(ngDevMode ? [{ debugName: "activeTooltip" }] : []));
|
|
195
195
|
const EXTRALINK_OPENER = new InjectionToken('EXTRALINK_OPENER');
|
|
196
196
|
class MenuItemComponent {
|
|
197
197
|
menuService = inject(MenuService);
|
|
@@ -199,27 +199,27 @@ class MenuItemComponent {
|
|
|
199
199
|
tabsService = inject(TabsService);
|
|
200
200
|
router = inject(Router);
|
|
201
201
|
extralinkOpener = inject(EXTRALINK_OPENER, { optional: true });
|
|
202
|
-
item = input.required();
|
|
203
|
-
isSidebarOpen = input(true);
|
|
204
|
-
isSidebarHovering = input(false);
|
|
205
|
-
level = input(0);
|
|
206
|
-
parentModuleName = input(null);
|
|
207
|
-
accentColor = input('#398bf7');
|
|
202
|
+
item = input.required(...(ngDevMode ? [{ debugName: "item" }] : []));
|
|
203
|
+
isSidebarOpen = input(true, ...(ngDevMode ? [{ debugName: "isSidebarOpen" }] : []));
|
|
204
|
+
isSidebarHovering = input(false, ...(ngDevMode ? [{ debugName: "isSidebarHovering" }] : []));
|
|
205
|
+
level = input(0, ...(ngDevMode ? [{ debugName: "level" }] : []));
|
|
206
|
+
parentModuleName = input(null, ...(ngDevMode ? [{ debugName: "parentModuleName" }] : []));
|
|
207
|
+
accentColor = input('#398bf7', ...(ngDevMode ? [{ debugName: "accentColor" }] : []));
|
|
208
208
|
// Accesos/rol de la sesión: se reciben del consumidor (en vez de inyectar
|
|
209
209
|
// SesionService acá) para que layout-tsi no dependa de core-tsi.
|
|
210
|
-
accesos = input([]);
|
|
211
|
-
rolId = input(null);
|
|
212
|
-
open = signal(false);
|
|
213
|
-
flyoutY = signal(0);
|
|
214
|
-
expandedFlyoutChild = signal(null);
|
|
210
|
+
accesos = input([], ...(ngDevMode ? [{ debugName: "accesos" }] : []));
|
|
211
|
+
rolId = input(null, ...(ngDevMode ? [{ debugName: "rolId" }] : []));
|
|
212
|
+
open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
213
|
+
flyoutY = signal(0, ...(ngDevMode ? [{ debugName: "flyoutY" }] : []));
|
|
214
|
+
expandedFlyoutChild = signal(null, ...(ngDevMode ? [{ debugName: "expandedFlyoutChild" }] : []));
|
|
215
215
|
flyoutTimer = null;
|
|
216
216
|
tooltip = activeTooltip;
|
|
217
|
-
showFlyout = computed(() => activeFlyoutKey() === this.getFlyoutKey() && this.isSidebarOpen() && window.innerWidth > 1191);
|
|
217
|
+
showFlyout = computed(() => activeFlyoutKey() === this.getFlyoutKey() && this.isSidebarOpen() && window.innerWidth > 1191, ...(ngDevMode ? [{ debugName: "showFlyout" }] : []));
|
|
218
218
|
// El cierre tenía un delay de 80ms (debounce de onItemMouseLeave/onFlyoutMouseLeave)
|
|
219
219
|
// seguido de un @if que lo desmontaba en seco, sin animación — eso es lo que se
|
|
220
220
|
// sentía como "lag" (una pausa y después un salto). Ahora se anima la salida y
|
|
221
221
|
// recién se desmonta cuando esa animación termina.
|
|
222
|
-
flyoutRendered = signal(false);
|
|
222
|
+
flyoutRendered = signal(false, ...(ngDevMode ? [{ debugName: "flyoutRendered" }] : []));
|
|
223
223
|
flyoutExitTimer = null;
|
|
224
224
|
currentUrl = toSignal(this.router.events.pipe(filter$1((e) => e instanceof NavigationEnd), map$1(() => this.router.url), startWith(this.router.url)), { initialValue: this.router.url });
|
|
225
225
|
// Una ruta con query param "project" (p. ej. tareas de un proyecto específico)
|
|
@@ -238,7 +238,7 @@ class MenuItemComponent {
|
|
|
238
238
|
// tiene equivalente CSS puro (Angular removía el <ul> recién al terminar el
|
|
239
239
|
// :leave) — acá se mantiene montado con "--closing" el tiempo de esa
|
|
240
240
|
// animación y recién ahí se desmonta.
|
|
241
|
-
submenuRendered = signal(false);
|
|
241
|
+
submenuRendered = signal(false, ...(ngDevMode ? [{ debugName: "submenuRendered" }] : []));
|
|
242
242
|
submenuLeaveTimer = null;
|
|
243
243
|
constructor() {
|
|
244
244
|
effect(() => {
|
|
@@ -500,19 +500,19 @@ class MenuItemComponent {
|
|
|
500
500
|
return null;
|
|
501
501
|
return item.path;
|
|
502
502
|
}
|
|
503
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
504
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: MenuItemComponent, isStandalone: true, selector: "app-menu-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, isSidebarOpen: { classPropertyName: "isSidebarOpen", publicName: "isSidebarOpen", isSignal: true, isRequired: false, transformFunction: null }, isSidebarHovering: { classPropertyName: "isSidebarHovering", publicName: "isSidebarHovering", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, parentModuleName: { classPropertyName: "parentModuleName", publicName: "parentModuleName", isSignal: true, isRequired: false, transformFunction: null }, accentColor: { classPropertyName: "accentColor", publicName: "accentColor", isSignal: true, isRequired: false, transformFunction: null }, accesos: { classPropertyName: "accesos", publicName: "accesos", isSignal: true, isRequired: false, transformFunction: null }, rolId: { classPropertyName: "rolId", publicName: "rolId", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if(hasAccess()){\r\n<li (mouseenter)=\"onItemMouseEnter($event)\" (mouseleave)=\"onItemMouseLeave()\"\r\n (mouseover)=\"onItemMouseOver()\">\r\n <div class=\"d-flex align-items-center justify-content-between pt-2 pb-2 px-2 item-sidebar\" (click)=\"toggle()\"\r\n (mousedown)=\"onMiddleClick($event)\" (contextmenu)=\"onRightClick($event)\"\r\n [routerLink]=\"(!item().submenu?.length && item().path && !item().extralink) ? item().path : null\"\r\n [class.active-route]=\"esRutaActiva(item().path)\" [class.cursor-pointer]=\"item().submenu?.length == 0\"\r\n [class.cursor-drow]=\"item().submenu?.length > 0\">\r\n <span>\r\n @if (item().title) {\r\n <i [class]=\"(item().icon ? item().icon : '') + (isSidebarActuallyOpen ? ' me-1' : ' me-1 ms-2')\"></i>\r\n <span class=\"sidebar-text\" [class.sidebar-text--hidden]=\"!isSidebarActuallyOpen\">\r\n {{ item().title }}\r\n </span>\r\n }\r\n </span>\r\n @if (item().submenu?.length > 0) {\r\n <i class=\"fas sidebar-chevron\" [class.sidebar-chevron--hidden]=\"!isSidebarActuallyOpen\" [ngClass]=\"{\r\n 'fa-chevron-down': isOpen(),\r\n 'fa-chevron-right': !isOpen()\r\n }\"></i>\r\n }\r\n </div>\r\n @if (item().submenu?.length && isSidebarActuallyOpen && submenuRendered()) {\r\n <ul class=\"list-unstyled ms-3 submenu\" [class.submenu--closing]=\"!isOpen()\">\r\n @for (child of item().submenu; track $index) {\r\n <app-menu-item [item]=\"child\" [level]=\"level() + 1\" [isSidebarOpen]=\"!isSidebarActuallyOpen\" [parentModuleName]=\"parentModuleName()\" [accentColor]=\"accentColor()\" [accesos]=\"accesos()\" [rolId]=\"rolId()\" />\r\n }\r\n </ul>\r\n }\r\n\r\n @if (flyoutRendered()) {\r\n <div class=\"sidebar-flyout\" [class.sidebar-flyout--closing]=\"!showFlyout()\" [style.top.px]=\"flyoutY()\" [style.max-height]=\"'calc(100dvh - ' + flyoutY() + 'px - 8px)'\"\r\n [style.--flyout-accent]=\"accentColor()\" (mouseenter)=\"onFlyoutMouseEnter()\" (mouseleave)=\"onFlyoutMouseLeave()\">\r\n <div class=\"flyout-header\">\r\n <i [class]=\"(item().icon || '') + ' flyout-header-icon'\"></i>\r\n <span class=\"flyout-header-title\">{{ item().title }}</span>\r\n @if (codAcceso()) {\r\n <span class=\"flyout-header-acceso\">{{ codAcceso().split(': ')[1] }}</span>\r\n }\r\n </div>\r\n @if (item().submenu?.length > 0) {\r\n <ul class=\"list-unstyled flyout-items\">\r\n @for (child of item().submenu; track $index) {\r\n @if (hasAccess(child)) {\r\n <li class=\"flyout-group\">\r\n <div class=\"flyout-item\" [class.flyout-item-has-children]=\"child.submenu?.length > 0\"\r\n [class.flyout-item-expanded]=\"isFlyoutChildExpanded(child)\" [routerLink]=\"manejarRuta(child)\"\r\n [class.flyout-item-active]=\"!child.submenu?.length && esRutaActiva(child.path)\"\r\n (click)=\"onFlyoutItemClick(child, $event)\" (mousedown)=\"onFlyoutItemMiddleClick($event, child)\"\r\n (contextmenu)=\"onFlyoutItemRightClick($event, child)\" (mouseenter)=\"showChildTooltip($event, child)\"\r\n (mouseleave)=\"hideChildTooltip()\">\r\n @if (child.icon) {\r\n <i [class]=\"child.icon + ' flyout-item-icon'\"></i>\r\n }\r\n <span class=\"flyout-item-label\">{{ child.title }}</span>\r\n @if (child.submenu?.length > 0) {\r\n <i class=\"fas flyout-chevron\" [class.fa-chevron-down]=\"isFlyoutChildExpanded(child)\"\r\n [class.fa-chevron-right]=\"!isFlyoutChildExpanded(child)\"></i>\r\n }\r\n </div>\r\n\r\n @if (isFlyoutChildExpanded(child) && child.submenu?.length > 0) {\r\n <ul class=\"list-unstyled flyout-subitems\">\r\n @for (grandchild of child.submenu; track $index) {\r\n @if (hasAccess(grandchild)) {\r\n <li class=\"flyout-subitem\" [routerLink]=\"manejarRuta(grandchild)\" [class.flyout-subitem-active]=\"esRutaActiva(grandchild.path)\"\r\n (click)=\"onFlyoutGrandchildClick(grandchild)\" (mousedown)=\"onFlyoutItemMiddleClick($event, grandchild)\"\r\n (contextmenu)=\"onFlyoutItemRightClick($event, grandchild)\"\r\n (mouseenter)=\"showChildTooltip($event, grandchild)\" (mouseleave)=\"hideChildTooltip()\">\r\n @if (grandchild.icon) {\r\n <i [class]=\"grandchild.icon + ' flyout-item-icon'\"></i>\r\n }\r\n <span class=\"flyout-item-label\">{{ grandchild.title }}</span>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n</li>\r\n}\r\n\r\n@if (tooltip()?.text) {\r\n<div class=\"acceso-tooltip-fixed\" [style.left.px]=\"tooltip()!.x\" [style.top.px]=\"tooltip()!.y\">\r\n <span class=\"tooltip-label\">{{ tooltip()!.text.split(': ')[0] }}:</span>\r\n <span class=\"tooltip-value\">{{ tooltip()!.text.split(': ')[1] }}</span>\r\n</div>\r\n}\r\n", styles: [".active-route{color:var(--sidebar-active-text)!important;background:linear-gradient(90deg,#ffffff24,#ffffff0a)!important;border-left:3px solid var(--sidebar-accent, #c50048)!important;border-radius:0 8px 8px 0!important;box-shadow:inset 0 1px #ffffff0f!important}.cursor-drow{cursor:default}.submenu{transform-origin:top;animation:submenuIn .26s cubic-bezier(.4,0,.2,1) both}.submenu--closing{animation:submenuOut .22s cubic-bezier(.4,0,.2,1) both}@keyframes submenuIn{0%{opacity:0;transform:translateY(-8px) scaleY(.94)}to{opacity:1;transform:translateY(0) scaleY(1)}}@keyframes submenuOut{0%{opacity:1;transform:translateY(0) scaleY(1)}to{opacity:0;transform:translateY(-8px) scaleY(.94)}}.acceso-tooltip-fixed{position:fixed;z-index:99999;transform:translateY(-50%);pointer-events:none;padding:4px 10px 4px 8px;border-radius:6px;font-family:monospace;white-space:nowrap;background:#0f0f14;border:1px solid rgba(255,255,255,.07);border-left:2px solid var(--sidebar-accent, #c50048);display:flex;align-items:center;gap:5px;animation:tooltipFadeIn .14s cubic-bezier(.25,.46,.45,.94)}.acceso-tooltip-fixed .tooltip-label{font-size:10px;font-weight:400;color:#fff;letter-spacing:.3px}.acceso-tooltip-fixed .tooltip-value{font-size:11px;font-weight:700;color:var(--sidebar-accent, #c50048)}.acceso-tooltip-fixed:before{content:\"\";position:absolute;right:100%;top:50%;transform:translateY(-50%);border:4px solid transparent;border-right-color:var(--sidebar-accent, #c50048)}@keyframes tooltipFadeIn{0%{opacity:0;transform:translateY(-50%) translate(-4px)}to{opacity:1;transform:translateY(-50%) translate(0)}}.sidebar-text{display:inline-block;vertical-align:middle;white-space:normal;word-break:break-word;opacity:1;transform:translate(0);transition:opacity .15s ease .22s,transform .15s ease .22s}.sidebar-text--hidden{opacity:0;transform:translate(-4px);white-space:nowrap;max-width:0;overflow:hidden;transition:opacity .12s ease 0s,transform .12s ease 0s,max-width 0s linear .12s}.sidebar-chevron{opacity:1;transition:opacity .15s ease .22s}.sidebar-chevron--hidden{opacity:0;transition:opacity .12s ease 0s}.item-sidebar{color:var(--sidebar-text-color)!important;transition:all .2s ease;border-radius:8px}.item-sidebar>span:first-child{min-width:0;flex:1}.item-sidebar:hover{color:var(--sidebar-active-text)!important;background:#ffffff17!important;transform:translate(2px)}:host-context(.sidebar.open) .item-sidebar{border-radius:8px 0 0 8px;margin-right:-8px}:host-context(.sidebar.open) .item-sidebar:hover{transform:none}:host-context(.sidebar.open) .item-sidebar.active-route{border-radius:0!important;background:#ffffff24!important}.sidebar-flyout{position:fixed;left:70px;z-index:9999;min-width:220px;max-width:300px;overflow-y:auto;scrollbar-width:none;background:linear-gradient(160deg,var(--sidebar-gradient-start, #1a1a2e) 0%,var(--sidebar-bg, #16213e) 100%);border:1px solid rgba(255,255,255,.1);border-left:3px solid var(--flyout-accent, #c50048);border-radius:0 12px 12px;box-shadow:8px 6px 32px #0000008c,0 0 0 1px #ffffff0a;animation:flyout-slide-in .15s cubic-bezier(.25,.46,.45,.94);pointer-events:auto}.sidebar-flyout--closing{animation:flyout-slide-out .13s ease-in both}@keyframes flyout-slide-out{0%{opacity:1;transform:translate(0)}to{opacity:0;transform:translate(-8px)}}.flyout-header{display:flex;align-items:center;gap:10px;padding:12px 16px 10px;border-bottom:1px solid rgba(255,255,255,.08);background:#ffffff0a}.flyout-header-icon{color:var(--flyout-accent, #c50048);font-size:14px;min-width:16px;text-align:center}.flyout-header-title{font-size:12px;font-weight:700;color:var(--sidebar-active-text, #fff);letter-spacing:.5px;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}.flyout-header-acceso{font-size:10px;font-weight:700;font-family:monospace;color:var(--flyout-accent, #c50048);background:#ffffff12;border:1px solid rgba(255,255,255,.1);border-left:2px solid var(--flyout-accent, #c50048);padding:2px 7px;border-radius:4px;white-space:nowrap;flex-shrink:0}.flyout-items{padding:6px;margin:0}.flyout-item{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:8px;cursor:pointer;color:var(--sidebar-text-color, rgba(255, 255, 255, .7));font-size:13px;transition:background .15s ease,color .15s ease,transform .15s ease;white-space:nowrap;overflow:hidden;position:relative}.flyout-item:hover{background:#ffffff1a;color:var(--sidebar-active-text, #fff);transform:translate(3px)}.flyout-item-active{background:linear-gradient(90deg,#ffffff21,#ffffff08)!important;color:var(--sidebar-active-text, #fff)!important}.flyout-item-active:before{content:\"\";position:absolute;left:0;top:15%;height:70%;width:3px;background:var(--flyout-accent, #c50048);border-radius:0 2px 2px 0}.flyout-item-icon{font-size:12px;min-width:14px;text-align:center;color:inherit;opacity:.75}.flyout-item-label{flex:1;overflow:hidden;text-overflow:ellipsis}.flyout-chevron{font-size:10px;opacity:.5;margin-left:auto;flex-shrink:0;transition:transform .2s ease}.flyout-group{display:flex;flex-direction:column}.flyout-item-has-children{cursor:default}.flyout-item-expanded{background:#ffffff12!important;color:var(--sidebar-active-text, #fff)!important}.flyout-subitems{padding:2px 6px 2px 14px;border-left:2px solid rgba(255,255,255,.1);margin:0 6px 4px 20px}.flyout-subitem{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:6px;cursor:pointer;color:var(--sidebar-text-color, rgba(255, 255, 255, .65));font-size:12px;transition:background .15s ease,color .15s ease,transform .15s ease;white-space:nowrap;overflow:hidden}.flyout-subitem:hover{background:#ffffff17;color:var(--sidebar-active-text, #fff);transform:translate(2px)}.flyout-subitem-active{color:var(--sidebar-active-text, #fff)!important;position:relative}.flyout-subitem-active:before{content:\"\";position:absolute;left:-14px;top:20%;height:60%;width:2px;background:var(--flyout-accent, #c50048);border-radius:1px}@keyframes flyout-slide-in{0%{opacity:0;transform:translate(-10px)}to{opacity:1;transform:translate(0)}}\n"], dependencies: [{ kind: "component", type: MenuItemComponent, selector: "app-menu-item", inputs: ["item", "isSidebarOpen", "isSidebarHovering", "level", "parentModuleName", "accentColor", "accesos", "rolId"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
503
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: MenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
504
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: MenuItemComponent, isStandalone: true, selector: "app-menu-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, isSidebarOpen: { classPropertyName: "isSidebarOpen", publicName: "isSidebarOpen", isSignal: true, isRequired: false, transformFunction: null }, isSidebarHovering: { classPropertyName: "isSidebarHovering", publicName: "isSidebarHovering", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, parentModuleName: { classPropertyName: "parentModuleName", publicName: "parentModuleName", isSignal: true, isRequired: false, transformFunction: null }, accentColor: { classPropertyName: "accentColor", publicName: "accentColor", isSignal: true, isRequired: false, transformFunction: null }, accesos: { classPropertyName: "accesos", publicName: "accesos", isSignal: true, isRequired: false, transformFunction: null }, rolId: { classPropertyName: "rolId", publicName: "rolId", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if(hasAccess()){\r\n<li (mouseenter)=\"onItemMouseEnter($event)\" (mouseleave)=\"onItemMouseLeave()\"\r\n (mouseover)=\"onItemMouseOver()\">\r\n <div class=\"d-flex align-items-center justify-content-between pt-2 pb-2 px-2 item-sidebar\" (click)=\"toggle()\"\r\n (mousedown)=\"onMiddleClick($event)\" (contextmenu)=\"onRightClick($event)\"\r\n [routerLink]=\"(!item().submenu?.length && item().path && !item().extralink) ? item().path : null\"\r\n [class.active-route]=\"esRutaActiva(item().path)\" [class.cursor-pointer]=\"item().submenu?.length == 0\"\r\n [class.cursor-drow]=\"item().submenu?.length > 0\">\r\n <span>\r\n @if (item().title) {\r\n <i [class]=\"(item().icon ? item().icon : '') + (isSidebarActuallyOpen ? ' me-1' : ' me-1 ms-2')\"></i>\r\n <span class=\"sidebar-text\" [class.sidebar-text--hidden]=\"!isSidebarActuallyOpen\">\r\n {{ item().title }}\r\n </span>\r\n }\r\n </span>\r\n @if (item().submenu?.length > 0) {\r\n <i class=\"fas sidebar-chevron\" [class.sidebar-chevron--hidden]=\"!isSidebarActuallyOpen\" [ngClass]=\"{\r\n 'fa-chevron-down': isOpen(),\r\n 'fa-chevron-right': !isOpen()\r\n }\"></i>\r\n }\r\n </div>\r\n @if (item().submenu?.length && isSidebarActuallyOpen && submenuRendered()) {\r\n <ul class=\"list-unstyled ms-3 submenu\" [class.submenu--closing]=\"!isOpen()\">\r\n @for (child of item().submenu; track $index) {\r\n <app-menu-item [item]=\"child\" [level]=\"level() + 1\" [isSidebarOpen]=\"!isSidebarActuallyOpen\" [parentModuleName]=\"parentModuleName()\" [accentColor]=\"accentColor()\" [accesos]=\"accesos()\" [rolId]=\"rolId()\" />\r\n }\r\n </ul>\r\n }\r\n\r\n @if (flyoutRendered()) {\r\n <div class=\"sidebar-flyout\" [class.sidebar-flyout--closing]=\"!showFlyout()\" [style.top.px]=\"flyoutY()\" [style.max-height]=\"'calc(100dvh - ' + flyoutY() + 'px - 8px)'\"\r\n [style.--flyout-accent]=\"accentColor()\" (mouseenter)=\"onFlyoutMouseEnter()\" (mouseleave)=\"onFlyoutMouseLeave()\">\r\n <div class=\"flyout-header\">\r\n <i [class]=\"(item().icon || '') + ' flyout-header-icon'\"></i>\r\n <span class=\"flyout-header-title\">{{ item().title }}</span>\r\n @if (codAcceso()) {\r\n <span class=\"flyout-header-acceso\">{{ codAcceso().split(': ')[1] }}</span>\r\n }\r\n </div>\r\n @if (item().submenu?.length > 0) {\r\n <ul class=\"list-unstyled flyout-items\">\r\n @for (child of item().submenu; track $index) {\r\n @if (hasAccess(child)) {\r\n <li class=\"flyout-group\">\r\n <div class=\"flyout-item\" [class.flyout-item-has-children]=\"child.submenu?.length > 0\"\r\n [class.flyout-item-expanded]=\"isFlyoutChildExpanded(child)\" [routerLink]=\"manejarRuta(child)\"\r\n [class.flyout-item-active]=\"!child.submenu?.length && esRutaActiva(child.path)\"\r\n (click)=\"onFlyoutItemClick(child, $event)\" (mousedown)=\"onFlyoutItemMiddleClick($event, child)\"\r\n (contextmenu)=\"onFlyoutItemRightClick($event, child)\" (mouseenter)=\"showChildTooltip($event, child)\"\r\n (mouseleave)=\"hideChildTooltip()\">\r\n @if (child.icon) {\r\n <i [class]=\"child.icon + ' flyout-item-icon'\"></i>\r\n }\r\n <span class=\"flyout-item-label\">{{ child.title }}</span>\r\n @if (child.submenu?.length > 0) {\r\n <i class=\"fas flyout-chevron\" [class.fa-chevron-down]=\"isFlyoutChildExpanded(child)\"\r\n [class.fa-chevron-right]=\"!isFlyoutChildExpanded(child)\"></i>\r\n }\r\n </div>\r\n\r\n @if (isFlyoutChildExpanded(child) && child.submenu?.length > 0) {\r\n <ul class=\"list-unstyled flyout-subitems\">\r\n @for (grandchild of child.submenu; track $index) {\r\n @if (hasAccess(grandchild)) {\r\n <li class=\"flyout-subitem\" [routerLink]=\"manejarRuta(grandchild)\" [class.flyout-subitem-active]=\"esRutaActiva(grandchild.path)\"\r\n (click)=\"onFlyoutGrandchildClick(grandchild)\" (mousedown)=\"onFlyoutItemMiddleClick($event, grandchild)\"\r\n (contextmenu)=\"onFlyoutItemRightClick($event, grandchild)\"\r\n (mouseenter)=\"showChildTooltip($event, grandchild)\" (mouseleave)=\"hideChildTooltip()\">\r\n @if (grandchild.icon) {\r\n <i [class]=\"grandchild.icon + ' flyout-item-icon'\"></i>\r\n }\r\n <span class=\"flyout-item-label\">{{ grandchild.title }}</span>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n</li>\r\n}\r\n\r\n@if (tooltip()?.text) {\r\n<div class=\"acceso-tooltip-fixed\" [style.left.px]=\"tooltip()!.x\" [style.top.px]=\"tooltip()!.y\">\r\n <span class=\"tooltip-label\">{{ tooltip()!.text.split(': ')[0] }}:</span>\r\n <span class=\"tooltip-value\">{{ tooltip()!.text.split(': ')[1] }}</span>\r\n</div>\r\n}\r\n", styles: [".active-route{color:var(--sidebar-active-text)!important;background:linear-gradient(90deg,#ffffff24,#ffffff0a)!important;border-left:3px solid var(--sidebar-accent, #c50048)!important;border-radius:0 8px 8px 0!important;box-shadow:inset 0 1px #ffffff0f!important}.cursor-drow{cursor:default}.submenu{transform-origin:top;animation:submenuIn .26s cubic-bezier(.4,0,.2,1) both}.submenu--closing{animation:submenuOut .22s cubic-bezier(.4,0,.2,1) both}@keyframes submenuIn{0%{opacity:0;transform:translateY(-8px) scaleY(.94)}to{opacity:1;transform:translateY(0) scaleY(1)}}@keyframes submenuOut{0%{opacity:1;transform:translateY(0) scaleY(1)}to{opacity:0;transform:translateY(-8px) scaleY(.94)}}.acceso-tooltip-fixed{position:fixed;z-index:99999;transform:translateY(-50%);pointer-events:none;padding:4px 10px 4px 8px;border-radius:6px;font-family:monospace;white-space:nowrap;background:#0f0f14;border:1px solid rgba(255,255,255,.07);border-left:2px solid var(--sidebar-accent, #c50048);display:flex;align-items:center;gap:5px;animation:tooltipFadeIn .14s cubic-bezier(.25,.46,.45,.94)}.acceso-tooltip-fixed .tooltip-label{font-size:10px;font-weight:400;color:#fff;letter-spacing:.3px}.acceso-tooltip-fixed .tooltip-value{font-size:11px;font-weight:700;color:var(--sidebar-accent, #c50048)}.acceso-tooltip-fixed:before{content:\"\";position:absolute;right:100%;top:50%;transform:translateY(-50%);border:4px solid transparent;border-right-color:var(--sidebar-accent, #c50048)}@keyframes tooltipFadeIn{0%{opacity:0;transform:translateY(-50%) translate(-4px)}to{opacity:1;transform:translateY(-50%) translate(0)}}.sidebar-text{display:inline-block;vertical-align:middle;white-space:normal;word-break:break-word;opacity:1;transform:translate(0);transition:opacity .15s ease .22s,transform .15s ease .22s}.sidebar-text--hidden{opacity:0;transform:translate(-4px);white-space:nowrap;max-width:0;overflow:hidden;transition:opacity .12s ease 0s,transform .12s ease 0s,max-width 0s linear .12s}.sidebar-chevron{opacity:1;transition:opacity .15s ease .22s}.sidebar-chevron--hidden{opacity:0;transition:opacity .12s ease 0s}.item-sidebar{color:var(--sidebar-text-color)!important;transition:all .2s ease;border-radius:8px}.item-sidebar>span:first-child{min-width:0;flex:1}.item-sidebar:hover{color:var(--sidebar-active-text)!important;background:#ffffff17!important;transform:translate(2px)}:host-context(.sidebar.open) .item-sidebar{border-radius:8px 0 0 8px;margin-right:-8px}:host-context(.sidebar.open) .item-sidebar:hover{transform:none}:host-context(.sidebar.open) .item-sidebar.active-route{border-radius:0!important;background:#ffffff24!important}.sidebar-flyout{position:fixed;left:70px;z-index:9999;min-width:220px;max-width:300px;overflow-y:auto;scrollbar-width:none;background:linear-gradient(160deg,var(--sidebar-gradient-start, #1a1a2e) 0%,var(--sidebar-bg, #16213e) 100%);border:1px solid rgba(255,255,255,.1);border-left:3px solid var(--flyout-accent, #c50048);border-radius:0 12px 12px;box-shadow:8px 6px 32px #0000008c,0 0 0 1px #ffffff0a;animation:flyout-slide-in .15s cubic-bezier(.25,.46,.45,.94);pointer-events:auto}.sidebar-flyout--closing{animation:flyout-slide-out .13s ease-in both}@keyframes flyout-slide-out{0%{opacity:1;transform:translate(0)}to{opacity:0;transform:translate(-8px)}}.flyout-header{display:flex;align-items:center;gap:10px;padding:12px 16px 10px;border-bottom:1px solid rgba(255,255,255,.08);background:#ffffff0a}.flyout-header-icon{color:var(--flyout-accent, #c50048);font-size:14px;min-width:16px;text-align:center}.flyout-header-title{font-size:12px;font-weight:700;color:var(--sidebar-active-text, #fff);letter-spacing:.5px;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}.flyout-header-acceso{font-size:10px;font-weight:700;font-family:monospace;color:var(--flyout-accent, #c50048);background:#ffffff12;border:1px solid rgba(255,255,255,.1);border-left:2px solid var(--flyout-accent, #c50048);padding:2px 7px;border-radius:4px;white-space:nowrap;flex-shrink:0}.flyout-items{padding:6px;margin:0}.flyout-item{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:8px;cursor:pointer;color:var(--sidebar-text-color, rgba(255, 255, 255, .7));font-size:13px;transition:background .15s ease,color .15s ease,transform .15s ease;white-space:nowrap;overflow:hidden;position:relative}.flyout-item:hover{background:#ffffff1a;color:var(--sidebar-active-text, #fff);transform:translate(3px)}.flyout-item-active{background:linear-gradient(90deg,#ffffff21,#ffffff08)!important;color:var(--sidebar-active-text, #fff)!important}.flyout-item-active:before{content:\"\";position:absolute;left:0;top:15%;height:70%;width:3px;background:var(--flyout-accent, #c50048);border-radius:0 2px 2px 0}.flyout-item-icon{font-size:12px;min-width:14px;text-align:center;color:inherit;opacity:.75}.flyout-item-label{flex:1;overflow:hidden;text-overflow:ellipsis}.flyout-chevron{font-size:10px;opacity:.5;margin-left:auto;flex-shrink:0;transition:transform .2s ease}.flyout-group{display:flex;flex-direction:column}.flyout-item-has-children{cursor:default}.flyout-item-expanded{background:#ffffff12!important;color:var(--sidebar-active-text, #fff)!important}.flyout-subitems{padding:2px 6px 2px 14px;border-left:2px solid rgba(255,255,255,.1);margin:0 6px 4px 20px}.flyout-subitem{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:6px;cursor:pointer;color:var(--sidebar-text-color, rgba(255, 255, 255, .65));font-size:12px;transition:background .15s ease,color .15s ease,transform .15s ease;white-space:nowrap;overflow:hidden}.flyout-subitem:hover{background:#ffffff17;color:var(--sidebar-active-text, #fff);transform:translate(2px)}.flyout-subitem-active{color:var(--sidebar-active-text, #fff)!important;position:relative}.flyout-subitem-active:before{content:\"\";position:absolute;left:-14px;top:20%;height:60%;width:2px;background:var(--flyout-accent, #c50048);border-radius:1px}@keyframes flyout-slide-in{0%{opacity:0;transform:translate(-10px)}to{opacity:1;transform:translate(0)}}\n"], dependencies: [{ kind: "component", type: MenuItemComponent, selector: "app-menu-item", inputs: ["item", "isSidebarOpen", "isSidebarHovering", "level", "parentModuleName", "accentColor", "accesos", "rolId"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
505
505
|
}
|
|
506
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
506
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: MenuItemComponent, decorators: [{
|
|
507
507
|
type: Component,
|
|
508
508
|
args: [{ selector: 'app-menu-item', imports: [NgClass, RouterLink], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if(hasAccess()){\r\n<li (mouseenter)=\"onItemMouseEnter($event)\" (mouseleave)=\"onItemMouseLeave()\"\r\n (mouseover)=\"onItemMouseOver()\">\r\n <div class=\"d-flex align-items-center justify-content-between pt-2 pb-2 px-2 item-sidebar\" (click)=\"toggle()\"\r\n (mousedown)=\"onMiddleClick($event)\" (contextmenu)=\"onRightClick($event)\"\r\n [routerLink]=\"(!item().submenu?.length && item().path && !item().extralink) ? item().path : null\"\r\n [class.active-route]=\"esRutaActiva(item().path)\" [class.cursor-pointer]=\"item().submenu?.length == 0\"\r\n [class.cursor-drow]=\"item().submenu?.length > 0\">\r\n <span>\r\n @if (item().title) {\r\n <i [class]=\"(item().icon ? item().icon : '') + (isSidebarActuallyOpen ? ' me-1' : ' me-1 ms-2')\"></i>\r\n <span class=\"sidebar-text\" [class.sidebar-text--hidden]=\"!isSidebarActuallyOpen\">\r\n {{ item().title }}\r\n </span>\r\n }\r\n </span>\r\n @if (item().submenu?.length > 0) {\r\n <i class=\"fas sidebar-chevron\" [class.sidebar-chevron--hidden]=\"!isSidebarActuallyOpen\" [ngClass]=\"{\r\n 'fa-chevron-down': isOpen(),\r\n 'fa-chevron-right': !isOpen()\r\n }\"></i>\r\n }\r\n </div>\r\n @if (item().submenu?.length && isSidebarActuallyOpen && submenuRendered()) {\r\n <ul class=\"list-unstyled ms-3 submenu\" [class.submenu--closing]=\"!isOpen()\">\r\n @for (child of item().submenu; track $index) {\r\n <app-menu-item [item]=\"child\" [level]=\"level() + 1\" [isSidebarOpen]=\"!isSidebarActuallyOpen\" [parentModuleName]=\"parentModuleName()\" [accentColor]=\"accentColor()\" [accesos]=\"accesos()\" [rolId]=\"rolId()\" />\r\n }\r\n </ul>\r\n }\r\n\r\n @if (flyoutRendered()) {\r\n <div class=\"sidebar-flyout\" [class.sidebar-flyout--closing]=\"!showFlyout()\" [style.top.px]=\"flyoutY()\" [style.max-height]=\"'calc(100dvh - ' + flyoutY() + 'px - 8px)'\"\r\n [style.--flyout-accent]=\"accentColor()\" (mouseenter)=\"onFlyoutMouseEnter()\" (mouseleave)=\"onFlyoutMouseLeave()\">\r\n <div class=\"flyout-header\">\r\n <i [class]=\"(item().icon || '') + ' flyout-header-icon'\"></i>\r\n <span class=\"flyout-header-title\">{{ item().title }}</span>\r\n @if (codAcceso()) {\r\n <span class=\"flyout-header-acceso\">{{ codAcceso().split(': ')[1] }}</span>\r\n }\r\n </div>\r\n @if (item().submenu?.length > 0) {\r\n <ul class=\"list-unstyled flyout-items\">\r\n @for (child of item().submenu; track $index) {\r\n @if (hasAccess(child)) {\r\n <li class=\"flyout-group\">\r\n <div class=\"flyout-item\" [class.flyout-item-has-children]=\"child.submenu?.length > 0\"\r\n [class.flyout-item-expanded]=\"isFlyoutChildExpanded(child)\" [routerLink]=\"manejarRuta(child)\"\r\n [class.flyout-item-active]=\"!child.submenu?.length && esRutaActiva(child.path)\"\r\n (click)=\"onFlyoutItemClick(child, $event)\" (mousedown)=\"onFlyoutItemMiddleClick($event, child)\"\r\n (contextmenu)=\"onFlyoutItemRightClick($event, child)\" (mouseenter)=\"showChildTooltip($event, child)\"\r\n (mouseleave)=\"hideChildTooltip()\">\r\n @if (child.icon) {\r\n <i [class]=\"child.icon + ' flyout-item-icon'\"></i>\r\n }\r\n <span class=\"flyout-item-label\">{{ child.title }}</span>\r\n @if (child.submenu?.length > 0) {\r\n <i class=\"fas flyout-chevron\" [class.fa-chevron-down]=\"isFlyoutChildExpanded(child)\"\r\n [class.fa-chevron-right]=\"!isFlyoutChildExpanded(child)\"></i>\r\n }\r\n </div>\r\n\r\n @if (isFlyoutChildExpanded(child) && child.submenu?.length > 0) {\r\n <ul class=\"list-unstyled flyout-subitems\">\r\n @for (grandchild of child.submenu; track $index) {\r\n @if (hasAccess(grandchild)) {\r\n <li class=\"flyout-subitem\" [routerLink]=\"manejarRuta(grandchild)\" [class.flyout-subitem-active]=\"esRutaActiva(grandchild.path)\"\r\n (click)=\"onFlyoutGrandchildClick(grandchild)\" (mousedown)=\"onFlyoutItemMiddleClick($event, grandchild)\"\r\n (contextmenu)=\"onFlyoutItemRightClick($event, grandchild)\"\r\n (mouseenter)=\"showChildTooltip($event, grandchild)\" (mouseleave)=\"hideChildTooltip()\">\r\n @if (grandchild.icon) {\r\n <i [class]=\"grandchild.icon + ' flyout-item-icon'\"></i>\r\n }\r\n <span class=\"flyout-item-label\">{{ grandchild.title }}</span>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n</li>\r\n}\r\n\r\n@if (tooltip()?.text) {\r\n<div class=\"acceso-tooltip-fixed\" [style.left.px]=\"tooltip()!.x\" [style.top.px]=\"tooltip()!.y\">\r\n <span class=\"tooltip-label\">{{ tooltip()!.text.split(': ')[0] }}:</span>\r\n <span class=\"tooltip-value\">{{ tooltip()!.text.split(': ')[1] }}</span>\r\n</div>\r\n}\r\n", styles: [".active-route{color:var(--sidebar-active-text)!important;background:linear-gradient(90deg,#ffffff24,#ffffff0a)!important;border-left:3px solid var(--sidebar-accent, #c50048)!important;border-radius:0 8px 8px 0!important;box-shadow:inset 0 1px #ffffff0f!important}.cursor-drow{cursor:default}.submenu{transform-origin:top;animation:submenuIn .26s cubic-bezier(.4,0,.2,1) both}.submenu--closing{animation:submenuOut .22s cubic-bezier(.4,0,.2,1) both}@keyframes submenuIn{0%{opacity:0;transform:translateY(-8px) scaleY(.94)}to{opacity:1;transform:translateY(0) scaleY(1)}}@keyframes submenuOut{0%{opacity:1;transform:translateY(0) scaleY(1)}to{opacity:0;transform:translateY(-8px) scaleY(.94)}}.acceso-tooltip-fixed{position:fixed;z-index:99999;transform:translateY(-50%);pointer-events:none;padding:4px 10px 4px 8px;border-radius:6px;font-family:monospace;white-space:nowrap;background:#0f0f14;border:1px solid rgba(255,255,255,.07);border-left:2px solid var(--sidebar-accent, #c50048);display:flex;align-items:center;gap:5px;animation:tooltipFadeIn .14s cubic-bezier(.25,.46,.45,.94)}.acceso-tooltip-fixed .tooltip-label{font-size:10px;font-weight:400;color:#fff;letter-spacing:.3px}.acceso-tooltip-fixed .tooltip-value{font-size:11px;font-weight:700;color:var(--sidebar-accent, #c50048)}.acceso-tooltip-fixed:before{content:\"\";position:absolute;right:100%;top:50%;transform:translateY(-50%);border:4px solid transparent;border-right-color:var(--sidebar-accent, #c50048)}@keyframes tooltipFadeIn{0%{opacity:0;transform:translateY(-50%) translate(-4px)}to{opacity:1;transform:translateY(-50%) translate(0)}}.sidebar-text{display:inline-block;vertical-align:middle;white-space:normal;word-break:break-word;opacity:1;transform:translate(0);transition:opacity .15s ease .22s,transform .15s ease .22s}.sidebar-text--hidden{opacity:0;transform:translate(-4px);white-space:nowrap;max-width:0;overflow:hidden;transition:opacity .12s ease 0s,transform .12s ease 0s,max-width 0s linear .12s}.sidebar-chevron{opacity:1;transition:opacity .15s ease .22s}.sidebar-chevron--hidden{opacity:0;transition:opacity .12s ease 0s}.item-sidebar{color:var(--sidebar-text-color)!important;transition:all .2s ease;border-radius:8px}.item-sidebar>span:first-child{min-width:0;flex:1}.item-sidebar:hover{color:var(--sidebar-active-text)!important;background:#ffffff17!important;transform:translate(2px)}:host-context(.sidebar.open) .item-sidebar{border-radius:8px 0 0 8px;margin-right:-8px}:host-context(.sidebar.open) .item-sidebar:hover{transform:none}:host-context(.sidebar.open) .item-sidebar.active-route{border-radius:0!important;background:#ffffff24!important}.sidebar-flyout{position:fixed;left:70px;z-index:9999;min-width:220px;max-width:300px;overflow-y:auto;scrollbar-width:none;background:linear-gradient(160deg,var(--sidebar-gradient-start, #1a1a2e) 0%,var(--sidebar-bg, #16213e) 100%);border:1px solid rgba(255,255,255,.1);border-left:3px solid var(--flyout-accent, #c50048);border-radius:0 12px 12px;box-shadow:8px 6px 32px #0000008c,0 0 0 1px #ffffff0a;animation:flyout-slide-in .15s cubic-bezier(.25,.46,.45,.94);pointer-events:auto}.sidebar-flyout--closing{animation:flyout-slide-out .13s ease-in both}@keyframes flyout-slide-out{0%{opacity:1;transform:translate(0)}to{opacity:0;transform:translate(-8px)}}.flyout-header{display:flex;align-items:center;gap:10px;padding:12px 16px 10px;border-bottom:1px solid rgba(255,255,255,.08);background:#ffffff0a}.flyout-header-icon{color:var(--flyout-accent, #c50048);font-size:14px;min-width:16px;text-align:center}.flyout-header-title{font-size:12px;font-weight:700;color:var(--sidebar-active-text, #fff);letter-spacing:.5px;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}.flyout-header-acceso{font-size:10px;font-weight:700;font-family:monospace;color:var(--flyout-accent, #c50048);background:#ffffff12;border:1px solid rgba(255,255,255,.1);border-left:2px solid var(--flyout-accent, #c50048);padding:2px 7px;border-radius:4px;white-space:nowrap;flex-shrink:0}.flyout-items{padding:6px;margin:0}.flyout-item{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:8px;cursor:pointer;color:var(--sidebar-text-color, rgba(255, 255, 255, .7));font-size:13px;transition:background .15s ease,color .15s ease,transform .15s ease;white-space:nowrap;overflow:hidden;position:relative}.flyout-item:hover{background:#ffffff1a;color:var(--sidebar-active-text, #fff);transform:translate(3px)}.flyout-item-active{background:linear-gradient(90deg,#ffffff21,#ffffff08)!important;color:var(--sidebar-active-text, #fff)!important}.flyout-item-active:before{content:\"\";position:absolute;left:0;top:15%;height:70%;width:3px;background:var(--flyout-accent, #c50048);border-radius:0 2px 2px 0}.flyout-item-icon{font-size:12px;min-width:14px;text-align:center;color:inherit;opacity:.75}.flyout-item-label{flex:1;overflow:hidden;text-overflow:ellipsis}.flyout-chevron{font-size:10px;opacity:.5;margin-left:auto;flex-shrink:0;transition:transform .2s ease}.flyout-group{display:flex;flex-direction:column}.flyout-item-has-children{cursor:default}.flyout-item-expanded{background:#ffffff12!important;color:var(--sidebar-active-text, #fff)!important}.flyout-subitems{padding:2px 6px 2px 14px;border-left:2px solid rgba(255,255,255,.1);margin:0 6px 4px 20px}.flyout-subitem{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:6px;cursor:pointer;color:var(--sidebar-text-color, rgba(255, 255, 255, .65));font-size:12px;transition:background .15s ease,color .15s ease,transform .15s ease;white-space:nowrap;overflow:hidden}.flyout-subitem:hover{background:#ffffff17;color:var(--sidebar-active-text, #fff);transform:translate(2px)}.flyout-subitem-active{color:var(--sidebar-active-text, #fff)!important;position:relative}.flyout-subitem-active:before{content:\"\";position:absolute;left:-14px;top:20%;height:60%;width:2px;background:var(--flyout-accent, #c50048);border-radius:1px}@keyframes flyout-slide-in{0%{opacity:0;transform:translate(-10px)}to{opacity:1;transform:translate(0)}}\n"] }]
|
|
509
|
-
}], ctorParameters: () => [] });
|
|
509
|
+
}], ctorParameters: () => [], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], isSidebarOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSidebarOpen", required: false }] }], isSidebarHovering: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSidebarHovering", required: false }] }], level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], parentModuleName: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentModuleName", required: false }] }], accentColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "accentColor", required: false }] }], accesos: [{ type: i0.Input, args: [{ isSignal: true, alias: "accesos", required: false }] }], rolId: [{ type: i0.Input, args: [{ isSignal: true, alias: "rolId", required: false }] }] } });
|
|
510
510
|
|
|
511
511
|
class BottomNavigationComponent {
|
|
512
|
-
menuItems = input([]);
|
|
513
|
-
isVisible = input(true);
|
|
512
|
+
menuItems = input([], ...(ngDevMode ? [{ debugName: "menuItems" }] : []));
|
|
513
|
+
isVisible = input(true, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
|
|
514
514
|
itemClick = output();
|
|
515
|
-
activeDropdown = signal(null);
|
|
515
|
+
activeDropdown = signal(null, ...(ngDevMode ? [{ debugName: "activeDropdown" }] : []));
|
|
516
516
|
onDocumentClick() {
|
|
517
517
|
this.activeDropdown.set(null);
|
|
518
518
|
}
|
|
@@ -542,13 +542,13 @@ class BottomNavigationComponent {
|
|
|
542
542
|
subItem.action();
|
|
543
543
|
}
|
|
544
544
|
onDropdownClick(event) { event.stopPropagation(); }
|
|
545
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
546
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
545
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: BottomNavigationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
546
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: BottomNavigationComponent, isStandalone: true, selector: "app-bottom-navigation", inputs: { menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: false, transformFunction: null }, isVisible: { classPropertyName: "isVisible", publicName: "isVisible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, host: { listeners: { "document:click": "onDocumentClick()" } }, ngImport: i0, template: "<nav class=\"bottom-nav\" [class.visible]=\"isVisible()\">\r\n @for (item of menuItems(); track $index) {\r\n @if (item.type == 'dropdown') {\r\n <div class=\"bottom-nav-dropdown\">\r\n <button class=\"bottom-nav-item\" [class.active]=\"activeDropdown() === $index\"\r\n (click)=\"onItemClick($index, item, $event); toggleDropdown($index, $event)\">\r\n <i [class]=\"item.icon\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n\r\n @if (activeDropdown() == $index) {\r\n <div class=\"dropdown-menu show\" (click)=\"onDropdownClick($event)\">\r\n @for (subItem of item.items; track subItem.label; let last = $last; let first = $first) {\r\n <button class=\"dropdown-item\"\r\n [ngClass]=\"{'border-top-radius': first, 'border-bottom-radius': last}\"\r\n (click)=\"onSubItemClick(subItem, $event)\">\r\n\r\n <i [class]=\"subItem.icon\" class=\"me-2\"></i>\r\n <span class=\"flex-grow-1\">{{ subItem.label }}</span>\r\n\r\n @if (subItem.value) {\r\n <span class=\"fw-semibold ms-2\">{{ subItem.value }}</span>\r\n }\r\n </button>\r\n\r\n }\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <button class=\"bottom-nav-item\" [class.active]=\"item.active\" (click)=\"onItemClick($index, item, $event)\">\r\n <i [class]=\"item.icon\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n }\r\n }\r\n</nav>\r\n", styles: [".bottom-nav{position:fixed;bottom:0;left:0;right:0;background:var(--sidebar-bg, #ffffff);box-shadow:0 -2px 10px #0000001a;display:flex;justify-content:space-evenly;align-items:center;padding:8px 12px;z-index:1050;border-top:1px solid var(--font-border-input, #e0e0e0);transform:translateY(100%);transition:transform .3s cubic-bezier(.4,0,.2,1);height:60px}.bottom-nav.visible{transform:translateY(0)}@media(min-width:1192px){.bottom-nav{display:none}}.bottom-nav-item{display:flex;flex-direction:column;align-items:center;justify-content:center;background:none;border:none;padding:4px 2px;cursor:pointer;color:var(--sidebar-text-color, #666);transition:all .2s ease;border-radius:8px;flex:1;min-width:0;max-width:none;position:relative}.bottom-nav-item i{font-size:20px;margin-bottom:2px;transition:transform .2s cubic-bezier(.4,0,.2,1)}.bottom-nav-item span{font-size:11px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.bottom-nav-item:active{background:var(--bs-table-hover-bg, #f0f0f0);transform:scale(.95)}.bottom-nav-item.active{color:#398bf7}.bottom-nav-item.active i{transform:translateY(-2px)}.bottom-nav-dropdown{position:static;flex:1;display:flex;justify-content:center}.dropdown-menu{position:fixed;bottom:52px;left:50%;transform:translate(-50%) scale(.9);transform-origin:bottom center;background:var(--background-card, #ffffff);border:1px solid var(--border-color-modal, #dee2e6);border-radius:16px;padding:0;min-width:260px;max-width:90%;max-height:70vh;box-shadow:0 -4px 20px #00000026;z-index:1060;margin-bottom:10px;opacity:0;visibility:hidden;transition:all .25s cubic-bezier(.4,0,.2,1);pointer-events:none;overflow:hidden}.dropdown-menu.show{opacity:1;visibility:visible;transform:translate(-50%) scale(1);pointer-events:auto}.dropdown-menu .dropdown-item{display:flex;align-items:center;padding:14px 16px;font-size:10px;color:var(--text-color, #333);background:none;border:none;width:100%;text-align:left;border-bottom:1px solid var(--border-color-modal, #f0f0f0);opacity:0;transform:translateY(10px);animation:slideInItem .2s cubic-bezier(.4,0,.2,1) forwards;animation-delay:calc(.03s * var(--item-index, 0))}.dropdown-menu .dropdown-item:last-child{border-bottom:none}.dropdown-menu .dropdown-item i{width:24px;font-size:12px;transition:transform .2s ease}.dropdown-menu .dropdown-item:hover{background:var(--bs-table-hover-bg, #f8f9fa)}.dropdown-menu .dropdown-item:hover i{transform:scale(1.1)}.dropdown-menu .dropdown-item:active{background:var(--bs-table-hover-bg, #e9ecef);transform:scale(.98)}@keyframes slideInItem{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@media(max-width:480px){.bottom-nav-item span{font-size:10px}.bottom-nav-item i{font-size:18px}.dropdown-menu{min-width:220px}.dropdown-menu .dropdown-item{padding:12px 14px;font-size:10px}}@media(max-width:360px){.bottom-nav-item i{font-size:18px;margin-bottom:1px}.bottom-nav-item span{font-size:10px;font-weight:500}.dropdown-menu{min-width:200px}}.dropdown-overlay{position:fixed;inset:0;background:transparent;z-index:1055;display:none}.dropdown-overlay.active{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
547
547
|
}
|
|
548
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
548
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: BottomNavigationComponent, decorators: [{
|
|
549
549
|
type: Component,
|
|
550
|
-
args: [{ selector: 'app-bottom-navigation', imports: [CommonModule], template: "<nav class=\"bottom-nav\" [class.visible]=\"isVisible()\">\r\n @for (item of menuItems(); track $index) {\r\n @if (item.type == 'dropdown') {\r\n <div class=\"bottom-nav-dropdown\">\r\n <button class=\"bottom-nav-item\" [class.active]=\"activeDropdown() === $index\"\r\n (click)=\"onItemClick($index, item, $event); toggleDropdown($index, $event)\">\r\n <i [class]=\"item.icon\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n\r\n @if (activeDropdown() == $index) {\r\n <div class=\"dropdown-menu show\" (click)=\"onDropdownClick($event)\">\r\n @for (subItem of item.items; track subItem.label; let last = $last; let first = $first) {\r\n
|
|
551
|
-
}], propDecorators: { onDocumentClick: [{
|
|
550
|
+
args: [{ selector: 'app-bottom-navigation', imports: [CommonModule], template: "<nav class=\"bottom-nav\" [class.visible]=\"isVisible()\">\r\n @for (item of menuItems(); track $index) {\r\n @if (item.type == 'dropdown') {\r\n <div class=\"bottom-nav-dropdown\">\r\n <button class=\"bottom-nav-item\" [class.active]=\"activeDropdown() === $index\"\r\n (click)=\"onItemClick($index, item, $event); toggleDropdown($index, $event)\">\r\n <i [class]=\"item.icon\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n\r\n @if (activeDropdown() == $index) {\r\n <div class=\"dropdown-menu show\" (click)=\"onDropdownClick($event)\">\r\n @for (subItem of item.items; track subItem.label; let last = $last; let first = $first) {\r\n <button class=\"dropdown-item\"\r\n [ngClass]=\"{'border-top-radius': first, 'border-bottom-radius': last}\"\r\n (click)=\"onSubItemClick(subItem, $event)\">\r\n\r\n <i [class]=\"subItem.icon\" class=\"me-2\"></i>\r\n <span class=\"flex-grow-1\">{{ subItem.label }}</span>\r\n\r\n @if (subItem.value) {\r\n <span class=\"fw-semibold ms-2\">{{ subItem.value }}</span>\r\n }\r\n </button>\r\n\r\n }\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <button class=\"bottom-nav-item\" [class.active]=\"item.active\" (click)=\"onItemClick($index, item, $event)\">\r\n <i [class]=\"item.icon\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n }\r\n }\r\n</nav>\r\n", styles: [".bottom-nav{position:fixed;bottom:0;left:0;right:0;background:var(--sidebar-bg, #ffffff);box-shadow:0 -2px 10px #0000001a;display:flex;justify-content:space-evenly;align-items:center;padding:8px 12px;z-index:1050;border-top:1px solid var(--font-border-input, #e0e0e0);transform:translateY(100%);transition:transform .3s cubic-bezier(.4,0,.2,1);height:60px}.bottom-nav.visible{transform:translateY(0)}@media(min-width:1192px){.bottom-nav{display:none}}.bottom-nav-item{display:flex;flex-direction:column;align-items:center;justify-content:center;background:none;border:none;padding:4px 2px;cursor:pointer;color:var(--sidebar-text-color, #666);transition:all .2s ease;border-radius:8px;flex:1;min-width:0;max-width:none;position:relative}.bottom-nav-item i{font-size:20px;margin-bottom:2px;transition:transform .2s cubic-bezier(.4,0,.2,1)}.bottom-nav-item span{font-size:11px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.bottom-nav-item:active{background:var(--bs-table-hover-bg, #f0f0f0);transform:scale(.95)}.bottom-nav-item.active{color:#398bf7}.bottom-nav-item.active i{transform:translateY(-2px)}.bottom-nav-dropdown{position:static;flex:1;display:flex;justify-content:center}.dropdown-menu{position:fixed;bottom:52px;left:50%;transform:translate(-50%) scale(.9);transform-origin:bottom center;background:var(--background-card, #ffffff);border:1px solid var(--border-color-modal, #dee2e6);border-radius:16px;padding:0;min-width:260px;max-width:90%;max-height:70vh;box-shadow:0 -4px 20px #00000026;z-index:1060;margin-bottom:10px;opacity:0;visibility:hidden;transition:all .25s cubic-bezier(.4,0,.2,1);pointer-events:none;overflow:hidden}.dropdown-menu.show{opacity:1;visibility:visible;transform:translate(-50%) scale(1);pointer-events:auto}.dropdown-menu .dropdown-item{display:flex;align-items:center;padding:14px 16px;font-size:10px;color:var(--text-color, #333);background:none;border:none;width:100%;text-align:left;border-bottom:1px solid var(--border-color-modal, #f0f0f0);opacity:0;transform:translateY(10px);animation:slideInItem .2s cubic-bezier(.4,0,.2,1) forwards;animation-delay:calc(.03s * var(--item-index, 0))}.dropdown-menu .dropdown-item:last-child{border-bottom:none}.dropdown-menu .dropdown-item i{width:24px;font-size:12px;transition:transform .2s ease}.dropdown-menu .dropdown-item:hover{background:var(--bs-table-hover-bg, #f8f9fa)}.dropdown-menu .dropdown-item:hover i{transform:scale(1.1)}.dropdown-menu .dropdown-item:active{background:var(--bs-table-hover-bg, #e9ecef);transform:scale(.98)}@keyframes slideInItem{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@media(max-width:480px){.bottom-nav-item span{font-size:10px}.bottom-nav-item i{font-size:18px}.dropdown-menu{min-width:220px}.dropdown-menu .dropdown-item{padding:12px 14px;font-size:10px}}@media(max-width:360px){.bottom-nav-item i{font-size:18px;margin-bottom:1px}.bottom-nav-item span{font-size:10px;font-weight:500}.dropdown-menu{min-width:200px}}.dropdown-overlay{position:fixed;inset:0;background:transparent;z-index:1055;display:none}.dropdown-overlay.active{display:block}\n"] }]
|
|
551
|
+
}], propDecorators: { menuItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuItems", required: false }] }], isVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "isVisible", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], onDocumentClick: [{
|
|
552
552
|
type: HostListener,
|
|
553
553
|
args: ['document:click']
|
|
554
554
|
}] } });
|
|
@@ -563,37 +563,37 @@ class VerticalHeaderComponent {
|
|
|
563
563
|
// en vez de depender de un breakpoint fijo.
|
|
564
564
|
static SEARCH_WIDTH = 280;
|
|
565
565
|
static SEARCH_GAP = 16;
|
|
566
|
-
searchCollapsed = signal(false);
|
|
566
|
+
searchCollapsed = signal(false, ...(ngDevMode ? [{ debugName: "searchCollapsed" }] : []));
|
|
567
567
|
resizeObserver;
|
|
568
568
|
ngZone = inject(NgZone);
|
|
569
569
|
router = inject(Router);
|
|
570
570
|
tabsService = inject(TabsService);
|
|
571
|
-
actions = input([]);
|
|
571
|
+
actions = input([], ...(ngDevMode ? [{ debugName: "actions" }] : []));
|
|
572
572
|
// Algunas apps solo muestran el buscador global a ciertos roles.
|
|
573
|
-
showSearch = input(true);
|
|
573
|
+
showSearch = input(true, ...(ngDevMode ? [{ debugName: "showSearch" }] : []));
|
|
574
574
|
themes = input([
|
|
575
575
|
{ id: 'light', icon: 'fa-sun', label: 'Claro' },
|
|
576
576
|
{ id: 'dark', icon: 'fa-moon', label: 'Oscuro' },
|
|
577
577
|
{ id: 'sky-blue', icon: 'fa-cloud', label: 'Sky Blue' },
|
|
578
578
|
{ id: 'system', icon: 'fa-desktop', label: 'Sistema' },
|
|
579
|
-
]);
|
|
580
|
-
showThemeSwitcher = input(true);
|
|
581
|
-
showTabs = input(true);
|
|
579
|
+
], ...(ngDevMode ? [{ debugName: "themes" }] : []));
|
|
580
|
+
showThemeSwitcher = input(true, ...(ngDevMode ? [{ debugName: "showThemeSwitcher" }] : []));
|
|
581
|
+
showTabs = input(true, ...(ngDevMode ? [{ debugName: "showTabs" }] : []));
|
|
582
582
|
// Notificaciones: estándar en todas las apps TSI, ícono y estilo fijos —
|
|
583
583
|
// el consumidor solo decide si se muestra y provee el contador y el click.
|
|
584
|
-
showNotifications = input(false);
|
|
585
|
-
notificationsCount = input(0);
|
|
584
|
+
showNotifications = input(false, ...(ngDevMode ? [{ debugName: "showNotifications" }] : []));
|
|
585
|
+
notificationsCount = input(0, ...(ngDevMode ? [{ debugName: "notificationsCount" }] : []));
|
|
586
586
|
notificationsClick = output();
|
|
587
587
|
/** Opt-in: además de en el header, refleja las notificaciones en el bottom-nav (mobile). Por defecto no baja (igual que en consults). */
|
|
588
|
-
notificationsInBottomNav = input(false);
|
|
588
|
+
notificationsInBottomNav = input(false, ...(ngDevMode ? [{ debugName: "notificationsInBottomNav" }] : []));
|
|
589
589
|
// Soporte (chatbot): ídem, ícono y estilo fijos — el consumidor solo
|
|
590
590
|
// decide si está disponible y controla su visibilidad.
|
|
591
|
-
showChatbotToggle = input(false);
|
|
592
|
-
chatbotVisible = input(false);
|
|
591
|
+
showChatbotToggle = input(false, ...(ngDevMode ? [{ debugName: "showChatbotToggle" }] : []));
|
|
592
|
+
chatbotVisible = input(false, ...(ngDevMode ? [{ debugName: "chatbotVisible" }] : []));
|
|
593
593
|
chatbotVisibleChange = output();
|
|
594
594
|
/** Opt-in: además de en el header, refleja el toggle de soporte en el bottom-nav (mobile). Por defecto no baja. */
|
|
595
|
-
chatbotInBottomNav = input(false);
|
|
596
|
-
currentTheme = input('light');
|
|
595
|
+
chatbotInBottomNav = input(false, ...(ngDevMode ? [{ debugName: "chatbotInBottomNav" }] : []));
|
|
596
|
+
currentTheme = input('light', ...(ngDevMode ? [{ debugName: "currentTheme" }] : []));
|
|
597
597
|
themeChange = output();
|
|
598
598
|
// Espejo de las acciones del header hacia el bottom-nav (mobile): mismo dato,
|
|
599
599
|
// sin listas separadas — cada pieza (notificaciones, soporte, acciones) decide
|
|
@@ -623,7 +623,7 @@ class VerticalHeaderComponent {
|
|
|
623
623
|
label: action.label,
|
|
624
624
|
type: 'dropdown',
|
|
625
625
|
action: action.accion,
|
|
626
|
-
items: action.items.map(i => ({ icon: i.icon, label: i.label, action: i.accion })),
|
|
626
|
+
items: action.items.map(i => ({ icon: i.icon, label: i.label, value: i.value, action: i.accion })),
|
|
627
627
|
});
|
|
628
628
|
}
|
|
629
629
|
else if (action.accion) {
|
|
@@ -631,32 +631,32 @@ class VerticalHeaderComponent {
|
|
|
631
631
|
}
|
|
632
632
|
}
|
|
633
633
|
return items;
|
|
634
|
-
});
|
|
635
|
-
themeIcon = computed(() => this.themes().find(item => item.id === this.currentTheme())?.icon ?? 'fa-palette');
|
|
636
|
-
themeLabel = computed(() => this.themes().find(item => item.id === this.currentTheme())?.label ?? 'Personalizado');
|
|
637
|
-
versionApp = input('');
|
|
638
|
-
accentColor = input('#398bf7');
|
|
639
|
-
envClass = input('prod');
|
|
640
|
-
produccion = input(false);
|
|
634
|
+
}, ...(ngDevMode ? [{ debugName: "bottomNavItems" }] : []));
|
|
635
|
+
themeIcon = computed(() => this.themes().find(item => item.id === this.currentTheme())?.icon ?? 'fa-palette', ...(ngDevMode ? [{ debugName: "themeIcon" }] : []));
|
|
636
|
+
themeLabel = computed(() => this.themes().find(item => item.id === this.currentTheme())?.label ?? 'Personalizado', ...(ngDevMode ? [{ debugName: "themeLabel" }] : []));
|
|
637
|
+
versionApp = input('', ...(ngDevMode ? [{ debugName: "versionApp" }] : []));
|
|
638
|
+
accentColor = input('#398bf7', ...(ngDevMode ? [{ debugName: "accentColor" }] : []));
|
|
639
|
+
envClass = input('prod', ...(ngDevMode ? [{ debugName: "envClass" }] : []));
|
|
640
|
+
produccion = input(false, ...(ngDevMode ? [{ debugName: "produccion" }] : []));
|
|
641
641
|
emitirToogle = output();
|
|
642
|
-
isScrolled = input(false);
|
|
643
|
-
isSidebarOpen = input(false);
|
|
644
|
-
nameProyecto = input('');
|
|
642
|
+
isScrolled = input(false, ...(ngDevMode ? [{ debugName: "isScrolled" }] : []));
|
|
643
|
+
isSidebarOpen = input(false, ...(ngDevMode ? [{ debugName: "isSidebarOpen" }] : []));
|
|
644
|
+
nameProyecto = input('', ...(ngDevMode ? [{ debugName: "nameProyecto" }] : []));
|
|
645
645
|
searchComponents = output();
|
|
646
|
-
showPanelControl = input(true);
|
|
646
|
+
showPanelControl = input(true, ...(ngDevMode ? [{ debugName: "showPanelControl" }] : []));
|
|
647
647
|
panelControlClick = output();
|
|
648
648
|
logout = output();
|
|
649
649
|
// Datos de sesión: se reciben del consumidor (en vez de inyectar SesionService
|
|
650
650
|
// acá) para que layout-tsi no dependa de core-tsi.
|
|
651
|
-
userName = input('');
|
|
652
|
-
empresaName = input('');
|
|
653
|
-
tooltip = signal(null);
|
|
651
|
+
userName = input('', ...(ngDevMode ? [{ debugName: "userName" }] : []));
|
|
652
|
+
empresaName = input('', ...(ngDevMode ? [{ debugName: "empresaName" }] : []));
|
|
653
|
+
tooltip = signal(null, ...(ngDevMode ? [{ debugName: "tooltip" }] : []));
|
|
654
654
|
// Reemplazan a ngbDropdown (sin @ng-bootstrap acá): un dropdown nativo por
|
|
655
655
|
// click, reutilizando las clases de Bootstrap (dropdown/dropdown-menu/show)
|
|
656
656
|
// que ya vienen estilizadas — así no hace falta reimplementar el CSS.
|
|
657
|
-
openActionKey = signal(null);
|
|
658
|
-
themeMenuOpen = signal(false);
|
|
659
|
-
userMenuOpen = signal(false);
|
|
657
|
+
openActionKey = signal(null, ...(ngDevMode ? [{ debugName: "openActionKey" }] : []));
|
|
658
|
+
themeMenuOpen = signal(false, ...(ngDevMode ? [{ debugName: "themeMenuOpen" }] : []));
|
|
659
|
+
userMenuOpen = signal(false, ...(ngDevMode ? [{ debugName: "userMenuOpen" }] : []));
|
|
660
660
|
onDocumentClick() {
|
|
661
661
|
this.tooltip.set(null);
|
|
662
662
|
this.closeAllMenus();
|
|
@@ -738,10 +738,10 @@ class VerticalHeaderComponent {
|
|
|
738
738
|
if (collides !== this.searchCollapsed())
|
|
739
739
|
this.searchCollapsed.set(collides);
|
|
740
740
|
}
|
|
741
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
742
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: VerticalHeaderComponent, isStandalone: true, selector: "app-vertical-header", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, themes: { classPropertyName: "themes", publicName: "themes", isSignal: true, isRequired: false, transformFunction: null }, showThemeSwitcher: { classPropertyName: "showThemeSwitcher", publicName: "showThemeSwitcher", isSignal: true, isRequired: false, transformFunction: null }, showTabs: { classPropertyName: "showTabs", publicName: "showTabs", isSignal: true, isRequired: false, transformFunction: null }, showNotifications: { classPropertyName: "showNotifications", publicName: "showNotifications", isSignal: true, isRequired: false, transformFunction: null }, notificationsCount: { classPropertyName: "notificationsCount", publicName: "notificationsCount", isSignal: true, isRequired: false, transformFunction: null }, notificationsInBottomNav: { classPropertyName: "notificationsInBottomNav", publicName: "notificationsInBottomNav", isSignal: true, isRequired: false, transformFunction: null }, showChatbotToggle: { classPropertyName: "showChatbotToggle", publicName: "showChatbotToggle", isSignal: true, isRequired: false, transformFunction: null }, chatbotVisible: { classPropertyName: "chatbotVisible", publicName: "chatbotVisible", isSignal: true, isRequired: false, transformFunction: null }, chatbotInBottomNav: { classPropertyName: "chatbotInBottomNav", publicName: "chatbotInBottomNav", isSignal: true, isRequired: false, transformFunction: null }, currentTheme: { classPropertyName: "currentTheme", publicName: "currentTheme", isSignal: true, isRequired: false, transformFunction: null }, versionApp: { classPropertyName: "versionApp", publicName: "versionApp", isSignal: true, isRequired: false, transformFunction: null }, accentColor: { classPropertyName: "accentColor", publicName: "accentColor", isSignal: true, isRequired: false, transformFunction: null }, envClass: { classPropertyName: "envClass", publicName: "envClass", isSignal: true, isRequired: false, transformFunction: null }, produccion: { classPropertyName: "produccion", publicName: "produccion", isSignal: true, isRequired: false, transformFunction: null }, isScrolled: { classPropertyName: "isScrolled", publicName: "isScrolled", isSignal: true, isRequired: false, transformFunction: null }, isSidebarOpen: { classPropertyName: "isSidebarOpen", publicName: "isSidebarOpen", isSignal: true, isRequired: false, transformFunction: null }, nameProyecto: { classPropertyName: "nameProyecto", publicName: "nameProyecto", isSignal: true, isRequired: false, transformFunction: null }, showPanelControl: { classPropertyName: "showPanelControl", publicName: "showPanelControl", isSignal: true, isRequired: false, transformFunction: null }, userName: { classPropertyName: "userName", publicName: "userName", isSignal: true, isRequired: false, transformFunction: null }, empresaName: { classPropertyName: "empresaName", publicName: "empresaName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { notificationsClick: "notificationsClick", chatbotVisibleChange: "chatbotVisibleChange", themeChange: "themeChange", emitirToogle: "emitirToogle", searchComponents: "searchComponents", panelControlClick: "panelControlClick", logout: "logout" }, host: { listeners: { "document:click": "onDocumentClick()" } }, viewQueries: [{ propertyName: "headerContainerRef", first: true, predicate: ["headerContainer"], descendants: true }, { propertyName: "headerSideStartRef", first: true, predicate: ["headerSideStart"], descendants: true }, { propertyName: "headerSideEndRef", first: true, predicate: ["headerSideEnd"], descendants: true }, { propertyName: "compactSearchWrapperRef", first: true, predicate: ["compactSearchWrapper"], descendants: true }], ngImport: i0, template: "<div #headerContainer class=\"d-flex header-container\" [ngClass]=\"envClass()\">\r\n <div class=\"first-header d-none d-md-flex\">\r\n <img src=\"assets/images/logo-tsi-tres.png\" width=\"40px\" height=\"40px\" style=\"cursor:pointer\"\r\n (click)=\"goToHome()\" title=\"Ir a Home\">\r\n <span class=\"text-white empresa-nombre ps-2\" [title]=\"versionApp()\">{{empresaName()}}</span>\r\n </div>\r\n\r\n <div class=\"d-flex w-100 h-100 justify-content-between align-items-center pe-3 ps-0\">\r\n <div #headerSideStart class=\"d-flex align-items-center header-side\">\r\n <button class=\"btn text-white none-style sidebar-toggle-btn\" (click)=\"emitirToogle.emit()\">\r\n <i class=\"fa-solid fa-table-columns\" [class.flipped]=\"isSidebarOpen()\"></i>\r\n <i class=\"fa-solid fa-chevron-left toggle-arrow\" [class.flipped]=\"isSidebarOpen()\"></i>\r\n </button>\r\n <span class=\"text-white empresa-nombre d-inline d-md-none ps-2\">{{empresaName()}}</span>\r\n <span class=\"text-white fs-5 fw-normal d-none d-md-inline ps-2 text-nowrap\">{{nameProyecto()}}</span>\r\n @if (showTabs() && tabsService.tabs().length) {\r\n <button class=\"tabs-header-btn mx-2 d-none d-md-flex\"\r\n [class.tabs-header-btn--active]=\"tabsService.visible()\" (click)=\"tabsService.toggleVisible()\"\r\n [title]=\"tabsService.visible() ? 'Ocultar acceso r\u00E1pido' : 'Mostrar acceso r\u00E1pido'\">\r\n <i class=\"fas fa-layer-group\"></i>\r\n @if (!tabsService.visible()) {\r\n <span class=\"tabs-header-count\">{{ tabsService.tabs().length }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (showSearch()) {\r\n <button class=\"global-search-trigger d-none d-md-flex align-items-center\"\r\n [class.global-search-trigger--collapsed]=\"searchCollapsed()\" title=\"B\u00FAsqueda de p\u00E1ginas (F2)\"\r\n (click)=\"searchComponents.emit()\">\r\n <i class=\"fas fa-search global-search-icon\"></i>\r\n <span class=\"global-search-placeholder\">Buscar p\u00E1ginas...</span>\r\n <kbd class=\"global-search-kbd\">F2</kbd>\r\n </button>\r\n }\r\n\r\n <div #headerSideEnd class=\"d-flex align-items-center header-side header-side--end\">\r\n\r\n <!-- Fallback del buscador centrado cuando no entra (colisi\u00F3n) o en mobile\r\n (el buscador centrado se oculta por completo por debajo de md): la\r\n p\u00EDldora de texto \"F2\", igual que antes. -->\r\n <div #compactSearchWrapper class=\"h-100 d-flex align-items-center\">\r\n @if (showSearch() && searchCollapsed()) {\r\n <button class=\"global-search-compact-pill\" title=\"Buscar p\u00E1ginas (F2)\"\r\n (click)=\"searchComponents.emit()\">F2</button>\r\n }\r\n </div>\r\n\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[extra-actions]\" />\r\n\r\n <!-- Acciones adicionales, definidas por el consumidor: siempre a la izquierda\r\n de los tres fijos (tema, notificaciones, soporte). Solo se ocultan en mobile\r\n las que adem\u00E1s se reflejan en el bottom-nav (showInBottomNav) \u2014 si una acci\u00F3n\r\n no baja al bottom-nav, se queda visible ac\u00E1 para no desaparecer del todo. -->\r\n @for (action of actions(); track action.label) {\r\n @if (!action.hidden) {\r\n @if (action.items?.length) {\r\n <div class=\"dropdown d-inline-block z-index\" [class.show]=\"openActionKey() === action.label\" [class.desktop-only]=\"action.showInBottomNav\">\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" [title]=\"action.label\" (click)=\"action.accion?.(); toggleActionMenu($event, action)\">\r\n <i class=\"fas text-white\" [ngClass]=\"action.icon\"></i>\r\n </button>\r\n </div>\r\n\r\n <div class=\"dropdown-menu dropdown-menu-end mtp-9 mb-0 py-0 custom-dropdown\" [class.show]=\"openActionKey() === action.label\">\r\n @for (opcion of action.items; track opcion.label; let last = $last) {\r\n <button class=\"dropdown-item py-2 fs-7 fw-4 d-flex align-items-center\"\r\n [ngClass]=\"{'divider-border': !last,'border-top-radius': $index == 0,'border-bottom-radius': last}\"\r\n (click)=\"runAction(opcion)\"\r\n (mouseenter)=\"showTooltip($event, opcion.title ?? '')\" (mouseleave)=\"hideTooltip()\">\r\n <i [class]=\"opcion.icon\" class=\"me-1\"></i> {{ opcion.label }}\r\n @if (opcion.value) {\r\n <span class=\"ms-auto ps-3 fw-6\">{{ opcion.value }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"h-100 d-flex align-items-center\" [class.desktop-only]=\"action.showInBottomNav\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" [title]=\"action.label\" (click)=\"action.accion?.()\">\r\n <i class=\"fas text-white\" [ngClass]=\"action.icon\"></i>\r\n @if (action.badge) {\r\n <span class=\"notification-badge\" [ngClass]=\"produccion() ? 'bg-danger' : 'bg-info'\">\r\n {{ action.badge }}\r\n </span>\r\n }\r\n </button>\r\n </div>\r\n }\r\n }\r\n }\r\n\r\n @if (showThemeSwitcher()) {\r\n <div class=\"dropdown d-inline-block z-index\" [class.show]=\"themeMenuOpen()\">\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" (click)=\"toggleThemeMenu($event)\"\r\n [title]=\"'Tema: ' + themeLabel()\">\r\n <i class=\"fas text-white\" [ngClass]=\"themeIcon()\"></i>\r\n </button>\r\n </div>\r\n\r\n <div class=\"dropdown-menu dropdown-menu-end mtp-9 mb-0 py-0 custom-dropdown\" [class.show]=\"themeMenuOpen()\">\r\n @for (item of themes(); track item.id) {\r\n <button class=\"dropdown-item py-2 fs-7 fw-4 border-bottom-radius divider-border\"\r\n (click)=\"selectTheme(item.id)\">\r\n <i class=\"fas me-1\" [ngClass]=\"item.icon\"></i> {{ item.label }}\r\n @if (currentTheme() === item.id) {\r\n <i class=\"fas fa-check ms-auto text-success\"></i>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Notificaciones y soporte: \u00EDcono/estilo est\u00E1ndar, siempre visibles tambi\u00E9n en mobile -->\r\n @if (showNotifications()) {\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" title=\"Notificaciones\"\r\n (click)=\"notificationsClick.emit()\">\r\n <i class=\"fas fa-bell text-white\"></i>\r\n @if (notificationsCount() > 0) {\r\n <span class=\"notification-badge\" [ngClass]=\"produccion() ? 'bg-danger' : 'bg-info'\">\r\n {{ notificationsCount() }}\r\n </span>\r\n }\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showChatbotToggle()) {\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\"\r\n [title]=\"chatbotVisible() ? 'Ocultar soporte' : 'Mostrar soporte'\"\r\n (click)=\"chatbotVisibleChange.emit(!chatbotVisible())\">\r\n <i class=\"fas fa-robot text-white\"></i>\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"dropdown d-inline-block z-index\" [class.show]=\"userMenuOpen()\">\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"border-0 bg-none\" (click)=\"toggleUserMenu($event)\">\r\n <img class=\"circle-icon shadow-sm\" src=\"assets/images/admin-avatar.png\" alt=\"\">\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu dropdown-menu-end mtp-9 mb-0 py-0\" [class.show]=\"userMenuOpen()\">\r\n <div\r\n class=\"d-flex no-block align-items-center p-3 divider-border bg-gray-user-data border-top-radius\">\r\n <div class=\"d-flex align-items-center\">\r\n <img class=\"circle-icon shadow-sm\" src=\"assets/images/admin-avatar.png\">\r\n <div class=\"ms-2\">\r\n <p class=\"fs-7 my-0 py-0 fw-6\">{{userName()}}</p>\r\n @if (userName().startsWith('DESARROLLADOR')) {\r\n <span class=\"fs-7 fw-bold\">Desarrollador</span>\r\n } @else if (userName().startsWith('SOPORTE')) {\r\n <span class=\"fs-7 fw-bold\">Soporte</span>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n @if (showPanelControl()) {\r\n <button class=\"dropdown-item py-3 fs-7 fw-4\" (click)=\"userMenuOpen.set(false); panelControlClick.emit()\">\r\n Panel de control\r\n </button>\r\n }\r\n <button class=\"dropdown-item py-3 fs-7 fw-4 border-bottom-radius\" (click)=\"userMenuOpen.set(false); logout.emit()\"><i\r\n class=\"fas fa-power-off\"></i> Cerrar sesi\u00F3n</button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (tooltip()?.text) {\r\n<div class=\"acceso-tooltip-fixed\" [style.left.px]=\"tooltip()!.x\" [style.top.px]=\"tooltip()!.y\"\r\n [style.borderLeftColor]=\"accentColor()\" [style.--tooltip-accent]=\"accentColor()\">\r\n <span class=\"tooltip-label\">{{ tooltip()!.text.split(': ')[0] }}:</span>\r\n <span class=\"tooltip-value\" [style.color]=\"accentColor()\">{{ tooltip()!.text.split(': ')[1] }}</span>\r\n</div>\r\n}\r\n", styles: [".header-container{height:50px;display:flex;align-items:center;transition:position .5s ease-in-out,background-color .2s ease;padding:0;margin:0;position:relative;--header-accent: #398bf7;background:var(--header-accent);border-bottom:2px solid transparent}.header-container.dev{--header-accent: rgb(197, 0, 72)}.header-container.prod{--header-accent: #398bf7}.header-container.qa{--header-accent: #20c997}:host-context(.dark-mode) .header-container,:host-context(.sky-blue-mode) .header-container,:host-context(.high-contrast-green-mode) .header-container,:host-context(.purple-mode) .header-container{background:var(--header-bg);border-bottom-color:var(--header-accent)}.first-header{display:flex;align-items:center;gap:6px}.empresa-nombre{max-width:350px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;white-space:normal;line-height:1.25;max-height:2.5em;max-width:100%}@media(max-width:575px){.empresa-nombre{display:none!important}.first-header{min-width:auto!important;padding:10px!important}}@media(min-width:576px)and (max-width:1180px){.first-header{padding:10px!important}}@media(min-width:1181px){.first-header{min-width:260px;width:260px;padding:15px}}.bg-gray-user-data{background:var(--background-btn-light)}.dropdown-menu{transform-origin:top;background-color:var(--background-card);border-color:var(--border-color-modal);color:var(--text-color)}.dropdown-menu-end{right:0!important;left:auto!important}.dropdown-item{color:var(--text-color)}.dropdown-item:hover,.dropdown-item:focus{background-color:var(--bs-table-hover-bg);color:var(--text-color)}.dropdown-menu.show{animation:dropdownMenuIn .24s cubic-bezier(.2,0,.2,1) both}@keyframes dropdownMenuIn{0%{opacity:0;transform:translateY(10px) scale(.9)}to{opacity:1;transform:translateY(0) scale(1)}}.dropdown-menu{width:300px!important;min-width:300px!important}.circle-icon{min-height:30px;min-width:30px;height:30px;width:30px;border-radius:100%;border:2px solid white}.none-style{background:none;border:none}.sidebar-toggle-btn{display:flex;align-items:center;gap:4px}.sidebar-toggle-btn i{transition:transform .25s cubic-bezier(.4,0,.2,1)}.sidebar-toggle-btn i.flipped{transform:scaleX(-1)}.sidebar-toggle-btn .toggle-arrow{font-size:9px;color:#fff}.z-index{z-index:1001}.option{position:relative;border-radius:50px;width:33px;height:100%;transition:background-color .3s ease}.option:hover,.dropdown.show .option{background-color:var(--bs-table-hover-bg)!important}.custom-dropdown.dropdown-menu{min-width:unset!important;width:auto!important}.acceso-tooltip-fixed{position:fixed;z-index:99999;transform:translateY(-50%);pointer-events:none;padding:4px 10px 4px 8px;border-radius:6px;font-family:monospace;white-space:nowrap;background:#0f0f14;border:1px solid rgba(255,255,255,.07);border-left:2px solid;display:flex;align-items:center;gap:5px;animation:tooltipFadeIn .14s cubic-bezier(.25,.46,.45,.94)}.acceso-tooltip-fixed:before{content:\"\";position:absolute;right:100%;top:50%;transform:translateY(-50%);border:4px solid transparent;border-right-color:var(--tooltip-accent, #c50048)}.acceso-tooltip-fixed .tooltip-label{font-size:10px;font-weight:400;color:#fff;letter-spacing:.3px}.acceso-tooltip-fixed .tooltip-value{font-size:11px;font-weight:700}@keyframes tooltipFadeIn{0%{opacity:0;transform:translateY(-50%) translate(-4px)}to{opacity:1;transform:translateY(-50%) translate(0)}}.btn-print{border:1px solid rgba(0,0,0,.5764705882)!important;width:33px;height:30px!important;border-radius:6px}.btn-print:hover{border:1px solid rgba(61,61,61,.5254901961)!important;background-color:#dadadaf8!important}.btn-search{width:40px;height:31px!important;border-radius:6px}.logo-btn{width:25px;height:25px;object-fit:contain}.btn-deudas{background:#fff;border-radius:20px;border:none;white-space:nowrap;flex-shrink:0}.btn-deudas.titilando{animation:bordeTitilante 1s infinite alternate}@keyframes bordeTitilante{0%{box-shadow:0 0 2px red}50%{box-shadow:0 0 5px red,0 0 5px #ff4d4d}to{box-shadow:0 0 2px red}}@media(max-width:1100px){.btn-deudas{width:31px;height:31px!important;border-radius:50px;padding:0;display:flex;align-items:center;justify-content:center;aspect-ratio:1/1}.btn-deudas .texto-deudas{display:none}.btn-deudas .logo-btn{width:20px;height:20px;margin:0}}@keyframes icon-rotate-pop{0%{transform:rotate(0) scale(1)}25%{transform:rotate(10deg) scale(1.05)}50%{transform:rotate(-10deg) scale(1.1)}75%{transform:rotate(10deg) scale(1.05)}to{transform:rotate(0) scale(1)}}.button-icon-hover{display:inline-block}.button-tilt-hover:hover .button-icon-hover{animation:icon-rotate-pop 1s ease-in-out infinite}.desktop-only{display:flex}@media(max-width:667px){.desktop-only{display:none!important}}.notification-btn{position:relative;border:none;background:none;padding:0;margin-right:8px;cursor:pointer;width:33px;height:32px;display:flex;align-items:center;justify-content:center}.notification-btn i{color:#fff}.notification-badge{position:absolute;top:-5px;right:-3px;color:#fff;font-size:11px;font-weight:600;border-radius:4px;min-width:18px;height:18px;display:flex;align-items:center;justify-content:center;padding:0 4px}.header-side{flex:0 1 auto;min-width:0}.header-side--end{justify-content:flex-end}.global-search-trigger{position:absolute;left:50%;transform:translate(-50%);z-index:2;align-self:center;flex-shrink:0;margin:0;gap:8px;height:31px;width:280px;padding:0 6px 0 12px;background:#ffffff26;border:1px solid rgba(255,255,255,.3);border-radius:6px;color:#ffffffe6;font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s,border-color .15s,color .15s}.global-search-trigger:hover,.global-search-trigger:focus-visible{background:#ffffff47;border-color:#ffffff80;color:#fff}.global-search-trigger .global-search-icon{font-size:12px;color:#ffffffbf}.global-search-trigger .global-search-placeholder{flex-grow:1;text-align:start}.global-search-trigger .global-search-kbd{font-size:10px;font-weight:600;line-height:1;padding:3px 5px;border-radius:4px;background:#fff3;border:1px solid rgba(255,255,255,.35);color:#fff}.global-search-trigger--collapsed{display:none!important}.global-search-compact-pill{display:flex;align-items:center;justify-content:center;height:31px;margin-right:8px;padding:0 9px;background:#ffffff26;border:1px solid rgba(255,255,255,.3);border-radius:6px;color:#ffffffe6;font-size:11px;font-weight:700;cursor:pointer;transition:background .15s,border-color .15s,color .15s}.global-search-compact-pill:hover,.global-search-compact-pill:focus-visible{background:#ffffff47;border-color:#ffffff80;color:#fff}.tabs-header-btn{display:flex;align-items:center;gap:4px;background:#ffffff1a;border:1px solid rgba(255,255,255,.15);color:#fff9;border-radius:20px;padding:3px 8px;font-size:11px;cursor:pointer;transition:background .15s,color .15s;white-space:nowrap}.tabs-header-btn:hover{background:#fff3;color:#fff}.tabs-header-btn--active{background:#ffffff2e;color:#fff;border-color:#ffffff4d}.tabs-header-btn i{font-size:12px}.tabs-header-count{font-weight:700;font-size:11px;background:#fff3;border-radius:10px;padding:0 5px;min-width:16px;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
741
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: VerticalHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
742
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: VerticalHeaderComponent, isStandalone: true, selector: "app-vertical-header", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, themes: { classPropertyName: "themes", publicName: "themes", isSignal: true, isRequired: false, transformFunction: null }, showThemeSwitcher: { classPropertyName: "showThemeSwitcher", publicName: "showThemeSwitcher", isSignal: true, isRequired: false, transformFunction: null }, showTabs: { classPropertyName: "showTabs", publicName: "showTabs", isSignal: true, isRequired: false, transformFunction: null }, showNotifications: { classPropertyName: "showNotifications", publicName: "showNotifications", isSignal: true, isRequired: false, transformFunction: null }, notificationsCount: { classPropertyName: "notificationsCount", publicName: "notificationsCount", isSignal: true, isRequired: false, transformFunction: null }, notificationsInBottomNav: { classPropertyName: "notificationsInBottomNav", publicName: "notificationsInBottomNav", isSignal: true, isRequired: false, transformFunction: null }, showChatbotToggle: { classPropertyName: "showChatbotToggle", publicName: "showChatbotToggle", isSignal: true, isRequired: false, transformFunction: null }, chatbotVisible: { classPropertyName: "chatbotVisible", publicName: "chatbotVisible", isSignal: true, isRequired: false, transformFunction: null }, chatbotInBottomNav: { classPropertyName: "chatbotInBottomNav", publicName: "chatbotInBottomNav", isSignal: true, isRequired: false, transformFunction: null }, currentTheme: { classPropertyName: "currentTheme", publicName: "currentTheme", isSignal: true, isRequired: false, transformFunction: null }, versionApp: { classPropertyName: "versionApp", publicName: "versionApp", isSignal: true, isRequired: false, transformFunction: null }, accentColor: { classPropertyName: "accentColor", publicName: "accentColor", isSignal: true, isRequired: false, transformFunction: null }, envClass: { classPropertyName: "envClass", publicName: "envClass", isSignal: true, isRequired: false, transformFunction: null }, produccion: { classPropertyName: "produccion", publicName: "produccion", isSignal: true, isRequired: false, transformFunction: null }, isScrolled: { classPropertyName: "isScrolled", publicName: "isScrolled", isSignal: true, isRequired: false, transformFunction: null }, isSidebarOpen: { classPropertyName: "isSidebarOpen", publicName: "isSidebarOpen", isSignal: true, isRequired: false, transformFunction: null }, nameProyecto: { classPropertyName: "nameProyecto", publicName: "nameProyecto", isSignal: true, isRequired: false, transformFunction: null }, showPanelControl: { classPropertyName: "showPanelControl", publicName: "showPanelControl", isSignal: true, isRequired: false, transformFunction: null }, userName: { classPropertyName: "userName", publicName: "userName", isSignal: true, isRequired: false, transformFunction: null }, empresaName: { classPropertyName: "empresaName", publicName: "empresaName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { notificationsClick: "notificationsClick", chatbotVisibleChange: "chatbotVisibleChange", themeChange: "themeChange", emitirToogle: "emitirToogle", searchComponents: "searchComponents", panelControlClick: "panelControlClick", logout: "logout" }, host: { listeners: { "document:click": "onDocumentClick()" } }, viewQueries: [{ propertyName: "headerContainerRef", first: true, predicate: ["headerContainer"], descendants: true }, { propertyName: "headerSideStartRef", first: true, predicate: ["headerSideStart"], descendants: true }, { propertyName: "headerSideEndRef", first: true, predicate: ["headerSideEnd"], descendants: true }, { propertyName: "compactSearchWrapperRef", first: true, predicate: ["compactSearchWrapper"], descendants: true }], ngImport: i0, template: "<div #headerContainer class=\"d-flex header-container\" [ngClass]=\"envClass()\">\r\n <div class=\"first-header d-none d-md-flex\">\r\n <img src=\"assets/images/logo-tsi-tres.png\" width=\"40px\" height=\"40px\" style=\"cursor:pointer\"\r\n (click)=\"goToHome()\" title=\"Ir a Home\">\r\n <span class=\"text-white empresa-nombre ps-2\" [title]=\"versionApp()\">{{empresaName()}}</span>\r\n </div>\r\n\r\n <div class=\"d-flex w-100 h-100 justify-content-between align-items-center pe-3 ps-0\">\r\n <div #headerSideStart class=\"d-flex align-items-center header-side\">\r\n <button class=\"btn text-white none-style sidebar-toggle-btn\" (click)=\"emitirToogle.emit()\">\r\n <i class=\"fa-solid fa-table-columns\" [class.flipped]=\"isSidebarOpen()\"></i>\r\n <i class=\"fa-solid fa-chevron-left toggle-arrow\" [class.flipped]=\"isSidebarOpen()\"></i>\r\n </button>\r\n <span class=\"text-white empresa-nombre d-inline d-md-none ps-2\">{{empresaName()}}</span>\r\n <span class=\"text-white fs-5 fw-normal d-none d-md-inline ps-2 text-nowrap\">{{nameProyecto()}}</span>\r\n @if (showTabs() && tabsService.tabs().length) {\r\n <button class=\"tabs-header-btn mx-2 d-none d-md-flex\"\r\n [class.tabs-header-btn--active]=\"tabsService.visible()\" (click)=\"tabsService.toggleVisible()\"\r\n [title]=\"tabsService.visible() ? 'Ocultar acceso r\u00E1pido' : 'Mostrar acceso r\u00E1pido'\">\r\n <i class=\"fas fa-layer-group\"></i>\r\n @if (!tabsService.visible()) {\r\n <span class=\"tabs-header-count\">{{ tabsService.tabs().length }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (showSearch()) {\r\n <button class=\"global-search-trigger d-none d-md-flex align-items-center\"\r\n [class.global-search-trigger--collapsed]=\"searchCollapsed()\" title=\"B\u00FAsqueda de p\u00E1ginas (F2)\"\r\n (click)=\"searchComponents.emit()\">\r\n <i class=\"fas fa-search global-search-icon\"></i>\r\n <span class=\"global-search-placeholder\">Buscar p\u00E1ginas...</span>\r\n <kbd class=\"global-search-kbd\">F2</kbd>\r\n </button>\r\n }\r\n\r\n <div #headerSideEnd class=\"d-flex align-items-center header-side header-side--end\">\r\n\r\n <!-- Fallback del buscador centrado cuando no entra (colisi\u00F3n) o en mobile\r\n (el buscador centrado se oculta por completo por debajo de md): la\r\n p\u00EDldora de texto \"F2\", igual que antes. -->\r\n <div #compactSearchWrapper class=\"h-100 d-flex align-items-center\">\r\n @if (showSearch() && searchCollapsed()) {\r\n <button class=\"global-search-compact-pill\" title=\"Buscar p\u00E1ginas (F2)\"\r\n (click)=\"searchComponents.emit()\">F2</button>\r\n }\r\n </div>\r\n\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[extra-actions]\" />\r\n\r\n <!-- Acciones adicionales, definidas por el consumidor: siempre a la izquierda\r\n de los tres fijos (tema, notificaciones, soporte). Solo se ocultan en mobile\r\n las que adem\u00E1s se reflejan en el bottom-nav (showInBottomNav) \u2014 si una acci\u00F3n\r\n no baja al bottom-nav, se queda visible ac\u00E1 para no desaparecer del todo. -->\r\n @for (action of actions(); track action.label) {\r\n @if (!action.hidden) {\r\n @if (action.items?.length) {\r\n <div class=\"dropdown d-inline-block z-index\" [class.show]=\"openActionKey() === action.label\" [class.desktop-only]=\"action.showInBottomNav\">\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" [title]=\"action.label\" (click)=\"action.accion?.(); toggleActionMenu($event, action)\">\r\n <i class=\"fas text-white\" [ngClass]=\"action.icon\"></i>\r\n </button>\r\n </div>\r\n\r\n <div class=\"dropdown-menu dropdown-menu-end mtp-9 mb-0 py-0 custom-dropdown\" [class.show]=\"openActionKey() === action.label\">\r\n @for (opcion of action.items; track opcion.label; let last = $last) {\r\n <button class=\"dropdown-item py-2 fs-7 fw-4 d-flex align-items-center\"\r\n [ngClass]=\"{'divider-border': !last,'border-top-radius': $index == 0,'border-bottom-radius': last}\"\r\n (click)=\"runAction(opcion)\"\r\n (mouseenter)=\"showTooltip($event, opcion.title ?? '')\" (mouseleave)=\"hideTooltip()\">\r\n <i [class]=\"opcion.icon\" class=\"me-1\"></i> {{ opcion.label }}\r\n @if (opcion.value) {\r\n <span class=\"ms-auto ps-3 fw-6\">{{ opcion.value }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"h-100 d-flex align-items-center\" [class.desktop-only]=\"action.showInBottomNav\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" [title]=\"action.label\" (click)=\"action.accion?.()\">\r\n <i class=\"fas text-white\" [ngClass]=\"action.icon\"></i>\r\n @if (action.badge) {\r\n <span class=\"notification-badge\" [ngClass]=\"produccion() ? 'bg-danger' : 'bg-info'\">\r\n {{ action.badge }}\r\n </span>\r\n }\r\n </button>\r\n </div>\r\n }\r\n }\r\n }\r\n\r\n @if (showThemeSwitcher()) {\r\n <div class=\"dropdown d-inline-block z-index\" [class.show]=\"themeMenuOpen()\">\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" (click)=\"toggleThemeMenu($event)\"\r\n [title]=\"'Tema: ' + themeLabel()\">\r\n <i class=\"fas text-white\" [ngClass]=\"themeIcon()\"></i>\r\n </button>\r\n </div>\r\n\r\n <div class=\"dropdown-menu dropdown-menu-end mtp-9 mb-0 py-0 custom-dropdown\" [class.show]=\"themeMenuOpen()\">\r\n @for (item of themes(); track item.id) {\r\n <button class=\"dropdown-item py-2 fs-7 fw-4 border-bottom-radius divider-border\"\r\n (click)=\"selectTheme(item.id)\">\r\n <i class=\"fas me-1\" [ngClass]=\"item.icon\"></i> {{ item.label }}\r\n @if (currentTheme() === item.id) {\r\n <i class=\"fas fa-check ms-auto text-success\"></i>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Notificaciones y soporte: \u00EDcono/estilo est\u00E1ndar, siempre visibles tambi\u00E9n en mobile -->\r\n @if (showNotifications()) {\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" title=\"Notificaciones\"\r\n (click)=\"notificationsClick.emit()\">\r\n <i class=\"fas fa-bell text-white\"></i>\r\n @if (notificationsCount() > 0) {\r\n <span class=\"notification-badge\" [ngClass]=\"produccion() ? 'bg-danger' : 'bg-info'\">\r\n {{ notificationsCount() }}\r\n </span>\r\n }\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showChatbotToggle()) {\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\"\r\n [title]=\"chatbotVisible() ? 'Ocultar soporte' : 'Mostrar soporte'\"\r\n (click)=\"chatbotVisibleChange.emit(!chatbotVisible())\">\r\n <i class=\"fas fa-robot text-white\"></i>\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"dropdown d-inline-block z-index\" [class.show]=\"userMenuOpen()\">\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"border-0 bg-none\" (click)=\"toggleUserMenu($event)\">\r\n <img class=\"circle-icon shadow-sm\" src=\"assets/images/admin-avatar.png\" alt=\"\">\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu dropdown-menu-end mtp-9 mb-0 py-0\" [class.show]=\"userMenuOpen()\">\r\n <div\r\n class=\"d-flex no-block align-items-center p-3 divider-border bg-gray-user-data border-top-radius\">\r\n <div class=\"d-flex align-items-center\">\r\n <img class=\"circle-icon shadow-sm\" src=\"assets/images/admin-avatar.png\">\r\n <div class=\"ms-2\">\r\n <p class=\"fs-7 my-0 py-0 fw-6\">{{userName()}}</p>\r\n @if (userName().startsWith('DESARROLLADOR')) {\r\n <span class=\"fs-7 fw-bold\">Desarrollador</span>\r\n } @else if (userName().startsWith('SOPORTE')) {\r\n <span class=\"fs-7 fw-bold\">Soporte</span>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n @if (showPanelControl()) {\r\n <button class=\"dropdown-item py-3 fs-7 fw-4\" (click)=\"userMenuOpen.set(false); panelControlClick.emit()\">\r\n Panel de control\r\n </button>\r\n }\r\n <button class=\"dropdown-item py-3 fs-7 fw-4 border-bottom-radius\" (click)=\"userMenuOpen.set(false); logout.emit()\"><i\r\n class=\"fas fa-power-off\"></i> Cerrar sesi\u00F3n</button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (tooltip()?.text) {\r\n<div class=\"acceso-tooltip-fixed\" [style.left.px]=\"tooltip()!.x\" [style.top.px]=\"tooltip()!.y\"\r\n [style.borderLeftColor]=\"accentColor()\" [style.--tooltip-accent]=\"accentColor()\">\r\n <span class=\"tooltip-label\">{{ tooltip()!.text.split(': ')[0] }}:</span>\r\n <span class=\"tooltip-value\" [style.color]=\"accentColor()\">{{ tooltip()!.text.split(': ')[1] }}</span>\r\n</div>\r\n}\r\n", styles: [".header-container{height:50px;display:flex;align-items:center;transition:position .5s ease-in-out,background-color .2s ease;padding:0;margin:0;position:relative;--header-accent: #398bf7;background:var(--header-accent);border-bottom:2px solid transparent}.header-container.dev{--header-accent: rgb(197, 0, 72)}.header-container.prod{--header-accent: #398bf7}.header-container.qa{--header-accent: #20c997}:host-context(.dark-mode) .header-container,:host-context(.sky-blue-mode) .header-container,:host-context(.high-contrast-green-mode) .header-container,:host-context(.purple-mode) .header-container{background:var(--header-bg);border-bottom-color:var(--header-accent)}.first-header{display:flex;align-items:center;gap:6px}.empresa-nombre{max-width:350px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;white-space:normal;line-height:1.25;max-height:2.5em;max-width:100%}@media(max-width:575px){.empresa-nombre{display:none!important}.first-header{min-width:auto!important;padding:10px!important}}@media(min-width:576px)and (max-width:1180px){.first-header{padding:10px!important}}@media(min-width:1181px){.first-header{min-width:260px;width:260px;padding:15px}}.bg-gray-user-data{background:var(--background-btn-light)}.dropdown-menu{transform-origin:top;background-color:var(--background-card);border-color:var(--border-color-modal);color:var(--text-color)}.dropdown-menu-end{right:0!important;left:auto!important}.dropdown-item{color:var(--text-color)}.dropdown-item:hover,.dropdown-item:focus{background-color:var(--bs-table-hover-bg);color:var(--text-color)}.dropdown-menu.show{animation:dropdownMenuIn .24s cubic-bezier(.2,0,.2,1) both}@keyframes dropdownMenuIn{0%{opacity:0;transform:translateY(10px) scale(.9)}to{opacity:1;transform:translateY(0) scale(1)}}.dropdown-menu{width:300px!important;min-width:300px!important}.circle-icon{min-height:30px;min-width:30px;height:30px;width:30px;border-radius:100%;border:2px solid white}.none-style{background:none;border:none}.sidebar-toggle-btn{display:flex;align-items:center;gap:4px}.sidebar-toggle-btn i{transition:transform .25s cubic-bezier(.4,0,.2,1)}.sidebar-toggle-btn i.flipped{transform:scaleX(-1)}.sidebar-toggle-btn .toggle-arrow{font-size:9px;color:#fff}.z-index{z-index:1001}.option{position:relative;border-radius:50px;width:33px;height:100%;transition:background-color .3s ease}.option:hover,.dropdown.show .option{background-color:var(--bs-table-hover-bg)!important}.custom-dropdown.dropdown-menu{min-width:unset!important;width:auto!important}.acceso-tooltip-fixed{position:fixed;z-index:99999;transform:translateY(-50%);pointer-events:none;padding:4px 10px 4px 8px;border-radius:6px;font-family:monospace;white-space:nowrap;background:#0f0f14;border:1px solid rgba(255,255,255,.07);border-left:2px solid;display:flex;align-items:center;gap:5px;animation:tooltipFadeIn .14s cubic-bezier(.25,.46,.45,.94)}.acceso-tooltip-fixed:before{content:\"\";position:absolute;right:100%;top:50%;transform:translateY(-50%);border:4px solid transparent;border-right-color:var(--tooltip-accent, #c50048)}.acceso-tooltip-fixed .tooltip-label{font-size:10px;font-weight:400;color:#fff;letter-spacing:.3px}.acceso-tooltip-fixed .tooltip-value{font-size:11px;font-weight:700}@keyframes tooltipFadeIn{0%{opacity:0;transform:translateY(-50%) translate(-4px)}to{opacity:1;transform:translateY(-50%) translate(0)}}.btn-print{border:1px solid rgba(0,0,0,.5764705882)!important;width:33px;height:30px!important;border-radius:6px}.btn-print:hover{border:1px solid rgba(61,61,61,.5254901961)!important;background-color:#dadadaf8!important}.btn-search{width:40px;height:31px!important;border-radius:6px}.logo-btn{width:25px;height:25px;object-fit:contain}.btn-deudas{background:#fff;border-radius:20px;border:none;white-space:nowrap;flex-shrink:0}.btn-deudas.titilando{animation:bordeTitilante 1s infinite alternate}@keyframes bordeTitilante{0%{box-shadow:0 0 2px red}50%{box-shadow:0 0 5px red,0 0 5px #ff4d4d}to{box-shadow:0 0 2px red}}@media(max-width:1100px){.btn-deudas{width:31px;height:31px!important;border-radius:50px;padding:0;display:flex;align-items:center;justify-content:center;aspect-ratio:1/1}.btn-deudas .texto-deudas{display:none}.btn-deudas .logo-btn{width:20px;height:20px;margin:0}}@keyframes icon-rotate-pop{0%{transform:rotate(0) scale(1)}25%{transform:rotate(10deg) scale(1.05)}50%{transform:rotate(-10deg) scale(1.1)}75%{transform:rotate(10deg) scale(1.05)}to{transform:rotate(0) scale(1)}}.button-icon-hover{display:inline-block}.button-tilt-hover:hover .button-icon-hover{animation:icon-rotate-pop 1s ease-in-out infinite}.desktop-only{display:flex}@media(max-width:667px){.desktop-only{display:none!important}}.notification-btn{position:relative;border:none;background:none;padding:0;margin-right:8px;cursor:pointer;width:33px;height:32px;display:flex;align-items:center;justify-content:center}.notification-btn i{color:#fff}.notification-badge{position:absolute;top:-5px;right:-3px;color:#fff;font-size:11px;font-weight:600;border-radius:4px;min-width:18px;height:18px;display:flex;align-items:center;justify-content:center;padding:0 4px}.header-side{flex:0 1 auto;min-width:0}.header-side--end{justify-content:flex-end}.global-search-trigger{position:absolute;left:50%;transform:translate(-50%);z-index:2;align-self:center;flex-shrink:0;margin:0;gap:8px;height:31px;width:280px;padding:0 6px 0 12px;background:#ffffff26;border:1px solid rgba(255,255,255,.3);border-radius:6px;color:#ffffffe6;font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s,border-color .15s,color .15s}.global-search-trigger:hover,.global-search-trigger:focus-visible{background:#ffffff47;border-color:#ffffff80;color:#fff}.global-search-trigger .global-search-icon{font-size:12px;color:#ffffffbf}.global-search-trigger .global-search-placeholder{flex-grow:1;text-align:start}.global-search-trigger .global-search-kbd{font-size:10px;font-weight:600;line-height:1;padding:3px 5px;border-radius:4px;background:#fff3;border:1px solid rgba(255,255,255,.35);color:#fff}.global-search-trigger--collapsed{display:none!important}.global-search-compact-pill{display:flex;align-items:center;justify-content:center;height:31px;margin-right:8px;padding:0 9px;background:#ffffff26;border:1px solid rgba(255,255,255,.3);border-radius:6px;color:#ffffffe6;font-size:11px;font-weight:700;cursor:pointer;transition:background .15s,border-color .15s,color .15s}.global-search-compact-pill:hover,.global-search-compact-pill:focus-visible{background:#ffffff47;border-color:#ffffff80;color:#fff}.tabs-header-btn{display:flex;align-items:center;gap:4px;background:#ffffff1a;border:1px solid rgba(255,255,255,.15);color:#fff9;border-radius:20px;padding:3px 8px;font-size:11px;cursor:pointer;transition:background .15s,color .15s;white-space:nowrap}.tabs-header-btn:hover{background:#fff3;color:#fff}.tabs-header-btn--active{background:#ffffff2e;color:#fff;border-color:#ffffff4d}.tabs-header-btn i{font-size:12px}.tabs-header-count{font-weight:700;font-size:11px;background:#fff3;border-radius:10px;padding:0 5px;min-width:16px;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
743
743
|
}
|
|
744
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
744
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: VerticalHeaderComponent, decorators: [{
|
|
745
745
|
type: Component,
|
|
746
746
|
args: [{ selector: 'app-vertical-header', imports: [CommonModule], template: "<div #headerContainer class=\"d-flex header-container\" [ngClass]=\"envClass()\">\r\n <div class=\"first-header d-none d-md-flex\">\r\n <img src=\"assets/images/logo-tsi-tres.png\" width=\"40px\" height=\"40px\" style=\"cursor:pointer\"\r\n (click)=\"goToHome()\" title=\"Ir a Home\">\r\n <span class=\"text-white empresa-nombre ps-2\" [title]=\"versionApp()\">{{empresaName()}}</span>\r\n </div>\r\n\r\n <div class=\"d-flex w-100 h-100 justify-content-between align-items-center pe-3 ps-0\">\r\n <div #headerSideStart class=\"d-flex align-items-center header-side\">\r\n <button class=\"btn text-white none-style sidebar-toggle-btn\" (click)=\"emitirToogle.emit()\">\r\n <i class=\"fa-solid fa-table-columns\" [class.flipped]=\"isSidebarOpen()\"></i>\r\n <i class=\"fa-solid fa-chevron-left toggle-arrow\" [class.flipped]=\"isSidebarOpen()\"></i>\r\n </button>\r\n <span class=\"text-white empresa-nombre d-inline d-md-none ps-2\">{{empresaName()}}</span>\r\n <span class=\"text-white fs-5 fw-normal d-none d-md-inline ps-2 text-nowrap\">{{nameProyecto()}}</span>\r\n @if (showTabs() && tabsService.tabs().length) {\r\n <button class=\"tabs-header-btn mx-2 d-none d-md-flex\"\r\n [class.tabs-header-btn--active]=\"tabsService.visible()\" (click)=\"tabsService.toggleVisible()\"\r\n [title]=\"tabsService.visible() ? 'Ocultar acceso r\u00E1pido' : 'Mostrar acceso r\u00E1pido'\">\r\n <i class=\"fas fa-layer-group\"></i>\r\n @if (!tabsService.visible()) {\r\n <span class=\"tabs-header-count\">{{ tabsService.tabs().length }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n @if (showSearch()) {\r\n <button class=\"global-search-trigger d-none d-md-flex align-items-center\"\r\n [class.global-search-trigger--collapsed]=\"searchCollapsed()\" title=\"B\u00FAsqueda de p\u00E1ginas (F2)\"\r\n (click)=\"searchComponents.emit()\">\r\n <i class=\"fas fa-search global-search-icon\"></i>\r\n <span class=\"global-search-placeholder\">Buscar p\u00E1ginas...</span>\r\n <kbd class=\"global-search-kbd\">F2</kbd>\r\n </button>\r\n }\r\n\r\n <div #headerSideEnd class=\"d-flex align-items-center header-side header-side--end\">\r\n\r\n <!-- Fallback del buscador centrado cuando no entra (colisi\u00F3n) o en mobile\r\n (el buscador centrado se oculta por completo por debajo de md): la\r\n p\u00EDldora de texto \"F2\", igual que antes. -->\r\n <div #compactSearchWrapper class=\"h-100 d-flex align-items-center\">\r\n @if (showSearch() && searchCollapsed()) {\r\n <button class=\"global-search-compact-pill\" title=\"Buscar p\u00E1ginas (F2)\"\r\n (click)=\"searchComponents.emit()\">F2</button>\r\n }\r\n </div>\r\n\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[extra-actions]\" />\r\n\r\n <!-- Acciones adicionales, definidas por el consumidor: siempre a la izquierda\r\n de los tres fijos (tema, notificaciones, soporte). Solo se ocultan en mobile\r\n las que adem\u00E1s se reflejan en el bottom-nav (showInBottomNav) \u2014 si una acci\u00F3n\r\n no baja al bottom-nav, se queda visible ac\u00E1 para no desaparecer del todo. -->\r\n @for (action of actions(); track action.label) {\r\n @if (!action.hidden) {\r\n @if (action.items?.length) {\r\n <div class=\"dropdown d-inline-block z-index\" [class.show]=\"openActionKey() === action.label\" [class.desktop-only]=\"action.showInBottomNav\">\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" [title]=\"action.label\" (click)=\"action.accion?.(); toggleActionMenu($event, action)\">\r\n <i class=\"fas text-white\" [ngClass]=\"action.icon\"></i>\r\n </button>\r\n </div>\r\n\r\n <div class=\"dropdown-menu dropdown-menu-end mtp-9 mb-0 py-0 custom-dropdown\" [class.show]=\"openActionKey() === action.label\">\r\n @for (opcion of action.items; track opcion.label; let last = $last) {\r\n <button class=\"dropdown-item py-2 fs-7 fw-4 d-flex align-items-center\"\r\n [ngClass]=\"{'divider-border': !last,'border-top-radius': $index == 0,'border-bottom-radius': last}\"\r\n (click)=\"runAction(opcion)\"\r\n (mouseenter)=\"showTooltip($event, opcion.title ?? '')\" (mouseleave)=\"hideTooltip()\">\r\n <i [class]=\"opcion.icon\" class=\"me-1\"></i> {{ opcion.label }}\r\n @if (opcion.value) {\r\n <span class=\"ms-auto ps-3 fw-6\">{{ opcion.value }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"h-100 d-flex align-items-center\" [class.desktop-only]=\"action.showInBottomNav\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" [title]=\"action.label\" (click)=\"action.accion?.()\">\r\n <i class=\"fas text-white\" [ngClass]=\"action.icon\"></i>\r\n @if (action.badge) {\r\n <span class=\"notification-badge\" [ngClass]=\"produccion() ? 'bg-danger' : 'bg-info'\">\r\n {{ action.badge }}\r\n </span>\r\n }\r\n </button>\r\n </div>\r\n }\r\n }\r\n }\r\n\r\n @if (showThemeSwitcher()) {\r\n <div class=\"dropdown d-inline-block z-index\" [class.show]=\"themeMenuOpen()\">\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" (click)=\"toggleThemeMenu($event)\"\r\n [title]=\"'Tema: ' + themeLabel()\">\r\n <i class=\"fas text-white\" [ngClass]=\"themeIcon()\"></i>\r\n </button>\r\n </div>\r\n\r\n <div class=\"dropdown-menu dropdown-menu-end mtp-9 mb-0 py-0 custom-dropdown\" [class.show]=\"themeMenuOpen()\">\r\n @for (item of themes(); track item.id) {\r\n <button class=\"dropdown-item py-2 fs-7 fw-4 border-bottom-radius divider-border\"\r\n (click)=\"selectTheme(item.id)\">\r\n <i class=\"fas me-1\" [ngClass]=\"item.icon\"></i> {{ item.label }}\r\n @if (currentTheme() === item.id) {\r\n <i class=\"fas fa-check ms-auto text-success\"></i>\r\n }\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Notificaciones y soporte: \u00EDcono/estilo est\u00E1ndar, siempre visibles tambi\u00E9n en mobile -->\r\n @if (showNotifications()) {\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\" title=\"Notificaciones\"\r\n (click)=\"notificationsClick.emit()\">\r\n <i class=\"fas fa-bell text-white\"></i>\r\n @if (notificationsCount() > 0) {\r\n <span class=\"notification-badge\" [ngClass]=\"produccion() ? 'bg-danger' : 'bg-info'\">\r\n {{ notificationsCount() }}\r\n </span>\r\n }\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showChatbotToggle()) {\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"notification-btn option p-0 m-0 me-2\"\r\n [title]=\"chatbotVisible() ? 'Ocultar soporte' : 'Mostrar soporte'\"\r\n (click)=\"chatbotVisibleChange.emit(!chatbotVisible())\">\r\n <i class=\"fas fa-robot text-white\"></i>\r\n </button>\r\n </div>\r\n }\r\n\r\n <div class=\"dropdown d-inline-block z-index\" [class.show]=\"userMenuOpen()\">\r\n <div class=\"h-100 d-flex align-items-center\">\r\n <button class=\"border-0 bg-none\" (click)=\"toggleUserMenu($event)\">\r\n <img class=\"circle-icon shadow-sm\" src=\"assets/images/admin-avatar.png\" alt=\"\">\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu dropdown-menu-end mtp-9 mb-0 py-0\" [class.show]=\"userMenuOpen()\">\r\n <div\r\n class=\"d-flex no-block align-items-center p-3 divider-border bg-gray-user-data border-top-radius\">\r\n <div class=\"d-flex align-items-center\">\r\n <img class=\"circle-icon shadow-sm\" src=\"assets/images/admin-avatar.png\">\r\n <div class=\"ms-2\">\r\n <p class=\"fs-7 my-0 py-0 fw-6\">{{userName()}}</p>\r\n @if (userName().startsWith('DESARROLLADOR')) {\r\n <span class=\"fs-7 fw-bold\">Desarrollador</span>\r\n } @else if (userName().startsWith('SOPORTE')) {\r\n <span class=\"fs-7 fw-bold\">Soporte</span>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n @if (showPanelControl()) {\r\n <button class=\"dropdown-item py-3 fs-7 fw-4\" (click)=\"userMenuOpen.set(false); panelControlClick.emit()\">\r\n Panel de control\r\n </button>\r\n }\r\n <button class=\"dropdown-item py-3 fs-7 fw-4 border-bottom-radius\" (click)=\"userMenuOpen.set(false); logout.emit()\"><i\r\n class=\"fas fa-power-off\"></i> Cerrar sesi\u00F3n</button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (tooltip()?.text) {\r\n<div class=\"acceso-tooltip-fixed\" [style.left.px]=\"tooltip()!.x\" [style.top.px]=\"tooltip()!.y\"\r\n [style.borderLeftColor]=\"accentColor()\" [style.--tooltip-accent]=\"accentColor()\">\r\n <span class=\"tooltip-label\">{{ tooltip()!.text.split(': ')[0] }}:</span>\r\n <span class=\"tooltip-value\" [style.color]=\"accentColor()\">{{ tooltip()!.text.split(': ')[1] }}</span>\r\n</div>\r\n}\r\n", styles: [".header-container{height:50px;display:flex;align-items:center;transition:position .5s ease-in-out,background-color .2s ease;padding:0;margin:0;position:relative;--header-accent: #398bf7;background:var(--header-accent);border-bottom:2px solid transparent}.header-container.dev{--header-accent: rgb(197, 0, 72)}.header-container.prod{--header-accent: #398bf7}.header-container.qa{--header-accent: #20c997}:host-context(.dark-mode) .header-container,:host-context(.sky-blue-mode) .header-container,:host-context(.high-contrast-green-mode) .header-container,:host-context(.purple-mode) .header-container{background:var(--header-bg);border-bottom-color:var(--header-accent)}.first-header{display:flex;align-items:center;gap:6px}.empresa-nombre{max-width:350px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;white-space:normal;line-height:1.25;max-height:2.5em;max-width:100%}@media(max-width:575px){.empresa-nombre{display:none!important}.first-header{min-width:auto!important;padding:10px!important}}@media(min-width:576px)and (max-width:1180px){.first-header{padding:10px!important}}@media(min-width:1181px){.first-header{min-width:260px;width:260px;padding:15px}}.bg-gray-user-data{background:var(--background-btn-light)}.dropdown-menu{transform-origin:top;background-color:var(--background-card);border-color:var(--border-color-modal);color:var(--text-color)}.dropdown-menu-end{right:0!important;left:auto!important}.dropdown-item{color:var(--text-color)}.dropdown-item:hover,.dropdown-item:focus{background-color:var(--bs-table-hover-bg);color:var(--text-color)}.dropdown-menu.show{animation:dropdownMenuIn .24s cubic-bezier(.2,0,.2,1) both}@keyframes dropdownMenuIn{0%{opacity:0;transform:translateY(10px) scale(.9)}to{opacity:1;transform:translateY(0) scale(1)}}.dropdown-menu{width:300px!important;min-width:300px!important}.circle-icon{min-height:30px;min-width:30px;height:30px;width:30px;border-radius:100%;border:2px solid white}.none-style{background:none;border:none}.sidebar-toggle-btn{display:flex;align-items:center;gap:4px}.sidebar-toggle-btn i{transition:transform .25s cubic-bezier(.4,0,.2,1)}.sidebar-toggle-btn i.flipped{transform:scaleX(-1)}.sidebar-toggle-btn .toggle-arrow{font-size:9px;color:#fff}.z-index{z-index:1001}.option{position:relative;border-radius:50px;width:33px;height:100%;transition:background-color .3s ease}.option:hover,.dropdown.show .option{background-color:var(--bs-table-hover-bg)!important}.custom-dropdown.dropdown-menu{min-width:unset!important;width:auto!important}.acceso-tooltip-fixed{position:fixed;z-index:99999;transform:translateY(-50%);pointer-events:none;padding:4px 10px 4px 8px;border-radius:6px;font-family:monospace;white-space:nowrap;background:#0f0f14;border:1px solid rgba(255,255,255,.07);border-left:2px solid;display:flex;align-items:center;gap:5px;animation:tooltipFadeIn .14s cubic-bezier(.25,.46,.45,.94)}.acceso-tooltip-fixed:before{content:\"\";position:absolute;right:100%;top:50%;transform:translateY(-50%);border:4px solid transparent;border-right-color:var(--tooltip-accent, #c50048)}.acceso-tooltip-fixed .tooltip-label{font-size:10px;font-weight:400;color:#fff;letter-spacing:.3px}.acceso-tooltip-fixed .tooltip-value{font-size:11px;font-weight:700}@keyframes tooltipFadeIn{0%{opacity:0;transform:translateY(-50%) translate(-4px)}to{opacity:1;transform:translateY(-50%) translate(0)}}.btn-print{border:1px solid rgba(0,0,0,.5764705882)!important;width:33px;height:30px!important;border-radius:6px}.btn-print:hover{border:1px solid rgba(61,61,61,.5254901961)!important;background-color:#dadadaf8!important}.btn-search{width:40px;height:31px!important;border-radius:6px}.logo-btn{width:25px;height:25px;object-fit:contain}.btn-deudas{background:#fff;border-radius:20px;border:none;white-space:nowrap;flex-shrink:0}.btn-deudas.titilando{animation:bordeTitilante 1s infinite alternate}@keyframes bordeTitilante{0%{box-shadow:0 0 2px red}50%{box-shadow:0 0 5px red,0 0 5px #ff4d4d}to{box-shadow:0 0 2px red}}@media(max-width:1100px){.btn-deudas{width:31px;height:31px!important;border-radius:50px;padding:0;display:flex;align-items:center;justify-content:center;aspect-ratio:1/1}.btn-deudas .texto-deudas{display:none}.btn-deudas .logo-btn{width:20px;height:20px;margin:0}}@keyframes icon-rotate-pop{0%{transform:rotate(0) scale(1)}25%{transform:rotate(10deg) scale(1.05)}50%{transform:rotate(-10deg) scale(1.1)}75%{transform:rotate(10deg) scale(1.05)}to{transform:rotate(0) scale(1)}}.button-icon-hover{display:inline-block}.button-tilt-hover:hover .button-icon-hover{animation:icon-rotate-pop 1s ease-in-out infinite}.desktop-only{display:flex}@media(max-width:667px){.desktop-only{display:none!important}}.notification-btn{position:relative;border:none;background:none;padding:0;margin-right:8px;cursor:pointer;width:33px;height:32px;display:flex;align-items:center;justify-content:center}.notification-btn i{color:#fff}.notification-badge{position:absolute;top:-5px;right:-3px;color:#fff;font-size:11px;font-weight:600;border-radius:4px;min-width:18px;height:18px;display:flex;align-items:center;justify-content:center;padding:0 4px}.header-side{flex:0 1 auto;min-width:0}.header-side--end{justify-content:flex-end}.global-search-trigger{position:absolute;left:50%;transform:translate(-50%);z-index:2;align-self:center;flex-shrink:0;margin:0;gap:8px;height:31px;width:280px;padding:0 6px 0 12px;background:#ffffff26;border:1px solid rgba(255,255,255,.3);border-radius:6px;color:#ffffffe6;font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s,border-color .15s,color .15s}.global-search-trigger:hover,.global-search-trigger:focus-visible{background:#ffffff47;border-color:#ffffff80;color:#fff}.global-search-trigger .global-search-icon{font-size:12px;color:#ffffffbf}.global-search-trigger .global-search-placeholder{flex-grow:1;text-align:start}.global-search-trigger .global-search-kbd{font-size:10px;font-weight:600;line-height:1;padding:3px 5px;border-radius:4px;background:#fff3;border:1px solid rgba(255,255,255,.35);color:#fff}.global-search-trigger--collapsed{display:none!important}.global-search-compact-pill{display:flex;align-items:center;justify-content:center;height:31px;margin-right:8px;padding:0 9px;background:#ffffff26;border:1px solid rgba(255,255,255,.3);border-radius:6px;color:#ffffffe6;font-size:11px;font-weight:700;cursor:pointer;transition:background .15s,border-color .15s,color .15s}.global-search-compact-pill:hover,.global-search-compact-pill:focus-visible{background:#ffffff47;border-color:#ffffff80;color:#fff}.tabs-header-btn{display:flex;align-items:center;gap:4px;background:#ffffff1a;border:1px solid rgba(255,255,255,.15);color:#fff9;border-radius:20px;padding:3px 8px;font-size:11px;cursor:pointer;transition:background .15s,color .15s;white-space:nowrap}.tabs-header-btn:hover{background:#fff3;color:#fff}.tabs-header-btn--active{background:#ffffff2e;color:#fff;border-color:#ffffff4d}.tabs-header-btn i{font-size:12px}.tabs-header-count{font-weight:700;font-size:11px;background:#fff3;border-radius:10px;padding:0 5px;min-width:16px;text-align:center}\n"] }]
|
|
747
747
|
}], propDecorators: { headerContainerRef: [{
|
|
@@ -756,7 +756,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
756
756
|
}], compactSearchWrapperRef: [{
|
|
757
757
|
type: ViewChild,
|
|
758
758
|
args: ['compactSearchWrapper']
|
|
759
|
-
}], onDocumentClick: [{
|
|
759
|
+
}], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], showSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearch", required: false }] }], themes: [{ type: i0.Input, args: [{ isSignal: true, alias: "themes", required: false }] }], showThemeSwitcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "showThemeSwitcher", required: false }] }], showTabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTabs", required: false }] }], showNotifications: [{ type: i0.Input, args: [{ isSignal: true, alias: "showNotifications", required: false }] }], notificationsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "notificationsCount", required: false }] }], notificationsClick: [{ type: i0.Output, args: ["notificationsClick"] }], notificationsInBottomNav: [{ type: i0.Input, args: [{ isSignal: true, alias: "notificationsInBottomNav", required: false }] }], showChatbotToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChatbotToggle", required: false }] }], chatbotVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "chatbotVisible", required: false }] }], chatbotVisibleChange: [{ type: i0.Output, args: ["chatbotVisibleChange"] }], chatbotInBottomNav: [{ type: i0.Input, args: [{ isSignal: true, alias: "chatbotInBottomNav", required: false }] }], currentTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentTheme", required: false }] }], themeChange: [{ type: i0.Output, args: ["themeChange"] }], versionApp: [{ type: i0.Input, args: [{ isSignal: true, alias: "versionApp", required: false }] }], accentColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "accentColor", required: false }] }], envClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "envClass", required: false }] }], produccion: [{ type: i0.Input, args: [{ isSignal: true, alias: "produccion", required: false }] }], emitirToogle: [{ type: i0.Output, args: ["emitirToogle"] }], isScrolled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isScrolled", required: false }] }], isSidebarOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSidebarOpen", required: false }] }], nameProyecto: [{ type: i0.Input, args: [{ isSignal: true, alias: "nameProyecto", required: false }] }], searchComponents: [{ type: i0.Output, args: ["searchComponents"] }], showPanelControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPanelControl", required: false }] }], panelControlClick: [{ type: i0.Output, args: ["panelControlClick"] }], logout: [{ type: i0.Output, args: ["logout"] }], userName: [{ type: i0.Input, args: [{ isSignal: true, alias: "userName", required: false }] }], empresaName: [{ type: i0.Input, args: [{ isSignal: true, alias: "empresaName", required: false }] }], onDocumentClick: [{
|
|
760
760
|
type: HostListener,
|
|
761
761
|
args: ['document:click']
|
|
762
762
|
}] } });
|
|
@@ -778,8 +778,8 @@ class TabBarComponent {
|
|
|
778
778
|
// tiene equivalente CSS puro porque Angular remueve el elemento del DOM al
|
|
779
779
|
// instante — acá lo mantenemos montado con una clase "--leaving" el tiempo
|
|
780
780
|
// que dura la animación de salida, y recién ahí lo desmontamos.
|
|
781
|
-
shouldShow = computed(() => this.tabs.tabs().length > 0 && this.tabs.visible());
|
|
782
|
-
rendered = signal(false);
|
|
781
|
+
shouldShow = computed(() => this.tabs.tabs().length > 0 && this.tabs.visible(), ...(ngDevMode ? [{ debugName: "shouldShow" }] : []));
|
|
782
|
+
rendered = signal(false, ...(ngDevMode ? [{ debugName: "rendered" }] : []));
|
|
783
783
|
leaveTimer = null;
|
|
784
784
|
constructor() {
|
|
785
785
|
effect(() => {
|
|
@@ -797,11 +797,11 @@ class TabBarComponent {
|
|
|
797
797
|
}
|
|
798
798
|
// Se combina con los colores por defecto en vez de reemplazarlos: un proyecto solo
|
|
799
799
|
// necesita pasar los módulos que quiera personalizar, el resto sigue con su color base.
|
|
800
|
-
moduleColors = input({});
|
|
800
|
+
moduleColors = input({}, ...(ngDevMode ? [{ debugName: "moduleColors" }] : []));
|
|
801
801
|
// Tooltip nativo al hover (sin ng-bootstrap): mismo patrón fixed-position
|
|
802
802
|
// que ya usan menu-item/vertical-header en esta librería.
|
|
803
|
-
hoveredTab = signal(null);
|
|
804
|
-
tipPosition = signal({ x: 0, y: 0 });
|
|
803
|
+
hoveredTab = signal(null, ...(ngDevMode ? [{ debugName: "hoveredTab" }] : []));
|
|
804
|
+
tipPosition = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "tipPosition" }] : []));
|
|
805
805
|
hoverTimer = null;
|
|
806
806
|
getModuleColor(tab) {
|
|
807
807
|
const key = tab.moduleKey ?? tab.module ?? '';
|
|
@@ -829,26 +829,26 @@ class TabBarComponent {
|
|
|
829
829
|
this.tabs.close(tab.id, event);
|
|
830
830
|
}
|
|
831
831
|
}
|
|
832
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
833
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
832
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: TabBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
833
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: TabBarComponent, isStandalone: true, selector: "app-tab-bar", inputs: { moduleColors: { classPropertyName: "moduleColors", publicName: "moduleColors", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (rendered()) {\r\n<div class=\"tab-bar\" [class.tab-bar--leaving]=\"!shouldShow()\">\r\n <div class=\"tab-list\">\r\n @for (tab of tabs.sortedTabs(); track tab.id) {\r\n\r\n <div class=\"tab\" [class.tab--active]=\"tabs.activeId() === tab.id\" [class.tab--pinned]=\"tab.pinned\"\r\n [class.tab--with-module]=\"!!tab.module\" (mouseenter)=\"onTabMouseEnter($event, tab)\" (mouseleave)=\"onTabMouseLeave()\"\r\n (click)=\"tabs.activate(tab.id)\" (mousedown)=\"onTabMouseDown($event, tab)\">\r\n @if (tab.icon) {\r\n <i [class]=\"tab.icon + ' tab-icon'\"></i>\r\n }\r\n <div class=\"tab-body\">\r\n <span class=\"tab-title\">{{ tab.title }}</span>\r\n @if (tab.module) {\r\n <span class=\"tab-module\">\r\n <span class=\"tab-module-dot\" [style.background]=\"getModuleColor(tab)\"></span>\r\n {{ tab.module }}\r\n </span>\r\n }\r\n </div>\r\n <button class=\"tab-btn tab-pin\" [class.tab-pin--active]=\"tab.pinned\" (click)=\"tabs.togglePin(tab.id, $event)\"\r\n [title]=\"tab.pinned ? 'Desfijar' : 'Fijar'\">\r\n <i class=\"fas fa-thumbtack\"></i>\r\n </button>\r\n @if (!tab.pinned) {\r\n <button class=\"tab-btn tab-close\" (click)=\"tabs.close(tab.id, $event)\" title=\"Cerrar\">\r\n <i class=\"fas fa-times\"></i>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"tab-actions\">\r\n <button class=\"tab-close-all\" (click)=\"tabs.closeAll()\" title=\"Cerrar todas las pesta\u00F1as\">\r\n <i class=\"fas fa-times-circle\"></i>\r\n <span>Cerrar todo</span>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n@if (hoveredTab(); as tab) {\r\n<div class=\"tab-tip-fixed\" [style.left.px]=\"tipPosition().x\" [style.top.px]=\"tipPosition().y\">\r\n <span class=\"tab-tip-title\">{{ tab.title }}</span>\r\n @if (tab.module) {\r\n <span class=\"tab-tip-module\">\r\n <span class=\"tab-tip-dot\" [style.background]=\"getModuleColor(tab)\"></span>\r\n {{ tab.module }}\r\n </span>\r\n }\r\n</div>\r\n}\r\n}\r\n", styles: ["@media(max-width:767px){.tab-bar{display:none!important}}.tab-bar{display:flex;align-items:center;padding:4px 8px;background:var(--sidebar-bg, #0b1a3d);border-bottom:1px solid rgba(255,255,255,.1);min-height:38px;width:100%;flex-shrink:0;box-shadow:0 2px 8px #00000040;animation:tabBarSlideIn .22s cubic-bezier(.25,.46,.45,.94) both}.tab-bar--leaving{animation:tabBarSlideOut .16s ease-in both}@keyframes tabBarSlideIn{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes tabBarSlideOut{0%{transform:translateY(0);opacity:1}to{transform:translateY(-100%);opacity:0}}.tab-list{display:flex;align-items:stretch;gap:3px;flex:1;min-width:0;overflow-x:auto;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.15) transparent}.tab-list::-webkit-scrollbar{height:2px}.tab-list::-webkit-scrollbar-track{background:transparent}.tab-list::-webkit-scrollbar-thumb{background:#fff3;border-radius:2px}.tab{display:flex;align-items:center;gap:5px;padding:4px 8px;border-radius:5px;cursor:pointer;white-space:nowrap;font-size:12px;color:#ffffff8c;background:#ffffff0a;border:1px solid transparent;transition:background .15s,border-color .15s,color .15s;flex:1 1 0;min-width:60px;max-width:180px;overflow:hidden;-webkit-user-select:none;user-select:none}.tab--with-module{align-items:flex-start;padding-top:5px;padding-bottom:5px}.tab:hover{background:#ffffff17;color:#fffc}.tab:hover .tab-pin{opacity:.5}.tab--active{background:#398bf726;border-color:#398bf773;color:#93c5fd}.tab--pinned{border-color:#fbbf2459;background:#fbbf2412;flex:0 0 auto}.tab--pinned.tab--active{border-color:#398bf773;background:#398bf726}.tab-icon{font-size:11px;flex-shrink:0;margin-top:1px}.tab--with-module .tab-icon{margin-top:2px}.tab-body{display:flex;flex-direction:column;flex:1;min-width:0;gap:2px}.tab-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.2}.tab-module{display:flex;align-items:center;gap:4px;font-size:10.5px;color:#fff9;line-height:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-module-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0;align-self:center;display:block}.tab-btn{background:none;border:none;padding:0 1px;cursor:pointer;color:inherit;font-size:9px;line-height:1;display:flex;align-items:center;flex-shrink:0}.tab-pin{opacity:0;transition:opacity .15s,color .15s,transform .2s;transform:rotate(45deg)}.tab-pin--active{opacity:1!important;color:#fbbf24;transform:rotate(0)}.tab-pin:hover{opacity:1!important}.tab-close{opacity:.4}.tab-close:hover{opacity:1}.tab-actions{display:flex;align-items:center;gap:4px;padding-left:8px;border-left:1px solid rgba(255,255,255,.08);margin-left:4px;flex-shrink:0}.tab-tip-fixed{position:fixed;z-index:99999;transform:translate(-50%);pointer-events:none;padding:6px 10px;border-radius:6px;background:#0f0f14;border:1px solid rgba(255,255,255,.07);white-space:nowrap;display:flex;flex-direction:column;gap:3px;animation:tabTipFadeIn .14s ease}.tab-tip-fixed:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border:5px solid transparent;border-bottom-color:#0f0f14}.tab-tip-title{font-size:11px;font-weight:600;color:#fff}.tab-tip-module{display:flex;align-items:center;gap:4px;font-size:10px;color:#ffffffa6}.tab-tip-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}@keyframes tabTipFadeIn{0%{opacity:0;transform:translate(-50%) translateY(-4px)}to{opacity:1;transform:translate(-50%) translateY(0)}}.tab-close-all{display:flex;align-items:center;gap:5px;background:none;border:none;cursor:pointer;color:#fff6;font-size:11px;padding:3px 6px;border-radius:4px;white-space:nowrap;transition:color .15s,background .15s}.tab-close-all:hover{color:#f87171;background:#f871711a}.tab-close-all i{font-size:12px}\n"] });
|
|
834
834
|
}
|
|
835
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
835
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: TabBarComponent, decorators: [{
|
|
836
836
|
type: Component,
|
|
837
837
|
args: [{ selector: 'app-tab-bar', imports: [], template: "@if (rendered()) {\r\n<div class=\"tab-bar\" [class.tab-bar--leaving]=\"!shouldShow()\">\r\n <div class=\"tab-list\">\r\n @for (tab of tabs.sortedTabs(); track tab.id) {\r\n\r\n <div class=\"tab\" [class.tab--active]=\"tabs.activeId() === tab.id\" [class.tab--pinned]=\"tab.pinned\"\r\n [class.tab--with-module]=\"!!tab.module\" (mouseenter)=\"onTabMouseEnter($event, tab)\" (mouseleave)=\"onTabMouseLeave()\"\r\n (click)=\"tabs.activate(tab.id)\" (mousedown)=\"onTabMouseDown($event, tab)\">\r\n @if (tab.icon) {\r\n <i [class]=\"tab.icon + ' tab-icon'\"></i>\r\n }\r\n <div class=\"tab-body\">\r\n <span class=\"tab-title\">{{ tab.title }}</span>\r\n @if (tab.module) {\r\n <span class=\"tab-module\">\r\n <span class=\"tab-module-dot\" [style.background]=\"getModuleColor(tab)\"></span>\r\n {{ tab.module }}\r\n </span>\r\n }\r\n </div>\r\n <button class=\"tab-btn tab-pin\" [class.tab-pin--active]=\"tab.pinned\" (click)=\"tabs.togglePin(tab.id, $event)\"\r\n [title]=\"tab.pinned ? 'Desfijar' : 'Fijar'\">\r\n <i class=\"fas fa-thumbtack\"></i>\r\n </button>\r\n @if (!tab.pinned) {\r\n <button class=\"tab-btn tab-close\" (click)=\"tabs.close(tab.id, $event)\" title=\"Cerrar\">\r\n <i class=\"fas fa-times\"></i>\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"tab-actions\">\r\n <button class=\"tab-close-all\" (click)=\"tabs.closeAll()\" title=\"Cerrar todas las pesta\u00F1as\">\r\n <i class=\"fas fa-times-circle\"></i>\r\n <span>Cerrar todo</span>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n@if (hoveredTab(); as tab) {\r\n<div class=\"tab-tip-fixed\" [style.left.px]=\"tipPosition().x\" [style.top.px]=\"tipPosition().y\">\r\n <span class=\"tab-tip-title\">{{ tab.title }}</span>\r\n @if (tab.module) {\r\n <span class=\"tab-tip-module\">\r\n <span class=\"tab-tip-dot\" [style.background]=\"getModuleColor(tab)\"></span>\r\n {{ tab.module }}\r\n </span>\r\n }\r\n</div>\r\n}\r\n}\r\n", styles: ["@media(max-width:767px){.tab-bar{display:none!important}}.tab-bar{display:flex;align-items:center;padding:4px 8px;background:var(--sidebar-bg, #0b1a3d);border-bottom:1px solid rgba(255,255,255,.1);min-height:38px;width:100%;flex-shrink:0;box-shadow:0 2px 8px #00000040;animation:tabBarSlideIn .22s cubic-bezier(.25,.46,.45,.94) both}.tab-bar--leaving{animation:tabBarSlideOut .16s ease-in both}@keyframes tabBarSlideIn{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes tabBarSlideOut{0%{transform:translateY(0);opacity:1}to{transform:translateY(-100%);opacity:0}}.tab-list{display:flex;align-items:stretch;gap:3px;flex:1;min-width:0;overflow-x:auto;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.15) transparent}.tab-list::-webkit-scrollbar{height:2px}.tab-list::-webkit-scrollbar-track{background:transparent}.tab-list::-webkit-scrollbar-thumb{background:#fff3;border-radius:2px}.tab{display:flex;align-items:center;gap:5px;padding:4px 8px;border-radius:5px;cursor:pointer;white-space:nowrap;font-size:12px;color:#ffffff8c;background:#ffffff0a;border:1px solid transparent;transition:background .15s,border-color .15s,color .15s;flex:1 1 0;min-width:60px;max-width:180px;overflow:hidden;-webkit-user-select:none;user-select:none}.tab--with-module{align-items:flex-start;padding-top:5px;padding-bottom:5px}.tab:hover{background:#ffffff17;color:#fffc}.tab:hover .tab-pin{opacity:.5}.tab--active{background:#398bf726;border-color:#398bf773;color:#93c5fd}.tab--pinned{border-color:#fbbf2459;background:#fbbf2412;flex:0 0 auto}.tab--pinned.tab--active{border-color:#398bf773;background:#398bf726}.tab-icon{font-size:11px;flex-shrink:0;margin-top:1px}.tab--with-module .tab-icon{margin-top:2px}.tab-body{display:flex;flex-direction:column;flex:1;min-width:0;gap:2px}.tab-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.2}.tab-module{display:flex;align-items:center;gap:4px;font-size:10.5px;color:#fff9;line-height:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-module-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0;align-self:center;display:block}.tab-btn{background:none;border:none;padding:0 1px;cursor:pointer;color:inherit;font-size:9px;line-height:1;display:flex;align-items:center;flex-shrink:0}.tab-pin{opacity:0;transition:opacity .15s,color .15s,transform .2s;transform:rotate(45deg)}.tab-pin--active{opacity:1!important;color:#fbbf24;transform:rotate(0)}.tab-pin:hover{opacity:1!important}.tab-close{opacity:.4}.tab-close:hover{opacity:1}.tab-actions{display:flex;align-items:center;gap:4px;padding-left:8px;border-left:1px solid rgba(255,255,255,.08);margin-left:4px;flex-shrink:0}.tab-tip-fixed{position:fixed;z-index:99999;transform:translate(-50%);pointer-events:none;padding:6px 10px;border-radius:6px;background:#0f0f14;border:1px solid rgba(255,255,255,.07);white-space:nowrap;display:flex;flex-direction:column;gap:3px;animation:tabTipFadeIn .14s ease}.tab-tip-fixed:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border:5px solid transparent;border-bottom-color:#0f0f14}.tab-tip-title{font-size:11px;font-weight:600;color:#fff}.tab-tip-module{display:flex;align-items:center;gap:4px;font-size:10px;color:#ffffffa6}.tab-tip-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0}@keyframes tabTipFadeIn{0%{opacity:0;transform:translate(-50%) translateY(-4px)}to{opacity:1;transform:translate(-50%) translateY(0)}}.tab-close-all{display:flex;align-items:center;gap:5px;background:none;border:none;cursor:pointer;color:#fff6;font-size:11px;padding:3px 6px;border-radius:4px;white-space:nowrap;transition:color .15s,background .15s}.tab-close-all:hover{color:#f87171;background:#f871711a}.tab-close-all i{font-size:12px}\n"] }]
|
|
838
|
-
}], ctorParameters: () => [] });
|
|
838
|
+
}], ctorParameters: () => [], propDecorators: { moduleColors: [{ type: i0.Input, args: [{ isSignal: true, alias: "moduleColors", required: false }] }] } });
|
|
839
839
|
|
|
840
840
|
class DetectorService {
|
|
841
|
-
componenteActual = signal(null);
|
|
841
|
+
componenteActual = signal(null, ...(ngDevMode ? [{ debugName: "componenteActual" }] : []));
|
|
842
842
|
setComponente(componente) {
|
|
843
843
|
this.componenteActual.set(componente);
|
|
844
844
|
}
|
|
845
845
|
getComponente() {
|
|
846
846
|
return this.componenteActual.asReadonly();
|
|
847
847
|
}
|
|
848
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
849
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
848
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: DetectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
849
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: DetectorService, providedIn: 'root' });
|
|
850
850
|
}
|
|
851
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
851
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: DetectorService, decorators: [{
|
|
852
852
|
type: Injectable,
|
|
853
853
|
args: [{
|
|
854
854
|
providedIn: 'root'
|
|
@@ -860,35 +860,35 @@ class FullComponent {
|
|
|
860
860
|
contexts = inject(ChildrenOutletContexts);
|
|
861
861
|
router = inject(Router);
|
|
862
862
|
tabsService = inject(TabsService);
|
|
863
|
-
menuItems = input([]);
|
|
864
|
-
nameProyecto = input('');
|
|
865
|
-
accentColor = input('#398bf7');
|
|
866
|
-
showTabs = input(true);
|
|
867
|
-
tabModuleColors = input({});
|
|
863
|
+
menuItems = input([], ...(ngDevMode ? [{ debugName: "menuItems" }] : []));
|
|
864
|
+
nameProyecto = input('', ...(ngDevMode ? [{ debugName: "nameProyecto" }] : []));
|
|
865
|
+
accentColor = input('#398bf7', ...(ngDevMode ? [{ debugName: "accentColor" }] : []));
|
|
866
|
+
showTabs = input(true, ...(ngDevMode ? [{ debugName: "showTabs" }] : []));
|
|
867
|
+
tabModuleColors = input({}, ...(ngDevMode ? [{ debugName: "tabModuleColors" }] : []));
|
|
868
868
|
currentYear = new Date().getFullYear();
|
|
869
869
|
// El vertical-header se recibe proyectado (<ng-content select="[header]">), así
|
|
870
870
|
// que no es un ViewChild del template propio de `full` sino contenido — por eso
|
|
871
871
|
// ContentChild en vez de ViewChild (mismo mecanismo que usa consults con ViewChild
|
|
872
872
|
// porque ahí el header vive directo en su propio template, no proyectado).
|
|
873
873
|
// El bottom-nav SOLO sale de ahí — igual que en consults, sin lista aparte.
|
|
874
|
-
verticalHeaderSignal = signal(null);
|
|
874
|
+
verticalHeaderSignal = signal(null, ...(ngDevMode ? [{ debugName: "verticalHeaderSignal" }] : []));
|
|
875
875
|
set verticalHeaderRef(vh) {
|
|
876
876
|
if (vh)
|
|
877
877
|
this.verticalHeaderSignal.set(vh);
|
|
878
878
|
}
|
|
879
|
-
bottomMenuItems = computed(() => this.verticalHeaderSignal()?.bottomNavItems() ?? []);
|
|
880
|
-
isSidebarOpen = signal(false);
|
|
881
|
-
isSidebarHovering = signal(false);
|
|
882
|
-
isScrolled = signal(false);
|
|
879
|
+
bottomMenuItems = computed(() => this.verticalHeaderSignal()?.bottomNavItems() ?? [], ...(ngDevMode ? [{ debugName: "bottomMenuItems" }] : []));
|
|
880
|
+
isSidebarOpen = signal(false, ...(ngDevMode ? [{ debugName: "isSidebarOpen" }] : []));
|
|
881
|
+
isSidebarHovering = signal(false, ...(ngDevMode ? [{ debugName: "isSidebarHovering" }] : []));
|
|
882
|
+
isScrolled = signal(false, ...(ngDevMode ? [{ debugName: "isScrolled" }] : []));
|
|
883
883
|
isDesktop = window.innerWidth >= 1191;
|
|
884
|
-
isMobileView = signal(window.innerWidth <= 667);
|
|
885
|
-
sidebarWidth = signal(260);
|
|
884
|
+
isMobileView = signal(window.innerWidth <= 667, ...(ngDevMode ? [{ debugName: "isMobileView" }] : []));
|
|
885
|
+
sidebarWidth = signal(260, ...(ngDevMode ? [{ debugName: "sidebarWidth" }] : []));
|
|
886
886
|
// Datos de sesión: se reciben del consumidor (en vez de inyectar SesionService
|
|
887
887
|
// acá) para que layout-tsi no dependa de core-tsi. Es un solo objeto requerido
|
|
888
888
|
// (input.required) en vez de 6 inputs sueltos, para que Angular tire error si
|
|
889
889
|
// el consumidor se olvida de pasarlo, en vez de fallar en silencio con '' o [].
|
|
890
|
-
sessionData = input.required();
|
|
891
|
-
nombreSucursal = computed(() => this.sessionData().sucursales?.find(s => s.codsuc == this.sessionData().codsuc)?.sucursal ?? '');
|
|
890
|
+
sessionData = input.required(...(ngDevMode ? [{ debugName: "sessionData" }] : []));
|
|
891
|
+
nombreSucursal = computed(() => this.sessionData().sucursales?.find(s => s.codsuc == this.sessionData().codsuc)?.sucursal ?? '', ...(ngDevMode ? [{ debugName: "nombreSucursal" }] : []));
|
|
892
892
|
cambiarSucursal() {
|
|
893
893
|
this.router.navigateByUrl('seleccionar-sucursal');
|
|
894
894
|
}
|
|
@@ -900,7 +900,7 @@ class FullComponent {
|
|
|
900
900
|
// saca la clase y se vuelve a poner en el siguiente frame para forzar que
|
|
901
901
|
// el @keyframes de entrada se reinicie (una clase ya puesta no reinicia su
|
|
902
902
|
// animación si se la vuelve a poner sin sacarla antes).
|
|
903
|
-
routeAnimating = signal(false);
|
|
903
|
+
routeAnimating = signal(false, ...(ngDevMode ? [{ debugName: "routeAnimating" }] : []));
|
|
904
904
|
onRouteActivate() {
|
|
905
905
|
this.routeAnimating.set(false);
|
|
906
906
|
requestAnimationFrame(() => requestAnimationFrame(() => this.routeAnimating.set(true)));
|
|
@@ -982,17 +982,17 @@ class FullComponent {
|
|
|
982
982
|
this.isSidebarHovering.set(false);
|
|
983
983
|
}
|
|
984
984
|
}
|
|
985
|
-
showBottomNav = computed(() => this.isMobileView() && !this.isSidebarOpen() && this.bottomMenuItems().length > 0);
|
|
986
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
987
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
985
|
+
showBottomNav = computed(() => this.isMobileView() && !this.isSidebarOpen() && this.bottomMenuItems().length > 0, ...(ngDevMode ? [{ debugName: "showBottomNav" }] : []));
|
|
986
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: FullComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
987
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: FullComponent, isStandalone: true, selector: "app-full", inputs: { menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: false, transformFunction: null }, nameProyecto: { classPropertyName: "nameProyecto", publicName: "nameProyecto", isSignal: true, isRequired: false, transformFunction: null }, accentColor: { classPropertyName: "accentColor", publicName: "accentColor", isSignal: true, isRequired: false, transformFunction: null }, showTabs: { classPropertyName: "showTabs", publicName: "showTabs", isSignal: true, isRequired: false, transformFunction: null }, tabModuleColors: { classPropertyName: "tabModuleColors", publicName: "tabModuleColors", isSignal: true, isRequired: false, transformFunction: null }, sessionData: { classPropertyName: "sessionData", publicName: "sessionData", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "window:resize": "onResize($event)", "document:click": "onClickOutside($event)" } }, queries: [{ propertyName: "verticalHeaderRef", first: true, predicate: VerticalHeaderComponent, descendants: true }], viewQueries: [{ propertyName: "contentContainer", first: true, predicate: ["contentContainer"], descendants: true }, { propertyName: "sidebarRef", first: true, predicate: ["sidebar"], descendants: true }], ngImport: i0, template: "<ng-content select=\"[header]\" />\r\n\r\n<div [ngClass]=\"{'layout': true, 'open': isSidebarOpen()}\">\r\n <div #sidebar class=\"sidebar\" id=\"sidebar\" [ngClass]=\"isSidebarOpen() ? 'open' : ''\"\r\n (mouseenter)=\"onSidebarHoverEnter()\" (mouseleave)=\"onSidebarHoverLeave()\">\r\n <div class=\"sub-sidebar py-3\">\r\n <div class=\"user-profile\" [class.collapsed]=\"!isSidebarActuallyOpen\">\r\n <div class=\"user-info\" [class.user-info--hidden]=\"!isSidebarActuallyOpen\">\r\n <span class=\"fw-6 fs-7 truncate-text user-name\">{{ sessionData().nombreUser }}</span>\r\n <span class=\"truncate-text user-sucursal\">{{ nombreSucursal() }}</span>\r\n </div>\r\n @if (sessionData().sucursales.length > 1) {\r\n <button type=\"button\" class=\"btn-cambiar-sucursal\" title=\"Cambiar sucursal\" aria-label=\"Cambiar sucursal\"\r\n (click)=\"cambiarSucursal()\">\r\n <i class=\"fas fa-right-left\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"pt-3 px-2 list-menu-sidebar\">\r\n <ul class=\"list-unstyled\">\r\n @for (item of menuItems(); track $index) {\r\n <app-menu-item [item]=\"item\" [isSidebarOpen]=\"isSidebarOpen()\" [isSidebarHovering]=\"isSidebarHovering()\"\r\n [parentModuleName]=\"item.title\" [accentColor]=\"accentColor()\" [accesos]=\"sessionData().accesos\" [rolId]=\"sessionData().rolId\" />\r\n }\r\n </ul>\r\n </div>\r\n\r\n <div class=\"sidebar-footer text-center\" [class.sidebar-footer--hidden]=\"!isSidebarActuallyOpen\">\r\n <p> \u00A9 {{ currentYear }} Grupo TSI - {{ sessionData().idCia }} </p>\r\n </div>\r\n </div>\r\n\r\n <div #contentContainer class=\"content\" [class.has-bottom-nav]=\"showBottomNav()\"\r\n [ngStyle]=\"{'background-color': 'var(--background-color)'}\">\r\n @if (showTabs()) {\r\n <app-tab-bar [moduleColors]=\"tabModuleColors()\" />\r\n }\r\n <div class=\"content-scroll\">\r\n <div class=\"container-fluid\" [class.route-fade-in]=\"routeAnimating()\">\r\n <router-outlet (activate)=\"onRouteActivate()\" />\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (showBottomNav()) {\r\n<app-bottom-navigation [menuItems]=\"bottomMenuItems()\" [isVisible]=\"true\" />\r\n}\r\n<ng-content select=\"[chatbot]\" />\r\n", styles: [".hidden{display:none!important}.header-container{height:50px;background:#c50048;display:flex;justify-content:space-between;align-items:center}.header-sidebar{height:50px;background:#c50048;display:flex;align-items:center;justify-content:space-between;gap:5px}.sub-sidebar{border-bottom:1px solid rgba(255,255,255,.1);background:#ffffff08;min-width:0}.user-profile{display:flex;align-items:center;gap:10px;padding:0 12px;min-width:0;min-height:36px}.user-profile.collapsed{justify-content:center;padding:0;gap:0}.btn-cambiar-sucursal{flex:0 0 auto;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border:1px solid rgba(255,255,255,.15);border-radius:8px;background:#ffffff0f;color:var(--sidebar-active-text);cursor:pointer;transition:background .2s ease,border-color .2s ease,transform .15s ease}.btn-cambiar-sucursal:hover{background:#ffffff24;border-color:#ffffff4d}.btn-cambiar-sucursal:active{transform:scale(.94)}.btn-cambiar-sucursal:focus-visible{outline:2px solid var(--sidebar-accent, #c50048);outline-offset:2px}.user-avatar{width:38px;height:38px;min-width:38px;border-radius:50%;background:linear-gradient(135deg,var(--sidebar-accent, #c50048),color-mix(in srgb,var(--sidebar-accent, #c50048) 60%,white));color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;letter-spacing:.5px;box-shadow:0 0 0 2px #ffffff1a,0 4px 12px #0006}.user-info{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;visibility:visible;opacity:1;transition:opacity .15s ease .22s,visibility 0s ease .22s}.user-info--hidden{visibility:hidden!important;opacity:0!important;max-height:0!important;flex:0 0 0!important;width:0!important;overflow:hidden!important;padding:0!important;margin:0!important;transition:opacity .08s ease 0s,visibility 0s ease .08s,max-height 0s ease .08s!important}.user-name{color:var(--sidebar-active-text)}.user-sucursal{font-size:11px;color:var(--sidebar-text-color);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.list-unstyled{font-size:13px;color:var(--sidebar-text-color)}.layout{display:grid;grid-template-columns:260px 1fr;height:calc(100dvh - 50px)}.sidebar{background:linear-gradient(160deg,var(--sidebar-gradient-start) 0%,var(--sidebar-bg) 100%)!important;box-shadow:4px 0 24px #00000059;border-right:1px solid rgba(255,255,255,.05);transition:transform .3s ease-in-out;width:260px;overflow:hidden;scrollbar-width:none;display:flex;flex-direction:column}.list-menu-sidebar{flex:1;overflow-y:auto;scrollbar-width:none;margin-bottom:0}.sidebar-footer{font-size:11px;color:var(--sidebar-text-color);padding:10px 12px;border-top:1px solid rgba(255,255,255,.08);margin-top:auto;width:100%;display:flex;align-items:center;justify-content:center;opacity:.65;visibility:visible;transition:opacity .15s ease .25s,visibility 0s ease .25s}.sidebar-footer--hidden{opacity:0;visibility:hidden;transition:opacity .1s ease 0s,visibility 0s ease .1s}.sidebar-footer p{margin:0}.content{display:flex;flex-direction:column;overflow:hidden;max-height:100%}.content-scroll{flex:1;overflow-x:auto;overflow-y:auto;min-height:0;--content-space: .75rem}.content-scroll .container-fluid{padding:var(--content-space)!important}.content-scroll .container-fluid.route-fade-in{animation:routeContentFadeIn .32s cubic-bezier(.4,0,.2,1)}@keyframes routeContentFadeIn{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@media(max-width:1191px){.layout{grid-template-columns:1fr}.sidebar{position:fixed;top:50px;left:0;width:260px;height:calc(100dvh - 50px);z-index:1000;transform:translate(-100%);scrollbar-width:none;display:flex;flex-direction:column;overflow:visible}.sidebar-footer{display:flex!important}.sidebar.open{transform:translate(0)}}@media(min-width:1192px){.layout{grid-template-columns:260px 1fr;transition:grid-template-columns .3s ease-in-out}.layout.open{grid-template-columns:70px 1fr}.sidebar{width:260px;max-width:260px;transition:width .3s ease-in-out,max-width .3s ease-in-out}.sidebar.open{width:70px;max-width:70px}}.truncate-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;width:100%}.tc-bubble-container{position:fixed;top:111px;right:30px;z-index:9999}.tc-bubble{background:#c50048;color:#fff;padding:10px 14px;border-radius:50px;cursor:pointer;display:flex;align-items:center;gap:8px;box-shadow:0 4px 12px #0003;transition:all .2s ease}.tc-bubble:hover{transform:scale(1.05)}.tc-label{font-size:13px;font-weight:600}.tc-dropdown{margin-top:10px;background:#fff;border-radius:12px;padding:10px;min-width:220px;box-shadow:0 6px 18px #00000026}.tc-item{display:flex;align-items:center;gap:8px;padding:6px 4px;font-size:13px}.tc-item i{color:#c50048}.tc-item .item-content{display:flex;justify-content:space-between;align-items:center;width:100%}.tc-item .item-label{color:#333;text-align:left}.tc-item .item-value{color:#333;text-align:right;font-weight:500;margin-left:16px}@media(max-width:700px){.tc-bubble-container{top:auto;bottom:55px;right:40px}}.mobile-view .content{min-height:calc(100dvh - 110px)}@media(max-width:1191px){.content.has-bottom-nav{padding-bottom:60px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: MenuItemComponent, selector: "app-menu-item", inputs: ["item", "isSidebarOpen", "isSidebarHovering", "level", "parentModuleName", "accentColor", "accesos", "rolId"] }, { kind: "component", type: BottomNavigationComponent, selector: "app-bottom-navigation", inputs: ["menuItems", "isVisible"], outputs: ["itemClick"] }, { kind: "component", type: TabBarComponent, selector: "app-tab-bar", inputs: ["moduleColors"] }] });
|
|
988
988
|
}
|
|
989
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
989
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: FullComponent, decorators: [{
|
|
990
990
|
type: Component,
|
|
991
991
|
args: [{ selector: 'app-full', imports: [CommonModule, RouterModule, MenuItemComponent, BottomNavigationComponent, TabBarComponent], template: "<ng-content select=\"[header]\" />\r\n\r\n<div [ngClass]=\"{'layout': true, 'open': isSidebarOpen()}\">\r\n <div #sidebar class=\"sidebar\" id=\"sidebar\" [ngClass]=\"isSidebarOpen() ? 'open' : ''\"\r\n (mouseenter)=\"onSidebarHoverEnter()\" (mouseleave)=\"onSidebarHoverLeave()\">\r\n <div class=\"sub-sidebar py-3\">\r\n <div class=\"user-profile\" [class.collapsed]=\"!isSidebarActuallyOpen\">\r\n <div class=\"user-info\" [class.user-info--hidden]=\"!isSidebarActuallyOpen\">\r\n <span class=\"fw-6 fs-7 truncate-text user-name\">{{ sessionData().nombreUser }}</span>\r\n <span class=\"truncate-text user-sucursal\">{{ nombreSucursal() }}</span>\r\n </div>\r\n @if (sessionData().sucursales.length > 1) {\r\n <button type=\"button\" class=\"btn-cambiar-sucursal\" title=\"Cambiar sucursal\" aria-label=\"Cambiar sucursal\"\r\n (click)=\"cambiarSucursal()\">\r\n <i class=\"fas fa-right-left\"></i>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"pt-3 px-2 list-menu-sidebar\">\r\n <ul class=\"list-unstyled\">\r\n @for (item of menuItems(); track $index) {\r\n <app-menu-item [item]=\"item\" [isSidebarOpen]=\"isSidebarOpen()\" [isSidebarHovering]=\"isSidebarHovering()\"\r\n [parentModuleName]=\"item.title\" [accentColor]=\"accentColor()\" [accesos]=\"sessionData().accesos\" [rolId]=\"sessionData().rolId\" />\r\n }\r\n </ul>\r\n </div>\r\n\r\n <div class=\"sidebar-footer text-center\" [class.sidebar-footer--hidden]=\"!isSidebarActuallyOpen\">\r\n <p> \u00A9 {{ currentYear }} Grupo TSI - {{ sessionData().idCia }} </p>\r\n </div>\r\n </div>\r\n\r\n <div #contentContainer class=\"content\" [class.has-bottom-nav]=\"showBottomNav()\"\r\n [ngStyle]=\"{'background-color': 'var(--background-color)'}\">\r\n @if (showTabs()) {\r\n <app-tab-bar [moduleColors]=\"tabModuleColors()\" />\r\n }\r\n <div class=\"content-scroll\">\r\n <div class=\"container-fluid\" [class.route-fade-in]=\"routeAnimating()\">\r\n <router-outlet (activate)=\"onRouteActivate()\" />\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n@if (showBottomNav()) {\r\n<app-bottom-navigation [menuItems]=\"bottomMenuItems()\" [isVisible]=\"true\" />\r\n}\r\n<ng-content select=\"[chatbot]\" />\r\n", styles: [".hidden{display:none!important}.header-container{height:50px;background:#c50048;display:flex;justify-content:space-between;align-items:center}.header-sidebar{height:50px;background:#c50048;display:flex;align-items:center;justify-content:space-between;gap:5px}.sub-sidebar{border-bottom:1px solid rgba(255,255,255,.1);background:#ffffff08;min-width:0}.user-profile{display:flex;align-items:center;gap:10px;padding:0 12px;min-width:0;min-height:36px}.user-profile.collapsed{justify-content:center;padding:0;gap:0}.btn-cambiar-sucursal{flex:0 0 auto;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;font-size:12px;border:1px solid rgba(255,255,255,.15);border-radius:8px;background:#ffffff0f;color:var(--sidebar-active-text);cursor:pointer;transition:background .2s ease,border-color .2s ease,transform .15s ease}.btn-cambiar-sucursal:hover{background:#ffffff24;border-color:#ffffff4d}.btn-cambiar-sucursal:active{transform:scale(.94)}.btn-cambiar-sucursal:focus-visible{outline:2px solid var(--sidebar-accent, #c50048);outline-offset:2px}.user-avatar{width:38px;height:38px;min-width:38px;border-radius:50%;background:linear-gradient(135deg,var(--sidebar-accent, #c50048),color-mix(in srgb,var(--sidebar-accent, #c50048) 60%,white));color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;letter-spacing:.5px;box-shadow:0 0 0 2px #ffffff1a,0 4px 12px #0006}.user-info{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;visibility:visible;opacity:1;transition:opacity .15s ease .22s,visibility 0s ease .22s}.user-info--hidden{visibility:hidden!important;opacity:0!important;max-height:0!important;flex:0 0 0!important;width:0!important;overflow:hidden!important;padding:0!important;margin:0!important;transition:opacity .08s ease 0s,visibility 0s ease .08s,max-height 0s ease .08s!important}.user-name{color:var(--sidebar-active-text)}.user-sucursal{font-size:11px;color:var(--sidebar-text-color);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.list-unstyled{font-size:13px;color:var(--sidebar-text-color)}.layout{display:grid;grid-template-columns:260px 1fr;height:calc(100dvh - 50px)}.sidebar{background:linear-gradient(160deg,var(--sidebar-gradient-start) 0%,var(--sidebar-bg) 100%)!important;box-shadow:4px 0 24px #00000059;border-right:1px solid rgba(255,255,255,.05);transition:transform .3s ease-in-out;width:260px;overflow:hidden;scrollbar-width:none;display:flex;flex-direction:column}.list-menu-sidebar{flex:1;overflow-y:auto;scrollbar-width:none;margin-bottom:0}.sidebar-footer{font-size:11px;color:var(--sidebar-text-color);padding:10px 12px;border-top:1px solid rgba(255,255,255,.08);margin-top:auto;width:100%;display:flex;align-items:center;justify-content:center;opacity:.65;visibility:visible;transition:opacity .15s ease .25s,visibility 0s ease .25s}.sidebar-footer--hidden{opacity:0;visibility:hidden;transition:opacity .1s ease 0s,visibility 0s ease .1s}.sidebar-footer p{margin:0}.content{display:flex;flex-direction:column;overflow:hidden;max-height:100%}.content-scroll{flex:1;overflow-x:auto;overflow-y:auto;min-height:0;--content-space: .75rem}.content-scroll .container-fluid{padding:var(--content-space)!important}.content-scroll .container-fluid.route-fade-in{animation:routeContentFadeIn .32s cubic-bezier(.4,0,.2,1)}@keyframes routeContentFadeIn{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@media(max-width:1191px){.layout{grid-template-columns:1fr}.sidebar{position:fixed;top:50px;left:0;width:260px;height:calc(100dvh - 50px);z-index:1000;transform:translate(-100%);scrollbar-width:none;display:flex;flex-direction:column;overflow:visible}.sidebar-footer{display:flex!important}.sidebar.open{transform:translate(0)}}@media(min-width:1192px){.layout{grid-template-columns:260px 1fr;transition:grid-template-columns .3s ease-in-out}.layout.open{grid-template-columns:70px 1fr}.sidebar{width:260px;max-width:260px;transition:width .3s ease-in-out,max-width .3s ease-in-out}.sidebar.open{width:70px;max-width:70px}}.truncate-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;width:100%}.tc-bubble-container{position:fixed;top:111px;right:30px;z-index:9999}.tc-bubble{background:#c50048;color:#fff;padding:10px 14px;border-radius:50px;cursor:pointer;display:flex;align-items:center;gap:8px;box-shadow:0 4px 12px #0003;transition:all .2s ease}.tc-bubble:hover{transform:scale(1.05)}.tc-label{font-size:13px;font-weight:600}.tc-dropdown{margin-top:10px;background:#fff;border-radius:12px;padding:10px;min-width:220px;box-shadow:0 6px 18px #00000026}.tc-item{display:flex;align-items:center;gap:8px;padding:6px 4px;font-size:13px}.tc-item i{color:#c50048}.tc-item .item-content{display:flex;justify-content:space-between;align-items:center;width:100%}.tc-item .item-label{color:#333;text-align:left}.tc-item .item-value{color:#333;text-align:right;font-weight:500;margin-left:16px}@media(max-width:700px){.tc-bubble-container{top:auto;bottom:55px;right:40px}}.mobile-view .content{min-height:calc(100dvh - 110px)}@media(max-width:1191px){.content.has-bottom-nav{padding-bottom:60px}}\n"] }]
|
|
992
|
-
}], ctorParameters: () => [], propDecorators: { verticalHeaderRef: [{
|
|
992
|
+
}], ctorParameters: () => [], propDecorators: { menuItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuItems", required: false }] }], nameProyecto: [{ type: i0.Input, args: [{ isSignal: true, alias: "nameProyecto", required: false }] }], accentColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "accentColor", required: false }] }], showTabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTabs", required: false }] }], tabModuleColors: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabModuleColors", required: false }] }], verticalHeaderRef: [{
|
|
993
993
|
type: ContentChild,
|
|
994
994
|
args: [VerticalHeaderComponent]
|
|
995
|
-
}], contentContainer: [{
|
|
995
|
+
}], sessionData: [{ type: i0.Input, args: [{ isSignal: true, alias: "sessionData", required: true }] }], contentContainer: [{
|
|
996
996
|
type: ViewChild,
|
|
997
997
|
args: ['contentContainer']
|
|
998
998
|
}], sidebarRef: [{
|
|
@@ -1010,10 +1010,10 @@ const CHATBOT_CONFIG = new InjectionToken('CHATBOT_CONFIG');
|
|
|
1010
1010
|
|
|
1011
1011
|
class ChatbotService {
|
|
1012
1012
|
config = inject(CHATBOT_CONFIG);
|
|
1013
|
-
messages = signal([]);
|
|
1014
|
-
isTyping = signal(false);
|
|
1015
|
-
isOpen = signal(false);
|
|
1016
|
-
hasActiveConversation = computed(() => this.messages().length > 1);
|
|
1013
|
+
messages = signal([], ...(ngDevMode ? [{ debugName: "messages" }] : []));
|
|
1014
|
+
isTyping = signal(false, ...(ngDevMode ? [{ debugName: "isTyping" }] : []));
|
|
1015
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
1016
|
+
hasActiveConversation = computed(() => this.messages().length > 1, ...(ngDevMode ? [{ debugName: "hasActiveConversation" }] : []));
|
|
1017
1017
|
constructor() {
|
|
1018
1018
|
this.init();
|
|
1019
1019
|
}
|
|
@@ -1068,10 +1068,10 @@ class ChatbotService {
|
|
|
1068
1068
|
restart() {
|
|
1069
1069
|
this.init();
|
|
1070
1070
|
}
|
|
1071
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1072
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
1071
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: ChatbotService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1072
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: ChatbotService });
|
|
1073
1073
|
}
|
|
1074
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1074
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: ChatbotService, decorators: [{
|
|
1075
1075
|
type: Injectable
|
|
1076
1076
|
}], ctorParameters: () => [] });
|
|
1077
1077
|
|
|
@@ -1079,12 +1079,12 @@ class ChatbotComponent {
|
|
|
1079
1079
|
service = inject(ChatbotService);
|
|
1080
1080
|
config = inject(CHATBOT_CONFIG);
|
|
1081
1081
|
zone = inject(NgZone);
|
|
1082
|
-
messagesEnd = viewChild('messagesEnd');
|
|
1083
|
-
wrapper = viewChild('wrapper');
|
|
1084
|
-
position = signal(null);
|
|
1085
|
-
isDragging = signal(false);
|
|
1086
|
-
openDir = signal('above');
|
|
1087
|
-
openHDir = signal('right');
|
|
1082
|
+
messagesEnd = viewChild('messagesEnd', ...(ngDevMode ? [{ debugName: "messagesEnd" }] : []));
|
|
1083
|
+
wrapper = viewChild('wrapper', ...(ngDevMode ? [{ debugName: "wrapper" }] : []));
|
|
1084
|
+
position = signal(null, ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
1085
|
+
isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
|
|
1086
|
+
openDir = signal('above', ...(ngDevMode ? [{ debugName: "openDir" }] : []));
|
|
1087
|
+
openHDir = signal('right', ...(ngDevMode ? [{ debugName: "openHDir" }] : []));
|
|
1088
1088
|
dragOffset = { x: 0, y: 0 };
|
|
1089
1089
|
hasDragged = false;
|
|
1090
1090
|
constructor() {
|
|
@@ -1144,36 +1144,36 @@ class ChatbotComponent {
|
|
|
1144
1144
|
scrollToBottom() {
|
|
1145
1145
|
this.messagesEnd()?.nativeElement.scrollIntoView({ behavior: 'smooth' });
|
|
1146
1146
|
}
|
|
1147
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1148
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: ChatbotComponent, isStandalone: true, selector: "app-chatbot", providers: [ChatbotService], viewQueries: [{ propertyName: "messagesEnd", first: true, predicate: ["messagesEnd"], descendants: true, isSignal: true }, { propertyName: "wrapper", first: true, predicate: ["wrapper"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #wrapper class=\"chatbot-wrapper\"\r\n [class.chatbot-left]=\"config.position === 'bottom-left'\"\r\n [class.chatbot-dragging]=\"isDragging()\"\r\n [style.--chatbot-primary]=\"primaryColor\"\r\n [style.left.px]=\"position()?.x\"\r\n [style.top.px]=\"position()?.y\"\r\n [style.right]=\"position() ? 'auto' : null\"\r\n [style.bottom]=\"position() ? 'auto' : null\">\r\n\r\n @if (!service.isOpen()) {\r\n <span class=\"chatbot-beta\">Beta</span>\r\n }\r\n <button class=\"chatbot-fab\"\r\n [class.chatbot-fab--hidden]=\"service.isOpen()\"\r\n (mousedown)=\"startDrag($event)\"\r\n (click)=\"onFabClick()\"\r\n title=\"Abrir asistente\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"26\" height=\"26\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n @if (service.hasActiveConversation()) {\r\n <span class=\"chatbot-badge\" title=\"Conversaci\u00F3n en progreso\"></span>\r\n }\r\n </button>\r\n\r\n @if (service.isOpen()) {\r\n <div class=\"chatbot-window\"\r\n [class.open-above]=\"openDir() === 'above'\"\r\n [class.open-below]=\"openDir() === 'below'\"\r\n [class.open-right]=\"openHDir() === 'right'\"\r\n [class.open-left]=\"openHDir() === 'left'\">\r\n\r\n <div class=\"chatbot-header\" (mousedown)=\"startDrag($event)\">\r\n <div class=\"chatbot-header-info\">\r\n <span class=\"chatbot-avatar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"22\" height=\"22\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n </span>\r\n <div>\r\n <div class=\"chatbot-name\">{{ config.botName || 'Asistente' }}</div>\r\n <div class=\"chatbot-status\">En l\u00EDnea</div>\r\n </div>\r\n </div>\r\n <div class=\"chatbot-header-actions\">\r\n <button class=\"chatbot-action-btn\" (click)=\"service.minimize()\" title=\"Minimizar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M2 8a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11A.5.5 0 0 1 2 8z\" />\r\n </svg>\r\n </button>\r\n <button class=\"chatbot-action-btn\" (click)=\"service.close()\" title=\"Cerrar y reiniciar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8z\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chatbot-body\">\r\n @for (msg of service.messages(); track $index; let i = $index) {\r\n <div class=\"chat-row\" [class.chat-row-user]=\"msg.from === 'user'\">\r\n @if (msg.from === 'bot') {\r\n <span class=\"bot-icon\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n </span>\r\n }\r\n <div class=\"chat-col\">\r\n <div class=\"message-bubble\" [class.bubble-bot]=\"msg.from === 'bot'\" [class.bubble-user]=\"msg.from === 'user'\">\r\n {{ msg.text }}\r\n </div>\r\n @if (msg.options && msg.options.length > 0) {\r\n <div class=\"options-container\">\r\n @for (opt of msg.options; track $index) {\r\n <button class=\"option-btn\" [disabled]=\"msg.optionsDisabled\" (click)=\"selectOption(opt, i)\">\r\n {{ opt.label }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (service.isTyping()) {\r\n <div class=\"chat-row\">\r\n <span class=\"bot-icon\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n </span>\r\n <div class=\"message-bubble bubble-bot typing-bubble\">\r\n <span class=\"dot\"></span><span class=\"dot\"></span><span class=\"dot\"></span>\r\n </div>\r\n </div>\r\n }\r\n <div #messagesEnd></div>\r\n </div>\r\n\r\n <div class=\"chatbot-footer\">\r\n <button class=\"restart-btn\" (click)=\"service.restart()\">\u21BA Reiniciar conversaci\u00F3n</button>\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{--chatbot-primary: #c50048}.chatbot-wrapper{position:fixed;bottom:24px;right:24px;z-index:10000;font-family:Poppins,sans-serif;animation:chatbotFabIn .26s cubic-bezier(.2,0,.2,1) both}.chatbot-wrapper.chatbot-left{right:auto;left:24px}@keyframes chatbotFabIn{0%{opacity:0;transform:translateY(14px) scale(.85)}to{opacity:1;transform:translateY(0) scale(1)}}.chatbot-dragging{-webkit-user-select:none;user-select:none}.chatbot-dragging *{cursor:grabbing!important}.chatbot-beta{position:absolute;bottom:calc(100% + 6px);left:50%;transform:translate(-50%);background:#0000008c;color:#ffffffd9;font-size:9px;font-weight:600;letter-spacing:.08em;padding:2px 6px;border-radius:4px;pointer-events:none;text-transform:uppercase;white-space:nowrap}.chatbot-fab{cursor:grab;position:relative;width:54px;height:54px;border-radius:50%;border:none;background:var(--chatbot-primary);color:#fff;cursor:pointer;box-shadow:0 4px 18px #0000004d;display:flex;align-items:center;justify-content:center;transition:transform .2s ease,box-shadow .2s ease}.chatbot-fab:hover{transform:scale(1.08);box-shadow:0 6px 22px #0006}.chatbot-badge{position:absolute;top:4px;right:4px;width:12px;height:12px;border-radius:50%;background:#facc15;border:2px solid #fff;animation:cbPulse 1.8s ease-in-out infinite}@keyframes cbPulse{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.3);opacity:.75}}.chatbot-fab--hidden{visibility:hidden;pointer-events:none}.chatbot-window{position:absolute;width:320px;max-height:490px;border-radius:16px;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 8px 36px #00000038;background:var(--background-card, #ffffff);animation:cbSlideUp .22s ease}.chatbot-window.open-above{bottom:62px}.chatbot-window.open-below{top:62px}.chatbot-window.open-right{left:0}.chatbot-window.open-left{right:0}@keyframes cbSlideUp{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}.chatbot-header{padding:12px 14px;background:var(--chatbot-primary);color:#fff;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;cursor:grab}.chatbot-header-info{display:flex;align-items:center;gap:8px}.chatbot-avatar{font-size:20px;line-height:1}.chatbot-name{font-size:13px;font-weight:600}.chatbot-status{font-size:10px;opacity:.82}.chatbot-header-actions{display:flex;align-items:center;gap:2px}.chatbot-action-btn{background:none;border:none;color:#fff;cursor:pointer;padding:4px 6px;border-radius:4px;opacity:.75;display:flex;align-items:center;justify-content:center;transition:opacity .15s,background .15s}.chatbot-action-btn:hover{opacity:1;background:#ffffff2e}.chatbot-body{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:8px;background:var(--background-color, #f0f0f0)}.chat-row{display:flex;align-items:flex-start;gap:6px}.chat-row.chat-row-user{flex-direction:row-reverse}.bot-icon{font-size:16px;flex-shrink:0;margin-top:4px}.chat-col{display:flex;flex-direction:column;gap:4px;max-width:82%}.message-bubble{padding:8px 11px;border-radius:12px;font-size:11.5px;line-height:1.55;word-break:break-word}.message-bubble.bubble-bot{background:var(--background-card, #ffffff);color:var(--text-color, #1d1d1d);border-bottom-left-radius:4px;box-shadow:0 1px 4px #00000012}.message-bubble.bubble-user{background:var(--chatbot-primary);color:#fff;border-bottom-right-radius:4px;align-self:flex-end}.options-container{display:flex;flex-direction:column;gap:4px}.option-btn{background:var(--background-card, #ffffff);color:var(--chatbot-primary);border:1.5px solid var(--chatbot-primary);border-radius:8px;padding:5px 10px;font-size:11px;font-weight:600;cursor:pointer;text-align:left;transition:background .18s ease,color .18s ease}.option-btn:hover:not(:disabled){background:var(--chatbot-primary);color:#fff}.option-btn:disabled{opacity:.38;cursor:default}.typing-bubble{display:flex;gap:4px;align-items:center;padding:10px 14px!important}.dot{width:7px;height:7px;background:var(--placeholder-color, #aaa);border-radius:50%;animation:cbBounce 1.2s ease-in-out infinite}.dot:nth-child(2){animation-delay:.18s}.dot:nth-child(3){animation-delay:.36s}@keyframes cbBounce{0%,80%,to{transform:translateY(0)}40%{transform:translateY(-6px)}}.chatbot-footer{padding:7px 12px;background:var(--background-card, #ffffff);border-top:1px solid var(--border-color-modal, #e0e0e0);flex-shrink:0;display:flex;justify-content:center}.restart-btn{background:none;border:none;font-size:10.5px;color:var(--placeholder-color, #999);cursor:pointer;padding:3px 8px;border-radius:4px;transition:color .15s}.restart-btn:hover{color:var(--text-color, #333)}@media(max-width:768px){.chatbot-wrapper{display:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1147
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: ChatbotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1148
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: ChatbotComponent, isStandalone: true, selector: "app-chatbot", providers: [ChatbotService], viewQueries: [{ propertyName: "messagesEnd", first: true, predicate: ["messagesEnd"], descendants: true, isSignal: true }, { propertyName: "wrapper", first: true, predicate: ["wrapper"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #wrapper class=\"chatbot-wrapper\"\r\n [class.chatbot-left]=\"config.position === 'bottom-left'\"\r\n [class.chatbot-dragging]=\"isDragging()\"\r\n [style.--chatbot-primary]=\"primaryColor\"\r\n [style.left.px]=\"position()?.x\"\r\n [style.top.px]=\"position()?.y\"\r\n [style.right]=\"position() ? 'auto' : null\"\r\n [style.bottom]=\"position() ? 'auto' : null\">\r\n\r\n @if (!service.isOpen()) {\r\n <span class=\"chatbot-beta\">Beta</span>\r\n }\r\n <button class=\"chatbot-fab\"\r\n [class.chatbot-fab--hidden]=\"service.isOpen()\"\r\n (mousedown)=\"startDrag($event)\"\r\n (click)=\"onFabClick()\"\r\n title=\"Abrir asistente\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"26\" height=\"26\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n @if (service.hasActiveConversation()) {\r\n <span class=\"chatbot-badge\" title=\"Conversaci\u00F3n en progreso\"></span>\r\n }\r\n </button>\r\n\r\n @if (service.isOpen()) {\r\n <div class=\"chatbot-window\"\r\n [class.open-above]=\"openDir() === 'above'\"\r\n [class.open-below]=\"openDir() === 'below'\"\r\n [class.open-right]=\"openHDir() === 'right'\"\r\n [class.open-left]=\"openHDir() === 'left'\">\r\n\r\n <div class=\"chatbot-header\" (mousedown)=\"startDrag($event)\">\r\n <div class=\"chatbot-header-info\">\r\n <span class=\"chatbot-avatar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"22\" height=\"22\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n </span>\r\n <div>\r\n <div class=\"chatbot-name\">{{ config.botName || 'Asistente' }}</div>\r\n <div class=\"chatbot-status\">En l\u00EDnea</div>\r\n </div>\r\n </div>\r\n <div class=\"chatbot-header-actions\">\r\n <button class=\"chatbot-action-btn\" (click)=\"service.minimize()\" title=\"Minimizar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M2 8a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11A.5.5 0 0 1 2 8z\" />\r\n </svg>\r\n </button>\r\n <button class=\"chatbot-action-btn\" (click)=\"service.close()\" title=\"Cerrar y reiniciar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8z\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chatbot-body\">\r\n @for (msg of service.messages(); track $index; let i = $index) {\r\n <div class=\"chat-row\" [class.chat-row-user]=\"msg.from === 'user'\">\r\n @if (msg.from === 'bot') {\r\n <span class=\"bot-icon\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n </span>\r\n }\r\n <div class=\"chat-col\">\r\n <div class=\"message-bubble\" [class.bubble-bot]=\"msg.from === 'bot'\" [class.bubble-user]=\"msg.from === 'user'\">\r\n {{ msg.text }}\r\n </div>\r\n @if (msg.options && msg.options.length > 0) {\r\n <div class=\"options-container\">\r\n @for (opt of msg.options; track $index) {\r\n <button class=\"option-btn\" [disabled]=\"msg.optionsDisabled\" (click)=\"selectOption(opt, i)\">\r\n {{ opt.label }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (service.isTyping()) {\r\n <div class=\"chat-row\">\r\n <span class=\"bot-icon\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n </span>\r\n <div class=\"message-bubble bubble-bot typing-bubble\">\r\n <span class=\"dot\"></span><span class=\"dot\"></span><span class=\"dot\"></span>\r\n </div>\r\n </div>\r\n }\r\n <div #messagesEnd></div>\r\n </div>\r\n\r\n <div class=\"chatbot-footer\">\r\n <button class=\"restart-btn\" (click)=\"service.restart()\">\u21BA Reiniciar conversaci\u00F3n</button>\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{--chatbot-primary: #c50048}.chatbot-wrapper{position:fixed;bottom:24px;right:24px;z-index:10000;font-family:Poppins,sans-serif;animation:chatbotFabIn .26s cubic-bezier(.2,0,.2,1) both}.chatbot-wrapper.chatbot-left{right:auto;left:24px}@keyframes chatbotFabIn{0%{opacity:0;transform:translateY(14px) scale(.85)}to{opacity:1;transform:translateY(0) scale(1)}}.chatbot-dragging{-webkit-user-select:none;user-select:none}.chatbot-dragging *{cursor:grabbing!important}.chatbot-beta{position:absolute;bottom:calc(100% + 6px);left:50%;transform:translate(-50%);background:#0000008c;color:#ffffffd9;font-size:9px;font-weight:600;letter-spacing:.08em;padding:2px 6px;border-radius:4px;pointer-events:none;text-transform:uppercase;white-space:nowrap}.chatbot-fab{cursor:grab;position:relative;width:54px;height:54px;border-radius:50%;border:none;background:var(--chatbot-primary);color:#fff;cursor:pointer;box-shadow:0 4px 18px #0000004d;display:flex;align-items:center;justify-content:center;transition:transform .2s ease,box-shadow .2s ease}.chatbot-fab:hover{transform:scale(1.08);box-shadow:0 6px 22px #0006}.chatbot-badge{position:absolute;top:4px;right:4px;width:12px;height:12px;border-radius:50%;background:#facc15;border:2px solid #fff;animation:cbPulse 1.8s ease-in-out infinite}@keyframes cbPulse{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.3);opacity:.75}}.chatbot-fab--hidden{visibility:hidden;pointer-events:none}.chatbot-window{position:absolute;width:320px;max-height:490px;border-radius:16px;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 8px 36px #00000038;background:var(--background-card, #ffffff);animation:cbSlideUp .22s ease}.chatbot-window.open-above{bottom:62px}.chatbot-window.open-below{top:62px}.chatbot-window.open-right{left:0}.chatbot-window.open-left{right:0}@keyframes cbSlideUp{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}.chatbot-header{padding:12px 14px;background:var(--chatbot-primary);color:#fff;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;cursor:grab}.chatbot-header-info{display:flex;align-items:center;gap:8px}.chatbot-avatar{font-size:20px;line-height:1}.chatbot-name{font-size:13px;font-weight:600}.chatbot-status{font-size:10px;opacity:.82}.chatbot-header-actions{display:flex;align-items:center;gap:2px}.chatbot-action-btn{background:none;border:none;color:#fff;cursor:pointer;padding:4px 6px;border-radius:4px;opacity:.75;display:flex;align-items:center;justify-content:center;transition:opacity .15s,background .15s}.chatbot-action-btn:hover{opacity:1;background:#ffffff2e}.chatbot-body{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:8px;background:var(--background-color, #f0f0f0)}.chat-row{display:flex;align-items:flex-start;gap:6px}.chat-row.chat-row-user{flex-direction:row-reverse}.bot-icon{font-size:16px;flex-shrink:0;margin-top:4px}.chat-col{display:flex;flex-direction:column;gap:4px;max-width:82%}.message-bubble{padding:8px 11px;border-radius:12px;font-size:11.5px;line-height:1.55;word-break:break-word}.message-bubble.bubble-bot{background:var(--background-card, #ffffff);color:var(--text-color, #1d1d1d);border-bottom-left-radius:4px;box-shadow:0 1px 4px #00000012}.message-bubble.bubble-user{background:var(--chatbot-primary);color:#fff;border-bottom-right-radius:4px;align-self:flex-end}.options-container{display:flex;flex-direction:column;gap:4px}.option-btn{background:var(--background-card, #ffffff);color:var(--chatbot-primary);border:1.5px solid var(--chatbot-primary);border-radius:8px;padding:5px 10px;font-size:11px;font-weight:600;cursor:pointer;text-align:left;transition:background .18s ease,color .18s ease}.option-btn:hover:not(:disabled){background:var(--chatbot-primary);color:#fff}.option-btn:disabled{opacity:.38;cursor:default}.typing-bubble{display:flex;gap:4px;align-items:center;padding:10px 14px!important}.dot{width:7px;height:7px;background:var(--placeholder-color, #aaa);border-radius:50%;animation:cbBounce 1.2s ease-in-out infinite}.dot:nth-child(2){animation-delay:.18s}.dot:nth-child(3){animation-delay:.36s}@keyframes cbBounce{0%,80%,to{transform:translateY(0)}40%{transform:translateY(-6px)}}.chatbot-footer{padding:7px 12px;background:var(--background-card, #ffffff);border-top:1px solid var(--border-color-modal, #e0e0e0);flex-shrink:0;display:flex;justify-content:center}.restart-btn{background:none;border:none;font-size:10.5px;color:var(--placeholder-color, #999);cursor:pointer;padding:3px 8px;border-radius:4px;transition:color .15s}.restart-btn:hover{color:var(--text-color, #333)}@media(max-width:768px){.chatbot-wrapper{display:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1149
1149
|
}
|
|
1150
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1150
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: ChatbotComponent, decorators: [{
|
|
1151
1151
|
type: Component,
|
|
1152
1152
|
args: [{ selector: 'app-chatbot', providers: [ChatbotService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div #wrapper class=\"chatbot-wrapper\"\r\n [class.chatbot-left]=\"config.position === 'bottom-left'\"\r\n [class.chatbot-dragging]=\"isDragging()\"\r\n [style.--chatbot-primary]=\"primaryColor\"\r\n [style.left.px]=\"position()?.x\"\r\n [style.top.px]=\"position()?.y\"\r\n [style.right]=\"position() ? 'auto' : null\"\r\n [style.bottom]=\"position() ? 'auto' : null\">\r\n\r\n @if (!service.isOpen()) {\r\n <span class=\"chatbot-beta\">Beta</span>\r\n }\r\n <button class=\"chatbot-fab\"\r\n [class.chatbot-fab--hidden]=\"service.isOpen()\"\r\n (mousedown)=\"startDrag($event)\"\r\n (click)=\"onFabClick()\"\r\n title=\"Abrir asistente\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"26\" height=\"26\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n @if (service.hasActiveConversation()) {\r\n <span class=\"chatbot-badge\" title=\"Conversaci\u00F3n en progreso\"></span>\r\n }\r\n </button>\r\n\r\n @if (service.isOpen()) {\r\n <div class=\"chatbot-window\"\r\n [class.open-above]=\"openDir() === 'above'\"\r\n [class.open-below]=\"openDir() === 'below'\"\r\n [class.open-right]=\"openHDir() === 'right'\"\r\n [class.open-left]=\"openHDir() === 'left'\">\r\n\r\n <div class=\"chatbot-header\" (mousedown)=\"startDrag($event)\">\r\n <div class=\"chatbot-header-info\">\r\n <span class=\"chatbot-avatar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"22\" height=\"22\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n </span>\r\n <div>\r\n <div class=\"chatbot-name\">{{ config.botName || 'Asistente' }}</div>\r\n <div class=\"chatbot-status\">En l\u00EDnea</div>\r\n </div>\r\n </div>\r\n <div class=\"chatbot-header-actions\">\r\n <button class=\"chatbot-action-btn\" (click)=\"service.minimize()\" title=\"Minimizar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M2 8a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11A.5.5 0 0 1 2 8z\" />\r\n </svg>\r\n </button>\r\n <button class=\"chatbot-action-btn\" (click)=\"service.close()\" title=\"Cerrar y reiniciar\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\" fill=\"currentColor\" viewBox=\"0 0 16 16\">\r\n <path d=\"M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8z\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chatbot-body\">\r\n @for (msg of service.messages(); track $index; let i = $index) {\r\n <div class=\"chat-row\" [class.chat-row-user]=\"msg.from === 'user'\">\r\n @if (msg.from === 'bot') {\r\n <span class=\"bot-icon\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n </span>\r\n }\r\n <div class=\"chat-col\">\r\n <div class=\"message-bubble\" [class.bubble-bot]=\"msg.from === 'bot'\" [class.bubble-user]=\"msg.from === 'user'\">\r\n {{ msg.text }}\r\n </div>\r\n @if (msg.options && msg.options.length > 0) {\r\n <div class=\"options-container\">\r\n @for (opt of msg.options; track $index) {\r\n <button class=\"option-btn\" [disabled]=\"msg.optionsDisabled\" (click)=\"selectOption(opt, i)\">\r\n {{ opt.label }}\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n @if (service.isTyping()) {\r\n <div class=\"chat-row\">\r\n <span class=\"bot-icon\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path d=\"M12 2a2 2 0 0 1 2 2c0 .74-.4 1.39-1 1.73V7h1a7 7 0 0 1 7 7h1a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-1v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-1H2a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1h1a7 7 0 0 1 7-7h1V5.73c-.6-.34-1-.99-1-1.73a2 2 0 0 1 2-2M7.5 13A2.5 2.5 0 0 0 5 15.5 2.5 2.5 0 0 0 7.5 18a2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 7.5 13m9 0a2.5 2.5 0 0 0-2.5 2.5 2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5A2.5 2.5 0 0 0 16.5 13z\" />\r\n </svg>\r\n </span>\r\n <div class=\"message-bubble bubble-bot typing-bubble\">\r\n <span class=\"dot\"></span><span class=\"dot\"></span><span class=\"dot\"></span>\r\n </div>\r\n </div>\r\n }\r\n <div #messagesEnd></div>\r\n </div>\r\n\r\n <div class=\"chatbot-footer\">\r\n <button class=\"restart-btn\" (click)=\"service.restart()\">\u21BA Reiniciar conversaci\u00F3n</button>\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{--chatbot-primary: #c50048}.chatbot-wrapper{position:fixed;bottom:24px;right:24px;z-index:10000;font-family:Poppins,sans-serif;animation:chatbotFabIn .26s cubic-bezier(.2,0,.2,1) both}.chatbot-wrapper.chatbot-left{right:auto;left:24px}@keyframes chatbotFabIn{0%{opacity:0;transform:translateY(14px) scale(.85)}to{opacity:1;transform:translateY(0) scale(1)}}.chatbot-dragging{-webkit-user-select:none;user-select:none}.chatbot-dragging *{cursor:grabbing!important}.chatbot-beta{position:absolute;bottom:calc(100% + 6px);left:50%;transform:translate(-50%);background:#0000008c;color:#ffffffd9;font-size:9px;font-weight:600;letter-spacing:.08em;padding:2px 6px;border-radius:4px;pointer-events:none;text-transform:uppercase;white-space:nowrap}.chatbot-fab{cursor:grab;position:relative;width:54px;height:54px;border-radius:50%;border:none;background:var(--chatbot-primary);color:#fff;cursor:pointer;box-shadow:0 4px 18px #0000004d;display:flex;align-items:center;justify-content:center;transition:transform .2s ease,box-shadow .2s ease}.chatbot-fab:hover{transform:scale(1.08);box-shadow:0 6px 22px #0006}.chatbot-badge{position:absolute;top:4px;right:4px;width:12px;height:12px;border-radius:50%;background:#facc15;border:2px solid #fff;animation:cbPulse 1.8s ease-in-out infinite}@keyframes cbPulse{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.3);opacity:.75}}.chatbot-fab--hidden{visibility:hidden;pointer-events:none}.chatbot-window{position:absolute;width:320px;max-height:490px;border-radius:16px;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 8px 36px #00000038;background:var(--background-card, #ffffff);animation:cbSlideUp .22s ease}.chatbot-window.open-above{bottom:62px}.chatbot-window.open-below{top:62px}.chatbot-window.open-right{left:0}.chatbot-window.open-left{right:0}@keyframes cbSlideUp{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}.chatbot-header{padding:12px 14px;background:var(--chatbot-primary);color:#fff;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;cursor:grab}.chatbot-header-info{display:flex;align-items:center;gap:8px}.chatbot-avatar{font-size:20px;line-height:1}.chatbot-name{font-size:13px;font-weight:600}.chatbot-status{font-size:10px;opacity:.82}.chatbot-header-actions{display:flex;align-items:center;gap:2px}.chatbot-action-btn{background:none;border:none;color:#fff;cursor:pointer;padding:4px 6px;border-radius:4px;opacity:.75;display:flex;align-items:center;justify-content:center;transition:opacity .15s,background .15s}.chatbot-action-btn:hover{opacity:1;background:#ffffff2e}.chatbot-body{flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:8px;background:var(--background-color, #f0f0f0)}.chat-row{display:flex;align-items:flex-start;gap:6px}.chat-row.chat-row-user{flex-direction:row-reverse}.bot-icon{font-size:16px;flex-shrink:0;margin-top:4px}.chat-col{display:flex;flex-direction:column;gap:4px;max-width:82%}.message-bubble{padding:8px 11px;border-radius:12px;font-size:11.5px;line-height:1.55;word-break:break-word}.message-bubble.bubble-bot{background:var(--background-card, #ffffff);color:var(--text-color, #1d1d1d);border-bottom-left-radius:4px;box-shadow:0 1px 4px #00000012}.message-bubble.bubble-user{background:var(--chatbot-primary);color:#fff;border-bottom-right-radius:4px;align-self:flex-end}.options-container{display:flex;flex-direction:column;gap:4px}.option-btn{background:var(--background-card, #ffffff);color:var(--chatbot-primary);border:1.5px solid var(--chatbot-primary);border-radius:8px;padding:5px 10px;font-size:11px;font-weight:600;cursor:pointer;text-align:left;transition:background .18s ease,color .18s ease}.option-btn:hover:not(:disabled){background:var(--chatbot-primary);color:#fff}.option-btn:disabled{opacity:.38;cursor:default}.typing-bubble{display:flex;gap:4px;align-items:center;padding:10px 14px!important}.dot{width:7px;height:7px;background:var(--placeholder-color, #aaa);border-radius:50%;animation:cbBounce 1.2s ease-in-out infinite}.dot:nth-child(2){animation-delay:.18s}.dot:nth-child(3){animation-delay:.36s}@keyframes cbBounce{0%,80%,to{transform:translateY(0)}40%{transform:translateY(-6px)}}.chatbot-footer{padding:7px 12px;background:var(--background-card, #ffffff);border-top:1px solid var(--border-color-modal, #e0e0e0);flex-shrink:0;display:flex;justify-content:center}.restart-btn{background:none;border:none;font-size:10.5px;color:var(--placeholder-color, #999);cursor:pointer;padding:3px 8px;border-radius:4px;transition:color .15s}.restart-btn:hover{color:var(--text-color, #333)}@media(max-width:768px){.chatbot-wrapper{display:none}}\n"] }]
|
|
1153
|
-
}], ctorParameters: () => [] });
|
|
1153
|
+
}], ctorParameters: () => [], propDecorators: { messagesEnd: [{ type: i0.ViewChild, args: ['messagesEnd', { isSignal: true }] }], wrapper: [{ type: i0.ViewChild, args: ['wrapper', { isSignal: true }] }] } });
|
|
1154
1154
|
|
|
1155
1155
|
class NotFoundComponent {
|
|
1156
1156
|
location = inject(Location);
|
|
1157
1157
|
onBack() {
|
|
1158
1158
|
this.location.back();
|
|
1159
1159
|
}
|
|
1160
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1161
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
1160
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: NotFoundComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1161
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.32", type: NotFoundComponent, isStandalone: true, selector: "app-not-found", ngImport: i0, template: "<div class=\"nf-page d-flex align-items-center justify-content-center vh-100\">\r\n\r\n <!-- Blobs decorativos de fondo -->\r\n <div class=\"nf-blob nf-blob-1\"></div>\r\n <div class=\"nf-blob nf-blob-2\"></div>\r\n\r\n <div class=\"nf-card bg-white shadow-s text-center px-4 px-md-5 py-4 mx-3\">\r\n\r\n <!-- Ilustraci\u00F3n: ventana con 404 y lupa buscando -->\r\n <svg class=\"nf-illustration\" viewBox=\"0 0 520 340\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" role=\"img\" aria-label=\"P\u00E1gina no encontrada\">\r\n <defs>\r\n <linearGradient id=\"nfGrad\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\r\n <stop offset=\"0%\" style=\"stop-color: var(--sidebar-accent)\" />\r\n <stop offset=\"100%\" style=\"stop-color: var(--sidebar-accent); stop-opacity: 0.55\" />\r\n </linearGradient>\r\n </defs>\r\n\r\n <!-- \u00D3rbita punteada de fondo -->\r\n <circle class=\"nf-orbit\" cx=\"260\" cy=\"170\" r=\"150\"\r\n stroke=\"var(--font-border-input)\" stroke-width=\"1.5\"\r\n stroke-dasharray=\"6 10\" opacity=\"0.7\" />\r\n\r\n <!-- Decoraciones flotantes -->\r\n <g class=\"nf-spark nf-spark-1\" stroke=\"var(--sidebar-accent)\" stroke-width=\"3\" stroke-linecap=\"round\">\r\n <path d=\"M92 78 v20 M82 88 h20\" />\r\n </g>\r\n <g class=\"nf-spark nf-spark-2\" stroke=\"var(--placeholder-color)\" stroke-width=\"3\" stroke-linecap=\"round\">\r\n <path d=\"M448 220 v16 M440 228 h16\" />\r\n </g>\r\n <circle class=\"nf-spark nf-spark-3\" cx=\"430\" cy=\"70\" r=\"6\" fill=\"var(--sidebar-accent)\" opacity=\"0.7\" />\r\n <circle class=\"nf-spark nf-spark-1\" cx=\"70\" cy=\"230\" r=\"5\" fill=\"var(--placeholder-color)\" opacity=\"0.7\" />\r\n <path class=\"nf-spark nf-spark-2\" d=\"M120 300 q8 -10 16 0 q8 10 16 0\"\r\n stroke=\"var(--font-border-input)\" stroke-width=\"3\" stroke-linecap=\"round\" fill=\"none\" />\r\n\r\n <!-- Ventana de navegador -->\r\n <g class=\"nf-window\">\r\n <rect x=\"120\" y=\"60\" width=\"280\" height=\"200\" rx=\"16\"\r\n fill=\"var(--background-input)\" stroke=\"var(--font-border-input)\" stroke-width=\"2\" />\r\n <!-- Barra superior -->\r\n <line x1=\"120\" y1=\"98\" x2=\"400\" y2=\"98\" stroke=\"var(--font-border-input)\" stroke-width=\"2\" />\r\n <circle cx=\"144\" cy=\"79\" r=\"5\" fill=\"var(--sidebar-accent)\" />\r\n <circle cx=\"162\" cy=\"79\" r=\"5\" fill=\"var(--placeholder-color)\" opacity=\"0.8\" />\r\n <circle cx=\"180\" cy=\"79\" r=\"5\" fill=\"var(--font-border-input)\" />\r\n <!-- Barra de direcci\u00F3n -->\r\n <rect x=\"200\" y=\"71\" width=\"184\" height=\"16\" rx=\"8\" fill=\"var(--font-border-input)\" opacity=\"0.5\" />\r\n\r\n <!-- 404 dentro de la ventana -->\r\n <text x=\"260\" y=\"188\" text-anchor=\"middle\" class=\"nf-404-text\" fill=\"url(#nfGrad)\">404</text>\r\n\r\n <!-- L\u00EDneas de contenido (skeleton) -->\r\n <rect x=\"180\" y=\"212\" width=\"160\" height=\"9\" rx=\"4.5\" fill=\"var(--font-border-input)\" opacity=\"0.7\" />\r\n <rect x=\"205\" y=\"230\" width=\"110\" height=\"9\" rx=\"4.5\" fill=\"var(--font-border-input)\" opacity=\"0.45\" />\r\n </g>\r\n\r\n <!-- Lupa buscando -->\r\n <g class=\"nf-lens\">\r\n <circle cx=\"352\" cy=\"238\" r=\"46\" fill=\"var(--background-card)\" fill-opacity=\"0.55\"\r\n stroke=\"url(#nfGrad)\" stroke-width=\"8\" />\r\n <line x1=\"386\" y1=\"272\" x2=\"424\" y2=\"310\" stroke=\"url(#nfGrad)\" stroke-width=\"14\" stroke-linecap=\"round\" />\r\n <!-- Signo de interrogaci\u00F3n dentro de la lupa -->\r\n <path d=\"M340 224 q0 -14 13 -14 q13 0 13 12 q0 9 -10 13 q-3 1.5 -3 7\"\r\n stroke=\"var(--text-color)\" stroke-width=\"5\" stroke-linecap=\"round\" fill=\"none\" />\r\n <circle cx=\"353\" cy=\"256\" r=\"3.5\" fill=\"var(--text-color)\" />\r\n </g>\r\n </svg>\r\n\r\n <!-- Badge -->\r\n <span class=\"nf-badge fw-semibold\">ERROR 404</span>\r\n\r\n <h2 class=\"fw-semibold text-input mt-3\">P\u00E1gina no encontrada</h2>\r\n\r\n <p class=\"nf-desc fs-6 mt-2 mb-4 mx-auto\">\r\n Lo sentimos, la p\u00E1gina que buscas no existe o fue movida.\r\n Verifica la direcci\u00F3n o regresa al inicio.\r\n </p>\r\n\r\n <!-- Acciones -->\r\n <div class=\"d-flex gap-3 justify-content-center flex-wrap\">\r\n <button type=\"button\" (click)=\"onBack()\" class=\"btn nf-btn-primary px-4 py-2 shadow\">\r\n <i class=\"fa-solid fa-arrow-left me-2\"></i>Volver\r\n </button>\r\n <a routerLink=\"/\" class=\"btn nf-btn-ghost text-dark px-4 py-2\">\r\n <i class=\"fa-solid fa-house me-2\"></i>Ir al inicio\r\n </a>\r\n </div>\r\n\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.nf-page{position:relative;overflow:hidden;background:var(--background-color)}.nf-blob{position:absolute;border-radius:50%;filter:blur(90px);opacity:.22;pointer-events:none;animation:nf-drift 12s ease-in-out infinite alternate}.nf-blob-1{width:420px;height:420px;top:-120px;left:-100px;background:var(--sidebar-accent)}.nf-blob-2{width:360px;height:360px;bottom:-100px;right:-80px;background:color-mix(in srgb,var(--sidebar-accent) 60%,var(--text-color));animation-delay:-6s}@keyframes nf-drift{0%{transform:translate(0) scale(1)}to{transform:translate(40px,30px) scale(1.12)}}.nf-card{position:relative;z-index:1;max-width:560px;width:100%;border-radius:1.5rem;border:1px solid var(--font-border-input);-webkit-backdrop-filter:blur(var(--blur-modal));backdrop-filter:blur(var(--blur-modal))}.nf-illustration{width:100%;max-width:380px;height:auto;margin-bottom:.5rem}.nf-404-text{font-size:68px;font-weight:800;letter-spacing:4px}.nf-window{animation:nf-float 5s ease-in-out infinite}.nf-lens{transform-origin:370px 260px;animation:nf-search 4s ease-in-out infinite}@keyframes nf-float{0%,to{transform:translateY(0)}50%{transform:translateY(-8px)}}@keyframes nf-search{0%,to{transform:translate(0) rotate(0)}35%{transform:translate(-10px,-12px) rotate(-4deg)}70%{transform:translate(6px,-4px) rotate(3deg)}}.nf-orbit{transform-origin:260px 170px;animation:nf-spin 40s linear infinite}@keyframes nf-spin{to{transform:rotate(360deg)}}.nf-spark{animation:nf-twinkle 3s ease-in-out infinite}.nf-spark-2{animation-delay:-1s}.nf-spark-3{animation-delay:-2s}@keyframes nf-twinkle{0%,to{opacity:.9}50%{opacity:.25}}.nf-badge{display:inline-block;font-size:.75rem;letter-spacing:.15em;padding:.35rem .9rem;border-radius:999px;color:var(--sidebar-accent);background:color-mix(in srgb,var(--sidebar-accent) 12%,transparent);border:1px solid color-mix(in srgb,var(--sidebar-accent) 35%,transparent)}.nf-desc{color:var(--placeholder-color);max-width:380px}.nf-btn-primary{color:#fff;border:none;border-radius:.75rem;background:linear-gradient(135deg,var(--sidebar-accent),color-mix(in srgb,var(--sidebar-accent) 70%,#000));transition:transform .25s ease,box-shadow .25s ease}.nf-btn-primary:hover{color:#fff;transform:translateY(-2px);box-shadow:0 8px 20px color-mix(in srgb,var(--sidebar-accent) 40%,transparent)}.nf-btn-ghost{border-radius:.75rem;border:1px solid var(--font-border-input);background:transparent;transition:transform .25s ease,background .25s ease}.nf-btn-ghost:hover{transform:translateY(-2px);background:var(--background-btn-light);border-color:var(--font-border-input)}@media(prefers-reduced-motion:reduce){.nf-blob,.nf-window,.nf-lens,.nf-orbit,.nf-spark{animation:none}}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
|
|
1162
1162
|
}
|
|
1163
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1163
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: NotFoundComponent, decorators: [{
|
|
1164
1164
|
type: Component,
|
|
1165
|
-
args: [{ selector: 'app-not-found', imports: [RouterLink], template: "<div class=\"nf-page d-flex align-items-center justify-content-center vh-100\">\r\n\r\n <!-- Blobs decorativos de fondo -->\r\n <div class=\"nf-blob nf-blob-1\"></div>\r\n <div class=\"nf-blob nf-blob-2\"></div>\r\n\r\n <div class=\"nf-card bg-white shadow-s text-center px-4 px-md-5 py-4 mx-3\">\r\n\r\n <!-- Ilustraci\u00F3n: ventana con 404 y lupa buscando -->\r\n <svg class=\"nf-illustration\" viewBox=\"0 0 520 340\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" role=\"img\" aria-label=\"P\u00E1gina no encontrada\">\r\n <defs>\r\n <linearGradient id=\"nfGrad\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\r\n <stop offset=\"0%\" style=\"stop-color: var(--sidebar-accent)\" />\r\n <stop offset=\"100%\" style=\"stop-color: var(--sidebar-accent); stop-opacity: 0.55\" />\r\n </linearGradient>\r\n </defs>\r\n\r\n <!-- \u00D3rbita punteada de fondo -->\r\n <circle class=\"nf-orbit\" cx=\"260\" cy=\"170\" r=\"150\"\r\n stroke=\"var(--font-border-input)\" stroke-width=\"1.5\"\r\n stroke-dasharray=\"6 10\" opacity=\"0.7\" />\r\n\r\n <!-- Decoraciones flotantes -->\r\n <g class=\"nf-spark nf-spark-1\" stroke=\"var(--sidebar-accent)\" stroke-width=\"3\" stroke-linecap=\"round\">\r\n <path d=\"M92 78 v20 M82 88 h20\" />\r\n </g>\r\n <g class=\"nf-spark nf-spark-2\" stroke=\"var(--placeholder-color)\" stroke-width=\"3\" stroke-linecap=\"round\">\r\n <path d=\"M448 220 v16 M440 228 h16\" />\r\n </g>\r\n <circle class=\"nf-spark nf-spark-3\" cx=\"430\" cy=\"70\" r=\"6\" fill=\"var(--sidebar-accent)\" opacity=\"0.7\" />\r\n <circle class=\"nf-spark nf-spark-1\" cx=\"70\" cy=\"230\" r=\"5\" fill=\"var(--placeholder-color)\" opacity=\"0.7\" />\r\n <path class=\"nf-spark nf-spark-2\" d=\"M120 300 q8 -10 16 0 q8 10 16 0\"\r\n stroke=\"var(--font-border-input)\" stroke-width=\"3\" stroke-linecap=\"round\" fill=\"none\" />\r\n\r\n <!-- Ventana de navegador -->\r\n <g class=\"nf-window\">\r\n <rect x=\"120\" y=\"60\" width=\"280\" height=\"200\" rx=\"16\"\r\n fill=\"var(--background-input)\" stroke=\"var(--font-border-input)\" stroke-width=\"2\" />\r\n <!-- Barra superior -->\r\n <line x1=\"120\" y1=\"98\" x2=\"400\" y2=\"98\" stroke=\"var(--font-border-input)\" stroke-width=\"2\" />\r\n <circle cx=\"144\" cy=\"79\" r=\"5\" fill=\"var(--sidebar-accent)\" />\r\n <circle cx=\"162\" cy=\"79\" r=\"5\" fill=\"var(--placeholder-color)\" opacity=\"0.8\" />\r\n <circle cx=\"180\" cy=\"79\" r=\"5\" fill=\"var(--font-border-input)\" />\r\n <!-- Barra de direcci\u00F3n -->\r\n <rect x=\"200\" y=\"71\" width=\"184\" height=\"16\" rx=\"8\" fill=\"var(--font-border-input)\" opacity=\"0.5\" />\r\n\r\n <!-- 404 dentro de la ventana -->\r\n <text x=\"260\" y=\"188\" text-anchor=\"middle\" class=\"nf-404-text\" fill=\"url(#nfGrad)\">404</text>\r\n\r\n <!-- L\u00EDneas de contenido (skeleton) -->\r\n <rect x=\"180\" y=\"212\" width=\"160\" height=\"9\" rx=\"4.5\" fill=\"var(--font-border-input)\" opacity=\"0.7\" />\r\n <rect x=\"205\" y=\"230\" width=\"110\" height=\"9\" rx=\"4.5\" fill=\"var(--font-border-input)\" opacity=\"0.45\" />\r\n </g>\r\n\r\n <!-- Lupa buscando -->\r\n <g class=\"nf-lens\">\r\n <circle cx=\"352\" cy=\"238\" r=\"46\" fill=\"var(--background-card)\" fill-opacity=\"0.55\"\r\n stroke=\"url(#nfGrad)\" stroke-width=\"8\" />\r\n <line x1=\"386\" y1=\"272\" x2=\"424\" y2=\"310\" stroke=\"url(#nfGrad)\" stroke-width=\"14\" stroke-linecap=\"round\" />\r\n <!-- Signo de interrogaci\u00F3n dentro de la lupa -->\r\n <path d=\"M340 224 q0 -14 13 -14 q13 0 13 12 q0 9 -10 13 q-3 1.5 -3 7\"\r\n stroke=\"var(--text-color)\" stroke-width=\"5\" stroke-linecap=\"round\" fill=\"none\" />\r\n <circle cx=\"353\" cy=\"256\" r=\"3.5\" fill=\"var(--text-color)\" />\r\n </g>\r\n </svg>\r\n\r\n <!-- Badge -->\r\n <span class=\"nf-badge fw-semibold\">ERROR 404</span>\r\n\r\n <h2 class=\"fw-semibold text-input mt-3\">P\u00E1gina no encontrada</h2>\r\n\r\n <p class=\"nf-desc fs-6 mt-2 mb-4 mx-auto\">\r\n Lo sentimos, la p\u00E1gina que buscas no existe o fue movida.\r\n Verifica la direcci\u00F3n o regresa al inicio.\r\n </p>\r\n\r\n <!-- Acciones -->\r\n <div class=\"d-flex gap-3 justify-content-center flex-wrap\">\r\n <button type=\"button\" (click)=\"onBack()\" class=\"btn nf-btn-primary px-4 py-2 shadow\">\r\n <i class=\"fa-solid fa-arrow-left me-2\"></i>Volver\r\n </button>\r\n <a routerLink=\"/\" class=\"btn nf-btn-ghost text-dark px-4 py-2\">\r\n <i class=\"fa-solid fa-house me-2\"></i>Ir al inicio\r\n </a>\r\n </div>\r\n\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.nf-page{position:relative;overflow:hidden;background:var(--background-color)}.nf-blob{position:absolute;border-radius:50%;filter:blur(90px);opacity:.22;pointer-events:none;animation:nf-drift 12s ease-in-out infinite alternate}.nf-blob-1{width:420px;height:420px;top:-120px;left:-100px;background:var(--sidebar-accent)}.nf-blob-2{width:360px;height:360px;bottom:-100px;right:-80px;background:color-mix(in srgb,var(--sidebar-accent) 60%,var(--text-color));animation-delay:-6s}@keyframes nf-drift{0%{transform:translate(0) scale(1)}to{transform:translate(40px,30px) scale(1.12)}}.nf-card{position:relative;z-index:1;max-width:560px;width:100%;border-radius:1.5rem;border:1px solid var(--font-border-input);backdrop-filter:blur(var(--blur-modal))}.nf-illustration{width:100%;max-width:380px;height:auto;margin-bottom:.5rem}.nf-404-text{font-size:68px;font-weight:800;letter-spacing:4px}.nf-window{animation:nf-float 5s ease-in-out infinite}.nf-lens{transform-origin:370px 260px;animation:nf-search 4s ease-in-out infinite}@keyframes nf-float{0%,to{transform:translateY(0)}50%{transform:translateY(-8px)}}@keyframes nf-search{0%,to{transform:translate(0) rotate(0)}35%{transform:translate(-10px,-12px) rotate(-4deg)}70%{transform:translate(6px,-4px) rotate(3deg)}}.nf-orbit{transform-origin:260px 170px;animation:nf-spin 40s linear infinite}@keyframes nf-spin{to{transform:rotate(360deg)}}.nf-spark{animation:nf-twinkle 3s ease-in-out infinite}.nf-spark-2{animation-delay:-1s}.nf-spark-3{animation-delay:-2s}@keyframes nf-twinkle{0%,to{opacity:.9}50%{opacity:.25}}.nf-badge{display:inline-block;font-size:.75rem;letter-spacing:.15em;padding:.35rem .9rem;border-radius:999px;color:var(--sidebar-accent);background:color-mix(in srgb,var(--sidebar-accent) 12%,transparent);border:1px solid color-mix(in srgb,var(--sidebar-accent) 35%,transparent)}.nf-desc{color:var(--placeholder-color);max-width:380px}.nf-btn-primary{color:#fff;border:none;border-radius:.75rem;background:linear-gradient(135deg,var(--sidebar-accent),color-mix(in srgb,var(--sidebar-accent) 70%,#000));transition:transform .25s ease,box-shadow .25s ease}.nf-btn-primary:hover{color:#fff;transform:translateY(-2px);box-shadow:0 8px 20px color-mix(in srgb,var(--sidebar-accent) 40%,transparent)}.nf-btn-ghost{border-radius:.75rem;border:1px solid var(--font-border-input);background:transparent;transition:transform .25s ease,background .25s ease}.nf-btn-ghost:hover{transform:translateY(-2px);background:var(--background-btn-light);border-color:var(--font-border-input)}@media(prefers-reduced-motion:reduce){.nf-blob,.nf-window,.nf-lens,.nf-orbit,.nf-spark{animation:none}}\n"] }]
|
|
1165
|
+
args: [{ selector: 'app-not-found', imports: [RouterLink], template: "<div class=\"nf-page d-flex align-items-center justify-content-center vh-100\">\r\n\r\n <!-- Blobs decorativos de fondo -->\r\n <div class=\"nf-blob nf-blob-1\"></div>\r\n <div class=\"nf-blob nf-blob-2\"></div>\r\n\r\n <div class=\"nf-card bg-white shadow-s text-center px-4 px-md-5 py-4 mx-3\">\r\n\r\n <!-- Ilustraci\u00F3n: ventana con 404 y lupa buscando -->\r\n <svg class=\"nf-illustration\" viewBox=\"0 0 520 340\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" role=\"img\" aria-label=\"P\u00E1gina no encontrada\">\r\n <defs>\r\n <linearGradient id=\"nfGrad\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\r\n <stop offset=\"0%\" style=\"stop-color: var(--sidebar-accent)\" />\r\n <stop offset=\"100%\" style=\"stop-color: var(--sidebar-accent); stop-opacity: 0.55\" />\r\n </linearGradient>\r\n </defs>\r\n\r\n <!-- \u00D3rbita punteada de fondo -->\r\n <circle class=\"nf-orbit\" cx=\"260\" cy=\"170\" r=\"150\"\r\n stroke=\"var(--font-border-input)\" stroke-width=\"1.5\"\r\n stroke-dasharray=\"6 10\" opacity=\"0.7\" />\r\n\r\n <!-- Decoraciones flotantes -->\r\n <g class=\"nf-spark nf-spark-1\" stroke=\"var(--sidebar-accent)\" stroke-width=\"3\" stroke-linecap=\"round\">\r\n <path d=\"M92 78 v20 M82 88 h20\" />\r\n </g>\r\n <g class=\"nf-spark nf-spark-2\" stroke=\"var(--placeholder-color)\" stroke-width=\"3\" stroke-linecap=\"round\">\r\n <path d=\"M448 220 v16 M440 228 h16\" />\r\n </g>\r\n <circle class=\"nf-spark nf-spark-3\" cx=\"430\" cy=\"70\" r=\"6\" fill=\"var(--sidebar-accent)\" opacity=\"0.7\" />\r\n <circle class=\"nf-spark nf-spark-1\" cx=\"70\" cy=\"230\" r=\"5\" fill=\"var(--placeholder-color)\" opacity=\"0.7\" />\r\n <path class=\"nf-spark nf-spark-2\" d=\"M120 300 q8 -10 16 0 q8 10 16 0\"\r\n stroke=\"var(--font-border-input)\" stroke-width=\"3\" stroke-linecap=\"round\" fill=\"none\" />\r\n\r\n <!-- Ventana de navegador -->\r\n <g class=\"nf-window\">\r\n <rect x=\"120\" y=\"60\" width=\"280\" height=\"200\" rx=\"16\"\r\n fill=\"var(--background-input)\" stroke=\"var(--font-border-input)\" stroke-width=\"2\" />\r\n <!-- Barra superior -->\r\n <line x1=\"120\" y1=\"98\" x2=\"400\" y2=\"98\" stroke=\"var(--font-border-input)\" stroke-width=\"2\" />\r\n <circle cx=\"144\" cy=\"79\" r=\"5\" fill=\"var(--sidebar-accent)\" />\r\n <circle cx=\"162\" cy=\"79\" r=\"5\" fill=\"var(--placeholder-color)\" opacity=\"0.8\" />\r\n <circle cx=\"180\" cy=\"79\" r=\"5\" fill=\"var(--font-border-input)\" />\r\n <!-- Barra de direcci\u00F3n -->\r\n <rect x=\"200\" y=\"71\" width=\"184\" height=\"16\" rx=\"8\" fill=\"var(--font-border-input)\" opacity=\"0.5\" />\r\n\r\n <!-- 404 dentro de la ventana -->\r\n <text x=\"260\" y=\"188\" text-anchor=\"middle\" class=\"nf-404-text\" fill=\"url(#nfGrad)\">404</text>\r\n\r\n <!-- L\u00EDneas de contenido (skeleton) -->\r\n <rect x=\"180\" y=\"212\" width=\"160\" height=\"9\" rx=\"4.5\" fill=\"var(--font-border-input)\" opacity=\"0.7\" />\r\n <rect x=\"205\" y=\"230\" width=\"110\" height=\"9\" rx=\"4.5\" fill=\"var(--font-border-input)\" opacity=\"0.45\" />\r\n </g>\r\n\r\n <!-- Lupa buscando -->\r\n <g class=\"nf-lens\">\r\n <circle cx=\"352\" cy=\"238\" r=\"46\" fill=\"var(--background-card)\" fill-opacity=\"0.55\"\r\n stroke=\"url(#nfGrad)\" stroke-width=\"8\" />\r\n <line x1=\"386\" y1=\"272\" x2=\"424\" y2=\"310\" stroke=\"url(#nfGrad)\" stroke-width=\"14\" stroke-linecap=\"round\" />\r\n <!-- Signo de interrogaci\u00F3n dentro de la lupa -->\r\n <path d=\"M340 224 q0 -14 13 -14 q13 0 13 12 q0 9 -10 13 q-3 1.5 -3 7\"\r\n stroke=\"var(--text-color)\" stroke-width=\"5\" stroke-linecap=\"round\" fill=\"none\" />\r\n <circle cx=\"353\" cy=\"256\" r=\"3.5\" fill=\"var(--text-color)\" />\r\n </g>\r\n </svg>\r\n\r\n <!-- Badge -->\r\n <span class=\"nf-badge fw-semibold\">ERROR 404</span>\r\n\r\n <h2 class=\"fw-semibold text-input mt-3\">P\u00E1gina no encontrada</h2>\r\n\r\n <p class=\"nf-desc fs-6 mt-2 mb-4 mx-auto\">\r\n Lo sentimos, la p\u00E1gina que buscas no existe o fue movida.\r\n Verifica la direcci\u00F3n o regresa al inicio.\r\n </p>\r\n\r\n <!-- Acciones -->\r\n <div class=\"d-flex gap-3 justify-content-center flex-wrap\">\r\n <button type=\"button\" (click)=\"onBack()\" class=\"btn nf-btn-primary px-4 py-2 shadow\">\r\n <i class=\"fa-solid fa-arrow-left me-2\"></i>Volver\r\n </button>\r\n <a routerLink=\"/\" class=\"btn nf-btn-ghost text-dark px-4 py-2\">\r\n <i class=\"fa-solid fa-house me-2\"></i>Ir al inicio\r\n </a>\r\n </div>\r\n\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.nf-page{position:relative;overflow:hidden;background:var(--background-color)}.nf-blob{position:absolute;border-radius:50%;filter:blur(90px);opacity:.22;pointer-events:none;animation:nf-drift 12s ease-in-out infinite alternate}.nf-blob-1{width:420px;height:420px;top:-120px;left:-100px;background:var(--sidebar-accent)}.nf-blob-2{width:360px;height:360px;bottom:-100px;right:-80px;background:color-mix(in srgb,var(--sidebar-accent) 60%,var(--text-color));animation-delay:-6s}@keyframes nf-drift{0%{transform:translate(0) scale(1)}to{transform:translate(40px,30px) scale(1.12)}}.nf-card{position:relative;z-index:1;max-width:560px;width:100%;border-radius:1.5rem;border:1px solid var(--font-border-input);-webkit-backdrop-filter:blur(var(--blur-modal));backdrop-filter:blur(var(--blur-modal))}.nf-illustration{width:100%;max-width:380px;height:auto;margin-bottom:.5rem}.nf-404-text{font-size:68px;font-weight:800;letter-spacing:4px}.nf-window{animation:nf-float 5s ease-in-out infinite}.nf-lens{transform-origin:370px 260px;animation:nf-search 4s ease-in-out infinite}@keyframes nf-float{0%,to{transform:translateY(0)}50%{transform:translateY(-8px)}}@keyframes nf-search{0%,to{transform:translate(0) rotate(0)}35%{transform:translate(-10px,-12px) rotate(-4deg)}70%{transform:translate(6px,-4px) rotate(3deg)}}.nf-orbit{transform-origin:260px 170px;animation:nf-spin 40s linear infinite}@keyframes nf-spin{to{transform:rotate(360deg)}}.nf-spark{animation:nf-twinkle 3s ease-in-out infinite}.nf-spark-2{animation-delay:-1s}.nf-spark-3{animation-delay:-2s}@keyframes nf-twinkle{0%,to{opacity:.9}50%{opacity:.25}}.nf-badge{display:inline-block;font-size:.75rem;letter-spacing:.15em;padding:.35rem .9rem;border-radius:999px;color:var(--sidebar-accent);background:color-mix(in srgb,var(--sidebar-accent) 12%,transparent);border:1px solid color-mix(in srgb,var(--sidebar-accent) 35%,transparent)}.nf-desc{color:var(--placeholder-color);max-width:380px}.nf-btn-primary{color:#fff;border:none;border-radius:.75rem;background:linear-gradient(135deg,var(--sidebar-accent),color-mix(in srgb,var(--sidebar-accent) 70%,#000));transition:transform .25s ease,box-shadow .25s ease}.nf-btn-primary:hover{color:#fff;transform:translateY(-2px);box-shadow:0 8px 20px color-mix(in srgb,var(--sidebar-accent) 40%,transparent)}.nf-btn-ghost{border-radius:.75rem;border:1px solid var(--font-border-input);background:transparent;transition:transform .25s ease,background .25s ease}.nf-btn-ghost:hover{transform:translateY(-2px);background:var(--background-btn-light);border-color:var(--font-border-input)}@media(prefers-reduced-motion:reduce){.nf-blob,.nf-window,.nf-lens,.nf-orbit,.nf-spark{animation:none}}\n"] }]
|
|
1166
1166
|
}] });
|
|
1167
1167
|
|
|
1168
1168
|
class DashboardChartDonutComponent {
|
|
1169
|
-
textClass = input('text-white');
|
|
1170
|
-
complemento = input('');
|
|
1171
|
-
data = input([]);
|
|
1172
|
-
keyValue = input('value');
|
|
1173
|
-
keyDescri = input('descri');
|
|
1174
|
-
palette = input([]);
|
|
1169
|
+
textClass = input('text-white', ...(ngDevMode ? [{ debugName: "textClass" }] : []));
|
|
1170
|
+
complemento = input('', ...(ngDevMode ? [{ debugName: "complemento" }] : []));
|
|
1171
|
+
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
1172
|
+
keyValue = input('value', ...(ngDevMode ? [{ debugName: "keyValue" }] : []));
|
|
1173
|
+
keyDescri = input('descri', ...(ngDevMode ? [{ debugName: "keyDescri" }] : []));
|
|
1174
|
+
palette = input([], ...(ngDevMode ? [{ debugName: "palette" }] : []));
|
|
1175
1175
|
clicked = output();
|
|
1176
|
-
hoveredIndex = signal(-1);
|
|
1176
|
+
hoveredIndex = signal(-1, ...(ngDevMode ? [{ debugName: "hoveredIndex" }] : []));
|
|
1177
1177
|
// ── Dona ──────────────────────────────────────────────────────────────────
|
|
1178
1178
|
C = 2 * Math.PI * 70;
|
|
1179
1179
|
GAP = 2;
|
|
@@ -1201,7 +1201,7 @@ class DashboardChartDonutComponent {
|
|
|
1201
1201
|
item,
|
|
1202
1202
|
};
|
|
1203
1203
|
});
|
|
1204
|
-
});
|
|
1204
|
+
}, ...(ngDevMode ? [{ debugName: "donutSegments" }] : []));
|
|
1205
1205
|
centerDisplay = computed(() => {
|
|
1206
1206
|
const idx = this.hoveredIndex();
|
|
1207
1207
|
const segs = this.donutSegments();
|
|
@@ -1211,9 +1211,9 @@ class DashboardChartDonutComponent {
|
|
|
1211
1211
|
}
|
|
1212
1212
|
const total = segs.reduce((acc, s) => acc + s.value, 0);
|
|
1213
1213
|
return { value: String(total), sub: 'Total' };
|
|
1214
|
-
});
|
|
1215
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1216
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1214
|
+
}, ...(ngDevMode ? [{ debugName: "centerDisplay" }] : []));
|
|
1215
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: DashboardChartDonutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1216
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: DashboardChartDonutComponent, isStandalone: true, selector: "app-dashboard-chart-donut", inputs: { textClass: { classPropertyName: "textClass", publicName: "textClass", isSignal: true, isRequired: false, transformFunction: null }, complemento: { classPropertyName: "complemento", publicName: "complemento", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, keyValue: { classPropertyName: "keyValue", publicName: "keyValue", isSignal: true, isRequired: false, transformFunction: null }, keyDescri: { classPropertyName: "keyDescri", publicName: "keyDescri", isSignal: true, isRequired: false, transformFunction: null }, palette: { classPropertyName: "palette", publicName: "palette", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: `
|
|
1217
1217
|
<div class="d-flex flex-column align-items-center py-1 px-2">
|
|
1218
1218
|
|
|
1219
1219
|
<!-- SVG ring -->
|
|
@@ -1273,7 +1273,7 @@ class DashboardChartDonutComponent {
|
|
|
1273
1273
|
</div>
|
|
1274
1274
|
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
1275
1275
|
}
|
|
1276
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1276
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: DashboardChartDonutComponent, decorators: [{
|
|
1277
1277
|
type: Component,
|
|
1278
1278
|
args: [{
|
|
1279
1279
|
selector: 'app-dashboard-chart-donut',
|
|
@@ -1338,18 +1338,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
1338
1338
|
</div>
|
|
1339
1339
|
`
|
|
1340
1340
|
}]
|
|
1341
|
-
}] });
|
|
1341
|
+
}], propDecorators: { textClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "textClass", required: false }] }], complemento: [{ type: i0.Input, args: [{ isSignal: true, alias: "complemento", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], keyValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyValue", required: false }] }], keyDescri: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyDescri", required: false }] }], palette: [{ type: i0.Input, args: [{ isSignal: true, alias: "palette", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
|
|
1342
1342
|
|
|
1343
1343
|
class DashboardChartBarsComponent {
|
|
1344
|
-
data = input.required();
|
|
1345
|
-
maxValue = input(null);
|
|
1346
|
-
keyValue = input('value');
|
|
1347
|
-
keyDescri = input('descri');
|
|
1348
|
-
palette = input([]);
|
|
1349
|
-
textClass = input('text-white');
|
|
1350
|
-
complemento = input('');
|
|
1344
|
+
data = input.required(...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
1345
|
+
maxValue = input(null, ...(ngDevMode ? [{ debugName: "maxValue" }] : []));
|
|
1346
|
+
keyValue = input('value', ...(ngDevMode ? [{ debugName: "keyValue" }] : []));
|
|
1347
|
+
keyDescri = input('descri', ...(ngDevMode ? [{ debugName: "keyDescri" }] : []));
|
|
1348
|
+
palette = input([], ...(ngDevMode ? [{ debugName: "palette" }] : []));
|
|
1349
|
+
textClass = input('text-white', ...(ngDevMode ? [{ debugName: "textClass" }] : []));
|
|
1350
|
+
complemento = input('', ...(ngDevMode ? [{ debugName: "complemento" }] : []));
|
|
1351
1351
|
clicked = output();
|
|
1352
|
-
hoveredIndex = signal(-1);
|
|
1352
|
+
hoveredIndex = signal(-1, ...(ngDevMode ? [{ debugName: "hoveredIndex" }] : []));
|
|
1353
1353
|
// ── Barras horizontales SVG ───────────────────────────────────────────────
|
|
1354
1354
|
chartData = computed(() => {
|
|
1355
1355
|
const data = this.data();
|
|
@@ -1384,9 +1384,9 @@ class DashboardChartBarsComponent {
|
|
|
1384
1384
|
};
|
|
1385
1385
|
});
|
|
1386
1386
|
return { bars, xTicks, svgW: SVG_W, svgH, axisY, axisLft: LFT, svgRgt: SVG_W - RGT, svgTop: TOP };
|
|
1387
|
-
});
|
|
1388
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1389
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1387
|
+
}, ...(ngDevMode ? [{ debugName: "chartData" }] : []));
|
|
1388
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: DashboardChartBarsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1389
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: DashboardChartBarsComponent, isStandalone: true, selector: "app-dashboard-chart-bars", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, keyValue: { classPropertyName: "keyValue", publicName: "keyValue", isSignal: true, isRequired: false, transformFunction: null }, keyDescri: { classPropertyName: "keyDescri", publicName: "keyDescri", isSignal: true, isRequired: false, transformFunction: null }, palette: { classPropertyName: "palette", publicName: "palette", isSignal: true, isRequired: false, transformFunction: null }, textClass: { classPropertyName: "textClass", publicName: "textClass", isSignal: true, isRequired: false, transformFunction: null }, complemento: { classPropertyName: "complemento", publicName: "complemento", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: `
|
|
1390
1390
|
<div class="d-flex flex-column align-items-center py-1 px-2">
|
|
1391
1391
|
|
|
1392
1392
|
<!-- SVG: barras horizontales + ejes -->
|
|
@@ -1476,7 +1476,7 @@ class DashboardChartBarsComponent {
|
|
|
1476
1476
|
</div>
|
|
1477
1477
|
`, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
1478
1478
|
}
|
|
1479
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1479
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: DashboardChartBarsComponent, decorators: [{
|
|
1480
1480
|
type: Component,
|
|
1481
1481
|
args: [{
|
|
1482
1482
|
selector: 'app-dashboard-chart-bars',
|
|
@@ -1571,28 +1571,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
|
|
|
1571
1571
|
</div>
|
|
1572
1572
|
`
|
|
1573
1573
|
}]
|
|
1574
|
-
}] });
|
|
1574
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], keyValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyValue", required: false }] }], keyDescri: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyDescri", required: false }] }], palette: [{ type: i0.Input, args: [{ isSignal: true, alias: "palette", required: false }] }], textClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "textClass", required: false }] }], complemento: [{ type: i0.Input, args: [{ isSignal: true, alias: "complemento", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
|
|
1575
1575
|
|
|
1576
1576
|
class ItemDashboardComponent {
|
|
1577
|
-
data = input([]);
|
|
1578
|
-
titulo = input('');
|
|
1579
|
-
textClass = input('text-white');
|
|
1580
|
-
colorClass = input('');
|
|
1581
|
-
keyValue = input('value');
|
|
1582
|
-
keyDescri = input('descri');
|
|
1583
|
-
complemento = input('');
|
|
1584
|
-
isDesplegable = input(false);
|
|
1585
|
-
isLoading = input(false);
|
|
1586
|
-
viewMode = input('cards');
|
|
1587
|
-
showContent = signal(false);
|
|
1577
|
+
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
1578
|
+
titulo = input('', ...(ngDevMode ? [{ debugName: "titulo" }] : []));
|
|
1579
|
+
textClass = input('text-white', ...(ngDevMode ? [{ debugName: "textClass" }] : []));
|
|
1580
|
+
colorClass = input('', ...(ngDevMode ? [{ debugName: "colorClass" }] : []));
|
|
1581
|
+
keyValue = input('value', ...(ngDevMode ? [{ debugName: "keyValue" }] : []));
|
|
1582
|
+
keyDescri = input('descri', ...(ngDevMode ? [{ debugName: "keyDescri" }] : []));
|
|
1583
|
+
complemento = input('', ...(ngDevMode ? [{ debugName: "complemento" }] : []));
|
|
1584
|
+
isDesplegable = input(false, ...(ngDevMode ? [{ debugName: "isDesplegable" }] : []));
|
|
1585
|
+
isLoading = input(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1586
|
+
viewMode = input('cards', ...(ngDevMode ? [{ debugName: "viewMode" }] : []));
|
|
1587
|
+
showContent = signal(false, ...(ngDevMode ? [{ debugName: "showContent" }] : []));
|
|
1588
1588
|
emit = output();
|
|
1589
1589
|
emitContent = output();
|
|
1590
|
-
filteredData = computed(() => this.data().filter(item => item[this.keyValue()] > 0));
|
|
1591
|
-
totalItems = computed(() => this.filteredData().reduce((sum, item) => sum + (item[this.keyValue()] || 0), 0));
|
|
1590
|
+
filteredData = computed(() => this.data().filter(item => item[this.keyValue()] > 0), ...(ngDevMode ? [{ debugName: "filteredData" }] : []));
|
|
1591
|
+
totalItems = computed(() => this.filteredData().reduce((sum, item) => sum + (item[this.keyValue()] || 0), 0), ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
|
|
1592
1592
|
maxValue = computed(() => {
|
|
1593
1593
|
const vals = this.filteredData().map(item => item[this.keyValue()] || 0);
|
|
1594
1594
|
return vals.length > 0 ? Math.max(...vals) : 1;
|
|
1595
|
-
});
|
|
1595
|
+
}, ...(ngDevMode ? [{ debugName: "maxValue" }] : []));
|
|
1596
1596
|
// ── Paleta compartida entre dona y barras ──────────────────────────────────
|
|
1597
1597
|
palette = [
|
|
1598
1598
|
'#ffffff', '#48dae4', '#06d6a0', '#ff9f1c',
|
|
@@ -1612,29 +1612,29 @@ class ItemDashboardComponent {
|
|
|
1612
1612
|
mover(item) {
|
|
1613
1613
|
this.emit.emit(item);
|
|
1614
1614
|
}
|
|
1615
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1616
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: ItemDashboardComponent, isStandalone: true, selector: "app-item-dashboard", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, titulo: { classPropertyName: "titulo", publicName: "titulo", isSignal: true, isRequired: false, transformFunction: null }, textClass: { classPropertyName: "textClass", publicName: "textClass", isSignal: true, isRequired: false, transformFunction: null }, colorClass: { classPropertyName: "colorClass", publicName: "colorClass", isSignal: true, isRequired: false, transformFunction: null }, keyValue: { classPropertyName: "keyValue", publicName: "keyValue", isSignal: true, isRequired: false, transformFunction: null }, keyDescri: { classPropertyName: "keyDescri", publicName: "keyDescri", isSignal: true, isRequired: false, transformFunction: null }, complemento: { classPropertyName: "complemento", publicName: "complemento", isSignal: true, isRequired: false, transformFunction: null }, isDesplegable: { classPropertyName: "isDesplegable", publicName: "isDesplegable", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { emit: "emit", emitContent: "emitContent" }, ngImport: i0, template: "<div class=\"iv2-card mb-2\" [ngClass]=\"colorClass() ? colorClass() : 'bg-danger'\">\r\n\r\n <!-- \u2500\u2500 HEADER \u2500\u2500 -->\r\n <div class=\"iv2-header\">\r\n\r\n <div class=\"iv2-icon-dot\"></div>\r\n\r\n <div class=\"iv2-title-wrap\">\r\n <h5 class=\"iv2-title\" [ngClass]=\"textClass()\">{{ titulo() }}</h5>\r\n\r\n @if (!isLoading() && totalItems() > 0) {\r\n <span class=\"iv2-total-badge\">{{ totalItems() }}</span>\r\n }\r\n </div>\r\n\r\n @if (isDesplegable()) {\r\n <button class=\"iv2-toggle-btn\" [ngClass]=\"textClass()\" (click)=\"toggleMostrar()\"\r\n [attr.aria-expanded]=\"showContent()\">\r\n <svg class=\"iv2-chevron\" [class.iv2-chevron--open]=\"showContent()\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 CONTENIDO (expandible) \u2500\u2500 -->\r\n <div class=\"iv2-content\" [class.iv2-content--expanded]=\"showContent() || !isDesplegable()\">\r\n <div class=\"iv2-inner\">\r\n\r\n <!-- SKELETON -->\r\n @if (isLoading()) {\r\n <div class=\"iv2-skeleton\">\r\n <div class=\"iv2-sk-row\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n </div>\r\n\r\n } @else {\r\n\r\n <!-- \u2550\u2550 CARDS \u2550\u2550 -->\r\n @if (viewMode() === 'cards') {\r\n @if (filteredData().length > 0) {\r\n <ul class=\"iv2-list\">\r\n @for (item of filteredData(); track $index) {\r\n <li class=\"iv2-item\" [class.iv2-item--clickable]=\"item[keyValue()] > 0\"\r\n (click)=\"mover(item)\">\r\n <div class=\"iv2-item-info\">\r\n <span class=\"iv2-item-label\" [ngClass]=\"textClass()\">{{ item[keyDescri()] }}</span>\r\n <div class=\"iv2-bar-track\">\r\n <div class=\"iv2-bar-fill\" [style.width.%]=\"getPercent(item)\"></div>\r\n </div>\r\n </div>\r\n <div class=\"iv2-item-right\">\r\n <span class=\"iv2-value-badge\">{{ complemento() }}{{ item[keyValue()] }}</span>\r\n </div>\r\n </li>\r\n }\r\n </ul>\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 BARRAS \u2550\u2550 -->\r\n @if (viewMode() === 'bars') {\r\n @if (filteredData().length > 0) {\r\n <app-dashboard-chart-bars\r\n [data]=\"filteredData()\"\r\n [complemento]=\"complemento()\"\r\n [keyValue]=\"keyValue()\"\r\n [keyDescri]=\"keyDescri()\"\r\n [palette]=\"palette\"\r\n [maxValue]=\"maxValue()\"\r\n (clicked)=\"mover($event)\" />\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 DONA \u2550\u2550 -->\r\n @if (viewMode() === 'donut') {\r\n @if (filteredData().length > 0) {\r\n <app-dashboard-chart-donut\r\n [data]=\"filteredData()\"\r\n [textClass]=\"textClass()\"\r\n [complemento]=\"complemento()\"\r\n [keyValue]=\"keyValue()\"\r\n [keyDescri]=\"keyDescri()\"\r\n [palette]=\"palette\"\r\n (clicked)=\"mover($event)\" />\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n }\r\n\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".iv2-card{border-radius:16px;border:1px solid rgba(255,255,255,.18);overflow:hidden;transition:transform .2s ease,box-shadow .2s ease}.iv2-card:hover{transform:translateY(-2px)}.bg-danger{background:linear-gradient(145deg,#ff4b2b,#dc3545)!important;box-shadow:0 8px 24px #dc354559;border-color:#ffffff26}.bg-success{background:linear-gradient(135deg,#2ecc71,#00cc6a)!important;box-shadow:0 8px 24px #15734759;border-color:#ffffff26}.bg-warning{background:linear-gradient(135deg,#f60,#fa9600)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.bg-info{background:linear-gradient(135deg,#4b84ff,#1b6ad8)!important;box-shadow:0 8px 24px #1b6ad859;border-color:#ffffff26}.bg-alert{background:linear-gradient(135deg,#ffc400,#fa0)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.iv2-header{display:flex;align-items:center;gap:10px;padding:14px 16px 12px}.iv2-icon-dot{width:8px;height:8px;border-radius:50%;background:#ffffff80;flex-shrink:0;animation:pulse-dot 2s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.iv2-title-wrap{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.iv2-title{font-size:.82rem;font-weight:700;letter-spacing:.02em;margin:0;line-height:1.3;flex:1;min-width:0}.iv2-total-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:22px;padding:0 7px;border-radius:999px;background:#ffffff40;color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.01em;backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);flex-shrink:0;animation:badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.iv2-toggle-btn{background:#ffffff26;border:1px solid rgba(255,255,255,.25);border-radius:8px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:background .2s ease;padding:0}.iv2-toggle-btn:hover{background:#ffffff47}.iv2-chevron{width:16px;height:16px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.iv2-chevron--open{transform:rotate(180deg)}.iv2-content{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(.4,0,.2,1),opacity .25s ease;opacity:0}.iv2-content--expanded{max-height:600px;opacity:1}.iv2-inner{background:#0000001f;backdrop-filter:blur(6px);border-top:1px solid rgba(255,255,255,.15);padding:4px 0 6px}.iv2-list{list-style:none;margin:0;padding:0}.iv2-item{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid rgba(255,255,255,.1);transition:background .18s ease}.iv2-item--clickable{cursor:pointer}.iv2-item--clickable:hover{background:#ffffff1f}.iv2-item--clickable:hover .iv2-arrow{opacity:1;transform:translate(3px)}.iv2-item:first-child{border-top:none}.iv2-item-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}.iv2-item-label{font-size:.78rem;font-weight:600;line-height:1.3;white-space:normal;word-break:break-word}.iv2-bar-track{height:3px;border-radius:99px;background:#fff3;overflow:hidden}.iv2-bar-fill{height:100%;border-radius:99px;background:#fff9;transition:width .6s cubic-bezier(.4,0,.2,1)}.iv2-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.iv2-value-badge{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:26px;padding:0 9px;border-radius:999px;background:#ffffffe6;color:#333;font-size:.78rem;font-weight:700;letter-spacing:.01em;box-shadow:0 2px 6px #00000026}.iv2-arrow{width:14px;height:14px;opacity:.5;transition:opacity .18s ease,transform .18s ease}.iv2-empty{display:flex;flex-direction:column;align-items:center;padding:20px 16px 18px;gap:4px}.iv2-empty-icon{width:40px;height:40px;border-radius:50%;background:#fff3;border:1.5px solid rgba(255,255,255,.4);display:flex;align-items:center;justify-content:center;margin-bottom:6px}.iv2-empty-icon svg{width:20px;height:20px;color:#fff}.iv2-empty-title{font-size:.82rem;font-weight:700;margin:0;opacity:.95}.iv2-empty-sub{font-size:.72rem;margin:0;opacity:.65}.iv2-skeleton{padding:10px 14px 8px}.iv2-sk-row{display:flex;gap:12px;align-items:center}.iv2-sk-line{height:12px;border-radius:6px;background-size:200% 100%;animation:shimmer 1.5s infinite}.iv2-sk-line--long{flex:1}.iv2-sk-line--short{width:36px;flex-shrink:0}.bg-warning-line,.bg-alert-line{background:linear-gradient(90deg,#f9a825 25%,#fff59d,#f9a825 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-danger-line{background:linear-gradient(90deg,#c62828 25%,#ffcdd2,#c62828 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-info-line{background:linear-gradient(90deg,#1e88e5 25%,#90caf9,#1e88e5 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-success-line{background:linear-gradient(90deg,#2e7d32 25%,#a5d6a7,#2e7d32 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: DashboardChartDonutComponent, selector: "app-dashboard-chart-donut", inputs: ["textClass", "complemento", "data", "keyValue", "keyDescri", "palette"], outputs: ["clicked"] }, { kind: "component", type: DashboardChartBarsComponent, selector: "app-dashboard-chart-bars", inputs: ["data", "maxValue", "keyValue", "keyDescri", "palette", "textClass", "complemento"], outputs: ["clicked"] }] });
|
|
1615
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: ItemDashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1616
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: ItemDashboardComponent, isStandalone: true, selector: "app-item-dashboard", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, titulo: { classPropertyName: "titulo", publicName: "titulo", isSignal: true, isRequired: false, transformFunction: null }, textClass: { classPropertyName: "textClass", publicName: "textClass", isSignal: true, isRequired: false, transformFunction: null }, colorClass: { classPropertyName: "colorClass", publicName: "colorClass", isSignal: true, isRequired: false, transformFunction: null }, keyValue: { classPropertyName: "keyValue", publicName: "keyValue", isSignal: true, isRequired: false, transformFunction: null }, keyDescri: { classPropertyName: "keyDescri", publicName: "keyDescri", isSignal: true, isRequired: false, transformFunction: null }, complemento: { classPropertyName: "complemento", publicName: "complemento", isSignal: true, isRequired: false, transformFunction: null }, isDesplegable: { classPropertyName: "isDesplegable", publicName: "isDesplegable", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { emit: "emit", emitContent: "emitContent" }, ngImport: i0, template: "<div class=\"iv2-card mb-2\" [ngClass]=\"colorClass() ? colorClass() : 'bg-danger'\">\r\n\r\n <!-- \u2500\u2500 HEADER \u2500\u2500 -->\r\n <div class=\"iv2-header\">\r\n\r\n <div class=\"iv2-icon-dot\"></div>\r\n\r\n <div class=\"iv2-title-wrap\">\r\n <h5 class=\"iv2-title\" [ngClass]=\"textClass()\">{{ titulo() }}</h5>\r\n\r\n @if (!isLoading() && totalItems() > 0) {\r\n <span class=\"iv2-total-badge\">{{ totalItems() }}</span>\r\n }\r\n </div>\r\n\r\n @if (isDesplegable()) {\r\n <button class=\"iv2-toggle-btn\" [ngClass]=\"textClass()\" (click)=\"toggleMostrar()\"\r\n [attr.aria-expanded]=\"showContent()\">\r\n <svg class=\"iv2-chevron\" [class.iv2-chevron--open]=\"showContent()\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 CONTENIDO (expandible) \u2500\u2500 -->\r\n <div class=\"iv2-content\" [class.iv2-content--expanded]=\"showContent() || !isDesplegable()\">\r\n <div class=\"iv2-inner\">\r\n\r\n <!-- SKELETON -->\r\n @if (isLoading()) {\r\n <div class=\"iv2-skeleton\">\r\n <div class=\"iv2-sk-row\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n </div>\r\n\r\n } @else {\r\n\r\n <!-- \u2550\u2550 CARDS \u2550\u2550 -->\r\n @if (viewMode() === 'cards') {\r\n @if (filteredData().length > 0) {\r\n <ul class=\"iv2-list\">\r\n @for (item of filteredData(); track $index) {\r\n <li class=\"iv2-item\" [class.iv2-item--clickable]=\"item[keyValue()] > 0\"\r\n (click)=\"mover(item)\">\r\n <div class=\"iv2-item-info\">\r\n <span class=\"iv2-item-label\" [ngClass]=\"textClass()\">{{ item[keyDescri()] }}</span>\r\n <div class=\"iv2-bar-track\">\r\n <div class=\"iv2-bar-fill\" [style.width.%]=\"getPercent(item)\"></div>\r\n </div>\r\n </div>\r\n <div class=\"iv2-item-right\">\r\n <span class=\"iv2-value-badge\">{{ complemento() }}{{ item[keyValue()] }}</span>\r\n </div>\r\n </li>\r\n }\r\n </ul>\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 BARRAS \u2550\u2550 -->\r\n @if (viewMode() === 'bars') {\r\n @if (filteredData().length > 0) {\r\n <app-dashboard-chart-bars\r\n [data]=\"filteredData()\"\r\n [complemento]=\"complemento()\"\r\n [keyValue]=\"keyValue()\"\r\n [keyDescri]=\"keyDescri()\"\r\n [palette]=\"palette\"\r\n [maxValue]=\"maxValue()\"\r\n (clicked)=\"mover($event)\" />\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 DONA \u2550\u2550 -->\r\n @if (viewMode() === 'donut') {\r\n @if (filteredData().length > 0) {\r\n <app-dashboard-chart-donut\r\n [data]=\"filteredData()\"\r\n [textClass]=\"textClass()\"\r\n [complemento]=\"complemento()\"\r\n [keyValue]=\"keyValue()\"\r\n [keyDescri]=\"keyDescri()\"\r\n [palette]=\"palette\"\r\n (clicked)=\"mover($event)\" />\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n }\r\n\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".iv2-card{border-radius:16px;border:1px solid rgba(255,255,255,.18);overflow:hidden;transition:transform .2s ease,box-shadow .2s ease}.iv2-card:hover{transform:translateY(-2px)}.bg-danger{background:linear-gradient(145deg,#ff4b2b,#dc3545)!important;box-shadow:0 8px 24px #dc354559;border-color:#ffffff26}.bg-success{background:linear-gradient(135deg,#2ecc71,#00cc6a)!important;box-shadow:0 8px 24px #15734759;border-color:#ffffff26}.bg-warning{background:linear-gradient(135deg,#f60,#fa9600)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.bg-info{background:linear-gradient(135deg,#4b84ff,#1b6ad8)!important;box-shadow:0 8px 24px #1b6ad859;border-color:#ffffff26}.bg-alert{background:linear-gradient(135deg,#ffc400,#fa0)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.iv2-header{display:flex;align-items:center;gap:10px;padding:14px 16px 12px}.iv2-icon-dot{width:8px;height:8px;border-radius:50%;background:#ffffff80;flex-shrink:0;animation:pulse-dot 2s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.iv2-title-wrap{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.iv2-title{font-size:.82rem;font-weight:700;letter-spacing:.02em;margin:0;line-height:1.3;flex:1;min-width:0}.iv2-total-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:22px;padding:0 7px;border-radius:999px;background:#ffffff40;color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.01em;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);flex-shrink:0;animation:badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.iv2-toggle-btn{background:#ffffff26;border:1px solid rgba(255,255,255,.25);border-radius:8px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:background .2s ease;padding:0}.iv2-toggle-btn:hover{background:#ffffff47}.iv2-chevron{width:16px;height:16px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.iv2-chevron--open{transform:rotate(180deg)}.iv2-content{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(.4,0,.2,1),opacity .25s ease;opacity:0}.iv2-content--expanded{max-height:600px;opacity:1}.iv2-inner{background:#0000001f;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border-top:1px solid rgba(255,255,255,.15);padding:4px 0 6px}.iv2-list{list-style:none;margin:0;padding:0}.iv2-item{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid rgba(255,255,255,.1);transition:background .18s ease}.iv2-item--clickable{cursor:pointer}.iv2-item--clickable:hover{background:#ffffff1f}.iv2-item--clickable:hover .iv2-arrow{opacity:1;transform:translate(3px)}.iv2-item:first-child{border-top:none}.iv2-item-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}.iv2-item-label{font-size:.78rem;font-weight:600;line-height:1.3;white-space:normal;word-break:break-word}.iv2-bar-track{height:3px;border-radius:99px;background:#fff3;overflow:hidden}.iv2-bar-fill{height:100%;border-radius:99px;background:#fff9;transition:width .6s cubic-bezier(.4,0,.2,1)}.iv2-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.iv2-value-badge{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:26px;padding:0 9px;border-radius:999px;background:#ffffffe6;color:#333;font-size:.78rem;font-weight:700;letter-spacing:.01em;box-shadow:0 2px 6px #00000026}.iv2-arrow{width:14px;height:14px;opacity:.5;transition:opacity .18s ease,transform .18s ease}.iv2-empty{display:flex;flex-direction:column;align-items:center;padding:20px 16px 18px;gap:4px}.iv2-empty-icon{width:40px;height:40px;border-radius:50%;background:#fff3;border:1.5px solid rgba(255,255,255,.4);display:flex;align-items:center;justify-content:center;margin-bottom:6px}.iv2-empty-icon svg{width:20px;height:20px;color:#fff}.iv2-empty-title{font-size:.82rem;font-weight:700;margin:0;opacity:.95}.iv2-empty-sub{font-size:.72rem;margin:0;opacity:.65}.iv2-skeleton{padding:10px 14px 8px}.iv2-sk-row{display:flex;gap:12px;align-items:center}.iv2-sk-line{height:12px;border-radius:6px;background-size:200% 100%;animation:shimmer 1.5s infinite}.iv2-sk-line--long{flex:1}.iv2-sk-line--short{width:36px;flex-shrink:0}.bg-warning-line,.bg-alert-line{background:linear-gradient(90deg,#f9a825 25%,#fff59d,#f9a825 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-danger-line{background:linear-gradient(90deg,#c62828 25%,#ffcdd2,#c62828 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-info-line{background:linear-gradient(90deg,#1e88e5 25%,#90caf9,#1e88e5 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-success-line{background:linear-gradient(90deg,#2e7d32 25%,#a5d6a7,#2e7d32 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: DashboardChartDonutComponent, selector: "app-dashboard-chart-donut", inputs: ["textClass", "complemento", "data", "keyValue", "keyDescri", "palette"], outputs: ["clicked"] }, { kind: "component", type: DashboardChartBarsComponent, selector: "app-dashboard-chart-bars", inputs: ["data", "maxValue", "keyValue", "keyDescri", "palette", "textClass", "complemento"], outputs: ["clicked"] }] });
|
|
1617
1617
|
}
|
|
1618
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1618
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: ItemDashboardComponent, decorators: [{
|
|
1619
1619
|
type: Component,
|
|
1620
|
-
args: [{ selector: 'app-item-dashboard', imports: [NgClass, DashboardChartDonutComponent, DashboardChartBarsComponent], template: "<div class=\"iv2-card mb-2\" [ngClass]=\"colorClass() ? colorClass() : 'bg-danger'\">\r\n\r\n <!-- \u2500\u2500 HEADER \u2500\u2500 -->\r\n <div class=\"iv2-header\">\r\n\r\n <div class=\"iv2-icon-dot\"></div>\r\n\r\n <div class=\"iv2-title-wrap\">\r\n <h5 class=\"iv2-title\" [ngClass]=\"textClass()\">{{ titulo() }}</h5>\r\n\r\n @if (!isLoading() && totalItems() > 0) {\r\n <span class=\"iv2-total-badge\">{{ totalItems() }}</span>\r\n }\r\n </div>\r\n\r\n @if (isDesplegable()) {\r\n <button class=\"iv2-toggle-btn\" [ngClass]=\"textClass()\" (click)=\"toggleMostrar()\"\r\n [attr.aria-expanded]=\"showContent()\">\r\n <svg class=\"iv2-chevron\" [class.iv2-chevron--open]=\"showContent()\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 CONTENIDO (expandible) \u2500\u2500 -->\r\n <div class=\"iv2-content\" [class.iv2-content--expanded]=\"showContent() || !isDesplegable()\">\r\n <div class=\"iv2-inner\">\r\n\r\n <!-- SKELETON -->\r\n @if (isLoading()) {\r\n <div class=\"iv2-skeleton\">\r\n <div class=\"iv2-sk-row\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n </div>\r\n\r\n } @else {\r\n\r\n <!-- \u2550\u2550 CARDS \u2550\u2550 -->\r\n @if (viewMode() === 'cards') {\r\n @if (filteredData().length > 0) {\r\n <ul class=\"iv2-list\">\r\n @for (item of filteredData(); track $index) {\r\n <li class=\"iv2-item\" [class.iv2-item--clickable]=\"item[keyValue()] > 0\"\r\n (click)=\"mover(item)\">\r\n <div class=\"iv2-item-info\">\r\n <span class=\"iv2-item-label\" [ngClass]=\"textClass()\">{{ item[keyDescri()] }}</span>\r\n <div class=\"iv2-bar-track\">\r\n <div class=\"iv2-bar-fill\" [style.width.%]=\"getPercent(item)\"></div>\r\n </div>\r\n </div>\r\n <div class=\"iv2-item-right\">\r\n <span class=\"iv2-value-badge\">{{ complemento() }}{{ item[keyValue()] }}</span>\r\n </div>\r\n </li>\r\n }\r\n </ul>\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 BARRAS \u2550\u2550 -->\r\n @if (viewMode() === 'bars') {\r\n @if (filteredData().length > 0) {\r\n <app-dashboard-chart-bars\r\n [data]=\"filteredData()\"\r\n [complemento]=\"complemento()\"\r\n [keyValue]=\"keyValue()\"\r\n [keyDescri]=\"keyDescri()\"\r\n [palette]=\"palette\"\r\n [maxValue]=\"maxValue()\"\r\n (clicked)=\"mover($event)\" />\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 DONA \u2550\u2550 -->\r\n @if (viewMode() === 'donut') {\r\n @if (filteredData().length > 0) {\r\n <app-dashboard-chart-donut\r\n [data]=\"filteredData()\"\r\n [textClass]=\"textClass()\"\r\n [complemento]=\"complemento()\"\r\n [keyValue]=\"keyValue()\"\r\n [keyDescri]=\"keyDescri()\"\r\n [palette]=\"palette\"\r\n (clicked)=\"mover($event)\" />\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n }\r\n\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".iv2-card{border-radius:16px;border:1px solid rgba(255,255,255,.18);overflow:hidden;transition:transform .2s ease,box-shadow .2s ease}.iv2-card:hover{transform:translateY(-2px)}.bg-danger{background:linear-gradient(145deg,#ff4b2b,#dc3545)!important;box-shadow:0 8px 24px #dc354559;border-color:#ffffff26}.bg-success{background:linear-gradient(135deg,#2ecc71,#00cc6a)!important;box-shadow:0 8px 24px #15734759;border-color:#ffffff26}.bg-warning{background:linear-gradient(135deg,#f60,#fa9600)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.bg-info{background:linear-gradient(135deg,#4b84ff,#1b6ad8)!important;box-shadow:0 8px 24px #1b6ad859;border-color:#ffffff26}.bg-alert{background:linear-gradient(135deg,#ffc400,#fa0)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.iv2-header{display:flex;align-items:center;gap:10px;padding:14px 16px 12px}.iv2-icon-dot{width:8px;height:8px;border-radius:50%;background:#ffffff80;flex-shrink:0;animation:pulse-dot 2s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.iv2-title-wrap{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.iv2-title{font-size:.82rem;font-weight:700;letter-spacing:.02em;margin:0;line-height:1.3;flex:1;min-width:0}.iv2-total-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:22px;padding:0 7px;border-radius:999px;background:#ffffff40;color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.01em;backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);flex-shrink:0;animation:badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.iv2-toggle-btn{background:#ffffff26;border:1px solid rgba(255,255,255,.25);border-radius:8px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:background .2s ease;padding:0}.iv2-toggle-btn:hover{background:#ffffff47}.iv2-chevron{width:16px;height:16px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.iv2-chevron--open{transform:rotate(180deg)}.iv2-content{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(.4,0,.2,1),opacity .25s ease;opacity:0}.iv2-content--expanded{max-height:600px;opacity:1}.iv2-inner{background:#0000001f;backdrop-filter:blur(6px);border-top:1px solid rgba(255,255,255,.15);padding:4px 0 6px}.iv2-list{list-style:none;margin:0;padding:0}.iv2-item{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid rgba(255,255,255,.1);transition:background .18s ease}.iv2-item--clickable{cursor:pointer}.iv2-item--clickable:hover{background:#ffffff1f}.iv2-item--clickable:hover .iv2-arrow{opacity:1;transform:translate(3px)}.iv2-item:first-child{border-top:none}.iv2-item-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}.iv2-item-label{font-size:.78rem;font-weight:600;line-height:1.3;white-space:normal;word-break:break-word}.iv2-bar-track{height:3px;border-radius:99px;background:#fff3;overflow:hidden}.iv2-bar-fill{height:100%;border-radius:99px;background:#fff9;transition:width .6s cubic-bezier(.4,0,.2,1)}.iv2-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.iv2-value-badge{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:26px;padding:0 9px;border-radius:999px;background:#ffffffe6;color:#333;font-size:.78rem;font-weight:700;letter-spacing:.01em;box-shadow:0 2px 6px #00000026}.iv2-arrow{width:14px;height:14px;opacity:.5;transition:opacity .18s ease,transform .18s ease}.iv2-empty{display:flex;flex-direction:column;align-items:center;padding:20px 16px 18px;gap:4px}.iv2-empty-icon{width:40px;height:40px;border-radius:50%;background:#fff3;border:1.5px solid rgba(255,255,255,.4);display:flex;align-items:center;justify-content:center;margin-bottom:6px}.iv2-empty-icon svg{width:20px;height:20px;color:#fff}.iv2-empty-title{font-size:.82rem;font-weight:700;margin:0;opacity:.95}.iv2-empty-sub{font-size:.72rem;margin:0;opacity:.65}.iv2-skeleton{padding:10px 14px 8px}.iv2-sk-row{display:flex;gap:12px;align-items:center}.iv2-sk-line{height:12px;border-radius:6px;background-size:200% 100%;animation:shimmer 1.5s infinite}.iv2-sk-line--long{flex:1}.iv2-sk-line--short{width:36px;flex-shrink:0}.bg-warning-line,.bg-alert-line{background:linear-gradient(90deg,#f9a825 25%,#fff59d,#f9a825 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-danger-line{background:linear-gradient(90deg,#c62828 25%,#ffcdd2,#c62828 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-info-line{background:linear-gradient(90deg,#1e88e5 25%,#90caf9,#1e88e5 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-success-line{background:linear-gradient(90deg,#2e7d32 25%,#a5d6a7,#2e7d32 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
|
|
1621
|
-
}] });
|
|
1620
|
+
args: [{ selector: 'app-item-dashboard', imports: [NgClass, DashboardChartDonutComponent, DashboardChartBarsComponent], template: "<div class=\"iv2-card mb-2\" [ngClass]=\"colorClass() ? colorClass() : 'bg-danger'\">\r\n\r\n <!-- \u2500\u2500 HEADER \u2500\u2500 -->\r\n <div class=\"iv2-header\">\r\n\r\n <div class=\"iv2-icon-dot\"></div>\r\n\r\n <div class=\"iv2-title-wrap\">\r\n <h5 class=\"iv2-title\" [ngClass]=\"textClass()\">{{ titulo() }}</h5>\r\n\r\n @if (!isLoading() && totalItems() > 0) {\r\n <span class=\"iv2-total-badge\">{{ totalItems() }}</span>\r\n }\r\n </div>\r\n\r\n @if (isDesplegable()) {\r\n <button class=\"iv2-toggle-btn\" [ngClass]=\"textClass()\" (click)=\"toggleMostrar()\"\r\n [attr.aria-expanded]=\"showContent()\">\r\n <svg class=\"iv2-chevron\" [class.iv2-chevron--open]=\"showContent()\"\r\n viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 CONTENIDO (expandible) \u2500\u2500 -->\r\n <div class=\"iv2-content\" [class.iv2-content--expanded]=\"showContent() || !isDesplegable()\">\r\n <div class=\"iv2-inner\">\r\n\r\n <!-- SKELETON -->\r\n @if (isLoading()) {\r\n <div class=\"iv2-skeleton\">\r\n <div class=\"iv2-sk-row\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n </div>\r\n\r\n } @else {\r\n\r\n <!-- \u2550\u2550 CARDS \u2550\u2550 -->\r\n @if (viewMode() === 'cards') {\r\n @if (filteredData().length > 0) {\r\n <ul class=\"iv2-list\">\r\n @for (item of filteredData(); track $index) {\r\n <li class=\"iv2-item\" [class.iv2-item--clickable]=\"item[keyValue()] > 0\"\r\n (click)=\"mover(item)\">\r\n <div class=\"iv2-item-info\">\r\n <span class=\"iv2-item-label\" [ngClass]=\"textClass()\">{{ item[keyDescri()] }}</span>\r\n <div class=\"iv2-bar-track\">\r\n <div class=\"iv2-bar-fill\" [style.width.%]=\"getPercent(item)\"></div>\r\n </div>\r\n </div>\r\n <div class=\"iv2-item-right\">\r\n <span class=\"iv2-value-badge\">{{ complemento() }}{{ item[keyValue()] }}</span>\r\n </div>\r\n </li>\r\n }\r\n </ul>\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 BARRAS \u2550\u2550 -->\r\n @if (viewMode() === 'bars') {\r\n @if (filteredData().length > 0) {\r\n <app-dashboard-chart-bars\r\n [data]=\"filteredData()\"\r\n [complemento]=\"complemento()\"\r\n [keyValue]=\"keyValue()\"\r\n [keyDescri]=\"keyDescri()\"\r\n [palette]=\"palette\"\r\n [maxValue]=\"maxValue()\"\r\n (clicked)=\"mover($event)\" />\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 DONA \u2550\u2550 -->\r\n @if (viewMode() === 'donut') {\r\n @if (filteredData().length > 0) {\r\n <app-dashboard-chart-donut\r\n [data]=\"filteredData()\"\r\n [textClass]=\"textClass()\"\r\n [complemento]=\"complemento()\"\r\n [keyValue]=\"keyValue()\"\r\n [keyDescri]=\"keyDescri()\"\r\n [palette]=\"palette\"\r\n (clicked)=\"mover($event)\" />\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"></polyline></svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n }\r\n\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".iv2-card{border-radius:16px;border:1px solid rgba(255,255,255,.18);overflow:hidden;transition:transform .2s ease,box-shadow .2s ease}.iv2-card:hover{transform:translateY(-2px)}.bg-danger{background:linear-gradient(145deg,#ff4b2b,#dc3545)!important;box-shadow:0 8px 24px #dc354559;border-color:#ffffff26}.bg-success{background:linear-gradient(135deg,#2ecc71,#00cc6a)!important;box-shadow:0 8px 24px #15734759;border-color:#ffffff26}.bg-warning{background:linear-gradient(135deg,#f60,#fa9600)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.bg-info{background:linear-gradient(135deg,#4b84ff,#1b6ad8)!important;box-shadow:0 8px 24px #1b6ad859;border-color:#ffffff26}.bg-alert{background:linear-gradient(135deg,#ffc400,#fa0)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.iv2-header{display:flex;align-items:center;gap:10px;padding:14px 16px 12px}.iv2-icon-dot{width:8px;height:8px;border-radius:50%;background:#ffffff80;flex-shrink:0;animation:pulse-dot 2s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.iv2-title-wrap{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.iv2-title{font-size:.82rem;font-weight:700;letter-spacing:.02em;margin:0;line-height:1.3;flex:1;min-width:0}.iv2-total-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:22px;padding:0 7px;border-radius:999px;background:#ffffff40;color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.01em;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);flex-shrink:0;animation:badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.iv2-toggle-btn{background:#ffffff26;border:1px solid rgba(255,255,255,.25);border-radius:8px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:background .2s ease;padding:0}.iv2-toggle-btn:hover{background:#ffffff47}.iv2-chevron{width:16px;height:16px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.iv2-chevron--open{transform:rotate(180deg)}.iv2-content{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(.4,0,.2,1),opacity .25s ease;opacity:0}.iv2-content--expanded{max-height:600px;opacity:1}.iv2-inner{background:#0000001f;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border-top:1px solid rgba(255,255,255,.15);padding:4px 0 6px}.iv2-list{list-style:none;margin:0;padding:0}.iv2-item{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid rgba(255,255,255,.1);transition:background .18s ease}.iv2-item--clickable{cursor:pointer}.iv2-item--clickable:hover{background:#ffffff1f}.iv2-item--clickable:hover .iv2-arrow{opacity:1;transform:translate(3px)}.iv2-item:first-child{border-top:none}.iv2-item-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}.iv2-item-label{font-size:.78rem;font-weight:600;line-height:1.3;white-space:normal;word-break:break-word}.iv2-bar-track{height:3px;border-radius:99px;background:#fff3;overflow:hidden}.iv2-bar-fill{height:100%;border-radius:99px;background:#fff9;transition:width .6s cubic-bezier(.4,0,.2,1)}.iv2-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.iv2-value-badge{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:26px;padding:0 9px;border-radius:999px;background:#ffffffe6;color:#333;font-size:.78rem;font-weight:700;letter-spacing:.01em;box-shadow:0 2px 6px #00000026}.iv2-arrow{width:14px;height:14px;opacity:.5;transition:opacity .18s ease,transform .18s ease}.iv2-empty{display:flex;flex-direction:column;align-items:center;padding:20px 16px 18px;gap:4px}.iv2-empty-icon{width:40px;height:40px;border-radius:50%;background:#fff3;border:1.5px solid rgba(255,255,255,.4);display:flex;align-items:center;justify-content:center;margin-bottom:6px}.iv2-empty-icon svg{width:20px;height:20px;color:#fff}.iv2-empty-title{font-size:.82rem;font-weight:700;margin:0;opacity:.95}.iv2-empty-sub{font-size:.72rem;margin:0;opacity:.65}.iv2-skeleton{padding:10px 14px 8px}.iv2-sk-row{display:flex;gap:12px;align-items:center}.iv2-sk-line{height:12px;border-radius:6px;background-size:200% 100%;animation:shimmer 1.5s infinite}.iv2-sk-line--long{flex:1}.iv2-sk-line--short{width:36px;flex-shrink:0}.bg-warning-line,.bg-alert-line{background:linear-gradient(90deg,#f9a825 25%,#fff59d,#f9a825 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-danger-line{background:linear-gradient(90deg,#c62828 25%,#ffcdd2,#c62828 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-info-line{background:linear-gradient(90deg,#1e88e5 25%,#90caf9,#1e88e5 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-success-line{background:linear-gradient(90deg,#2e7d32 25%,#a5d6a7,#2e7d32 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
|
|
1621
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], titulo: [{ type: i0.Input, args: [{ isSignal: true, alias: "titulo", required: false }] }], textClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "textClass", required: false }] }], colorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "colorClass", required: false }] }], keyValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyValue", required: false }] }], keyDescri: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyDescri", required: false }] }], complemento: [{ type: i0.Input, args: [{ isSignal: true, alias: "complemento", required: false }] }], isDesplegable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDesplegable", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], emit: [{ type: i0.Output, args: ["emit"] }], emitContent: [{ type: i0.Output, args: ["emitContent"] }] } });
|
|
1622
1622
|
|
|
1623
1623
|
class ItemDashboardGroupComponent {
|
|
1624
|
-
data = input([]);
|
|
1625
|
-
titulo = input('');
|
|
1626
|
-
textClass = input('text-white');
|
|
1627
|
-
colorClass = input('');
|
|
1628
|
-
keyValue = input('value');
|
|
1629
|
-
keyDescri = input('descri');
|
|
1630
|
-
complemento = input('');
|
|
1631
|
-
isDesplegable = input(false);
|
|
1632
|
-
isLoading = input(false);
|
|
1633
|
-
viewMode = input('cards');
|
|
1634
|
-
showContent = signal(false);
|
|
1624
|
+
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
1625
|
+
titulo = input('', ...(ngDevMode ? [{ debugName: "titulo" }] : []));
|
|
1626
|
+
textClass = input('text-white', ...(ngDevMode ? [{ debugName: "textClass" }] : []));
|
|
1627
|
+
colorClass = input('', ...(ngDevMode ? [{ debugName: "colorClass" }] : []));
|
|
1628
|
+
keyValue = input('value', ...(ngDevMode ? [{ debugName: "keyValue" }] : []));
|
|
1629
|
+
keyDescri = input('descri', ...(ngDevMode ? [{ debugName: "keyDescri" }] : []));
|
|
1630
|
+
complemento = input('', ...(ngDevMode ? [{ debugName: "complemento" }] : []));
|
|
1631
|
+
isDesplegable = input(false, ...(ngDevMode ? [{ debugName: "isDesplegable" }] : []));
|
|
1632
|
+
isLoading = input(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1633
|
+
viewMode = input('cards', ...(ngDevMode ? [{ debugName: "viewMode" }] : []));
|
|
1634
|
+
showContent = signal(false, ...(ngDevMode ? [{ debugName: "showContent" }] : []));
|
|
1635
1635
|
emit = output();
|
|
1636
1636
|
emitContent = output();
|
|
1637
|
-
dataGroup = computed(() => this.groupBy(this.data(), 'GROUP'));
|
|
1637
|
+
dataGroup = computed(() => this.groupBy(this.data(), 'GROUP'), ...(ngDevMode ? [{ debugName: "dataGroup" }] : []));
|
|
1638
1638
|
filteredDataGroup = computed(() => {
|
|
1639
1639
|
const grouped = this.dataGroup();
|
|
1640
1640
|
const result = {};
|
|
@@ -1644,15 +1644,15 @@ class ItemDashboardGroupComponent {
|
|
|
1644
1644
|
result[key] = items;
|
|
1645
1645
|
}
|
|
1646
1646
|
return result;
|
|
1647
|
-
});
|
|
1648
|
-
totalItems = computed(() => this.data().reduce((sum, item) => sum + (item[this.keyValue()] || 0), 0));
|
|
1647
|
+
}, ...(ngDevMode ? [{ debugName: "filteredDataGroup" }] : []));
|
|
1648
|
+
totalItems = computed(() => this.data().reduce((sum, item) => sum + (item[this.keyValue()] || 0), 0), ...(ngDevMode ? [{ debugName: "totalItems" }] : []));
|
|
1649
1649
|
maxValue = computed(() => {
|
|
1650
1650
|
const vals = this.data()
|
|
1651
1651
|
.filter((item) => item[this.keyValue()] > 0)
|
|
1652
1652
|
.map((item) => item[this.keyValue()] || 0);
|
|
1653
1653
|
return vals.length > 0 ? Math.max(...vals) : 1;
|
|
1654
|
-
});
|
|
1655
|
-
hasData = computed(() => Object.keys(this.filteredDataGroup()).length > 0);
|
|
1654
|
+
}, ...(ngDevMode ? [{ debugName: "maxValue" }] : []));
|
|
1655
|
+
hasData = computed(() => Object.keys(this.filteredDataGroup()).length > 0, ...(ngDevMode ? [{ debugName: "hasData" }] : []));
|
|
1656
1656
|
getPercent(item) {
|
|
1657
1657
|
const max = this.maxValue();
|
|
1658
1658
|
return max === 0 ? 0 : Math.round((item[this.keyValue()] / max) * 100);
|
|
@@ -1676,26 +1676,26 @@ class ItemDashboardGroupComponent {
|
|
|
1676
1676
|
return acc;
|
|
1677
1677
|
}, {});
|
|
1678
1678
|
}
|
|
1679
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1680
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: ItemDashboardGroupComponent, isStandalone: true, selector: "app-item-dashboard-group", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, titulo: { classPropertyName: "titulo", publicName: "titulo", isSignal: true, isRequired: false, transformFunction: null }, textClass: { classPropertyName: "textClass", publicName: "textClass", isSignal: true, isRequired: false, transformFunction: null }, colorClass: { classPropertyName: "colorClass", publicName: "colorClass", isSignal: true, isRequired: false, transformFunction: null }, keyValue: { classPropertyName: "keyValue", publicName: "keyValue", isSignal: true, isRequired: false, transformFunction: null }, keyDescri: { classPropertyName: "keyDescri", publicName: "keyDescri", isSignal: true, isRequired: false, transformFunction: null }, complemento: { classPropertyName: "complemento", publicName: "complemento", isSignal: true, isRequired: false, transformFunction: null }, isDesplegable: { classPropertyName: "isDesplegable", publicName: "isDesplegable", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { emit: "emit", emitContent: "emitContent" }, ngImport: i0, template: "<div class=\"iv2-card mb-2\" [ngClass]=\"colorClass() ? colorClass() : 'bg-danger'\">\r\n\r\n <!-- \u2500\u2500 HEADER \u2500\u2500 -->\r\n <div class=\"iv2-header\">\r\n\r\n <div class=\"iv2-icon-dot\"></div>\r\n\r\n <div class=\"iv2-title-wrap\">\r\n <h5 class=\"iv2-title\" [ngClass]=\"textClass()\">{{ titulo() }}</h5>\r\n </div>\r\n\r\n @if (isDesplegable()) {\r\n <button class=\"iv2-toggle-btn\" [ngClass]=\"textClass()\" (click)=\"toggleMostrar()\"\r\n [attr.aria-expanded]=\"showContent()\">\r\n <svg class=\"iv2-chevron\" [class.iv2-chevron--open]=\"showContent()\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 CONTENIDO (expandible) \u2500\u2500 -->\r\n <div class=\"iv2-content\" [class.iv2-content--expanded]=\"showContent() || !isDesplegable()\">\r\n <div class=\"iv2-inner\">\r\n\r\n <!-- SKELETON -->\r\n @if (isLoading()) {\r\n <div class=\"iv2-skeleton\">\r\n <div class=\"iv2-sk-row\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n </div>\r\n\r\n } @else {\r\n\r\n <!-- \u2550\u2550 CARDS \u2550\u2550 -->\r\n @if (viewMode() === 'cards') {\r\n @if (hasData()) {\r\n <ul class=\"iv2-list\">\r\n @for (group of filteredDataGroup() | keyvalue; track group.key) {\r\n\r\n <li class=\"iv2-group-header\">\r\n <span class=\"iv2-group-label\" [ngClass]=\"textClass()\">{{ group.key }}</span>\r\n <div class=\"iv2-group-divider\"></div>\r\n </li>\r\n\r\n @for (item of group.value; track $index) {\r\n <li class=\"iv2-item\" [class.iv2-item--clickable]=\"item[keyValue()] > 0\"\r\n (click)=\"item[keyValue()] > 0 && mover(item)\">\r\n <div class=\"iv2-item-info\">\r\n <span class=\"iv2-item-label\" [ngClass]=\"textClass()\">{{ item[keyDescri()] }}</span>\r\n <div class=\"iv2-bar-track\">\r\n <div class=\"iv2-bar-fill\" [style.width.%]=\"getPercent(item)\"></div>\r\n </div>\r\n </div>\r\n <div class=\"iv2-item-right\">\r\n <span class=\"iv2-value-badge\">{{ complemento() }}{{ item[keyValue()] | number: '1.2-2' }}</span>\r\n </div>\r\n </li>\r\n }\r\n\r\n }\r\n </ul>\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 BARRAS \u2550\u2550 -->\r\n @if (viewMode() === 'bars') {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">En implementaci\u00F3n</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Muy pronto</p>\r\n </div>\r\n }\r\n\r\n <!-- \u2550\u2550 DONA \u2550\u2550 -->\r\n @if (viewMode() === 'donut') {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">En implementaci\u00F3n</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Muy pronto</p>\r\n </div>\r\n }\r\n\r\n }\r\n\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".iv2-card{border-radius:16px;border:1px solid rgba(255,255,255,.18);overflow:hidden;transition:transform .2s ease,box-shadow .2s ease;animation:iv2CardSlideIn .22s cubic-bezier(.25,.46,.45,.94) both}.iv2-card:hover{transform:translateY(-2px)}@keyframes iv2CardSlideIn{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.bg-danger{background:linear-gradient(145deg,#ff4b2b,#dc3545)!important;box-shadow:0 8px 24px #dc354559;border-color:#ffffff26}.bg-success{background:linear-gradient(135deg,#2ecc71,#00cc6a)!important;box-shadow:0 8px 24px #15734759;border-color:#ffffff26}.bg-warning{background:linear-gradient(135deg,#f60,#fa9600)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.bg-info{background:linear-gradient(135deg,#4b84ff,#1b6ad8)!important;box-shadow:0 8px 24px #1b6ad859;border-color:#ffffff26}.bg-alert{background:linear-gradient(135deg,#ffc400,#fa0)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.iv2-header{display:flex;align-items:center;gap:10px;padding:14px 16px 12px}.iv2-icon-dot{width:8px;height:8px;border-radius:50%;background:#ffffff80;flex-shrink:0;animation:pulse-dot 2s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.iv2-title-wrap{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.iv2-title{font-size:.82rem;font-weight:700;letter-spacing:.02em;margin:0;line-height:1.3;flex:1;min-width:0}.iv2-total-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:22px;padding:0 7px;border-radius:999px;background:#ffffff40;color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.01em;backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);flex-shrink:0;animation:badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.iv2-toggle-btn{background:#ffffff26;border:1px solid rgba(255,255,255,.25);border-radius:8px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:background .2s ease;padding:0}.iv2-toggle-btn:hover{background:#ffffff47}.iv2-chevron{width:16px;height:16px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.iv2-chevron--open{transform:rotate(180deg)}.iv2-content{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(.4,0,.2,1),opacity .25s ease;opacity:0}.iv2-content--expanded{max-height:1000px;opacity:1}.iv2-inner{background:#0000001f;backdrop-filter:blur(6px);border-top:1px solid rgba(255,255,255,.15);padding:4px 0 6px}.iv2-list{list-style:none;margin:0;padding:0}.iv2-group-header{display:flex;align-items:center;gap:8px;padding:10px 14px 6px}.iv2-group-label{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;flex-shrink:0}.iv2-group-divider{flex:1;height:1px;background:#ffffff40}.iv2-item{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid rgba(255,255,255,.08);transition:background .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.iv2-item--clickable{cursor:pointer}.iv2-item--clickable:hover{background:#ffffff1f}.iv2-item--clickable:active{transform:scale(.985);background:#ffffff2e}.iv2-item-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}.iv2-item-label{font-size:.78rem;font-weight:600;line-height:1.3;white-space:normal;word-break:break-word}.iv2-bar-track{height:3px;border-radius:99px;background:#fff3;overflow:hidden}.iv2-bar-fill{height:100%;border-radius:99px;background:#fff9;transition:width .6s cubic-bezier(.4,0,.2,1)}.iv2-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.iv2-value-badge{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:26px;padding:0 9px;border-radius:999px;background:#ffffffe6;color:#333;font-size:.78rem;font-weight:700;letter-spacing:.01em;box-shadow:0 2px 6px #00000026}.iv2-empty{display:flex;flex-direction:column;align-items:center;padding:20px 16px 18px;gap:4px}.iv2-empty-icon{width:40px;height:40px;border-radius:50%;background:#fff3;border:1.5px solid rgba(255,255,255,.4);display:flex;align-items:center;justify-content:center;margin-bottom:6px}.iv2-empty-icon svg{width:20px;height:20px;color:#fff}.iv2-empty-title{font-size:.82rem;font-weight:700;margin:0;opacity:.95}.iv2-empty-sub{font-size:.72rem;margin:0;opacity:.65}.iv2-skeleton{padding:10px 14px 8px}.iv2-sk-row{display:flex;gap:12px;align-items:center}.iv2-sk-line{height:12px;border-radius:6px;background-size:200% 100%;animation:shimmer 1.5s infinite}.iv2-sk-line--long{flex:1}.iv2-sk-line--short{width:36px;flex-shrink:0}.bg-warning-line,.bg-alert-line{background:linear-gradient(90deg,#f9a825 25%,#fff59d,#f9a825 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-danger-line{background:linear-gradient(90deg,#c62828 25%,#ffcdd2,#c62828 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-info-line{background:linear-gradient(90deg,#1e88e5 25%,#90caf9,#1e88e5 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-success-line{background:linear-gradient(90deg,#2e7d32 25%,#a5d6a7,#2e7d32 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: DecimalPipe, name: "number" }] });
|
|
1679
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: ItemDashboardGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1680
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: ItemDashboardGroupComponent, isStandalone: true, selector: "app-item-dashboard-group", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, titulo: { classPropertyName: "titulo", publicName: "titulo", isSignal: true, isRequired: false, transformFunction: null }, textClass: { classPropertyName: "textClass", publicName: "textClass", isSignal: true, isRequired: false, transformFunction: null }, colorClass: { classPropertyName: "colorClass", publicName: "colorClass", isSignal: true, isRequired: false, transformFunction: null }, keyValue: { classPropertyName: "keyValue", publicName: "keyValue", isSignal: true, isRequired: false, transformFunction: null }, keyDescri: { classPropertyName: "keyDescri", publicName: "keyDescri", isSignal: true, isRequired: false, transformFunction: null }, complemento: { classPropertyName: "complemento", publicName: "complemento", isSignal: true, isRequired: false, transformFunction: null }, isDesplegable: { classPropertyName: "isDesplegable", publicName: "isDesplegable", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { emit: "emit", emitContent: "emitContent" }, ngImport: i0, template: "<div class=\"iv2-card mb-2\" [ngClass]=\"colorClass() ? colorClass() : 'bg-danger'\">\r\n\r\n <!-- \u2500\u2500 HEADER \u2500\u2500 -->\r\n <div class=\"iv2-header\">\r\n\r\n <div class=\"iv2-icon-dot\"></div>\r\n\r\n <div class=\"iv2-title-wrap\">\r\n <h5 class=\"iv2-title\" [ngClass]=\"textClass()\">{{ titulo() }}</h5>\r\n </div>\r\n\r\n @if (isDesplegable()) {\r\n <button class=\"iv2-toggle-btn\" [ngClass]=\"textClass()\" (click)=\"toggleMostrar()\"\r\n [attr.aria-expanded]=\"showContent()\">\r\n <svg class=\"iv2-chevron\" [class.iv2-chevron--open]=\"showContent()\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 CONTENIDO (expandible) \u2500\u2500 -->\r\n <div class=\"iv2-content\" [class.iv2-content--expanded]=\"showContent() || !isDesplegable()\">\r\n <div class=\"iv2-inner\">\r\n\r\n <!-- SKELETON -->\r\n @if (isLoading()) {\r\n <div class=\"iv2-skeleton\">\r\n <div class=\"iv2-sk-row\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n </div>\r\n\r\n } @else {\r\n\r\n <!-- \u2550\u2550 CARDS \u2550\u2550 -->\r\n @if (viewMode() === 'cards') {\r\n @if (hasData()) {\r\n <ul class=\"iv2-list\">\r\n @for (group of filteredDataGroup() | keyvalue; track group.key) {\r\n\r\n <li class=\"iv2-group-header\">\r\n <span class=\"iv2-group-label\" [ngClass]=\"textClass()\">{{ group.key }}</span>\r\n <div class=\"iv2-group-divider\"></div>\r\n </li>\r\n\r\n @for (item of group.value; track $index) {\r\n <li class=\"iv2-item\" [class.iv2-item--clickable]=\"item[keyValue()] > 0\"\r\n (click)=\"item[keyValue()] > 0 && mover(item)\">\r\n <div class=\"iv2-item-info\">\r\n <span class=\"iv2-item-label\" [ngClass]=\"textClass()\">{{ item[keyDescri()] }}</span>\r\n <div class=\"iv2-bar-track\">\r\n <div class=\"iv2-bar-fill\" [style.width.%]=\"getPercent(item)\"></div>\r\n </div>\r\n </div>\r\n <div class=\"iv2-item-right\">\r\n <span class=\"iv2-value-badge\">{{ complemento() }}{{ item[keyValue()] | number: '1.2-2' }}</span>\r\n </div>\r\n </li>\r\n }\r\n\r\n }\r\n </ul>\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 BARRAS \u2550\u2550 -->\r\n @if (viewMode() === 'bars') {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">En implementaci\u00F3n</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Muy pronto</p>\r\n </div>\r\n }\r\n\r\n <!-- \u2550\u2550 DONA \u2550\u2550 -->\r\n @if (viewMode() === 'donut') {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">En implementaci\u00F3n</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Muy pronto</p>\r\n </div>\r\n }\r\n\r\n }\r\n\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".iv2-card{border-radius:16px;border:1px solid rgba(255,255,255,.18);overflow:hidden;transition:transform .2s ease,box-shadow .2s ease;animation:iv2CardSlideIn .22s cubic-bezier(.25,.46,.45,.94) both}.iv2-card:hover{transform:translateY(-2px)}@keyframes iv2CardSlideIn{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.bg-danger{background:linear-gradient(145deg,#ff4b2b,#dc3545)!important;box-shadow:0 8px 24px #dc354559;border-color:#ffffff26}.bg-success{background:linear-gradient(135deg,#2ecc71,#00cc6a)!important;box-shadow:0 8px 24px #15734759;border-color:#ffffff26}.bg-warning{background:linear-gradient(135deg,#f60,#fa9600)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.bg-info{background:linear-gradient(135deg,#4b84ff,#1b6ad8)!important;box-shadow:0 8px 24px #1b6ad859;border-color:#ffffff26}.bg-alert{background:linear-gradient(135deg,#ffc400,#fa0)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.iv2-header{display:flex;align-items:center;gap:10px;padding:14px 16px 12px}.iv2-icon-dot{width:8px;height:8px;border-radius:50%;background:#ffffff80;flex-shrink:0;animation:pulse-dot 2s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.iv2-title-wrap{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.iv2-title{font-size:.82rem;font-weight:700;letter-spacing:.02em;margin:0;line-height:1.3;flex:1;min-width:0}.iv2-total-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:22px;padding:0 7px;border-radius:999px;background:#ffffff40;color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.01em;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);flex-shrink:0;animation:badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.iv2-toggle-btn{background:#ffffff26;border:1px solid rgba(255,255,255,.25);border-radius:8px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:background .2s ease;padding:0}.iv2-toggle-btn:hover{background:#ffffff47}.iv2-chevron{width:16px;height:16px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.iv2-chevron--open{transform:rotate(180deg)}.iv2-content{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(.4,0,.2,1),opacity .25s ease;opacity:0}.iv2-content--expanded{max-height:1000px;opacity:1}.iv2-inner{background:#0000001f;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border-top:1px solid rgba(255,255,255,.15);padding:4px 0 6px}.iv2-list{list-style:none;margin:0;padding:0}.iv2-group-header{display:flex;align-items:center;gap:8px;padding:10px 14px 6px}.iv2-group-label{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;flex-shrink:0}.iv2-group-divider{flex:1;height:1px;background:#ffffff40}.iv2-item{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid rgba(255,255,255,.08);transition:background .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.iv2-item--clickable{cursor:pointer}.iv2-item--clickable:hover{background:#ffffff1f}.iv2-item--clickable:active{transform:scale(.985);background:#ffffff2e}.iv2-item-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}.iv2-item-label{font-size:.78rem;font-weight:600;line-height:1.3;white-space:normal;word-break:break-word}.iv2-bar-track{height:3px;border-radius:99px;background:#fff3;overflow:hidden}.iv2-bar-fill{height:100%;border-radius:99px;background:#fff9;transition:width .6s cubic-bezier(.4,0,.2,1)}.iv2-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.iv2-value-badge{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:26px;padding:0 9px;border-radius:999px;background:#ffffffe6;color:#333;font-size:.78rem;font-weight:700;letter-spacing:.01em;box-shadow:0 2px 6px #00000026}.iv2-empty{display:flex;flex-direction:column;align-items:center;padding:20px 16px 18px;gap:4px}.iv2-empty-icon{width:40px;height:40px;border-radius:50%;background:#fff3;border:1.5px solid rgba(255,255,255,.4);display:flex;align-items:center;justify-content:center;margin-bottom:6px}.iv2-empty-icon svg{width:20px;height:20px;color:#fff}.iv2-empty-title{font-size:.82rem;font-weight:700;margin:0;opacity:.95}.iv2-empty-sub{font-size:.72rem;margin:0;opacity:.65}.iv2-skeleton{padding:10px 14px 8px}.iv2-sk-row{display:flex;gap:12px;align-items:center}.iv2-sk-line{height:12px;border-radius:6px;background-size:200% 100%;animation:shimmer 1.5s infinite}.iv2-sk-line--long{flex:1}.iv2-sk-line--short{width:36px;flex-shrink:0}.bg-warning-line,.bg-alert-line{background:linear-gradient(90deg,#f9a825 25%,#fff59d,#f9a825 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-danger-line{background:linear-gradient(90deg,#c62828 25%,#ffcdd2,#c62828 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-info-line{background:linear-gradient(90deg,#1e88e5 25%,#90caf9,#1e88e5 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-success-line{background:linear-gradient(90deg,#2e7d32 25%,#a5d6a7,#2e7d32 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: DecimalPipe, name: "number" }] });
|
|
1681
1681
|
}
|
|
1682
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1682
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: ItemDashboardGroupComponent, decorators: [{
|
|
1683
1683
|
type: Component,
|
|
1684
|
-
args: [{ selector: 'app-item-dashboard-group', imports: [NgClass, KeyValuePipe, DecimalPipe], template: "<div class=\"iv2-card mb-2\" [ngClass]=\"colorClass() ? colorClass() : 'bg-danger'\">\r\n\r\n <!-- \u2500\u2500 HEADER \u2500\u2500 -->\r\n <div class=\"iv2-header\">\r\n\r\n <div class=\"iv2-icon-dot\"></div>\r\n\r\n <div class=\"iv2-title-wrap\">\r\n <h5 class=\"iv2-title\" [ngClass]=\"textClass()\">{{ titulo() }}</h5>\r\n </div>\r\n\r\n @if (isDesplegable()) {\r\n <button class=\"iv2-toggle-btn\" [ngClass]=\"textClass()\" (click)=\"toggleMostrar()\"\r\n [attr.aria-expanded]=\"showContent()\">\r\n <svg class=\"iv2-chevron\" [class.iv2-chevron--open]=\"showContent()\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 CONTENIDO (expandible) \u2500\u2500 -->\r\n <div class=\"iv2-content\" [class.iv2-content--expanded]=\"showContent() || !isDesplegable()\">\r\n <div class=\"iv2-inner\">\r\n\r\n <!-- SKELETON -->\r\n @if (isLoading()) {\r\n <div class=\"iv2-skeleton\">\r\n <div class=\"iv2-sk-row\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n </div>\r\n\r\n } @else {\r\n\r\n <!-- \u2550\u2550 CARDS \u2550\u2550 -->\r\n @if (viewMode() === 'cards') {\r\n @if (hasData()) {\r\n <ul class=\"iv2-list\">\r\n @for (group of filteredDataGroup() | keyvalue; track group.key) {\r\n\r\n <li class=\"iv2-group-header\">\r\n <span class=\"iv2-group-label\" [ngClass]=\"textClass()\">{{ group.key }}</span>\r\n <div class=\"iv2-group-divider\"></div>\r\n </li>\r\n\r\n @for (item of group.value; track $index) {\r\n <li class=\"iv2-item\" [class.iv2-item--clickable]=\"item[keyValue()] > 0\"\r\n (click)=\"item[keyValue()] > 0 && mover(item)\">\r\n <div class=\"iv2-item-info\">\r\n <span class=\"iv2-item-label\" [ngClass]=\"textClass()\">{{ item[keyDescri()] }}</span>\r\n <div class=\"iv2-bar-track\">\r\n <div class=\"iv2-bar-fill\" [style.width.%]=\"getPercent(item)\"></div>\r\n </div>\r\n </div>\r\n <div class=\"iv2-item-right\">\r\n <span class=\"iv2-value-badge\">{{ complemento() }}{{ item[keyValue()] | number: '1.2-2' }}</span>\r\n </div>\r\n </li>\r\n }\r\n\r\n }\r\n </ul>\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 BARRAS \u2550\u2550 -->\r\n @if (viewMode() === 'bars') {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">En implementaci\u00F3n</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Muy pronto</p>\r\n </div>\r\n }\r\n\r\n <!-- \u2550\u2550 DONA \u2550\u2550 -->\r\n @if (viewMode() === 'donut') {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">En implementaci\u00F3n</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Muy pronto</p>\r\n </div>\r\n }\r\n\r\n }\r\n\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".iv2-card{border-radius:16px;border:1px solid rgba(255,255,255,.18);overflow:hidden;transition:transform .2s ease,box-shadow .2s ease;animation:iv2CardSlideIn .22s cubic-bezier(.25,.46,.45,.94) both}.iv2-card:hover{transform:translateY(-2px)}@keyframes iv2CardSlideIn{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.bg-danger{background:linear-gradient(145deg,#ff4b2b,#dc3545)!important;box-shadow:0 8px 24px #dc354559;border-color:#ffffff26}.bg-success{background:linear-gradient(135deg,#2ecc71,#00cc6a)!important;box-shadow:0 8px 24px #15734759;border-color:#ffffff26}.bg-warning{background:linear-gradient(135deg,#f60,#fa9600)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.bg-info{background:linear-gradient(135deg,#4b84ff,#1b6ad8)!important;box-shadow:0 8px 24px #1b6ad859;border-color:#ffffff26}.bg-alert{background:linear-gradient(135deg,#ffc400,#fa0)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.iv2-header{display:flex;align-items:center;gap:10px;padding:14px 16px 12px}.iv2-icon-dot{width:8px;height:8px;border-radius:50%;background:#ffffff80;flex-shrink:0;animation:pulse-dot 2s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.iv2-title-wrap{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.iv2-title{font-size:.82rem;font-weight:700;letter-spacing:.02em;margin:0;line-height:1.3;flex:1;min-width:0}.iv2-total-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:22px;padding:0 7px;border-radius:999px;background:#ffffff40;color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.01em;backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);flex-shrink:0;animation:badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.iv2-toggle-btn{background:#ffffff26;border:1px solid rgba(255,255,255,.25);border-radius:8px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:background .2s ease;padding:0}.iv2-toggle-btn:hover{background:#ffffff47}.iv2-chevron{width:16px;height:16px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.iv2-chevron--open{transform:rotate(180deg)}.iv2-content{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(.4,0,.2,1),opacity .25s ease;opacity:0}.iv2-content--expanded{max-height:1000px;opacity:1}.iv2-inner{background:#0000001f;backdrop-filter:blur(6px);border-top:1px solid rgba(255,255,255,.15);padding:4px 0 6px}.iv2-list{list-style:none;margin:0;padding:0}.iv2-group-header{display:flex;align-items:center;gap:8px;padding:10px 14px 6px}.iv2-group-label{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;flex-shrink:0}.iv2-group-divider{flex:1;height:1px;background:#ffffff40}.iv2-item{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid rgba(255,255,255,.08);transition:background .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.iv2-item--clickable{cursor:pointer}.iv2-item--clickable:hover{background:#ffffff1f}.iv2-item--clickable:active{transform:scale(.985);background:#ffffff2e}.iv2-item-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}.iv2-item-label{font-size:.78rem;font-weight:600;line-height:1.3;white-space:normal;word-break:break-word}.iv2-bar-track{height:3px;border-radius:99px;background:#fff3;overflow:hidden}.iv2-bar-fill{height:100%;border-radius:99px;background:#fff9;transition:width .6s cubic-bezier(.4,0,.2,1)}.iv2-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.iv2-value-badge{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:26px;padding:0 9px;border-radius:999px;background:#ffffffe6;color:#333;font-size:.78rem;font-weight:700;letter-spacing:.01em;box-shadow:0 2px 6px #00000026}.iv2-empty{display:flex;flex-direction:column;align-items:center;padding:20px 16px 18px;gap:4px}.iv2-empty-icon{width:40px;height:40px;border-radius:50%;background:#fff3;border:1.5px solid rgba(255,255,255,.4);display:flex;align-items:center;justify-content:center;margin-bottom:6px}.iv2-empty-icon svg{width:20px;height:20px;color:#fff}.iv2-empty-title{font-size:.82rem;font-weight:700;margin:0;opacity:.95}.iv2-empty-sub{font-size:.72rem;margin:0;opacity:.65}.iv2-skeleton{padding:10px 14px 8px}.iv2-sk-row{display:flex;gap:12px;align-items:center}.iv2-sk-line{height:12px;border-radius:6px;background-size:200% 100%;animation:shimmer 1.5s infinite}.iv2-sk-line--long{flex:1}.iv2-sk-line--short{width:36px;flex-shrink:0}.bg-warning-line,.bg-alert-line{background:linear-gradient(90deg,#f9a825 25%,#fff59d,#f9a825 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-danger-line{background:linear-gradient(90deg,#c62828 25%,#ffcdd2,#c62828 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-info-line{background:linear-gradient(90deg,#1e88e5 25%,#90caf9,#1e88e5 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-success-line{background:linear-gradient(90deg,#2e7d32 25%,#a5d6a7,#2e7d32 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
|
|
1685
|
-
}] });
|
|
1684
|
+
args: [{ selector: 'app-item-dashboard-group', imports: [NgClass, KeyValuePipe, DecimalPipe], template: "<div class=\"iv2-card mb-2\" [ngClass]=\"colorClass() ? colorClass() : 'bg-danger'\">\r\n\r\n <!-- \u2500\u2500 HEADER \u2500\u2500 -->\r\n <div class=\"iv2-header\">\r\n\r\n <div class=\"iv2-icon-dot\"></div>\r\n\r\n <div class=\"iv2-title-wrap\">\r\n <h5 class=\"iv2-title\" [ngClass]=\"textClass()\">{{ titulo() }}</h5>\r\n </div>\r\n\r\n @if (isDesplegable()) {\r\n <button class=\"iv2-toggle-btn\" [ngClass]=\"textClass()\" (click)=\"toggleMostrar()\"\r\n [attr.aria-expanded]=\"showContent()\">\r\n <svg class=\"iv2-chevron\" [class.iv2-chevron--open]=\"showContent()\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\"></polyline>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- \u2500\u2500 CONTENIDO (expandible) \u2500\u2500 -->\r\n <div class=\"iv2-content\" [class.iv2-content--expanded]=\"showContent() || !isDesplegable()\">\r\n <div class=\"iv2-inner\">\r\n\r\n <!-- SKELETON -->\r\n @if (isLoading()) {\r\n <div class=\"iv2-skeleton\">\r\n <div class=\"iv2-sk-row\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n <div class=\"iv2-sk-row mt-2\">\r\n <div class=\"iv2-sk-line iv2-sk-line--long\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n <div class=\"iv2-sk-line iv2-sk-line--short\" [ngClass]=\"colorClass() + '-line'\"></div>\r\n </div>\r\n </div>\r\n\r\n } @else {\r\n\r\n <!-- \u2550\u2550 CARDS \u2550\u2550 -->\r\n @if (viewMode() === 'cards') {\r\n @if (hasData()) {\r\n <ul class=\"iv2-list\">\r\n @for (group of filteredDataGroup() | keyvalue; track group.key) {\r\n\r\n <li class=\"iv2-group-header\">\r\n <span class=\"iv2-group-label\" [ngClass]=\"textClass()\">{{ group.key }}</span>\r\n <div class=\"iv2-group-divider\"></div>\r\n </li>\r\n\r\n @for (item of group.value; track $index) {\r\n <li class=\"iv2-item\" [class.iv2-item--clickable]=\"item[keyValue()] > 0\"\r\n (click)=\"item[keyValue()] > 0 && mover(item)\">\r\n <div class=\"iv2-item-info\">\r\n <span class=\"iv2-item-label\" [ngClass]=\"textClass()\">{{ item[keyDescri()] }}</span>\r\n <div class=\"iv2-bar-track\">\r\n <div class=\"iv2-bar-fill\" [style.width.%]=\"getPercent(item)\"></div>\r\n </div>\r\n </div>\r\n <div class=\"iv2-item-right\">\r\n <span class=\"iv2-value-badge\">{{ complemento() }}{{ item[keyValue()] | number: '1.2-2' }}</span>\r\n </div>\r\n </li>\r\n }\r\n\r\n }\r\n </ul>\r\n } @else {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">Todo al d\u00EDa</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Sin pendientes por el momento</p>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- \u2550\u2550 BARRAS \u2550\u2550 -->\r\n @if (viewMode() === 'bars') {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">En implementaci\u00F3n</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Muy pronto</p>\r\n </div>\r\n }\r\n\r\n <!-- \u2550\u2550 DONA \u2550\u2550 -->\r\n @if (viewMode() === 'donut') {\r\n <div class=\"iv2-empty\">\r\n <div class=\"iv2-empty-icon\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg></div>\r\n <p class=\"iv2-empty-title\" [ngClass]=\"textClass()\">En implementaci\u00F3n</p>\r\n <p class=\"iv2-empty-sub\" [ngClass]=\"textClass()\">Muy pronto</p>\r\n </div>\r\n }\r\n\r\n }\r\n\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".iv2-card{border-radius:16px;border:1px solid rgba(255,255,255,.18);overflow:hidden;transition:transform .2s ease,box-shadow .2s ease;animation:iv2CardSlideIn .22s cubic-bezier(.25,.46,.45,.94) both}.iv2-card:hover{transform:translateY(-2px)}@keyframes iv2CardSlideIn{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.bg-danger{background:linear-gradient(145deg,#ff4b2b,#dc3545)!important;box-shadow:0 8px 24px #dc354559;border-color:#ffffff26}.bg-success{background:linear-gradient(135deg,#2ecc71,#00cc6a)!important;box-shadow:0 8px 24px #15734759;border-color:#ffffff26}.bg-warning{background:linear-gradient(135deg,#f60,#fa9600)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.bg-info{background:linear-gradient(135deg,#4b84ff,#1b6ad8)!important;box-shadow:0 8px 24px #1b6ad859;border-color:#ffffff26}.bg-alert{background:linear-gradient(135deg,#ffc400,#fa0)!important;box-shadow:0 8px 24px #ed8f0359;border-color:#ffffff26}.iv2-header{display:flex;align-items:center;gap:10px;padding:14px 16px 12px}.iv2-icon-dot{width:8px;height:8px;border-radius:50%;background:#ffffff80;flex-shrink:0;animation:pulse-dot 2s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.iv2-title-wrap{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.iv2-title{font-size:.82rem;font-weight:700;letter-spacing:.02em;margin:0;line-height:1.3;flex:1;min-width:0}.iv2-total-badge{display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:22px;padding:0 7px;border-radius:999px;background:#ffffff40;color:#fff;font-size:.72rem;font-weight:700;letter-spacing:.01em;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);flex-shrink:0;animation:badge-pop .3s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.iv2-toggle-btn{background:#ffffff26;border:1px solid rgba(255,255,255,.25);border-radius:8px;width:30px;height:30px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:background .2s ease;padding:0}.iv2-toggle-btn:hover{background:#ffffff47}.iv2-chevron{width:16px;height:16px;transition:transform .3s cubic-bezier(.4,0,.2,1)}.iv2-chevron--open{transform:rotate(180deg)}.iv2-content{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(.4,0,.2,1),opacity .25s ease;opacity:0}.iv2-content--expanded{max-height:1000px;opacity:1}.iv2-inner{background:#0000001f;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);border-top:1px solid rgba(255,255,255,.15);padding:4px 0 6px}.iv2-list{list-style:none;margin:0;padding:0}.iv2-group-header{display:flex;align-items:center;gap:8px;padding:10px 14px 6px}.iv2-group-label{font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;flex-shrink:0}.iv2-group-divider{flex:1;height:1px;background:#ffffff40}.iv2-item{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid rgba(255,255,255,.08);transition:background .2s cubic-bezier(.4,0,.2,1),transform .2s cubic-bezier(.4,0,.2,1)}.iv2-item--clickable{cursor:pointer}.iv2-item--clickable:hover{background:#ffffff1f}.iv2-item--clickable:active{transform:scale(.985);background:#ffffff2e}.iv2-item-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px}.iv2-item-label{font-size:.78rem;font-weight:600;line-height:1.3;white-space:normal;word-break:break-word}.iv2-bar-track{height:3px;border-radius:99px;background:#fff3;overflow:hidden}.iv2-bar-fill{height:100%;border-radius:99px;background:#fff9;transition:width .6s cubic-bezier(.4,0,.2,1)}.iv2-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.iv2-value-badge{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:26px;padding:0 9px;border-radius:999px;background:#ffffffe6;color:#333;font-size:.78rem;font-weight:700;letter-spacing:.01em;box-shadow:0 2px 6px #00000026}.iv2-empty{display:flex;flex-direction:column;align-items:center;padding:20px 16px 18px;gap:4px}.iv2-empty-icon{width:40px;height:40px;border-radius:50%;background:#fff3;border:1.5px solid rgba(255,255,255,.4);display:flex;align-items:center;justify-content:center;margin-bottom:6px}.iv2-empty-icon svg{width:20px;height:20px;color:#fff}.iv2-empty-title{font-size:.82rem;font-weight:700;margin:0;opacity:.95}.iv2-empty-sub{font-size:.72rem;margin:0;opacity:.65}.iv2-skeleton{padding:10px 14px 8px}.iv2-sk-row{display:flex;gap:12px;align-items:center}.iv2-sk-line{height:12px;border-radius:6px;background-size:200% 100%;animation:shimmer 1.5s infinite}.iv2-sk-line--long{flex:1}.iv2-sk-line--short{width:36px;flex-shrink:0}.bg-warning-line,.bg-alert-line{background:linear-gradient(90deg,#f9a825 25%,#fff59d,#f9a825 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-danger-line{background:linear-gradient(90deg,#c62828 25%,#ffcdd2,#c62828 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-info-line{background:linear-gradient(90deg,#1e88e5 25%,#90caf9,#1e88e5 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}.bg-success-line{background:linear-gradient(90deg,#2e7d32 25%,#a5d6a7,#2e7d32 75%);background-size:200% 100%;animation:shimmer 1.5s infinite}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}\n"] }]
|
|
1685
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], titulo: [{ type: i0.Input, args: [{ isSignal: true, alias: "titulo", required: false }] }], textClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "textClass", required: false }] }], colorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "colorClass", required: false }] }], keyValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyValue", required: false }] }], keyDescri: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyDescri", required: false }] }], complemento: [{ type: i0.Input, args: [{ isSignal: true, alias: "complemento", required: false }] }], isDesplegable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDesplegable", required: false }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], emit: [{ type: i0.Output, args: ["emit"] }], emitContent: [{ type: i0.Output, args: ["emitContent"] }] } });
|
|
1686
1686
|
|
|
1687
1687
|
// Duración de la animación de salida (@keyframes fabMiniOut en el scss): se
|
|
1688
1688
|
// mantiene montado este tiempo antes de desmontarlo de verdad.
|
|
1689
1689
|
const LEAVE_DURATION_MS = 150;
|
|
1690
1690
|
class DashboardViewSwitcherComponent {
|
|
1691
|
-
viewMode = input('cards');
|
|
1692
|
-
accentColor = input('#398bf7');
|
|
1691
|
+
viewMode = input('cards', ...(ngDevMode ? [{ debugName: "viewMode" }] : []));
|
|
1692
|
+
accentColor = input('#398bf7', ...(ngDevMode ? [{ debugName: "accentColor" }] : []));
|
|
1693
1693
|
viewModeChange = output();
|
|
1694
|
-
fabOpen = signal(false);
|
|
1694
|
+
fabOpen = signal(false, ...(ngDevMode ? [{ debugName: "fabOpen" }] : []));
|
|
1695
1695
|
// Reemplaza a @fabMenu (query + stagger, sin @angular/animations): el
|
|
1696
1696
|
// stagger se logra con animation-delay por :nth-child en el scss, y la
|
|
1697
1697
|
// salida se maneja igual que en tab-bar (mantener montado + clase "--closing").
|
|
1698
|
-
fabRendered = signal(false);
|
|
1698
|
+
fabRendered = signal(false, ...(ngDevMode ? [{ debugName: "fabRendered" }] : []));
|
|
1699
1699
|
closeTimer = null;
|
|
1700
1700
|
constructor() {
|
|
1701
1701
|
effect(() => {
|
|
@@ -1715,13 +1715,13 @@ class DashboardViewSwitcherComponent {
|
|
|
1715
1715
|
this.viewModeChange.emit(mode);
|
|
1716
1716
|
this.fabOpen.set(false);
|
|
1717
1717
|
}
|
|
1718
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1719
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
1718
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: DashboardViewSwitcherComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1719
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.32", type: DashboardViewSwitcherComponent, isStandalone: true, selector: "app-dashboard-view-switcher", inputs: { viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: true, isRequired: false, transformFunction: null }, accentColor: { classPropertyName: "accentColor", publicName: "accentColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { viewModeChange: "viewModeChange" }, ngImport: i0, template: "<div class=\"view-fab\" [style.--fab-main-from]=\"accentColor()\" [style.--fab-main-to]=\"accentColor()\"\r\n [style.--fab-active-bg]=\"accentColor()\" [style.--fab-mini-hover-border]=\"accentColor()\"\r\n [style.--fab-mini-hover-color]=\"accentColor()\" (mouseenter)=\"fabOpen.set(true)\" (mouseleave)=\"fabOpen.set(false)\">\r\n @if (fabRendered()) {\r\n <div class=\"fab-menu\" [class.fab-menu--closing]=\"!fabOpen()\">\r\n\r\n <div class=\"fab-mini-wrap\">\r\n <span class=\"fab-tooltip\">Dona</span>\r\n <button class=\"fab-mini\" [class.active]=\"viewMode() === 'donut'\" (click)=\"setView('donut')\"\r\n title=\"Vista de dona\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\"></circle>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"fab-mini-wrap\">\r\n <span class=\"fab-tooltip\">Barras</span>\r\n <button class=\"fab-mini\" [class.active]=\"viewMode() === 'bars'\" (click)=\"setView('bars')\"\r\n title=\"Vista de barras\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <rect x=\"2\" y=\"13\" width=\"5\" height=\"9\" rx=\"1\"></rect>\r\n <rect x=\"9\" y=\"7\" width=\"5\" height=\"15\" rx=\"1\"></rect>\r\n <rect x=\"16\" y=\"3\" width=\"5\" height=\"19\" rx=\"1\"></rect>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"fab-mini-wrap\">\r\n <span class=\"fab-tooltip\">Tarjetas</span>\r\n <button class=\"fab-mini\" [class.active]=\"viewMode() === 'cards'\" (click)=\"setView('cards')\"\r\n title=\"Vista de tarjetas\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n </div>\r\n }\r\n\r\n <button class=\"fab-main\" [class.is-open]=\"fabOpen()\" (click)=\"fabOpen.set(!fabOpen())\" title=\"Cambiar vista\">\r\n @switch (viewMode()) {\r\n @case ('cards') {\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n </svg>\r\n }\r\n @case ('bars') {\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <rect x=\"2\" y=\"13\" width=\"5\" height=\"9\" rx=\"1\"></rect>\r\n <rect x=\"9\" y=\"7\" width=\"5\" height=\"15\" rx=\"1\"></rect>\r\n <rect x=\"16\" y=\"3\" width=\"5\" height=\"19\" rx=\"1\"></rect>\r\n </svg>\r\n }\r\n @case ('donut') {\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\"></circle>\r\n </svg>\r\n }\r\n }\r\n </button>\r\n</div>\r\n", styles: [":host{--fab-mini-bg: #ffffff;--fab-mini-border: #e2e8f0;--fab-mini-color: #64748b;--fab-mini-shadow: rgba(0, 0, 0, .12);--fab-mini-hover-border: #4678e5;--fab-mini-hover-color: #4678e5;--fab-tooltip-bg: rgba(15, 23, 42, .82);--fab-tooltip-color: #ffffff;--fab-main-from: #002fff;--fab-main-to: #3a88ed;--fab-main-shadow: rgba(70, 134, 229, .55);--fab-main-hover-shadow: rgba(70, 139, 229, .7);--fab-active-bg: #0957ff;--fab-active-shadow: rgba(70, 152, 229, .45)}:host-context([data-bs-theme=dark]),:host-context(.dark-mode),:host-context(.theme-dark){--fab-mini-bg: #1e293b;--fab-mini-border: #334155;--fab-mini-color: #94a3b8;--fab-mini-shadow: rgba(0, 0, 0, .35);--fab-mini-hover-border: #60a5fa;--fab-mini-hover-color: #60a5fa;--fab-tooltip-bg: rgba(248, 250, 252, .92);--fab-tooltip-color: #0f172a}.view-fab{position:fixed;bottom:24px;right:24px;z-index:999;display:flex;flex-direction:column-reverse;align-items:center;gap:.55rem}.fab-main{width:54px;height:54px;border-radius:50%;border:none;background:linear-gradient(135deg,var(--fab-main-from) 0%,var(--fab-main-to) 100%);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 18px var(--fab-main-shadow);cursor:pointer;transition:transform .25s cubic-bezier(.34,1.56,.64,1),box-shadow .25s ease}.fab-main svg{transition:transform .35s ease}.fab-main:hover{transform:scale(1.1);box-shadow:0 6px 24px var(--fab-main-hover-shadow)}.fab-main.is-open{box-shadow:0 6px 24px var(--fab-main-hover-shadow)}.fab-mini{width:44px;height:44px;border-radius:50%;border:2px solid var(--fab-mini-border);background:var(--fab-mini-bg);color:var(--fab-mini-color);display:flex;align-items:center;justify-content:center;box-shadow:0 2px 10px var(--fab-mini-shadow);cursor:pointer;transition:background .2s ease,border-color .2s ease,color .2s ease,transform .2s cubic-bezier(.34,1.56,.64,1),box-shadow .2s ease}.fab-mini:hover{transform:scale(1.12);border-color:var(--fab-mini-hover-border);color:var(--fab-mini-hover-color)}.fab-mini.active{background:var(--fab-active-bg);border-color:var(--fab-active-bg);color:#fff;box-shadow:0 3px 12px var(--fab-active-shadow);transform:scale(1.08)}.fab-tooltip{position:absolute;right:calc(100% + 10px);top:50%;transform:translateY(-50%);font-size:.7rem;font-weight:600;background:var(--fab-tooltip-bg);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);color:var(--fab-tooltip-color);padding:3px 8px;border-radius:6px;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease}.fab-menu{display:flex;flex-direction:column;align-items:center;gap:.55rem}.fab-mini-wrap{position:relative;display:flex;align-items:center;animation:fabMiniIn .22s cubic-bezier(.34,1.56,.64,1) both}.fab-mini-wrap:nth-child(1){animation-delay:0ms}.fab-mini-wrap:nth-child(2){animation-delay:55ms}.fab-mini-wrap:nth-child(3){animation-delay:.11s}.fab-mini-wrap:hover .fab-tooltip{opacity:1}.fab-menu--closing .fab-mini-wrap{animation:fabMiniOut .15s ease-in both;animation-delay:0ms}@keyframes fabMiniIn{0%{opacity:0;transform:translateY(12px) scale(.75)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes fabMiniOut{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:translateY(10px) scale(.8)}}\n"] });
|
|
1720
1720
|
}
|
|
1721
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1721
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.32", ngImport: i0, type: DashboardViewSwitcherComponent, decorators: [{
|
|
1722
1722
|
type: Component,
|
|
1723
|
-
args: [{ selector: 'app-dashboard-view-switcher', imports: [], template: "<div class=\"view-fab\" [style.--fab-main-from]=\"accentColor()\" [style.--fab-main-to]=\"accentColor()\"\r\n [style.--fab-active-bg]=\"accentColor()\" [style.--fab-mini-hover-border]=\"accentColor()\"\r\n [style.--fab-mini-hover-color]=\"accentColor()\" (mouseenter)=\"fabOpen.set(true)\" (mouseleave)=\"fabOpen.set(false)\">\r\n @if (fabRendered()) {\r\n <div class=\"fab-menu\" [class.fab-menu--closing]=\"!fabOpen()\">\r\n\r\n <div class=\"fab-mini-wrap\">\r\n <span class=\"fab-tooltip\">Dona</span>\r\n <button class=\"fab-mini\" [class.active]=\"viewMode() === 'donut'\" (click)=\"setView('donut')\"\r\n title=\"Vista de dona\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\"></circle>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"fab-mini-wrap\">\r\n <span class=\"fab-tooltip\">Barras</span>\r\n <button class=\"fab-mini\" [class.active]=\"viewMode() === 'bars'\" (click)=\"setView('bars')\"\r\n title=\"Vista de barras\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <rect x=\"2\" y=\"13\" width=\"5\" height=\"9\" rx=\"1\"></rect>\r\n <rect x=\"9\" y=\"7\" width=\"5\" height=\"15\" rx=\"1\"></rect>\r\n <rect x=\"16\" y=\"3\" width=\"5\" height=\"19\" rx=\"1\"></rect>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"fab-mini-wrap\">\r\n <span class=\"fab-tooltip\">Tarjetas</span>\r\n <button class=\"fab-mini\" [class.active]=\"viewMode() === 'cards'\" (click)=\"setView('cards')\"\r\n title=\"Vista de tarjetas\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n </div>\r\n }\r\n\r\n <button class=\"fab-main\" [class.is-open]=\"fabOpen()\" (click)=\"fabOpen.set(!fabOpen())\" title=\"Cambiar vista\">\r\n @switch (viewMode()) {\r\n @case ('cards') {\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n </svg>\r\n }\r\n @case ('bars') {\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <rect x=\"2\" y=\"13\" width=\"5\" height=\"9\" rx=\"1\"></rect>\r\n <rect x=\"9\" y=\"7\" width=\"5\" height=\"15\" rx=\"1\"></rect>\r\n <rect x=\"16\" y=\"3\" width=\"5\" height=\"19\" rx=\"1\"></rect>\r\n </svg>\r\n }\r\n @case ('donut') {\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\"></circle>\r\n </svg>\r\n }\r\n }\r\n </button>\r\n</div>\r\n", styles: [":host{--fab-mini-bg: #ffffff;--fab-mini-border: #e2e8f0;--fab-mini-color: #64748b;--fab-mini-shadow: rgba(0, 0, 0, .12);--fab-mini-hover-border: #4678e5;--fab-mini-hover-color: #4678e5;--fab-tooltip-bg: rgba(15, 23, 42, .82);--fab-tooltip-color: #ffffff;--fab-main-from: #002fff;--fab-main-to: #3a88ed;--fab-main-shadow: rgba(70, 134, 229, .55);--fab-main-hover-shadow: rgba(70, 139, 229, .7);--fab-active-bg: #0957ff;--fab-active-shadow: rgba(70, 152, 229, .45)}:host-context([data-bs-theme=dark]),:host-context(.dark-mode),:host-context(.theme-dark){--fab-mini-bg: #1e293b;--fab-mini-border: #334155;--fab-mini-color: #94a3b8;--fab-mini-shadow: rgba(0, 0, 0, .35);--fab-mini-hover-border: #60a5fa;--fab-mini-hover-color: #60a5fa;--fab-tooltip-bg: rgba(248, 250, 252, .92);--fab-tooltip-color: #0f172a}.view-fab{position:fixed;bottom:24px;right:24px;z-index:999;display:flex;flex-direction:column-reverse;align-items:center;gap:.55rem}.fab-main{width:54px;height:54px;border-radius:50%;border:none;background:linear-gradient(135deg,var(--fab-main-from) 0%,var(--fab-main-to) 100%);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 18px var(--fab-main-shadow);cursor:pointer;transition:transform .25s cubic-bezier(.34,1.56,.64,1),box-shadow .25s ease}.fab-main svg{transition:transform .35s ease}.fab-main:hover{transform:scale(1.1);box-shadow:0 6px 24px var(--fab-main-hover-shadow)}.fab-main.is-open{box-shadow:0 6px 24px var(--fab-main-hover-shadow)}.fab-mini{width:44px;height:44px;border-radius:50%;border:2px solid var(--fab-mini-border);background:var(--fab-mini-bg);color:var(--fab-mini-color);display:flex;align-items:center;justify-content:center;box-shadow:0 2px 10px var(--fab-mini-shadow);cursor:pointer;transition:background .2s ease,border-color .2s ease,color .2s ease,transform .2s cubic-bezier(.34,1.56,.64,1),box-shadow .2s ease}.fab-mini:hover{transform:scale(1.12);border-color:var(--fab-mini-hover-border);color:var(--fab-mini-hover-color)}.fab-mini.active{background:var(--fab-active-bg);border-color:var(--fab-active-bg);color:#fff;box-shadow:0 3px 12px var(--fab-active-shadow);transform:scale(1.08)}.fab-tooltip{position:absolute;right:calc(100% + 10px);top:50%;transform:translateY(-50%);font-size:.7rem;font-weight:600;background:var(--fab-tooltip-bg);backdrop-filter:blur(4px);color:var(--fab-tooltip-color);padding:3px 8px;border-radius:6px;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease}.fab-menu{display:flex;flex-direction:column;align-items:center;gap:.55rem}.fab-mini-wrap{position:relative;display:flex;align-items:center;animation:fabMiniIn .22s cubic-bezier(.34,1.56,.64,1) both}.fab-mini-wrap:nth-child(1){animation-delay:0ms}.fab-mini-wrap:nth-child(2){animation-delay:55ms}.fab-mini-wrap:nth-child(3){animation-delay:.11s}.fab-mini-wrap:hover .fab-tooltip{opacity:1}.fab-menu--closing .fab-mini-wrap{animation:fabMiniOut .15s ease-in both;animation-delay:0ms}@keyframes fabMiniIn{0%{opacity:0;transform:translateY(12px) scale(.75)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes fabMiniOut{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:translateY(10px) scale(.8)}}\n"] }]
|
|
1724
|
-
}], ctorParameters: () => [] });
|
|
1723
|
+
args: [{ selector: 'app-dashboard-view-switcher', imports: [], template: "<div class=\"view-fab\" [style.--fab-main-from]=\"accentColor()\" [style.--fab-main-to]=\"accentColor()\"\r\n [style.--fab-active-bg]=\"accentColor()\" [style.--fab-mini-hover-border]=\"accentColor()\"\r\n [style.--fab-mini-hover-color]=\"accentColor()\" (mouseenter)=\"fabOpen.set(true)\" (mouseleave)=\"fabOpen.set(false)\">\r\n @if (fabRendered()) {\r\n <div class=\"fab-menu\" [class.fab-menu--closing]=\"!fabOpen()\">\r\n\r\n <div class=\"fab-mini-wrap\">\r\n <span class=\"fab-tooltip\">Dona</span>\r\n <button class=\"fab-mini\" [class.active]=\"viewMode() === 'donut'\" (click)=\"setView('donut')\"\r\n title=\"Vista de dona\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\"></circle>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"fab-mini-wrap\">\r\n <span class=\"fab-tooltip\">Barras</span>\r\n <button class=\"fab-mini\" [class.active]=\"viewMode() === 'bars'\" (click)=\"setView('bars')\"\r\n title=\"Vista de barras\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <rect x=\"2\" y=\"13\" width=\"5\" height=\"9\" rx=\"1\"></rect>\r\n <rect x=\"9\" y=\"7\" width=\"5\" height=\"15\" rx=\"1\"></rect>\r\n <rect x=\"16\" y=\"3\" width=\"5\" height=\"19\" rx=\"1\"></rect>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"fab-mini-wrap\">\r\n <span class=\"fab-tooltip\">Tarjetas</span>\r\n <button class=\"fab-mini\" [class.active]=\"viewMode() === 'cards'\" (click)=\"setView('cards')\"\r\n title=\"Vista de tarjetas\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n </div>\r\n }\r\n\r\n <button class=\"fab-main\" [class.is-open]=\"fabOpen()\" (click)=\"fabOpen.set(!fabOpen())\" title=\"Cambiar vista\">\r\n @switch (viewMode()) {\r\n @case ('cards') {\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"></rect>\r\n </svg>\r\n }\r\n @case ('bars') {\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <rect x=\"2\" y=\"13\" width=\"5\" height=\"9\" rx=\"1\"></rect>\r\n <rect x=\"9\" y=\"7\" width=\"5\" height=\"15\" rx=\"1\"></rect>\r\n <rect x=\"16\" y=\"3\" width=\"5\" height=\"19\" rx=\"1\"></rect>\r\n </svg>\r\n }\r\n @case ('donut') {\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\"></circle>\r\n </svg>\r\n }\r\n }\r\n </button>\r\n</div>\r\n", styles: [":host{--fab-mini-bg: #ffffff;--fab-mini-border: #e2e8f0;--fab-mini-color: #64748b;--fab-mini-shadow: rgba(0, 0, 0, .12);--fab-mini-hover-border: #4678e5;--fab-mini-hover-color: #4678e5;--fab-tooltip-bg: rgba(15, 23, 42, .82);--fab-tooltip-color: #ffffff;--fab-main-from: #002fff;--fab-main-to: #3a88ed;--fab-main-shadow: rgba(70, 134, 229, .55);--fab-main-hover-shadow: rgba(70, 139, 229, .7);--fab-active-bg: #0957ff;--fab-active-shadow: rgba(70, 152, 229, .45)}:host-context([data-bs-theme=dark]),:host-context(.dark-mode),:host-context(.theme-dark){--fab-mini-bg: #1e293b;--fab-mini-border: #334155;--fab-mini-color: #94a3b8;--fab-mini-shadow: rgba(0, 0, 0, .35);--fab-mini-hover-border: #60a5fa;--fab-mini-hover-color: #60a5fa;--fab-tooltip-bg: rgba(248, 250, 252, .92);--fab-tooltip-color: #0f172a}.view-fab{position:fixed;bottom:24px;right:24px;z-index:999;display:flex;flex-direction:column-reverse;align-items:center;gap:.55rem}.fab-main{width:54px;height:54px;border-radius:50%;border:none;background:linear-gradient(135deg,var(--fab-main-from) 0%,var(--fab-main-to) 100%);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 18px var(--fab-main-shadow);cursor:pointer;transition:transform .25s cubic-bezier(.34,1.56,.64,1),box-shadow .25s ease}.fab-main svg{transition:transform .35s ease}.fab-main:hover{transform:scale(1.1);box-shadow:0 6px 24px var(--fab-main-hover-shadow)}.fab-main.is-open{box-shadow:0 6px 24px var(--fab-main-hover-shadow)}.fab-mini{width:44px;height:44px;border-radius:50%;border:2px solid var(--fab-mini-border);background:var(--fab-mini-bg);color:var(--fab-mini-color);display:flex;align-items:center;justify-content:center;box-shadow:0 2px 10px var(--fab-mini-shadow);cursor:pointer;transition:background .2s ease,border-color .2s ease,color .2s ease,transform .2s cubic-bezier(.34,1.56,.64,1),box-shadow .2s ease}.fab-mini:hover{transform:scale(1.12);border-color:var(--fab-mini-hover-border);color:var(--fab-mini-hover-color)}.fab-mini.active{background:var(--fab-active-bg);border-color:var(--fab-active-bg);color:#fff;box-shadow:0 3px 12px var(--fab-active-shadow);transform:scale(1.08)}.fab-tooltip{position:absolute;right:calc(100% + 10px);top:50%;transform:translateY(-50%);font-size:.7rem;font-weight:600;background:var(--fab-tooltip-bg);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);color:var(--fab-tooltip-color);padding:3px 8px;border-radius:6px;white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease}.fab-menu{display:flex;flex-direction:column;align-items:center;gap:.55rem}.fab-mini-wrap{position:relative;display:flex;align-items:center;animation:fabMiniIn .22s cubic-bezier(.34,1.56,.64,1) both}.fab-mini-wrap:nth-child(1){animation-delay:0ms}.fab-mini-wrap:nth-child(2){animation-delay:55ms}.fab-mini-wrap:nth-child(3){animation-delay:.11s}.fab-mini-wrap:hover .fab-tooltip{opacity:1}.fab-menu--closing .fab-mini-wrap{animation:fabMiniOut .15s ease-in both;animation-delay:0ms}@keyframes fabMiniIn{0%{opacity:0;transform:translateY(12px) scale(.75)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes fabMiniOut{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:translateY(10px) scale(.8)}}\n"] }]
|
|
1724
|
+
}], ctorParameters: () => [], propDecorators: { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], accentColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "accentColor", required: false }] }], viewModeChange: [{ type: i0.Output, args: ["viewModeChange"] }] } });
|
|
1725
1725
|
|
|
1726
1726
|
/*
|
|
1727
1727
|
* Public API Surface of layout-tsi
|