@jvsoft/components 0.0.9 → 0.0.11

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.
Files changed (136) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/build.js +20 -0
  3. package/dialog-flotante/dialog-flotante.component.html +66 -0
  4. package/dialog-flotante/dialog-flotante.component.ts +115 -0
  5. package/dialog-flotante/dialog-flotante.interface.ts +13 -0
  6. package/dialog-flotante/index.ts +1 -0
  7. package/dialog-flotante/ng-package.json +5 -0
  8. package/{index.d.ts → index.ts} +8 -0
  9. package/lista-arbol/lista-arbol.component.html +66 -0
  10. package/lista-arbol/lista-arbol.component.ts +238 -0
  11. package/lista-arbol/lista-arbol.functions.ts +46 -0
  12. package/lista-arbol/ng-package.json +5 -0
  13. package/lista-arbol/public-api.ts +1 -0
  14. package/luces-navidad/christmas-tree.png +0 -0
  15. package/luces-navidad/index.ts +1 -0
  16. package/luces-navidad/luces-navidad.component.html +6 -0
  17. package/luces-navidad/luces-navidad.component.ts +24 -0
  18. package/luces-navidad/ng-package.json +5 -0
  19. package/mat-suffix-search-button/index.ts +1 -0
  20. package/mat-suffix-search-button/mat-suffix-search-button.component.html +5 -0
  21. package/mat-suffix-search-button/mat-suffix-search-button.component.ts +36 -0
  22. package/mat-suffix-search-button/ng-package.json +5 -0
  23. package/menu/index.ts +1 -0
  24. package/menu/menu.component.html +40 -0
  25. package/menu/menu.component.ts +88 -0
  26. package/menu/menu.interface.ts +16 -0
  27. package/menu/ng-package.json +5 -0
  28. package/ng-package.json +17 -0
  29. package/package.json +15 -36
  30. package/progress-spinner.zip +0 -0
  31. package/tabla-mantenimiento/classes/data-model.ts +150 -0
  32. package/tabla-mantenimiento/components/progress-bar/index.ts +1 -0
  33. package/tabla-mantenimiento/components/progress-bar/ng-package.json +5 -0
  34. package/tabla-mantenimiento/components/progress-bar/progress-bar.component.html +10 -0
  35. package/tabla-mantenimiento/components/progress-bar/progress-bar.component.ts +85 -0
  36. package/tabla-mantenimiento/components/progress-bar/public-api.ts +2 -0
  37. package/tabla-mantenimiento/index.ts +1 -0
  38. package/tabla-mantenimiento/interfaces/{archivo.d.ts → archivo.ts} +7 -4
  39. package/tabla-mantenimiento/interfaces/global/{boton-mantenimiento.d.ts → boton-mantenimiento.ts} +9 -3
  40. package/tabla-mantenimiento/interfaces/global/{columnas-tabla.d.ts → columnas-tabla.ts} +90 -13
  41. package/tabla-mantenimiento/interfaces/global/export-excel-servidor.ts +0 -0
  42. package/tabla-mantenimiento/interfaces/global/no-export.ts +11 -0
  43. package/tabla-mantenimiento/interfaces/global/{otros.d.ts → otros.ts} +15 -3
  44. package/tabla-mantenimiento/interfaces/implements/{incluye-tabla-mantenimiento.d.ts → incluye-tabla-mantenimiento.ts} +6 -4
  45. package/tabla-mantenimiento/interfaces/implements/{index.d.ts → index.ts} +1 -0
  46. package/tabla-mantenimiento/mat-row-keyboard-selection.directive.ts +97 -0
  47. package/tabla-mantenimiento/ng-package.json +5 -0
  48. package/tabla-mantenimiento/pipes/no-sanitize.pipe.ts +12 -0
  49. package/tabla-mantenimiento/pipes/zero-fill.pipe.ts +19 -0
  50. package/tabla-mantenimiento/{public-api.d.ts → public-api.ts} +3 -2
  51. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-date/column-type-date.component.html +22 -0
  52. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-date/column-type-date.component.ts +12 -0
  53. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-icons/column-type-icons.component.html +58 -0
  54. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-icons/column-type-icons.component.ts +19 -0
  55. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-money/column-type-money.component.html +40 -0
  56. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-money/column-type-money.component.ts +17 -0
  57. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-number/column-type-number.component.html +25 -0
  58. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-number/column-type-number.component.ts +14 -0
  59. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-progressbar/column-type-progressbar.component.html +28 -0
  60. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-progressbar/column-type-progressbar.component.ts +13 -0
  61. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-sino/column-type-sino.component.html +30 -0
  62. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-sino/column-type-sino.component.ts +38 -0
  63. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-text/column-type-text.component.html +97 -0
  64. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-text/column-type-text.component.ts +43 -0
  65. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type.component.html +26 -0
  66. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type.component.ts +36 -0
  67. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type.module.ts +54 -0
  68. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/tabla-mantenimiento-column-defs.component.html +76 -0
  69. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/tabla-mantenimiento-column-defs.component.ts +67 -0
  70. package/tabla-mantenimiento/tabla-mantenimiento-menu/tabla-mantenimiento-menu.component.html +7 -0
  71. package/tabla-mantenimiento/tabla-mantenimiento-menu/tabla-mantenimiento-menu.component.ts +39 -0
  72. package/tabla-mantenimiento/tabla-mantenimiento.component.html +385 -0
  73. package/tabla-mantenimiento/tabla-mantenimiento.component.ts +951 -0
  74. package/tabla-mantenimiento/tabla-mantenimiento.functions.ts +57 -0
  75. package/tabla-mantenimiento/tabla-mantenimiento.service.ts +44 -0
  76. package/tabla-mantenimiento/table-util.ts +49 -0
  77. package/tabla-mantenimiento.zip +0 -0
  78. package/tsconfig.lib.json +16 -0
  79. package/tsconfig.lib.prod.json +11 -0
  80. package/tsconfig.spec.json +15 -0
  81. package/yarn-error.log +68 -0
  82. package/dialog-flotante/dialog-flotante.component.d.ts +0 -32
  83. package/dialog-flotante/dialog-flotante.interface.d.ts +0 -11
  84. package/dialog-flotante/index.d.ts +0 -5
  85. package/fesm2022/jvsoft-components-dialog-flotante.mjs +0 -130
  86. package/fesm2022/jvsoft-components-dialog-flotante.mjs.map +0 -1
  87. package/fesm2022/jvsoft-components-luces-navidad.mjs +0 -33
  88. package/fesm2022/jvsoft-components-luces-navidad.mjs.map +0 -1
  89. package/fesm2022/jvsoft-components-mat-suffix-search-button.mjs +0 -47
  90. package/fesm2022/jvsoft-components-mat-suffix-search-button.mjs.map +0 -1
  91. package/fesm2022/jvsoft-components-menu.mjs +0 -102
  92. package/fesm2022/jvsoft-components-menu.mjs.map +0 -1
  93. package/fesm2022/jvsoft-components-tabla-mantenimiento-components-progress-bar.mjs +0 -91
  94. package/fesm2022/jvsoft-components-tabla-mantenimiento-components-progress-bar.mjs.map +0 -1
  95. package/fesm2022/jvsoft-components-tabla-mantenimiento.mjs +0 -1801
  96. package/fesm2022/jvsoft-components-tabla-mantenimiento.mjs.map +0 -1
  97. package/fesm2022/jvsoft-components.mjs +0 -2061
  98. package/fesm2022/jvsoft-components.mjs.map +0 -1
  99. package/luces-navidad/index.d.ts +0 -5
  100. package/luces-navidad/luces-navidad.component.d.ts +0 -11
  101. package/mat-suffix-search-button/index.d.ts +0 -5
  102. package/mat-suffix-search-button/mat-suffix-search-button.component.d.ts +0 -12
  103. package/menu/index.d.ts +0 -5
  104. package/menu/menu.component.d.ts +0 -25
  105. package/menu/menu.interface.d.ts +0 -16
  106. package/src/styles/base-jvsoft-components.css +0 -9
  107. package/tabla-mantenimiento/classes/data-model.d.ts +0 -25
  108. package/tabla-mantenimiento/components/progress-bar/index.d.ts +0 -5
  109. package/tabla-mantenimiento/components/progress-bar/progress-bar.component.d.ts +0 -30
  110. package/tabla-mantenimiento/components/progress-bar/public-api.d.ts +0 -1
  111. package/tabla-mantenimiento/index.d.ts +0 -5
  112. package/tabla-mantenimiento/interfaces/global/no-export.d.ts +0 -2
  113. package/tabla-mantenimiento/mat-row-keyboard-selection.directive.d.ts +0 -19
  114. package/tabla-mantenimiento/pipes/no-sanitize.pipe.d.ts +0 -10
  115. package/tabla-mantenimiento/pipes/zero-fill.pipe.d.ts +0 -8
  116. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-date/column-type-date.component.d.ts +0 -8
  117. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-icons/column-type-icons.component.d.ts +0 -9
  118. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-money/column-type-money.component.d.ts +0 -9
  119. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-number/column-type-number.component.d.ts +0 -8
  120. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-progressbar/column-type-progressbar.component.d.ts +0 -8
  121. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-sino/column-type-sino.component.d.ts +0 -9
  122. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type-text/column-type-text.component.d.ts +0 -8
  123. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type.component.d.ts +0 -18
  124. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/column-type/column-type.module.d.ts +0 -23
  125. package/tabla-mantenimiento/tabla-mantenimiento-column-defs/tabla-mantenimiento-column-defs.component.d.ts +0 -21
  126. package/tabla-mantenimiento/tabla-mantenimiento-menu/tabla-mantenimiento-menu.component.d.ts +0 -18
  127. package/tabla-mantenimiento/tabla-mantenimiento.component.d.ts +0 -147
  128. package/tabla-mantenimiento/tabla-mantenimiento.functions.d.ts +0 -5
  129. package/tabla-mantenimiento/tabla-mantenimiento.service.d.ts +0 -8
  130. package/tabla-mantenimiento/table-util.d.ts +0 -11
  131. /package/dialog-flotante/{public-api.d.ts → public-api.ts} +0 -0
  132. /package/luces-navidad/{public-api.d.ts → public-api.ts} +0 -0
  133. /package/mat-suffix-search-button/{public-api.d.ts → public-api.ts} +0 -0
  134. /package/menu/{public-api.d.ts → public-api.ts} +0 -0
  135. /package/tabla-mantenimiento/interfaces/global/{index.d.ts → index.ts} +0 -0
  136. /package/tabla-mantenimiento/interfaces/{index.d.ts → index.ts} +0 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # @jvsoft/components
2
+
3
+ ## 0.0.11
4
+
5
+ ### Patch Changes
6
+
7
+ - WSpace
8
+ - Updated dependencies
9
+ - @jvsoft/utils@0.0.11
package/build.js ADDED
@@ -0,0 +1,20 @@
1
+ const {execSync} = require('child_process');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ // 1. Generar estilos Tailwind
6
+ execSync('npx tailwindcss -i ./projects/components/src/styles/base.scss -o ./projects/components/src/styles/base-jvsoft-components.css');
7
+
8
+ // 2. Reemplazar en componentes
9
+ const componentsDir = path.join(__dirname);
10
+ fs.readdirSync(componentsDir).forEach(file => {
11
+ if (file.endsWith('.component.ts')) {
12
+ const filePath = path.join(componentsDir, file);
13
+ let content = fs.readFileSync(filePath, 'utf8');
14
+ content = content.replace(
15
+ /styleUrls: \[.*\]/,
16
+ `styles: [require('./${file.replace('.ts', '.scss')}').default]`
17
+ );
18
+ fs.writeFileSync(filePath, content);
19
+ }
20
+ });
@@ -0,0 +1,66 @@
1
+ <ng-container *ngIf="sinTitulo; else conTitulo">
2
+ <ng-container [ngTemplateOutlet]="parteComun"></ng-container>
3
+ </ng-container>
4
+
5
+ <ng-template #conTitulo>
6
+ <div cdkDrag class="block h-full" cdkDragRootElement=".cdk-overlay-pane" cdkDragBoundary="body">
7
+ <div class="flex-auto flex items-center justify-between hover:cursor-move gap-1"
8
+ [ngClass]="cssClases['titulo'] ?? 'bg-primary text-primary-contrast'"
9
+ mat-dialog-title cdkDragHandle>
10
+
11
+ <mat-icon *ngIf="iconoTitulo" class="flex-none icon-xs" [svgIcon]="iconoTitulo"></mat-icon>
12
+ <ng-content select="[tituloImagen]"></ng-content>
13
+ <h5 class="flex-1 m-0">
14
+ <ng-content select="[titulo]"></ng-content>
15
+ </h5>
16
+ <ng-content select="[selectTitulo]"></ng-content>
17
+
18
+ <ng-container *ngIf="btnCerrar || btnCerrarBarra">
19
+ <button matRipple class="flex items-center justify-center ml-2 h-6 w-6 bg-red-700 rounded-md text-white"
20
+ type="button" [mat-dialog-close]="!matDialogRefActual"
21
+ (click)="matDialogRefActual ? cerrarDialogo() : null">
22
+ <mat-icon svgIcon="roundClose"></mat-icon>
23
+ </button>
24
+ </ng-container>
25
+ </div>
26
+
27
+ <mat-divider class="flex-auto bg-primary"></mat-divider>
28
+ <ng-container [ngTemplateOutlet]="parteComun"></ng-container>
29
+ </div>
30
+ </ng-template>
31
+
32
+ <ng-template #parteComun>
33
+ <mat-dialog-content class="flex-1">
34
+ <div class="contenedor-cuerpo">
35
+ <ng-content select="[cuerpo]"></ng-content>
36
+ </div>
37
+ </mat-dialog-content>
38
+
39
+ <mat-dialog-actions class="flex-auto flex items-center justify-between gap-1 pt-0 mt-0" *ngIf="!sinBarraDeAccion">
40
+ <div class="flex items-start justify-start gap-1">
41
+ <ng-content select="[pieIzquierda]"></ng-content>
42
+ </div>
43
+ <div class="flex items-center justify-center gap-1">
44
+ <ng-content select="[pieCentro]"></ng-content>
45
+ </div>
46
+ <div class="flex items-end justify-end gap-1">
47
+ <ng-content select="[pieDerecha]"></ng-content>
48
+
49
+ <!-- Botón Guardar -->
50
+ <button matRipple *ngIf="btnGuardar" type="submit"
51
+ class="boton-dialog-flotante" [ngClass]="btnGuardar.class"
52
+ [class]="cssClases['btnGuardar']" (click)="guardarDialogo()">
53
+ <mat-icon class="icon-xs" [svgIcon]="btnGuardar?.icono ?? ''"></mat-icon>
54
+ <span>{{ btnGuardar.label }}</span>
55
+ </button>
56
+
57
+ <!-- Botón Cerrar -->
58
+ <button matRipple *ngIf="btnCerrar" type="button"
59
+ class="boton-dialog-flotante" [ngClass]="btnCerrar.class"
60
+ [mat-dialog-close]="!matDialogRefActual" (click)="matDialogRefActual ? cerrarDialogo() : null">
61
+ <mat-icon class="icon-xs" svgIcon="roundClose"></mat-icon>
62
+ <span>{{ btnCerrar.label }}</span>
63
+ </button>
64
+ </div>
65
+ </mat-dialog-actions>
66
+ </ng-template>
@@ -0,0 +1,115 @@
1
+ import {Component, EventEmitter, Input, Output} from '@angular/core';
2
+ import {MatDialogModule, MatDialogRef} from '@angular/material/dialog';
3
+ import {BotonDialog} from './dialog-flotante.interface';
4
+ import {MatIconModule} from '@angular/material/icon';
5
+ import {CommonModule} from '@angular/common';
6
+ import {CdkDrag, CdkDragHandle} from '@angular/cdk/drag-drop';
7
+ import {MatRipple} from '@angular/material/core';
8
+ import {MatDivider} from '@angular/material/divider';
9
+
10
+ @Component({
11
+ selector: '[jvsDialogFlotante]',
12
+ imports: [
13
+ CommonModule,
14
+ MatIconModule,
15
+ MatDialogModule,
16
+ CdkDrag,
17
+ CdkDragHandle,
18
+ MatRipple,
19
+ MatDivider,
20
+
21
+ ],
22
+ templateUrl: './dialog-flotante.component.html',
23
+ styleUrls: ['./dialog-flotante.component.scss'],
24
+ host: {
25
+ class: 'jvs-dialog-flotante',
26
+ }
27
+ })
28
+ export class DialogFlotanteComponent {
29
+ @Input() cssClases: Record<string, string> = {};
30
+
31
+ private _sinTitulo: boolean | '' = false;
32
+ get sinTitulo(): boolean {
33
+ return !!this._sinTitulo;
34
+ }
35
+
36
+ @Input() set sinTitulo(val: boolean | '') {
37
+ this._sinTitulo = val == '';
38
+ }
39
+
40
+ private _sinBarraDeAccion: boolean | '' = false;
41
+ get sinBarraDeAccion(): boolean {
42
+ return !!this._sinBarraDeAccion;
43
+ }
44
+
45
+ @Input() set sinBarraDeAccion(val: boolean | '') {
46
+ this._sinBarraDeAccion = val == '';
47
+ }
48
+
49
+ private readonly defaultBtnCerrar: BotonDialog = {label: 'CERRAR', class: 'text-gray-700 border-gray-700'};
50
+ private _btnCerrar: BotonDialog = this.defaultBtnCerrar;
51
+ get btnCerrar(): BotonDialog {
52
+ return this._btnCerrar;
53
+ }
54
+
55
+ @Input() set btnCerrar(val: BotonDialog | boolean | string | '') {
56
+ if (val == null || val === '') {
57
+ this._btnCerrar = this.defaultBtnCerrar;
58
+ }
59
+ else {
60
+ this._btnCerrar = (typeof val === 'string' && val !== '') ? {...this.defaultBtnCerrar, label: val}:
61
+ (typeof val === 'boolean' && val) ? this.defaultBtnCerrar:
62
+ (val as BotonDialog) ?? this.defaultBtnCerrar;
63
+ }
64
+ }
65
+
66
+ private _btnCerrarBarra: boolean = true;
67
+ get btnCerrarBarra(): boolean {
68
+ return this._btnCerrarBarra;
69
+ }
70
+
71
+ @Input() set btnCerrarBarra(val: boolean | '') {
72
+ this._btnCerrarBarra = val || true;
73
+ }
74
+
75
+ private readonly defaultBtnGuardar: BotonDialog = {
76
+ label: 'GUARDAR', class: 'text-blue-700 border-blue-700', icono: 'roundSave'
77
+ };
78
+ private _btnGuardar: BotonDialog = this.defaultBtnGuardar;
79
+ get btnGuardar(): BotonDialog {
80
+ return this._btnGuardar;
81
+ }
82
+
83
+ @Input() set btnGuardar(val: BotonDialog | boolean | string | '') {
84
+ if (val == null || val === '') {
85
+ this._btnGuardar = this.defaultBtnGuardar;
86
+ }
87
+ else {
88
+ this._btnGuardar = (typeof val === 'string' && val !== '') ? {...this.defaultBtnGuardar, label: val}:
89
+ (typeof val === 'boolean' && val) ? this.defaultBtnGuardar:
90
+ (val as BotonDialog) ?? this.defaultBtnGuardar;
91
+ }
92
+ }
93
+
94
+ @Input() iconoTitulo?: string;
95
+ @Input() matDialogRefActual!: MatDialogRef<any>;
96
+ @Output() btnGuardarClick = new EventEmitter<any>();
97
+ @Output() btnCerrarClick = new EventEmitter<any>();
98
+
99
+ guardarDialogo() {
100
+ this.btnGuardarClick.emit(true);
101
+ }
102
+
103
+ cerrarDialogo() {
104
+ this.btnCerrarClick.emit(true);
105
+ if (this.matDialogRefActual) {
106
+ if (this.matDialogRefActual.componentInstance?.validarCerrarDialog) {
107
+ this.matDialogRefActual.componentInstance?.validarCerrarDialog();
108
+ }
109
+ else {
110
+ this.matDialogRefActual.close('Cerrado GDLG');
111
+ }
112
+ }
113
+ }
114
+
115
+ }
@@ -0,0 +1,13 @@
1
+ export interface DialogFlotanteInterface {
2
+
3
+ }
4
+
5
+ type TiposOpciones = 'ver' | 'nuevo' | 'editar' | 'guardar' | 'eliminar' | 'seleccionar' | 'editar_item' | 'detalle' |
6
+ 'ver_archivos' | 'eliminar_fila' | 'imprimir' | 'descargar' | 'exportar_pdf' | 'exportar_excel' | string;
7
+ export interface BotonDialog {
8
+ tipo?: TiposOpciones;
9
+ class?: string;
10
+ icono?: string;
11
+ label?: string;
12
+ sinCondicion?: boolean;
13
+ }
@@ -0,0 +1 @@
1
+ export * from './public-api'
@@ -0,0 +1,5 @@
1
+ {
2
+ "lib": {
3
+ "entryFile": "public-api.ts"
4
+ }
5
+ }
@@ -1,6 +1,14 @@
1
+ // export {};
2
+ // import './src/styles.scss';
3
+
1
4
  export * from './dialog-flotante';
5
+ // export * from './progress-spinner';
2
6
  export * from './tabla-mantenimiento';
3
7
  export * from './tabla-mantenimiento/components/progress-bar';
4
8
  export * from './luces-navidad';
5
9
  export * from './mat-suffix-search-button';
6
10
  export * from './menu';
11
+ export * from './lista-arbol/public-api'
12
+
13
+
14
+
@@ -0,0 +1,66 @@
1
+ <mat-tree [dataSource]="listaMuestraArbol" [treeControl]="treeControl">
2
+ <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
3
+ <div class="flex flex-col trans-ease-out cursor-pointer" matTreeNodeToggle
4
+ [matTreeNodeToggleRecursive]="expandirRecursivo">
5
+ <ng-container [ngTemplateOutlet]="liDat"
6
+ [ngTemplateOutletContext]="{ node: node, nested: true }"></ng-container>
7
+ <div class="pl-4" [class.tree-invisible]="!treeControl.isExpanded(node)">
8
+ <ng-container matTreeNodeOutlet></ng-container>
9
+ </div>
10
+ </div>
11
+ </mat-nested-tree-node>
12
+
13
+ <!-- Cambiar mat-tree-node plano por mat-nested-tree-node sin hijos -->
14
+ <mat-nested-tree-node *matTreeNodeDef="let node">
15
+ <div class="flex flex-col trans-ease-out cursor-pointer">
16
+ <ng-container [ngTemplateOutlet]="liDat"
17
+ [ngTemplateOutletContext]="{ node: node, nested: false }"></ng-container>
18
+ </div>
19
+ </mat-nested-tree-node>
20
+ </mat-tree>
21
+
22
+ <!--
23
+
24
+
25
+ <mat-tree [dataSource]="listaMuestraArbol" [treeControl]="treeControl">
26
+ <mat-tree-node class="!pl-0 min-h-0" *matTreeNodeDef="let node" matTreeNodeToggle matTreeNodePadding
27
+ [matTreeNodeToggleRecursive]="expandirRecursivo">
28
+ <ng-container [ngTemplateOutlet]="liDat"
29
+ [ngTemplateOutletContext]="{ node: node, nested: false }"></ng-container>
30
+ </mat-tree-node>
31
+
32
+ <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
33
+ <div class="flex flex-col trans-ease-out cursor-pointer" matTreeNodeToggle [matTreeNodeToggleRecursive]="expandirRecursivo">
34
+ <ng-container [ngTemplateOutlet]="liDat"
35
+ [ngTemplateOutletContext]="{ node: node, nested: true }"></ng-container>
36
+ <div class="pl-4" [class.tree-invisible]="!treeControl.isExpanded(node)">
37
+ <ng-container matTreeNodeOutlet></ng-container>
38
+ </div>
39
+ </div>
40
+ </mat-nested-tree-node>
41
+ </mat-tree>
42
+ -->
43
+
44
+ <ng-template #liDat let-node="node" let-nested="nested">
45
+ <div class="flex items-center gap-0 text-sm trans-ease-out cursor-pointer p-0 w-full"
46
+ (contextmenu)="menuContextual?.abrirMenuContextual($event, node); $event.preventDefault();"
47
+ (click)="seleccionarItem(node); opcMenu({ seccion: nombreColeccion, tipo: 'ver', item: node }); menuContextual?.cerrarMenuContextual();"
48
+ [ngClass]="classFila(node)">
49
+ <mat-icon *ngIf="!nested"></mat-icon>
50
+ <mat-icon *ngIf="nested"
51
+ [svgIcon]="treeControl.isExpanded(node) ? 'roundExpandMore' : 'roundChevronRight'"></mat-icon>
52
+
53
+ <mat-checkbox *ngIf="checkbox"
54
+ [(ngModel)]="chkLista.modelosChk[node[campoId]]"
55
+ [ngModelOptions]="{ standalone: true }"
56
+ (click)="$event.stopPropagation()"
57
+ (change)="cambiarCheck(node, $event.checked); emitirModeloCheck()"
58
+ [checked]="nested ? hijosActivos('checked', node) : false"
59
+ [indeterminate]="nested ? hijosActivos('indeterminate', node) : false">
60
+ </mat-checkbox>
61
+
62
+ <span *ngIf="!templateTxtData" class="w-full">{{ node[campoStr] }}</span>
63
+ <ng-container *ngIf="templateTxtData" [ngTemplateOutlet]="templateTxtData"
64
+ [ngTemplateOutletContext]="{ data: node, treeControl }"></ng-container>
65
+ </div>
66
+ </ng-template>
@@ -0,0 +1,238 @@
1
+ import {Component, EventEmitter, Input, OnInit, Output, TemplateRef} from '@angular/core';
2
+ import {CommonModule} from '@angular/common';
3
+ import {MatTreeModule} from '@angular/material/tree';
4
+ import {MatIconModule} from '@angular/material/icon';
5
+ import {MatCheckboxModule} from '@angular/material/checkbox';
6
+ import {FormsModule} from '@angular/forms';
7
+ import {Observable} from 'rxjs';
8
+ import {NestedTreeControl} from '@angular/cdk/tree';
9
+ import {generarArbol} from './lista-arbol.functions';
10
+ import {DataModel} from '@jvsoft/utils';
11
+ import {SelectionModel} from '@angular/cdk/collections';
12
+ import shortHash from 'shorthash2';
13
+
14
+ @Component({
15
+ selector: 'jvs-lista-arbol',
16
+ standalone: true,
17
+ imports: [
18
+ CommonModule,
19
+ FormsModule,
20
+ MatTreeModule,
21
+ MatIconModule,
22
+ MatCheckboxModule,
23
+ ],
24
+ templateUrl: './lista-arbol.component.html',
25
+ })
26
+ export class ListaArbolComponent<T = any> implements OnInit {
27
+ @Input() listaSuscription!: Observable<T[]>;
28
+ @Input() nombreColeccion!: string;
29
+ @Input() checkbox = false;
30
+ @Input() expandirRecursivo = false;
31
+ @Input() checkboxSeleccionados: T[] = [];
32
+
33
+ @Input() campoId!: string;
34
+ @Input() campoIdPadre!: string;
35
+ @Input() campoStr!: string;
36
+ @Input() campoOrden?: string;
37
+ @Input() strHijoContainer = 'hijos';
38
+ @Input() menuContextual?: { abrirMenuContextual: Function; cerrarMenuContextual: Function };
39
+ @Input() classSeleccionado: string[] = ['bg-primary-activo', 'text-primary', 'dark:!bg-primary-dark-activo'];
40
+ @Input() classAnulado: string[] = ['line-through', 'text-red', 'italic'];
41
+ @Input() campoAnulado?: string | null;
42
+ @Input() templateTxtData?: TemplateRef<any>;
43
+ @Input() condicionMostrar?: (item: T) => boolean;
44
+ @Input() condicionesClaseFila: (item: T) => string[] = () => [];
45
+
46
+ @Input() set selectionModel(val: SelectionModel<any>) {
47
+ this.objSeleccionado = val;
48
+ }
49
+ @Output() selectionModelChange = new EventEmitter<SelectionModel<any>>();
50
+
51
+ @Output() seleccionado = new EventEmitter<any>();
52
+ @Output() listaCheck = new EventEmitter<T[]>();
53
+ @Output() listaCheckObj = new EventEmitter<Record<string, any>>();
54
+
55
+ private _idTabla: string[] = [];
56
+
57
+ get idTabla(): string[] {
58
+ return this._idTabla;
59
+ }
60
+
61
+ @Input({required: true}) set idTabla(val: string[] | string) {
62
+ if (Array.isArray(val)) {
63
+ this._idTabla = val;
64
+ }
65
+ else {
66
+ this._idTabla.push(val);
67
+ }
68
+ }
69
+
70
+ get buscarItemSeleccionado(): any {
71
+ const dRet = this.listaOriginal.find(itm => this._seleccionado === this.propiedadSeleccion(itm));
72
+ return dRet ?? null;
73
+ }
74
+ get objSeleccionado() {
75
+ return this.buscarItemSeleccionado; // ?? this.objThis?.['seleccionados']?.[this.nombreColeccion];
76
+ }
77
+
78
+ set objSeleccionado(val: any) {
79
+ this.seleccionarItem(val, true);
80
+ }
81
+
82
+ chkLista = new DataModel();
83
+ listaMuestraArbol: T[] = [];
84
+ listaOriginal: T[] = [];
85
+
86
+ treeControl = new NestedTreeControl((node: any) => node[this.strHijoContainer]);
87
+
88
+ _seleccionado: any = {};
89
+
90
+ ngOnInit(): void {
91
+ this.listaSuscription.subscribe(res => {
92
+ if (res) {
93
+ this.listaOriginal = res;
94
+ const listaAs = generarArbol({
95
+ lista: res,
96
+ campoId: this.campoId,
97
+ campoIdPadre: this.campoIdPadre,
98
+ idPadre: null,
99
+ strChildren: this.strHijoContainer,
100
+ campoOrden: this.campoOrden
101
+ });
102
+ this.listaMuestraArbol = [];
103
+ setTimeout(() => {
104
+ this.listaMuestraArbol = listaAs;
105
+ }, 1);
106
+ if (this.checkbox) {
107
+ this.chkLista.agregarControles(res, this.campoId);
108
+ this.checkboxSeleccionados.forEach((chkSel: any) => {
109
+ this.chkLista.setState(chkSel[this.campoId], true);
110
+ });
111
+ this.emitirModeloCheck();
112
+ }
113
+ }
114
+ });
115
+ }
116
+
117
+
118
+ idTablaValor(data: any): string {
119
+ if (data) {
120
+ if (this.idTabla.length < 1) {
121
+ return shortHash(JSON.stringify({data, claseFinal: undefined}))
122
+ }
123
+ return this.idTabla.map(d => data[d]).join('-');
124
+ }
125
+ return '';
126
+ }
127
+
128
+ propiedadSeleccion(item: any): string {
129
+ return `${this.nombreColeccion}_${this.idTablaValor(item)}`;
130
+ }
131
+
132
+ esSeleccionActual(item: any): boolean {
133
+ return this._seleccionado === this.propiedadSeleccion(item);
134
+ }
135
+ seleccionarItem(item?: any, forzado: boolean = false): void {
136
+ const idItem = this.propiedadSeleccion(item);
137
+ if (forzado) {
138
+ this._seleccionado = idItem;
139
+ }
140
+ else {
141
+ this._seleccionado = this._seleccionado === idItem ? null:idItem;
142
+ }
143
+ this.selectionModelChange.emit(this.objSeleccionado);
144
+ this.seleccionado.emit(this.objSeleccionado);
145
+ }
146
+
147
+
148
+ hasChild = (_: number, node: any) => !!node[this.strHijoContainer] && node[this.strHijoContainer].length > 0;
149
+
150
+
151
+ opcMenu(v: any) {
152
+ // console.warn(v);
153
+ // console.warn(this.objSeleccionado);
154
+ const opAdic: any = {seccion: this.nombreColeccion};
155
+ opAdic['itemSeleccionado'] = this.objSeleccionado;
156
+ // v = {...v, ...opAdic};
157
+ // this.seleccionado.emit(v);
158
+ }
159
+
160
+ emitirModeloCheck() {
161
+ this.listaCheck.emit(<any[]>this.chkLista.generarLista());
162
+ this.listaCheckObj.emit(<object>this.chkLista.generarLista('object'));
163
+ }
164
+
165
+
166
+ cambiarPadre(checkActual: T, estado: boolean): void {
167
+ const parentId = (checkActual as any)[this.campoIdPadre];
168
+ if (parentId) {
169
+ const padreAct = this.listaMuestraArbol.find((itm: any) => itm[this.campoId] == parentId);
170
+ if (padreAct) {
171
+ this.chkLista.setState(parentId, this.hijosActivos('checked', padreAct) || this.hijosActivos('indeterminate', padreAct));
172
+ this.cambiarPadre(padreAct, estado);
173
+ }
174
+ }
175
+ }
176
+
177
+ cambiarCheck(checkActual: T, estado: boolean): void {
178
+ if (this.hasChild(0, checkActual)) {
179
+ (this.treeControl.getChildren(checkActual) ?? []).forEach((vas: any) => {
180
+ this.cambiarCheck(vas, estado);
181
+ });
182
+ }
183
+ this.cambiarPadre(checkActual, estado);
184
+ this.chkLista.setState((checkActual as any)[this.campoId], estado);
185
+ }
186
+
187
+ hijosActivos(tipo: 'checked' | 'indeterminate', checkActual: T): boolean {
188
+ let totalHijos = 0;
189
+ let cantActivo = 0;
190
+ if (this.hasChild(0, checkActual)) {
191
+ (this.treeControl.getChildren(checkActual) ?? []).forEach((vas: any) => {
192
+ if (this.chkLista.getState(vas[this.campoId] + '')) {
193
+ cantActivo++;
194
+ }
195
+ totalHijos++;
196
+ });
197
+ }
198
+
199
+ switch (tipo) {
200
+ case 'checked':
201
+ return (cantActivo == totalHijos);
202
+ case 'indeterminate':
203
+ if (cantActivo == totalHijos) {
204
+ this.chkLista.setState((checkActual as any)[this.campoId], true);
205
+ }
206
+ return ((cantActivo > 0) && (cantActivo != totalHijos));
207
+ }
208
+ return false;
209
+ }
210
+
211
+
212
+ classFila2(item: T): string[] {
213
+ let clases: string[] = [];
214
+ if (this.campoAnulado && (item as any)[this.campoAnulado] === 1) {
215
+ clases = clases.concat(this.classAnulado);
216
+ }
217
+ if ((item as any)?.seleccionado) {
218
+ clases = clases.concat(this.classSeleccionado);
219
+ }
220
+ clases = clases.concat(this.condicionesClaseFila(item));
221
+ (item as any).claseFinal = clases;
222
+ return clases;
223
+ }
224
+
225
+ classFila(item: any) {
226
+ let claseFinal: any[] = [];
227
+ if (this.campoAnulado && (item[this.campoAnulado] == 1)) {
228
+ claseFinal = claseFinal.concat(this.classAnulado);
229
+ }
230
+ if (this.objSeleccionado == item || this.esSeleccionActual(item)) {
231
+ claseFinal = claseFinal.concat(this.classSeleccionado);
232
+ }
233
+ claseFinal = claseFinal.concat(this.condicionesClaseFila(item));
234
+ item.claseFinal = claseFinal;
235
+ return claseFinal;
236
+ }
237
+ }
238
+
@@ -0,0 +1,46 @@
1
+ export function generarArbol(params: {
2
+ lista: any[],
3
+ campoId: string,
4
+ campoIdPadre: string,
5
+ idPadre?: any,
6
+ strChildren?: string,
7
+ campoOrden?: string
8
+ }): any[] {
9
+ const {
10
+ lista,
11
+ campoId,
12
+ campoIdPadre,
13
+ idPadre = null,
14
+ strChildren = 'hijos',
15
+ campoOrden,
16
+ } = params;
17
+
18
+ const hijos = lista.filter(n => n[campoIdPadre] === idPadre);
19
+
20
+ if (campoOrden) {
21
+ hijos.sort((a, b) => {
22
+ const va = a[campoOrden];
23
+ const vb = b[campoOrden];
24
+
25
+ if (typeof va === 'string' && typeof vb === 'string') {
26
+ return va.localeCompare(vb);
27
+ }
28
+ if (typeof va === 'number' && typeof vb === 'number') {
29
+ return va - vb;
30
+ }
31
+ return 0;
32
+ });
33
+ }
34
+
35
+ return hijos.map(n => ({
36
+ ...n,
37
+ [strChildren]: generarArbol({
38
+ lista,
39
+ campoId,
40
+ campoIdPadre,
41
+ idPadre: n[campoId],
42
+ strChildren,
43
+ campoOrden,
44
+ }),
45
+ }));
46
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "lib": {
3
+ "entryFile": "public-api.ts"
4
+ }
5
+ }
@@ -0,0 +1 @@
1
+ export * from './lista-arbol.component';
Binary file
@@ -0,0 +1 @@
1
+ export * from './public-api'
@@ -0,0 +1,6 @@
1
+ <ng-container *ngIf="forzarMuestra || (mesActual == 12 && enProduccion)">
2
+ <ul class="lightrope">
3
+ <li *ngFor="let e of [].constructor(100); let i = index"></li>
4
+ </ul>
5
+ <div class="christmas-tree"></div>
6
+ </ng-container>
@@ -0,0 +1,24 @@
1
+ import {Component, Input, OnInit} from '@angular/core';
2
+ import {NgForOf, NgIf} from '@angular/common';
3
+
4
+ @Component({
5
+ selector: 'jvs-luces-navidad, [jvsLucesNavidad]',
6
+ templateUrl: './luces-navidad.component.html',
7
+ imports: [
8
+ NgIf,
9
+ NgForOf
10
+ ],
11
+ styleUrls: ['./luces-navidad.component.scss']
12
+ })
13
+ export class LucesNavidadComponent implements OnInit {
14
+ @Input() enProduccion = true;
15
+ @Input() forzarMuestra = false;
16
+ mesActual = new Date().getMonth() + 1;
17
+
18
+ constructor() {
19
+ }
20
+
21
+ ngOnInit(): void {
22
+ }
23
+
24
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "lib": {
3
+ "entryFile": "public-api.ts"
4
+ }
5
+ }
@@ -0,0 +1 @@
1
+ export * from './public-api'
@@ -0,0 +1,5 @@
1
+ <button matRipple type="button" class="boton-circular-gris"
2
+ (click)="emitirClick(); $event.preventDefault();"
3
+ >
4
+ <mat-icon [svgIcon]="(control.value ? 'roundCancel' : 'roundSearch')" class="icon-xs"></mat-icon>
5
+ </button>