@telcomdev/ui 0.1.37 → 0.1.38
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/fesm2022/telcomdev-ui.mjs +187 -172
- package/fesm2022/telcomdev-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/telcomdev-ui.d.ts +5 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { ChangeDetectionStrategy, Component, Injectable, inject, HostBinding, Input, booleanAttribute, EventEmitter, Output, ViewChild, Injector, ChangeDetectorRef, signal, input, model, output, computed, forwardRef, InjectionToken, ElementRef, HostListener, Directive, EnvironmentInjector,
|
|
2
|
+
import { ChangeDetectionStrategy, Component, Injectable, inject, HostBinding, Input, booleanAttribute, EventEmitter, Output, ViewChild, Injector, ChangeDetectorRef, signal, input, model, output, computed, forwardRef, InjectionToken, ElementRef, HostListener, Directive, EnvironmentInjector, DestroyRef, ContentChild, effect, TemplateRef, ViewChildren, ContentChildren, ViewContainerRef, Renderer2, numberAttribute } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
|
|
5
5
|
import { FORM_FIELD } from '@angular/forms/signals';
|
|
@@ -5958,6 +5958,176 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
5958
5958
|
type: Input
|
|
5959
5959
|
}], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
|
|
5960
5960
|
|
|
5961
|
+
class TdSidebar {
|
|
5962
|
+
router = inject(Router);
|
|
5963
|
+
destroyRef = inject(DestroyRef);
|
|
5964
|
+
titulo = 'Gestión Corporativa';
|
|
5965
|
+
subtitulo = 'Central Platform';
|
|
5966
|
+
etiquetaNavegacion = 'Navegación';
|
|
5967
|
+
logoUrl = '';
|
|
5968
|
+
logoAlt = 'Logo';
|
|
5969
|
+
textoCarga = 'Cargando menú...';
|
|
5970
|
+
mensajeVacio = 'No hay opciones disponibles.';
|
|
5971
|
+
error = '';
|
|
5972
|
+
cargando = false;
|
|
5973
|
+
oscuro = false;
|
|
5974
|
+
modoCerrado = 'compacto';
|
|
5975
|
+
set abierto(value) {
|
|
5976
|
+
this.abiertoInterno.set(value);
|
|
5977
|
+
}
|
|
5978
|
+
get abierto() {
|
|
5979
|
+
return this.abiertoInterno();
|
|
5980
|
+
}
|
|
5981
|
+
set menu(value) {
|
|
5982
|
+
this.menuNormalizado.set(this.normalizarMenu(value ?? []));
|
|
5983
|
+
this.expandirRutaActual();
|
|
5984
|
+
}
|
|
5985
|
+
get menu() {
|
|
5986
|
+
return this.menuNormalizado();
|
|
5987
|
+
}
|
|
5988
|
+
abiertoChange = new EventEmitter();
|
|
5989
|
+
seleccionar = new EventEmitter();
|
|
5990
|
+
abiertoInterno = signal(true, /* @ts-ignore */
|
|
5991
|
+
...(ngDevMode ? [{ debugName: "abiertoInterno" }] : /* istanbul ignore next */ []));
|
|
5992
|
+
menuNormalizado = signal([], /* @ts-ignore */
|
|
5993
|
+
...(ngDevMode ? [{ debugName: "menuNormalizado" }] : /* istanbul ignore next */ []));
|
|
5994
|
+
expandidos = signal(new Set(), /* @ts-ignore */
|
|
5995
|
+
...(ngDevMode ? [{ debugName: "expandidos" }] : /* istanbul ignore next */ []));
|
|
5996
|
+
rutaSeleccionada = signal('', /* @ts-ignore */
|
|
5997
|
+
...(ngDevMode ? [{ debugName: "rutaSeleccionada" }] : /* istanbul ignore next */ []));
|
|
5998
|
+
constructor() {
|
|
5999
|
+
this.router.events
|
|
6000
|
+
.pipe(filter((event) => event instanceof NavigationEnd), takeUntilDestroyed(this.destroyRef))
|
|
6001
|
+
.subscribe(() => this.expandirRutaActual());
|
|
6002
|
+
}
|
|
6003
|
+
alternarGrupo(clave) {
|
|
6004
|
+
if (!this.abiertoInterno()) {
|
|
6005
|
+
this.abiertoInterno.set(true);
|
|
6006
|
+
this.abiertoChange.emit(true);
|
|
6007
|
+
}
|
|
6008
|
+
this.expandidos.update((actuales) => {
|
|
6009
|
+
const siguientes = new Set(actuales);
|
|
6010
|
+
siguientes.has(clave) ? siguientes.delete(clave) : siguientes.add(clave);
|
|
6011
|
+
return siguientes;
|
|
6012
|
+
});
|
|
6013
|
+
}
|
|
6014
|
+
estaExpandido(clave) {
|
|
6015
|
+
return this.expandidos().has(clave);
|
|
6016
|
+
}
|
|
6017
|
+
seleccionarItem(item, nivel) {
|
|
6018
|
+
this.seleccionar.emit({ item, nivel });
|
|
6019
|
+
}
|
|
6020
|
+
esItemSeleccionado(item) {
|
|
6021
|
+
const ruta = this.normalizarRuta(item.ruta);
|
|
6022
|
+
return !!ruta && ruta === this.rutaSeleccionada();
|
|
6023
|
+
}
|
|
6024
|
+
claveItem(item, padre, indice) {
|
|
6025
|
+
return `${padre}/${item.nombre}-${indice}`;
|
|
6026
|
+
}
|
|
6027
|
+
inicialMarca() {
|
|
6028
|
+
return (this.titulo.trim().charAt(0) || 'T').toUpperCase();
|
|
6029
|
+
}
|
|
6030
|
+
normalizarMenu(items) {
|
|
6031
|
+
return [...items]
|
|
6032
|
+
.sort((a, b) => a.orden - b.orden)
|
|
6033
|
+
.map((item) => ({
|
|
6034
|
+
...item,
|
|
6035
|
+
icono: item.icono?.trim() || 'folder',
|
|
6036
|
+
subMenus: this.normalizarMenu(item.subMenus ?? []),
|
|
6037
|
+
}));
|
|
6038
|
+
}
|
|
6039
|
+
expandirRutaActual() {
|
|
6040
|
+
const rutaActual = this.normalizarRuta(this.router.url);
|
|
6041
|
+
const coincidencia = this.buscarMejorCoincidenciaPorRuta(this.menuNormalizado(), rutaActual);
|
|
6042
|
+
this.rutaSeleccionada.set(coincidencia?.ruta ?? '');
|
|
6043
|
+
const clavesPadre = coincidencia?.ancestros ?? [];
|
|
6044
|
+
if (!clavesPadre.length)
|
|
6045
|
+
return;
|
|
6046
|
+
this.expandidos.update((actuales) => {
|
|
6047
|
+
const siguientes = new Set(actuales);
|
|
6048
|
+
clavesPadre.forEach((clave) => siguientes.add(clave));
|
|
6049
|
+
return siguientes;
|
|
6050
|
+
});
|
|
6051
|
+
}
|
|
6052
|
+
buscarMejorCoincidenciaPorRuta(items, rutaActual, padre = 'raiz', ancestros = []) {
|
|
6053
|
+
let mejor = null;
|
|
6054
|
+
for (let indice = 0; indice < items.length; indice += 1) {
|
|
6055
|
+
const item = items[indice];
|
|
6056
|
+
const clave = this.claveItem(item, padre, indice);
|
|
6057
|
+
const ruta = this.normalizarRuta(item.ruta);
|
|
6058
|
+
if (this.rutaCoincide(ruta, rutaActual)) {
|
|
6059
|
+
mejor = this.mejorCoincidencia(mejor, {
|
|
6060
|
+
ruta,
|
|
6061
|
+
ancestros,
|
|
6062
|
+
peso: ruta === rutaActual ? Number.MAX_SAFE_INTEGER : ruta.length,
|
|
6063
|
+
});
|
|
6064
|
+
}
|
|
6065
|
+
const resultado = this.buscarMejorCoincidenciaPorRuta(item.subMenus ?? [], rutaActual, clave, [...ancestros, clave]);
|
|
6066
|
+
mejor = this.mejorCoincidencia(mejor, resultado);
|
|
6067
|
+
}
|
|
6068
|
+
return mejor;
|
|
6069
|
+
}
|
|
6070
|
+
mejorCoincidencia(actual, candidata) {
|
|
6071
|
+
if (!candidata)
|
|
6072
|
+
return actual;
|
|
6073
|
+
if (!actual)
|
|
6074
|
+
return candidata;
|
|
6075
|
+
return candidata.peso > actual.peso ? candidata : actual;
|
|
6076
|
+
}
|
|
6077
|
+
rutaCoincide(rutaMenu, rutaActual) {
|
|
6078
|
+
if (!rutaMenu)
|
|
6079
|
+
return false;
|
|
6080
|
+
if (rutaMenu === '/')
|
|
6081
|
+
return rutaActual === '/';
|
|
6082
|
+
return rutaActual === rutaMenu || rutaActual.startsWith(`${rutaMenu}/`);
|
|
6083
|
+
}
|
|
6084
|
+
normalizarRuta(ruta) {
|
|
6085
|
+
if (!ruta)
|
|
6086
|
+
return '';
|
|
6087
|
+
const limpia = ruta.split('?')[0].split('#')[0].trim();
|
|
6088
|
+
if (!limpia || limpia === '/')
|
|
6089
|
+
return '/';
|
|
6090
|
+
const conSlashInicial = limpia.startsWith('/') ? limpia : `/${limpia}`;
|
|
6091
|
+
return conSlashInicial.endsWith('/') ? conSlashInicial.slice(0, -1) : conSlashInicial;
|
|
6092
|
+
}
|
|
6093
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: TdSidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6094
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: TdSidebar, isStandalone: true, selector: "td-sidebar", inputs: { titulo: "titulo", subtitulo: "subtitulo", etiquetaNavegacion: "etiquetaNavegacion", logoUrl: "logoUrl", logoAlt: "logoAlt", textoCarga: "textoCarga", mensajeVacio: "mensajeVacio", error: "error", cargando: "cargando", oscuro: "oscuro", modoCerrado: "modoCerrado", abierto: "abierto", menu: "menu" }, outputs: { abiertoChange: "abiertoChange", seleccionar: "seleccionar" }, ngImport: i0, template: "<aside\n class=\"td-sidebar\"\n [class.td-sidebar--compacto]=\"!abiertoInterno() && modoCerrado === 'compacto'\"\n [class.td-sidebar--oculto]=\"!abiertoInterno() && modoCerrado === 'oculto'\"\n [class.td-sidebar--oscuro]=\"oscuro\"\n [attr.aria-hidden]=\"!abiertoInterno() && modoCerrado === 'oculto'\"\n>\n <header class=\"td-sidebar__marca\">\n <div class=\"td-sidebar__logo\">\n @if (logoUrl) {\n <img [src]=\"logoUrl\" [alt]=\"logoAlt\" />\n } @else {\n <span>{{ inicialMarca() }}</span>\n }\n </div>\n\n @if (abiertoInterno()) {\n <div class=\"td-sidebar__marca-texto\">\n <small>{{ subtitulo }}</small>\n <strong>{{ titulo }}</strong>\n </div>\n }\n\n </header>\n\n <div class=\"td-sidebar__encabezado\">\n @if (abiertoInterno()) {\n <span>{{ etiquetaNavegacion }}</span>\n } @else {\n <span aria-hidden=\"true\">\u2022\u2022\u2022</span>\n }\n </div>\n\n <nav class=\"td-sidebar__nav\" aria-label=\"Men\u00FA principal\">\n @if (cargando) {\n <p class=\"td-sidebar__estado\">{{ textoCarga }}</p>\n } @else if (error) {\n <p class=\"td-sidebar__estado td-sidebar__estado--error\">{{ error }}</p>\n } @else if (!menuNormalizado().length) {\n <p class=\"td-sidebar__estado\">{{ mensajeVacio }}</p>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"listaMenu\"\n [ngTemplateOutletContext]=\"{ items: menuNormalizado(), nivel: 0, padre: 'raiz' }\"\n />\n }\n </nav>\n</aside>\n\n<ng-template #listaMenu let-items=\"items\" let-nivel=\"nivel\" let-padre=\"padre\">\n <ul class=\"td-sidebar__lista\" [class.td-sidebar__lista--anidada]=\"nivel > 0\">\n @for (item of items; track item) {\n @let clave = claveItem(item, padre, $index);\n @let tieneHijos = item.subMenus.length > 0;\n\n <li class=\"td-sidebar__item\">\n @if (tieneHijos) {\n <button\n class=\"td-sidebar__enlace\"\n type=\"button\"\n [class.td-sidebar__enlace--ruta-activa]=\"esItemSeleccionado(item)\"\n [attr.aria-expanded]=\"estaExpandido(clave)\"\n [attr.title]=\"!abiertoInterno() ? item.nombre : null\"\n (click)=\"alternarGrupo(clave)\"\n >\n <td-icon class=\"td-sidebar__icono\" [nombre]=\"item.icono || 'folder'\" />\n @if (abiertoInterno()) {\n <span>{{ item.nombre }}</span>\n <td-icon\n class=\"td-sidebar__flecha\"\n [class.td-sidebar__flecha--abierta]=\"estaExpandido(clave)\"\n nombre=\"chevron_right\"\n />\n }\n </button>\n } @else {\n <a\n class=\"td-sidebar__enlace\"\n [routerLink]=\"item.ruta || '/'\"\n [class.td-sidebar__enlace--ruta-activa]=\"esItemSeleccionado(item)\"\n [attr.title]=\"!abiertoInterno() ? item.nombre : null\"\n (click)=\"seleccionarItem(item, nivel)\"\n >\n <td-icon class=\"td-sidebar__icono\" [nombre]=\"item.icono || 'folder'\" />\n @if (abiertoInterno()) {\n <span>{{ item.nombre }}</span>\n }\n </a>\n }\n\n @if (abiertoInterno() && tieneHijos && estaExpandido(clave)) {\n <ng-container\n [ngTemplateOutlet]=\"listaMenu\"\n [ngTemplateOutletContext]=\"{\n items: item.subMenus,\n nivel: nivel + 1,\n padre: clave\n }\"\n />\n }\n </li>\n }\n </ul>\n</ng-template>\n", styles: [":host{display:block;height:100%}*{box-sizing:border-box}.td-sidebar{--td-fondo: var(--td-color-surface, #fff);--td-borde: var(--td-color-border, #e2e8f0);--td-texto: var(--td-color-text, #334155);--td-texto-suave: var(--td-color-text-muted, #64748b);--td-hover: var(--td-color-surface-soft, #f1f5f9);--td-activo: var(--td-color-primary-soft, #e8efff);--td-acento: var(--td-color-primary, #2563eb);display:flex;width:18rem;height:100%;min-height:28rem;flex-direction:column;overflow:hidden;border-right:1px solid var(--td-borde);color:var(--td-texto);background:var(--td-fondo);font-family:var(--td-font-family, Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif);transition:width .2s ease,background .2s ease,border-color .2s ease}.td-sidebar--oscuro{--td-fondo: var(--td-color-surface, #09090b);--td-borde: var(--td-color-border, #27272a);--td-texto: var(--td-color-text, #d4d4d8);--td-texto-suave: var(--td-color-text-muted, #71717a);--td-hover: var(--td-color-surface-soft, #18181b);--td-activo: var(--td-color-primary-soft, #172554);--td-acento: var(--td-color-primary, #60a5fa)}.td-sidebar--compacto{width:5rem}.td-sidebar--oculto{width:0;min-width:0;border-right-width:0;visibility:hidden}.td-sidebar__marca{display:flex;min-height:5rem;align-items:center;gap:.75rem;border-bottom:1px solid var(--td-borde);padding:1rem}.td-sidebar__logo{display:grid;width:2.75rem;height:2.75rem;flex:0 0 2.75rem;place-items:center;overflow:hidden;border:1px solid var(--td-borde);border-radius:var(--td-radius-md, .75rem);color:var(--td-color-on-primary, #fff);background:linear-gradient(135deg,var(--td-color-primary, #2563eb),var(--td-color-info, #3157a4));font-size:1.15rem;font-weight:800}.td-sidebar__logo img{width:75%;height:75%;object-fit:contain}.td-sidebar__marca-texto{min-width:0;flex:1}.td-sidebar__marca-texto small,.td-sidebar__marca-texto strong{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.td-sidebar__marca-texto small{color:var(--td-acento);font-size:.64rem;font-weight:750;letter-spacing:.12em;text-transform:uppercase}.td-sidebar__marca-texto strong{margin-top:.18rem;font-size:.84rem}.td-sidebar__encabezado{min-height:3.35rem;padding:1.25rem 1rem .65rem;color:var(--td-texto-suave);font-size:.66rem;font-weight:750;letter-spacing:.12em;text-transform:uppercase}.td-sidebar--compacto .td-sidebar__encabezado{text-align:center}.td-sidebar__nav{min-height:0;flex:1;overflow-x:hidden;overflow-y:auto;padding:0 .7rem 1rem;scrollbar-width:thin;scrollbar-color:var(--td-borde) transparent}.td-sidebar__lista{margin:0;padding:0;list-style:none}.td-sidebar__lista--anidada{position:relative;margin:.2rem 0 .35rem 1.25rem;padding-left:.7rem}.td-sidebar__lista--anidada:before{position:absolute;inset:0 auto 0 0;width:1px;background:var(--td-borde);content:\"\"}.td-sidebar__item+.td-sidebar__item{margin-top:.2rem}.td-sidebar__enlace{display:flex;width:100%;min-width:0;min-height:2.5rem;align-items:center;gap:.7rem;border:0;border-radius:var(--td-radius-sm, .55rem);padding:.55rem .7rem;color:var(--td-texto);background:transparent;font:inherit;font-size:.82rem;font-weight:600;text-align:left;text-decoration:none;cursor:pointer;transition:color .12s ease,background .12s ease}.td-sidebar__enlace:hover{background:var(--td-hover)}.td-sidebar__enlace--activo,.td-sidebar__enlace--ruta-activa{color:var(--td-acento);background:var(--td-activo)}.td-sidebar__enlace span{overflow:hidden;flex:1;text-overflow:ellipsis;white-space:nowrap}.td-sidebar__icono{width:1.15rem;height:1.15rem;flex:0 0 1.15rem}.td-sidebar__flecha{width:.9rem;height:.9rem;flex:0 0 .9rem;transition:transform .16s ease}.td-sidebar__flecha--abierta{transform:rotate(90deg)}.td-sidebar--compacto .td-sidebar__marca{justify-content:center;padding-inline:.7rem}.td-sidebar--compacto .td-sidebar__nav{padding-inline:.65rem}.td-sidebar--compacto .td-sidebar__enlace{justify-content:center;padding-inline:0}.td-sidebar__lista--anidada .td-sidebar__enlace{min-height:2.2rem;font-size:.75rem;font-weight:500}.td-sidebar__lista--anidada .td-sidebar__lista--anidada .td-sidebar__enlace{min-height:2rem;color:var(--td-texto-suave);font-size:.7rem}.td-sidebar__estado{margin:0;padding:.75rem;color:var(--td-texto-suave);font-size:.75rem;line-height:1.45}.td-sidebar__estado--error{color:var(--td-color-warning, #d97706)}@media(prefers-reduced-motion:reduce){.td-sidebar,.td-sidebar__flecha{transition:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "component", type: TdIcon, selector: "td-icon", inputs: ["nombre", "titulo", "tamano"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6095
|
+
}
|
|
6096
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: TdSidebar, decorators: [{
|
|
6097
|
+
type: Component,
|
|
6098
|
+
args: [{ selector: 'td-sidebar', imports: [NgTemplateOutlet, RouterLink, TdIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<aside\n class=\"td-sidebar\"\n [class.td-sidebar--compacto]=\"!abiertoInterno() && modoCerrado === 'compacto'\"\n [class.td-sidebar--oculto]=\"!abiertoInterno() && modoCerrado === 'oculto'\"\n [class.td-sidebar--oscuro]=\"oscuro\"\n [attr.aria-hidden]=\"!abiertoInterno() && modoCerrado === 'oculto'\"\n>\n <header class=\"td-sidebar__marca\">\n <div class=\"td-sidebar__logo\">\n @if (logoUrl) {\n <img [src]=\"logoUrl\" [alt]=\"logoAlt\" />\n } @else {\n <span>{{ inicialMarca() }}</span>\n }\n </div>\n\n @if (abiertoInterno()) {\n <div class=\"td-sidebar__marca-texto\">\n <small>{{ subtitulo }}</small>\n <strong>{{ titulo }}</strong>\n </div>\n }\n\n </header>\n\n <div class=\"td-sidebar__encabezado\">\n @if (abiertoInterno()) {\n <span>{{ etiquetaNavegacion }}</span>\n } @else {\n <span aria-hidden=\"true\">\u2022\u2022\u2022</span>\n }\n </div>\n\n <nav class=\"td-sidebar__nav\" aria-label=\"Men\u00FA principal\">\n @if (cargando) {\n <p class=\"td-sidebar__estado\">{{ textoCarga }}</p>\n } @else if (error) {\n <p class=\"td-sidebar__estado td-sidebar__estado--error\">{{ error }}</p>\n } @else if (!menuNormalizado().length) {\n <p class=\"td-sidebar__estado\">{{ mensajeVacio }}</p>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"listaMenu\"\n [ngTemplateOutletContext]=\"{ items: menuNormalizado(), nivel: 0, padre: 'raiz' }\"\n />\n }\n </nav>\n</aside>\n\n<ng-template #listaMenu let-items=\"items\" let-nivel=\"nivel\" let-padre=\"padre\">\n <ul class=\"td-sidebar__lista\" [class.td-sidebar__lista--anidada]=\"nivel > 0\">\n @for (item of items; track item) {\n @let clave = claveItem(item, padre, $index);\n @let tieneHijos = item.subMenus.length > 0;\n\n <li class=\"td-sidebar__item\">\n @if (tieneHijos) {\n <button\n class=\"td-sidebar__enlace\"\n type=\"button\"\n [class.td-sidebar__enlace--ruta-activa]=\"esItemSeleccionado(item)\"\n [attr.aria-expanded]=\"estaExpandido(clave)\"\n [attr.title]=\"!abiertoInterno() ? item.nombre : null\"\n (click)=\"alternarGrupo(clave)\"\n >\n <td-icon class=\"td-sidebar__icono\" [nombre]=\"item.icono || 'folder'\" />\n @if (abiertoInterno()) {\n <span>{{ item.nombre }}</span>\n <td-icon\n class=\"td-sidebar__flecha\"\n [class.td-sidebar__flecha--abierta]=\"estaExpandido(clave)\"\n nombre=\"chevron_right\"\n />\n }\n </button>\n } @else {\n <a\n class=\"td-sidebar__enlace\"\n [routerLink]=\"item.ruta || '/'\"\n [class.td-sidebar__enlace--ruta-activa]=\"esItemSeleccionado(item)\"\n [attr.title]=\"!abiertoInterno() ? item.nombre : null\"\n (click)=\"seleccionarItem(item, nivel)\"\n >\n <td-icon class=\"td-sidebar__icono\" [nombre]=\"item.icono || 'folder'\" />\n @if (abiertoInterno()) {\n <span>{{ item.nombre }}</span>\n }\n </a>\n }\n\n @if (abiertoInterno() && tieneHijos && estaExpandido(clave)) {\n <ng-container\n [ngTemplateOutlet]=\"listaMenu\"\n [ngTemplateOutletContext]=\"{\n items: item.subMenus,\n nivel: nivel + 1,\n padre: clave\n }\"\n />\n }\n </li>\n }\n </ul>\n</ng-template>\n", styles: [":host{display:block;height:100%}*{box-sizing:border-box}.td-sidebar{--td-fondo: var(--td-color-surface, #fff);--td-borde: var(--td-color-border, #e2e8f0);--td-texto: var(--td-color-text, #334155);--td-texto-suave: var(--td-color-text-muted, #64748b);--td-hover: var(--td-color-surface-soft, #f1f5f9);--td-activo: var(--td-color-primary-soft, #e8efff);--td-acento: var(--td-color-primary, #2563eb);display:flex;width:18rem;height:100%;min-height:28rem;flex-direction:column;overflow:hidden;border-right:1px solid var(--td-borde);color:var(--td-texto);background:var(--td-fondo);font-family:var(--td-font-family, Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif);transition:width .2s ease,background .2s ease,border-color .2s ease}.td-sidebar--oscuro{--td-fondo: var(--td-color-surface, #09090b);--td-borde: var(--td-color-border, #27272a);--td-texto: var(--td-color-text, #d4d4d8);--td-texto-suave: var(--td-color-text-muted, #71717a);--td-hover: var(--td-color-surface-soft, #18181b);--td-activo: var(--td-color-primary-soft, #172554);--td-acento: var(--td-color-primary, #60a5fa)}.td-sidebar--compacto{width:5rem}.td-sidebar--oculto{width:0;min-width:0;border-right-width:0;visibility:hidden}.td-sidebar__marca{display:flex;min-height:5rem;align-items:center;gap:.75rem;border-bottom:1px solid var(--td-borde);padding:1rem}.td-sidebar__logo{display:grid;width:2.75rem;height:2.75rem;flex:0 0 2.75rem;place-items:center;overflow:hidden;border:1px solid var(--td-borde);border-radius:var(--td-radius-md, .75rem);color:var(--td-color-on-primary, #fff);background:linear-gradient(135deg,var(--td-color-primary, #2563eb),var(--td-color-info, #3157a4));font-size:1.15rem;font-weight:800}.td-sidebar__logo img{width:75%;height:75%;object-fit:contain}.td-sidebar__marca-texto{min-width:0;flex:1}.td-sidebar__marca-texto small,.td-sidebar__marca-texto strong{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.td-sidebar__marca-texto small{color:var(--td-acento);font-size:.64rem;font-weight:750;letter-spacing:.12em;text-transform:uppercase}.td-sidebar__marca-texto strong{margin-top:.18rem;font-size:.84rem}.td-sidebar__encabezado{min-height:3.35rem;padding:1.25rem 1rem .65rem;color:var(--td-texto-suave);font-size:.66rem;font-weight:750;letter-spacing:.12em;text-transform:uppercase}.td-sidebar--compacto .td-sidebar__encabezado{text-align:center}.td-sidebar__nav{min-height:0;flex:1;overflow-x:hidden;overflow-y:auto;padding:0 .7rem 1rem;scrollbar-width:thin;scrollbar-color:var(--td-borde) transparent}.td-sidebar__lista{margin:0;padding:0;list-style:none}.td-sidebar__lista--anidada{position:relative;margin:.2rem 0 .35rem 1.25rem;padding-left:.7rem}.td-sidebar__lista--anidada:before{position:absolute;inset:0 auto 0 0;width:1px;background:var(--td-borde);content:\"\"}.td-sidebar__item+.td-sidebar__item{margin-top:.2rem}.td-sidebar__enlace{display:flex;width:100%;min-width:0;min-height:2.5rem;align-items:center;gap:.7rem;border:0;border-radius:var(--td-radius-sm, .55rem);padding:.55rem .7rem;color:var(--td-texto);background:transparent;font:inherit;font-size:.82rem;font-weight:600;text-align:left;text-decoration:none;cursor:pointer;transition:color .12s ease,background .12s ease}.td-sidebar__enlace:hover{background:var(--td-hover)}.td-sidebar__enlace--activo,.td-sidebar__enlace--ruta-activa{color:var(--td-acento);background:var(--td-activo)}.td-sidebar__enlace span{overflow:hidden;flex:1;text-overflow:ellipsis;white-space:nowrap}.td-sidebar__icono{width:1.15rem;height:1.15rem;flex:0 0 1.15rem}.td-sidebar__flecha{width:.9rem;height:.9rem;flex:0 0 .9rem;transition:transform .16s ease}.td-sidebar__flecha--abierta{transform:rotate(90deg)}.td-sidebar--compacto .td-sidebar__marca{justify-content:center;padding-inline:.7rem}.td-sidebar--compacto .td-sidebar__nav{padding-inline:.65rem}.td-sidebar--compacto .td-sidebar__enlace{justify-content:center;padding-inline:0}.td-sidebar__lista--anidada .td-sidebar__enlace{min-height:2.2rem;font-size:.75rem;font-weight:500}.td-sidebar__lista--anidada .td-sidebar__lista--anidada .td-sidebar__enlace{min-height:2rem;color:var(--td-texto-suave);font-size:.7rem}.td-sidebar__estado{margin:0;padding:.75rem;color:var(--td-texto-suave);font-size:.75rem;line-height:1.45}.td-sidebar__estado--error{color:var(--td-color-warning, #d97706)}@media(prefers-reduced-motion:reduce){.td-sidebar,.td-sidebar__flecha{transition:none}}\n"] }]
|
|
6099
|
+
}], ctorParameters: () => [], propDecorators: { titulo: [{
|
|
6100
|
+
type: Input
|
|
6101
|
+
}], subtitulo: [{
|
|
6102
|
+
type: Input
|
|
6103
|
+
}], etiquetaNavegacion: [{
|
|
6104
|
+
type: Input
|
|
6105
|
+
}], logoUrl: [{
|
|
6106
|
+
type: Input
|
|
6107
|
+
}], logoAlt: [{
|
|
6108
|
+
type: Input
|
|
6109
|
+
}], textoCarga: [{
|
|
6110
|
+
type: Input
|
|
6111
|
+
}], mensajeVacio: [{
|
|
6112
|
+
type: Input
|
|
6113
|
+
}], error: [{
|
|
6114
|
+
type: Input
|
|
6115
|
+
}], cargando: [{
|
|
6116
|
+
type: Input
|
|
6117
|
+
}], oscuro: [{
|
|
6118
|
+
type: Input
|
|
6119
|
+
}], modoCerrado: [{
|
|
6120
|
+
type: Input
|
|
6121
|
+
}], abierto: [{
|
|
6122
|
+
type: Input
|
|
6123
|
+
}], menu: [{
|
|
6124
|
+
type: Input
|
|
6125
|
+
}], abiertoChange: [{
|
|
6126
|
+
type: Output
|
|
6127
|
+
}], seleccionar: [{
|
|
6128
|
+
type: Output
|
|
6129
|
+
}] } });
|
|
6130
|
+
|
|
5961
6131
|
class TdLayoutHeaderSlot {
|
|
5962
6132
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: TdLayoutHeaderSlot, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
5963
6133
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.4", type: TdLayoutHeaderSlot, isStandalone: true, selector: "[tdLayoutHeader]", ngImport: i0 });
|
|
@@ -6001,6 +6171,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
6001
6171
|
class TdLayout {
|
|
6002
6172
|
headerSlot;
|
|
6003
6173
|
sidebarSlot;
|
|
6174
|
+
sidebarComponent;
|
|
6004
6175
|
footerSlot;
|
|
6005
6176
|
headerHost;
|
|
6006
6177
|
sidebarHost;
|
|
@@ -6010,8 +6181,10 @@ class TdLayout {
|
|
|
6010
6181
|
mobile = signal(false, /* @ts-ignore */
|
|
6011
6182
|
...(ngDevMode ? [{ debugName: "mobile" }] : /* istanbul ignore next */ []));
|
|
6012
6183
|
resizeObserver;
|
|
6184
|
+
sidebarSelectionSubscription;
|
|
6013
6185
|
fillViewport = true;
|
|
6014
6186
|
closeSidebarOnBackdrop = true;
|
|
6187
|
+
closeSidebarOnNavigation = true;
|
|
6015
6188
|
mobileBreakpoint = 960;
|
|
6016
6189
|
sidebarPlacement = 'auto';
|
|
6017
6190
|
headerSpan = 'content';
|
|
@@ -6035,6 +6208,11 @@ class TdLayout {
|
|
|
6035
6208
|
}
|
|
6036
6209
|
ngAfterContentInit() {
|
|
6037
6210
|
this.syncViewport();
|
|
6211
|
+
this.sidebarSelectionSubscription = this.sidebarComponent?.seleccionar.subscribe(() => {
|
|
6212
|
+
if (this.closeSidebarOnNavigation && this.mobile() && this.sidebarAsOverlay()) {
|
|
6213
|
+
this.closeSidebar();
|
|
6214
|
+
}
|
|
6215
|
+
});
|
|
6038
6216
|
}
|
|
6039
6217
|
ngAfterViewInit() {
|
|
6040
6218
|
this.updateHeaderOffset();
|
|
@@ -6047,6 +6225,7 @@ class TdLayout {
|
|
|
6047
6225
|
}
|
|
6048
6226
|
ngOnDestroy() {
|
|
6049
6227
|
this.resizeObserver?.disconnect();
|
|
6228
|
+
this.sidebarSelectionSubscription?.unsubscribe();
|
|
6050
6229
|
}
|
|
6051
6230
|
syncViewport() {
|
|
6052
6231
|
if (typeof window === 'undefined') {
|
|
@@ -6119,7 +6298,7 @@ class TdLayout {
|
|
|
6119
6298
|
this.sidebarOpenChange.emit(value);
|
|
6120
6299
|
}
|
|
6121
6300
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: TdLayout, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6122
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: TdLayout, isStandalone: true, selector: "td-layout, td-shell", inputs: { fillViewport: ["fillViewport", "fillViewport", booleanAttribute], closeSidebarOnBackdrop: ["closeSidebarOnBackdrop", "closeSidebarOnBackdrop", booleanAttribute], mobileBreakpoint: "mobileBreakpoint", sidebarPlacement: "sidebarPlacement", headerSpan: "headerSpan", footerSpan: "footerSpan", mobileSidebarStyle: "mobileSidebarStyle", sidebarOpen: "sidebarOpen" }, outputs: { sidebarOpenChange: "sidebarOpenChange" }, host: { listeners: { "window:resize": "syncViewport()", "window:scroll": "syncOverlayPosition()", "document:pointerdown": "handlePointerDownOutside($event)" } }, queries: [{ propertyName: "headerSlot", first: true, predicate: TdLayoutHeaderSlot, descendants: true }, { propertyName: "sidebarSlot", first: true, predicate: TdLayoutSidebarSlot, descendants: true }, { propertyName: "footerSlot", first: true, predicate: TdLayoutFooterSlot, descendants: true }], viewQueries: [{ propertyName: "headerHost", first: true, predicate: ["headerHost"], descendants: true, read: ElementRef }, { propertyName: "sidebarHost", first: true, predicate: ["sidebarHost"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
6301
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: TdLayout, isStandalone: true, selector: "td-layout, td-shell", inputs: { fillViewport: ["fillViewport", "fillViewport", booleanAttribute], closeSidebarOnBackdrop: ["closeSidebarOnBackdrop", "closeSidebarOnBackdrop", booleanAttribute], closeSidebarOnNavigation: ["closeSidebarOnNavigation", "closeSidebarOnNavigation", booleanAttribute], mobileBreakpoint: "mobileBreakpoint", sidebarPlacement: "sidebarPlacement", headerSpan: "headerSpan", footerSpan: "footerSpan", mobileSidebarStyle: "mobileSidebarStyle", sidebarOpen: "sidebarOpen" }, outputs: { sidebarOpenChange: "sidebarOpenChange" }, host: { listeners: { "window:resize": "syncViewport()", "window:scroll": "syncOverlayPosition()", "document:pointerdown": "handlePointerDownOutside($event)" } }, queries: [{ propertyName: "headerSlot", first: true, predicate: TdLayoutHeaderSlot, descendants: true }, { propertyName: "sidebarSlot", first: true, predicate: TdLayoutSidebarSlot, descendants: true }, { propertyName: "sidebarComponent", first: true, predicate: TdSidebar, descendants: true }, { propertyName: "footerSlot", first: true, predicate: TdLayoutFooterSlot, descendants: true }], viewQueries: [{ propertyName: "headerHost", first: true, predicate: ["headerHost"], descendants: true, read: ElementRef }, { propertyName: "sidebarHost", first: true, predicate: ["sidebarHost"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
6123
6302
|
<div
|
|
6124
6303
|
class="td-layout"
|
|
6125
6304
|
[class.td-layout--viewport]="fillViewport"
|
|
@@ -6228,6 +6407,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
6228
6407
|
}], sidebarSlot: [{
|
|
6229
6408
|
type: ContentChild,
|
|
6230
6409
|
args: [TdLayoutSidebarSlot]
|
|
6410
|
+
}], sidebarComponent: [{
|
|
6411
|
+
type: ContentChild,
|
|
6412
|
+
args: [TdSidebar]
|
|
6231
6413
|
}], footerSlot: [{
|
|
6232
6414
|
type: ContentChild,
|
|
6233
6415
|
args: [TdLayoutFooterSlot]
|
|
@@ -6243,6 +6425,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
6243
6425
|
}], closeSidebarOnBackdrop: [{
|
|
6244
6426
|
type: Input,
|
|
6245
6427
|
args: [{ transform: booleanAttribute }]
|
|
6428
|
+
}], closeSidebarOnNavigation: [{
|
|
6429
|
+
type: Input,
|
|
6430
|
+
args: [{ transform: booleanAttribute }]
|
|
6246
6431
|
}], mobileBreakpoint: [{
|
|
6247
6432
|
type: Input
|
|
6248
6433
|
}], sidebarPlacement: [{
|
|
@@ -7845,176 +8030,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
7845
8030
|
type: Output
|
|
7846
8031
|
}], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
|
|
7847
8032
|
|
|
7848
|
-
class TdSidebar {
|
|
7849
|
-
router = inject(Router);
|
|
7850
|
-
destroyRef = inject(DestroyRef);
|
|
7851
|
-
titulo = 'Gestión Corporativa';
|
|
7852
|
-
subtitulo = 'Central Platform';
|
|
7853
|
-
etiquetaNavegacion = 'Navegación';
|
|
7854
|
-
logoUrl = '';
|
|
7855
|
-
logoAlt = 'Logo';
|
|
7856
|
-
textoCarga = 'Cargando menú...';
|
|
7857
|
-
mensajeVacio = 'No hay opciones disponibles.';
|
|
7858
|
-
error = '';
|
|
7859
|
-
cargando = false;
|
|
7860
|
-
oscuro = false;
|
|
7861
|
-
modoCerrado = 'compacto';
|
|
7862
|
-
set abierto(value) {
|
|
7863
|
-
this.abiertoInterno.set(value);
|
|
7864
|
-
}
|
|
7865
|
-
get abierto() {
|
|
7866
|
-
return this.abiertoInterno();
|
|
7867
|
-
}
|
|
7868
|
-
set menu(value) {
|
|
7869
|
-
this.menuNormalizado.set(this.normalizarMenu(value ?? []));
|
|
7870
|
-
this.expandirRutaActual();
|
|
7871
|
-
}
|
|
7872
|
-
get menu() {
|
|
7873
|
-
return this.menuNormalizado();
|
|
7874
|
-
}
|
|
7875
|
-
abiertoChange = new EventEmitter();
|
|
7876
|
-
seleccionar = new EventEmitter();
|
|
7877
|
-
abiertoInterno = signal(true, /* @ts-ignore */
|
|
7878
|
-
...(ngDevMode ? [{ debugName: "abiertoInterno" }] : /* istanbul ignore next */ []));
|
|
7879
|
-
menuNormalizado = signal([], /* @ts-ignore */
|
|
7880
|
-
...(ngDevMode ? [{ debugName: "menuNormalizado" }] : /* istanbul ignore next */ []));
|
|
7881
|
-
expandidos = signal(new Set(), /* @ts-ignore */
|
|
7882
|
-
...(ngDevMode ? [{ debugName: "expandidos" }] : /* istanbul ignore next */ []));
|
|
7883
|
-
rutaSeleccionada = signal('', /* @ts-ignore */
|
|
7884
|
-
...(ngDevMode ? [{ debugName: "rutaSeleccionada" }] : /* istanbul ignore next */ []));
|
|
7885
|
-
constructor() {
|
|
7886
|
-
this.router.events
|
|
7887
|
-
.pipe(filter((event) => event instanceof NavigationEnd), takeUntilDestroyed(this.destroyRef))
|
|
7888
|
-
.subscribe(() => this.expandirRutaActual());
|
|
7889
|
-
}
|
|
7890
|
-
alternarGrupo(clave) {
|
|
7891
|
-
if (!this.abiertoInterno()) {
|
|
7892
|
-
this.abiertoInterno.set(true);
|
|
7893
|
-
this.abiertoChange.emit(true);
|
|
7894
|
-
}
|
|
7895
|
-
this.expandidos.update((actuales) => {
|
|
7896
|
-
const siguientes = new Set(actuales);
|
|
7897
|
-
siguientes.has(clave) ? siguientes.delete(clave) : siguientes.add(clave);
|
|
7898
|
-
return siguientes;
|
|
7899
|
-
});
|
|
7900
|
-
}
|
|
7901
|
-
estaExpandido(clave) {
|
|
7902
|
-
return this.expandidos().has(clave);
|
|
7903
|
-
}
|
|
7904
|
-
seleccionarItem(item, nivel) {
|
|
7905
|
-
this.seleccionar.emit({ item, nivel });
|
|
7906
|
-
}
|
|
7907
|
-
esItemSeleccionado(item) {
|
|
7908
|
-
const ruta = this.normalizarRuta(item.ruta);
|
|
7909
|
-
return !!ruta && ruta === this.rutaSeleccionada();
|
|
7910
|
-
}
|
|
7911
|
-
claveItem(item, padre, indice) {
|
|
7912
|
-
return `${padre}/${item.nombre}-${indice}`;
|
|
7913
|
-
}
|
|
7914
|
-
inicialMarca() {
|
|
7915
|
-
return (this.titulo.trim().charAt(0) || 'T').toUpperCase();
|
|
7916
|
-
}
|
|
7917
|
-
normalizarMenu(items) {
|
|
7918
|
-
return [...items]
|
|
7919
|
-
.sort((a, b) => a.orden - b.orden)
|
|
7920
|
-
.map((item) => ({
|
|
7921
|
-
...item,
|
|
7922
|
-
icono: item.icono?.trim() || 'folder',
|
|
7923
|
-
subMenus: this.normalizarMenu(item.subMenus ?? []),
|
|
7924
|
-
}));
|
|
7925
|
-
}
|
|
7926
|
-
expandirRutaActual() {
|
|
7927
|
-
const rutaActual = this.normalizarRuta(this.router.url);
|
|
7928
|
-
const coincidencia = this.buscarMejorCoincidenciaPorRuta(this.menuNormalizado(), rutaActual);
|
|
7929
|
-
this.rutaSeleccionada.set(coincidencia?.ruta ?? '');
|
|
7930
|
-
const clavesPadre = coincidencia?.ancestros ?? [];
|
|
7931
|
-
if (!clavesPadre.length)
|
|
7932
|
-
return;
|
|
7933
|
-
this.expandidos.update((actuales) => {
|
|
7934
|
-
const siguientes = new Set(actuales);
|
|
7935
|
-
clavesPadre.forEach((clave) => siguientes.add(clave));
|
|
7936
|
-
return siguientes;
|
|
7937
|
-
});
|
|
7938
|
-
}
|
|
7939
|
-
buscarMejorCoincidenciaPorRuta(items, rutaActual, padre = 'raiz', ancestros = []) {
|
|
7940
|
-
let mejor = null;
|
|
7941
|
-
for (let indice = 0; indice < items.length; indice += 1) {
|
|
7942
|
-
const item = items[indice];
|
|
7943
|
-
const clave = this.claveItem(item, padre, indice);
|
|
7944
|
-
const ruta = this.normalizarRuta(item.ruta);
|
|
7945
|
-
if (this.rutaCoincide(ruta, rutaActual)) {
|
|
7946
|
-
mejor = this.mejorCoincidencia(mejor, {
|
|
7947
|
-
ruta,
|
|
7948
|
-
ancestros,
|
|
7949
|
-
peso: ruta === rutaActual ? Number.MAX_SAFE_INTEGER : ruta.length,
|
|
7950
|
-
});
|
|
7951
|
-
}
|
|
7952
|
-
const resultado = this.buscarMejorCoincidenciaPorRuta(item.subMenus ?? [], rutaActual, clave, [...ancestros, clave]);
|
|
7953
|
-
mejor = this.mejorCoincidencia(mejor, resultado);
|
|
7954
|
-
}
|
|
7955
|
-
return mejor;
|
|
7956
|
-
}
|
|
7957
|
-
mejorCoincidencia(actual, candidata) {
|
|
7958
|
-
if (!candidata)
|
|
7959
|
-
return actual;
|
|
7960
|
-
if (!actual)
|
|
7961
|
-
return candidata;
|
|
7962
|
-
return candidata.peso > actual.peso ? candidata : actual;
|
|
7963
|
-
}
|
|
7964
|
-
rutaCoincide(rutaMenu, rutaActual) {
|
|
7965
|
-
if (!rutaMenu)
|
|
7966
|
-
return false;
|
|
7967
|
-
if (rutaMenu === '/')
|
|
7968
|
-
return rutaActual === '/';
|
|
7969
|
-
return rutaActual === rutaMenu || rutaActual.startsWith(`${rutaMenu}/`);
|
|
7970
|
-
}
|
|
7971
|
-
normalizarRuta(ruta) {
|
|
7972
|
-
if (!ruta)
|
|
7973
|
-
return '';
|
|
7974
|
-
const limpia = ruta.split('?')[0].split('#')[0].trim();
|
|
7975
|
-
if (!limpia || limpia === '/')
|
|
7976
|
-
return '/';
|
|
7977
|
-
const conSlashInicial = limpia.startsWith('/') ? limpia : `/${limpia}`;
|
|
7978
|
-
return conSlashInicial.endsWith('/') ? conSlashInicial.slice(0, -1) : conSlashInicial;
|
|
7979
|
-
}
|
|
7980
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: TdSidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7981
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: TdSidebar, isStandalone: true, selector: "td-sidebar", inputs: { titulo: "titulo", subtitulo: "subtitulo", etiquetaNavegacion: "etiquetaNavegacion", logoUrl: "logoUrl", logoAlt: "logoAlt", textoCarga: "textoCarga", mensajeVacio: "mensajeVacio", error: "error", cargando: "cargando", oscuro: "oscuro", modoCerrado: "modoCerrado", abierto: "abierto", menu: "menu" }, outputs: { abiertoChange: "abiertoChange", seleccionar: "seleccionar" }, ngImport: i0, template: "<aside\n class=\"td-sidebar\"\n [class.td-sidebar--compacto]=\"!abiertoInterno() && modoCerrado === 'compacto'\"\n [class.td-sidebar--oculto]=\"!abiertoInterno() && modoCerrado === 'oculto'\"\n [class.td-sidebar--oscuro]=\"oscuro\"\n [attr.aria-hidden]=\"!abiertoInterno() && modoCerrado === 'oculto'\"\n>\n <header class=\"td-sidebar__marca\">\n <div class=\"td-sidebar__logo\">\n @if (logoUrl) {\n <img [src]=\"logoUrl\" [alt]=\"logoAlt\" />\n } @else {\n <span>{{ inicialMarca() }}</span>\n }\n </div>\n\n @if (abiertoInterno()) {\n <div class=\"td-sidebar__marca-texto\">\n <small>{{ subtitulo }}</small>\n <strong>{{ titulo }}</strong>\n </div>\n }\n\n </header>\n\n <div class=\"td-sidebar__encabezado\">\n @if (abiertoInterno()) {\n <span>{{ etiquetaNavegacion }}</span>\n } @else {\n <span aria-hidden=\"true\">\u2022\u2022\u2022</span>\n }\n </div>\n\n <nav class=\"td-sidebar__nav\" aria-label=\"Men\u00FA principal\">\n @if (cargando) {\n <p class=\"td-sidebar__estado\">{{ textoCarga }}</p>\n } @else if (error) {\n <p class=\"td-sidebar__estado td-sidebar__estado--error\">{{ error }}</p>\n } @else if (!menuNormalizado().length) {\n <p class=\"td-sidebar__estado\">{{ mensajeVacio }}</p>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"listaMenu\"\n [ngTemplateOutletContext]=\"{ items: menuNormalizado(), nivel: 0, padre: 'raiz' }\"\n />\n }\n </nav>\n</aside>\n\n<ng-template #listaMenu let-items=\"items\" let-nivel=\"nivel\" let-padre=\"padre\">\n <ul class=\"td-sidebar__lista\" [class.td-sidebar__lista--anidada]=\"nivel > 0\">\n @for (item of items; track item) {\n @let clave = claveItem(item, padre, $index);\n @let tieneHijos = item.subMenus.length > 0;\n\n <li class=\"td-sidebar__item\">\n @if (tieneHijos) {\n <button\n class=\"td-sidebar__enlace\"\n type=\"button\"\n [class.td-sidebar__enlace--ruta-activa]=\"esItemSeleccionado(item)\"\n [attr.aria-expanded]=\"estaExpandido(clave)\"\n [attr.title]=\"!abiertoInterno() ? item.nombre : null\"\n (click)=\"alternarGrupo(clave)\"\n >\n <td-icon class=\"td-sidebar__icono\" [nombre]=\"item.icono || 'folder'\" />\n @if (abiertoInterno()) {\n <span>{{ item.nombre }}</span>\n <td-icon\n class=\"td-sidebar__flecha\"\n [class.td-sidebar__flecha--abierta]=\"estaExpandido(clave)\"\n nombre=\"chevron_right\"\n />\n }\n </button>\n } @else {\n <a\n class=\"td-sidebar__enlace\"\n [routerLink]=\"item.ruta || '/'\"\n [class.td-sidebar__enlace--ruta-activa]=\"esItemSeleccionado(item)\"\n [attr.title]=\"!abiertoInterno() ? item.nombre : null\"\n (click)=\"seleccionarItem(item, nivel)\"\n >\n <td-icon class=\"td-sidebar__icono\" [nombre]=\"item.icono || 'folder'\" />\n @if (abiertoInterno()) {\n <span>{{ item.nombre }}</span>\n }\n </a>\n }\n\n @if (abiertoInterno() && tieneHijos && estaExpandido(clave)) {\n <ng-container\n [ngTemplateOutlet]=\"listaMenu\"\n [ngTemplateOutletContext]=\"{\n items: item.subMenus,\n nivel: nivel + 1,\n padre: clave\n }\"\n />\n }\n </li>\n }\n </ul>\n</ng-template>\n", styles: [":host{display:block;height:100%}*{box-sizing:border-box}.td-sidebar{--td-fondo: var(--td-color-surface, #fff);--td-borde: var(--td-color-border, #e2e8f0);--td-texto: var(--td-color-text, #334155);--td-texto-suave: var(--td-color-text-muted, #64748b);--td-hover: var(--td-color-surface-soft, #f1f5f9);--td-activo: var(--td-color-primary-soft, #e8efff);--td-acento: var(--td-color-primary, #2563eb);display:flex;width:18rem;height:100%;min-height:28rem;flex-direction:column;overflow:hidden;border-right:1px solid var(--td-borde);color:var(--td-texto);background:var(--td-fondo);font-family:var(--td-font-family, Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif);transition:width .2s ease,background .2s ease,border-color .2s ease}.td-sidebar--oscuro{--td-fondo: var(--td-color-surface, #09090b);--td-borde: var(--td-color-border, #27272a);--td-texto: var(--td-color-text, #d4d4d8);--td-texto-suave: var(--td-color-text-muted, #71717a);--td-hover: var(--td-color-surface-soft, #18181b);--td-activo: var(--td-color-primary-soft, #172554);--td-acento: var(--td-color-primary, #60a5fa)}.td-sidebar--compacto{width:5rem}.td-sidebar--oculto{width:0;min-width:0;border-right-width:0;visibility:hidden}.td-sidebar__marca{display:flex;min-height:5rem;align-items:center;gap:.75rem;border-bottom:1px solid var(--td-borde);padding:1rem}.td-sidebar__logo{display:grid;width:2.75rem;height:2.75rem;flex:0 0 2.75rem;place-items:center;overflow:hidden;border:1px solid var(--td-borde);border-radius:var(--td-radius-md, .75rem);color:var(--td-color-on-primary, #fff);background:linear-gradient(135deg,var(--td-color-primary, #2563eb),var(--td-color-info, #3157a4));font-size:1.15rem;font-weight:800}.td-sidebar__logo img{width:75%;height:75%;object-fit:contain}.td-sidebar__marca-texto{min-width:0;flex:1}.td-sidebar__marca-texto small,.td-sidebar__marca-texto strong{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.td-sidebar__marca-texto small{color:var(--td-acento);font-size:.64rem;font-weight:750;letter-spacing:.12em;text-transform:uppercase}.td-sidebar__marca-texto strong{margin-top:.18rem;font-size:.84rem}.td-sidebar__encabezado{min-height:3.35rem;padding:1.25rem 1rem .65rem;color:var(--td-texto-suave);font-size:.66rem;font-weight:750;letter-spacing:.12em;text-transform:uppercase}.td-sidebar--compacto .td-sidebar__encabezado{text-align:center}.td-sidebar__nav{min-height:0;flex:1;overflow-x:hidden;overflow-y:auto;padding:0 .7rem 1rem;scrollbar-width:thin;scrollbar-color:var(--td-borde) transparent}.td-sidebar__lista{margin:0;padding:0;list-style:none}.td-sidebar__lista--anidada{position:relative;margin:.2rem 0 .35rem 1.25rem;padding-left:.7rem}.td-sidebar__lista--anidada:before{position:absolute;inset:0 auto 0 0;width:1px;background:var(--td-borde);content:\"\"}.td-sidebar__item+.td-sidebar__item{margin-top:.2rem}.td-sidebar__enlace{display:flex;width:100%;min-width:0;min-height:2.5rem;align-items:center;gap:.7rem;border:0;border-radius:var(--td-radius-sm, .55rem);padding:.55rem .7rem;color:var(--td-texto);background:transparent;font:inherit;font-size:.82rem;font-weight:600;text-align:left;text-decoration:none;cursor:pointer;transition:color .12s ease,background .12s ease}.td-sidebar__enlace:hover{background:var(--td-hover)}.td-sidebar__enlace--activo,.td-sidebar__enlace--ruta-activa{color:var(--td-acento);background:var(--td-activo)}.td-sidebar__enlace span{overflow:hidden;flex:1;text-overflow:ellipsis;white-space:nowrap}.td-sidebar__icono{width:1.15rem;height:1.15rem;flex:0 0 1.15rem}.td-sidebar__flecha{width:.9rem;height:.9rem;flex:0 0 .9rem;transition:transform .16s ease}.td-sidebar__flecha--abierta{transform:rotate(90deg)}.td-sidebar--compacto .td-sidebar__marca{justify-content:center;padding-inline:.7rem}.td-sidebar--compacto .td-sidebar__nav{padding-inline:.65rem}.td-sidebar--compacto .td-sidebar__enlace{justify-content:center;padding-inline:0}.td-sidebar__lista--anidada .td-sidebar__enlace{min-height:2.2rem;font-size:.75rem;font-weight:500}.td-sidebar__lista--anidada .td-sidebar__lista--anidada .td-sidebar__enlace{min-height:2rem;color:var(--td-texto-suave);font-size:.7rem}.td-sidebar__estado{margin:0;padding:.75rem;color:var(--td-texto-suave);font-size:.75rem;line-height:1.45}.td-sidebar__estado--error{color:var(--td-color-warning, #d97706)}@media(prefers-reduced-motion:reduce){.td-sidebar,.td-sidebar__flecha{transition:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "component", type: TdIcon, selector: "td-icon", inputs: ["nombre", "titulo", "tamano"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7982
|
-
}
|
|
7983
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: TdSidebar, decorators: [{
|
|
7984
|
-
type: Component,
|
|
7985
|
-
args: [{ selector: 'td-sidebar', imports: [NgTemplateOutlet, RouterLink, TdIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<aside\n class=\"td-sidebar\"\n [class.td-sidebar--compacto]=\"!abiertoInterno() && modoCerrado === 'compacto'\"\n [class.td-sidebar--oculto]=\"!abiertoInterno() && modoCerrado === 'oculto'\"\n [class.td-sidebar--oscuro]=\"oscuro\"\n [attr.aria-hidden]=\"!abiertoInterno() && modoCerrado === 'oculto'\"\n>\n <header class=\"td-sidebar__marca\">\n <div class=\"td-sidebar__logo\">\n @if (logoUrl) {\n <img [src]=\"logoUrl\" [alt]=\"logoAlt\" />\n } @else {\n <span>{{ inicialMarca() }}</span>\n }\n </div>\n\n @if (abiertoInterno()) {\n <div class=\"td-sidebar__marca-texto\">\n <small>{{ subtitulo }}</small>\n <strong>{{ titulo }}</strong>\n </div>\n }\n\n </header>\n\n <div class=\"td-sidebar__encabezado\">\n @if (abiertoInterno()) {\n <span>{{ etiquetaNavegacion }}</span>\n } @else {\n <span aria-hidden=\"true\">\u2022\u2022\u2022</span>\n }\n </div>\n\n <nav class=\"td-sidebar__nav\" aria-label=\"Men\u00FA principal\">\n @if (cargando) {\n <p class=\"td-sidebar__estado\">{{ textoCarga }}</p>\n } @else if (error) {\n <p class=\"td-sidebar__estado td-sidebar__estado--error\">{{ error }}</p>\n } @else if (!menuNormalizado().length) {\n <p class=\"td-sidebar__estado\">{{ mensajeVacio }}</p>\n } @else {\n <ng-container\n [ngTemplateOutlet]=\"listaMenu\"\n [ngTemplateOutletContext]=\"{ items: menuNormalizado(), nivel: 0, padre: 'raiz' }\"\n />\n }\n </nav>\n</aside>\n\n<ng-template #listaMenu let-items=\"items\" let-nivel=\"nivel\" let-padre=\"padre\">\n <ul class=\"td-sidebar__lista\" [class.td-sidebar__lista--anidada]=\"nivel > 0\">\n @for (item of items; track item) {\n @let clave = claveItem(item, padre, $index);\n @let tieneHijos = item.subMenus.length > 0;\n\n <li class=\"td-sidebar__item\">\n @if (tieneHijos) {\n <button\n class=\"td-sidebar__enlace\"\n type=\"button\"\n [class.td-sidebar__enlace--ruta-activa]=\"esItemSeleccionado(item)\"\n [attr.aria-expanded]=\"estaExpandido(clave)\"\n [attr.title]=\"!abiertoInterno() ? item.nombre : null\"\n (click)=\"alternarGrupo(clave)\"\n >\n <td-icon class=\"td-sidebar__icono\" [nombre]=\"item.icono || 'folder'\" />\n @if (abiertoInterno()) {\n <span>{{ item.nombre }}</span>\n <td-icon\n class=\"td-sidebar__flecha\"\n [class.td-sidebar__flecha--abierta]=\"estaExpandido(clave)\"\n nombre=\"chevron_right\"\n />\n }\n </button>\n } @else {\n <a\n class=\"td-sidebar__enlace\"\n [routerLink]=\"item.ruta || '/'\"\n [class.td-sidebar__enlace--ruta-activa]=\"esItemSeleccionado(item)\"\n [attr.title]=\"!abiertoInterno() ? item.nombre : null\"\n (click)=\"seleccionarItem(item, nivel)\"\n >\n <td-icon class=\"td-sidebar__icono\" [nombre]=\"item.icono || 'folder'\" />\n @if (abiertoInterno()) {\n <span>{{ item.nombre }}</span>\n }\n </a>\n }\n\n @if (abiertoInterno() && tieneHijos && estaExpandido(clave)) {\n <ng-container\n [ngTemplateOutlet]=\"listaMenu\"\n [ngTemplateOutletContext]=\"{\n items: item.subMenus,\n nivel: nivel + 1,\n padre: clave\n }\"\n />\n }\n </li>\n }\n </ul>\n</ng-template>\n", styles: [":host{display:block;height:100%}*{box-sizing:border-box}.td-sidebar{--td-fondo: var(--td-color-surface, #fff);--td-borde: var(--td-color-border, #e2e8f0);--td-texto: var(--td-color-text, #334155);--td-texto-suave: var(--td-color-text-muted, #64748b);--td-hover: var(--td-color-surface-soft, #f1f5f9);--td-activo: var(--td-color-primary-soft, #e8efff);--td-acento: var(--td-color-primary, #2563eb);display:flex;width:18rem;height:100%;min-height:28rem;flex-direction:column;overflow:hidden;border-right:1px solid var(--td-borde);color:var(--td-texto);background:var(--td-fondo);font-family:var(--td-font-family, Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif);transition:width .2s ease,background .2s ease,border-color .2s ease}.td-sidebar--oscuro{--td-fondo: var(--td-color-surface, #09090b);--td-borde: var(--td-color-border, #27272a);--td-texto: var(--td-color-text, #d4d4d8);--td-texto-suave: var(--td-color-text-muted, #71717a);--td-hover: var(--td-color-surface-soft, #18181b);--td-activo: var(--td-color-primary-soft, #172554);--td-acento: var(--td-color-primary, #60a5fa)}.td-sidebar--compacto{width:5rem}.td-sidebar--oculto{width:0;min-width:0;border-right-width:0;visibility:hidden}.td-sidebar__marca{display:flex;min-height:5rem;align-items:center;gap:.75rem;border-bottom:1px solid var(--td-borde);padding:1rem}.td-sidebar__logo{display:grid;width:2.75rem;height:2.75rem;flex:0 0 2.75rem;place-items:center;overflow:hidden;border:1px solid var(--td-borde);border-radius:var(--td-radius-md, .75rem);color:var(--td-color-on-primary, #fff);background:linear-gradient(135deg,var(--td-color-primary, #2563eb),var(--td-color-info, #3157a4));font-size:1.15rem;font-weight:800}.td-sidebar__logo img{width:75%;height:75%;object-fit:contain}.td-sidebar__marca-texto{min-width:0;flex:1}.td-sidebar__marca-texto small,.td-sidebar__marca-texto strong{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.td-sidebar__marca-texto small{color:var(--td-acento);font-size:.64rem;font-weight:750;letter-spacing:.12em;text-transform:uppercase}.td-sidebar__marca-texto strong{margin-top:.18rem;font-size:.84rem}.td-sidebar__encabezado{min-height:3.35rem;padding:1.25rem 1rem .65rem;color:var(--td-texto-suave);font-size:.66rem;font-weight:750;letter-spacing:.12em;text-transform:uppercase}.td-sidebar--compacto .td-sidebar__encabezado{text-align:center}.td-sidebar__nav{min-height:0;flex:1;overflow-x:hidden;overflow-y:auto;padding:0 .7rem 1rem;scrollbar-width:thin;scrollbar-color:var(--td-borde) transparent}.td-sidebar__lista{margin:0;padding:0;list-style:none}.td-sidebar__lista--anidada{position:relative;margin:.2rem 0 .35rem 1.25rem;padding-left:.7rem}.td-sidebar__lista--anidada:before{position:absolute;inset:0 auto 0 0;width:1px;background:var(--td-borde);content:\"\"}.td-sidebar__item+.td-sidebar__item{margin-top:.2rem}.td-sidebar__enlace{display:flex;width:100%;min-width:0;min-height:2.5rem;align-items:center;gap:.7rem;border:0;border-radius:var(--td-radius-sm, .55rem);padding:.55rem .7rem;color:var(--td-texto);background:transparent;font:inherit;font-size:.82rem;font-weight:600;text-align:left;text-decoration:none;cursor:pointer;transition:color .12s ease,background .12s ease}.td-sidebar__enlace:hover{background:var(--td-hover)}.td-sidebar__enlace--activo,.td-sidebar__enlace--ruta-activa{color:var(--td-acento);background:var(--td-activo)}.td-sidebar__enlace span{overflow:hidden;flex:1;text-overflow:ellipsis;white-space:nowrap}.td-sidebar__icono{width:1.15rem;height:1.15rem;flex:0 0 1.15rem}.td-sidebar__flecha{width:.9rem;height:.9rem;flex:0 0 .9rem;transition:transform .16s ease}.td-sidebar__flecha--abierta{transform:rotate(90deg)}.td-sidebar--compacto .td-sidebar__marca{justify-content:center;padding-inline:.7rem}.td-sidebar--compacto .td-sidebar__nav{padding-inline:.65rem}.td-sidebar--compacto .td-sidebar__enlace{justify-content:center;padding-inline:0}.td-sidebar__lista--anidada .td-sidebar__enlace{min-height:2.2rem;font-size:.75rem;font-weight:500}.td-sidebar__lista--anidada .td-sidebar__lista--anidada .td-sidebar__enlace{min-height:2rem;color:var(--td-texto-suave);font-size:.7rem}.td-sidebar__estado{margin:0;padding:.75rem;color:var(--td-texto-suave);font-size:.75rem;line-height:1.45}.td-sidebar__estado--error{color:var(--td-color-warning, #d97706)}@media(prefers-reduced-motion:reduce){.td-sidebar,.td-sidebar__flecha{transition:none}}\n"] }]
|
|
7986
|
-
}], ctorParameters: () => [], propDecorators: { titulo: [{
|
|
7987
|
-
type: Input
|
|
7988
|
-
}], subtitulo: [{
|
|
7989
|
-
type: Input
|
|
7990
|
-
}], etiquetaNavegacion: [{
|
|
7991
|
-
type: Input
|
|
7992
|
-
}], logoUrl: [{
|
|
7993
|
-
type: Input
|
|
7994
|
-
}], logoAlt: [{
|
|
7995
|
-
type: Input
|
|
7996
|
-
}], textoCarga: [{
|
|
7997
|
-
type: Input
|
|
7998
|
-
}], mensajeVacio: [{
|
|
7999
|
-
type: Input
|
|
8000
|
-
}], error: [{
|
|
8001
|
-
type: Input
|
|
8002
|
-
}], cargando: [{
|
|
8003
|
-
type: Input
|
|
8004
|
-
}], oscuro: [{
|
|
8005
|
-
type: Input
|
|
8006
|
-
}], modoCerrado: [{
|
|
8007
|
-
type: Input
|
|
8008
|
-
}], abierto: [{
|
|
8009
|
-
type: Input
|
|
8010
|
-
}], menu: [{
|
|
8011
|
-
type: Input
|
|
8012
|
-
}], abiertoChange: [{
|
|
8013
|
-
type: Output
|
|
8014
|
-
}], seleccionar: [{
|
|
8015
|
-
type: Output
|
|
8016
|
-
}] } });
|
|
8017
|
-
|
|
8018
8033
|
let tabSequence = 0;
|
|
8019
8034
|
class TdTab {
|
|
8020
8035
|
generatedId = `td-tab-${++tabSequence}`;
|