libey-ng-component-library 0.0.32 → 0.0.34

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 (69) hide show
  1. package/karma.conf.js +44 -0
  2. package/ng-package.json +13 -0
  3. package/package.json +17 -24
  4. package/src/lib/cpm-indicator/libey-ng-cpm-indicator.component.css +216 -0
  5. package/src/lib/cpm-indicator/libey-ng-cpm-indicator.component.html +201 -0
  6. package/src/lib/cpm-indicator/libey-ng-cpm-indicator.component.spec.ts +25 -0
  7. package/src/lib/cpm-indicator/libey-ng-cpm-indicator.component.ts +203 -0
  8. package/src/lib/cpm-indicator/libey-ng-cpm-indicator.module.ts +19 -0
  9. package/src/lib/icons/icons.component.css +9 -0
  10. package/src/lib/icons/icons.module.ts +16 -0
  11. package/src/lib/icons/libey-ng-icons/libey-ng-icons.component.html +1831 -0
  12. package/src/lib/icons/libey-ng-icons/libey-ng-icons.component.ts +36 -0
  13. package/src/lib/libey-ng-component-library.component.spec.ts +25 -0
  14. package/src/lib/libey-ng-component-library.component.ts +20 -0
  15. package/src/lib/libey-ng-component-library.module.ts +32 -0
  16. package/src/lib/libey-ng-component-library.service.spec.ts +16 -0
  17. package/src/lib/libey-ng-component-library.service.ts +9 -0
  18. package/src/lib/signature/libey-ng-signature/libey-ng-signature.component.css +7 -0
  19. package/src/lib/signature/libey-ng-signature/libey-ng-signature.component.html +41 -0
  20. package/src/lib/signature/libey-ng-signature/libey-ng-signature.component.spec.ts +25 -0
  21. package/src/lib/signature/libey-ng-signature/libey-ng-signature.component.ts +214 -0
  22. package/src/lib/signature/libey-ng-signature.module.ts +30 -0
  23. package/src/lib/table/directives/libey-column.directive.ts +29 -0
  24. package/src/lib/table/libey-ng-table.component.css +249 -0
  25. package/src/lib/table/libey-ng-table.component.html +122 -0
  26. package/src/lib/table/libey-ng-table.component.ts +234 -0
  27. package/src/lib/table/libey-ng-table.module.ts +13 -0
  28. package/{public-api.d.ts → src/public-api.ts} +4 -0
  29. package/src/test.ts +28 -0
  30. package/src/utils/CpmIndicator/cpm-indicator-types.ts +63 -0
  31. package/src/utils/SigWeb/SigWeb.ts +1906 -0
  32. package/tsconfig.lib.json +20 -0
  33. package/tsconfig.lib.prod.json +10 -0
  34. package/tsconfig.spec.json +17 -0
  35. package/bundles/libey-ng-component-library.umd.js +0 -2497
  36. package/bundles/libey-ng-component-library.umd.js.map +0 -1
  37. package/esm2015/lib/cpm-indicator/libey-ng-cpm-indicator.component.js +0 -193
  38. package/esm2015/lib/cpm-indicator/libey-ng-cpm-indicator.module.js +0 -26
  39. package/esm2015/lib/icons/icons.module.js +0 -26
  40. package/esm2015/lib/icons/libey-ng-icons/libey-ng-icons.component.js +0 -52
  41. package/esm2015/lib/libey-ng-component-library.component.js +0 -26
  42. package/esm2015/lib/libey-ng-component-library.module.js +0 -60
  43. package/esm2015/lib/libey-ng-component-library.service.js +0 -14
  44. package/esm2015/lib/signature/libey-ng-signature/libey-ng-signature.component.js +0 -197
  45. package/esm2015/lib/signature/libey-ng-signature.module.js +0 -57
  46. package/esm2015/lib/table/directives/libey-column.directive.js +0 -56
  47. package/esm2015/lib/table/libey-ng-table.component.js +0 -229
  48. package/esm2015/lib/table/libey-ng-table.module.js +0 -21
  49. package/esm2015/libey-ng-component-library.js +0 -5
  50. package/esm2015/public-api.js +0 -23
  51. package/esm2015/utils/CpmIndicator/cpm-indicator-types.js +0 -25
  52. package/esm2015/utils/SigWeb/SigWeb.js +0 -1442
  53. package/fesm2015/libey-ng-component-library.js +0 -2393
  54. package/fesm2015/libey-ng-component-library.js.map +0 -1
  55. package/lib/cpm-indicator/libey-ng-cpm-indicator.component.d.ts +0 -66
  56. package/lib/cpm-indicator/libey-ng-cpm-indicator.module.d.ts +0 -8
  57. package/lib/icons/icons.module.d.ts +0 -8
  58. package/lib/icons/libey-ng-icons/libey-ng-icons.component.d.ts +0 -19
  59. package/lib/libey-ng-component-library.component.d.ts +0 -8
  60. package/lib/libey-ng-component-library.module.d.ts +0 -13
  61. package/lib/libey-ng-component-library.service.d.ts +0 -6
  62. package/lib/signature/libey-ng-signature/libey-ng-signature.component.d.ts +0 -40
  63. package/lib/signature/libey-ng-signature.module.d.ts +0 -13
  64. package/lib/table/directives/libey-column.directive.d.ts +0 -23
  65. package/lib/table/libey-ng-table.component.d.ts +0 -63
  66. package/lib/table/libey-ng-table.module.d.ts +0 -10
  67. package/libey-ng-component-library.d.ts +0 -5
  68. package/utils/CpmIndicator/cpm-indicator-types.d.ts +0 -40
  69. package/utils/SigWeb/SigWeb.d.ts +0 -219
@@ -0,0 +1,203 @@
1
+ import { Component, Input, OnInit, OnChanges, SimpleChanges, Output, EventEmitter, ViewChild, TemplateRef } from '@angular/core';
2
+ import { CpmIndicatorMode,CpmItemType,CpmItem,CpmThresholds,CpmSummary,ZoneColor,SvgPoint,DEFAULT_THRESHOLDS,ZONE_COLORS, CpmColorState,} from '../../utils/CpmIndicator/cpm-indicator-types';
3
+
4
+ @Component({
5
+ selector: 'lib-libey-ng-cpm-indicator',
6
+ templateUrl: './libey-ng-cpm-indicator.component.html',
7
+ styleUrls: ['./libey-ng-cpm-indicator.component.css']
8
+ })
9
+ export class LibeyNgCpmIndicatorComponent implements OnInit, OnChanges {
10
+
11
+ /** Tope máximo del contrato. */
12
+ @Input() limit: number = 250;
13
+
14
+ /**
15
+ * Ítems de gasto. El padre es responsable de:
16
+ * - Excluir ítems que no aplican al CPM
17
+ * - Marcar cada uno con CpmItemType.Base o CpmItemType.Projected
18
+ * - Actualizar el array al agregar o eliminar
19
+ */
20
+ @Input() items: CpmItem[] = [];
21
+
22
+ /** Símbolo de moneda. Por defecto 's/' (sol peruano). */
23
+ @Input() currency: string = 's/';
24
+
25
+ /** Umbrales de zonas como porcentaje del límite (0.0 → 1.0). Usa tercios si no se proporciona. */
26
+ @Input() thresholds?: CpmThresholds;
27
+
28
+ /** Modo de visualización: CPM (solo gauge) o Gauge (montos + leyenda). */
29
+ @Input() mode: CpmIndicatorMode = CpmIndicatorMode.Cpm;
30
+
31
+ /** Activa sliders de prueba. Solo para desarrollo, nunca en producción. */
32
+ @Input() devMode: boolean = false;
33
+
34
+ // ── Outputs ──
35
+ /** Emite el resumen de montos en cada recalculo. Usar para persistir en BD. */
36
+ @Output() cpmChange = new EventEmitter<CpmSummary>();
37
+
38
+ /** Emite true cuando la proyección supera el límite. */
39
+ @Output() limitExceeded = new EventEmitter<boolean>();
40
+
41
+ @ViewChild('cpmLegend') cpmLegend!: TemplateRef<any>;
42
+
43
+ @Output() colorChange = new EventEmitter<CpmColorState>();
44
+
45
+ @Input() scale: number = 1;
46
+
47
+ // ── Propiedades del template ──
48
+ baseAmount: number = 0;
49
+ projectedAmount: number = 0;
50
+ totalAmount: number = 0;
51
+ excess: number = 0;
52
+ activeColors: ZoneColor = ZONE_COLORS['zone1'];
53
+
54
+ trackArcPath: string = '';
55
+ baseArcPath: string = '';
56
+ totalArcPath: string = '';
57
+ dotBasePos: SvgPoint = { x: 0, y: 0 };
58
+ dotTotalPos: SvgPoint = { x: 0, y: 0 };
59
+ dotTotalVisible: boolean = false;
60
+ limitTextPos: SvgPoint = { x: 0, y: 0 };
61
+
62
+ // ── devMode ──
63
+ sliderBase: number = 0;
64
+ sliderProjected: number = 0;
65
+
66
+ get sliderMax(): number {
67
+ return this.limit * 1.5;
68
+ }
69
+
70
+ // Necesario para usar el enum en el template
71
+ readonly CpmIndicatorMode = CpmIndicatorMode;
72
+
73
+ // Geometría del SVG (coordenadas internas del viewBox 220x130)
74
+ private readonly CX = 110;
75
+ private readonly CY = 115;
76
+ private readonly R = 90;
77
+ private readonly ANGLE_START = Math.PI;
78
+ private readonly ANGLE_END = 0;
79
+
80
+ private readonly EXCESS_TOLERANCE = 0.005;
81
+
82
+ constructor() {}
83
+
84
+ ngOnInit(): void {
85
+ this.recalculate();
86
+ }
87
+
88
+ ngOnChanges(changes: SimpleChanges): void {
89
+ if (changes['items'] || changes['limit'] || changes['thresholds']) {
90
+ this.recalculate();
91
+ }
92
+ }
93
+
94
+ onDevBaseChange(event: Event): void {
95
+ this.sliderBase = parseFloat((event.target as HTMLInputElement).value);
96
+ if (this.sliderBase > this.sliderProjected) {
97
+ this.sliderProjected = this.sliderBase;
98
+ }
99
+ this.recalculateFromSliders();
100
+ }
101
+
102
+ onDevProjectedChange(event: Event): void {
103
+ this.sliderProjected = parseFloat((event.target as HTMLInputElement).value);
104
+ if (this.sliderProjected < this.sliderBase) {
105
+ this.sliderProjected = this.sliderBase;
106
+ }
107
+ this.recalculateFromSliders();
108
+ }
109
+
110
+ // Flujo de producción: calcula a partir del array de items
111
+ private recalculate(): void {
112
+ this.baseAmount = this.items
113
+ .filter(i => i.type === CpmItemType.Base)
114
+ .reduce((acc, i) => acc + i.amount, 0);
115
+
116
+ this.projectedAmount = this.items
117
+ .filter(i => i.type === CpmItemType.Projected)
118
+ .reduce((acc, i) => acc + i.amount, 0);
119
+
120
+ this.totalAmount = this.baseAmount + this.projectedAmount;
121
+
122
+ // Sincroniza sliders por si se activa devMode
123
+ this.sliderBase = this.baseAmount;
124
+ this.sliderProjected = this.totalAmount;
125
+
126
+ this.updateGauge();
127
+ this.emitSummary();
128
+ }
129
+
130
+ // Flujo de devMode: calcula a partir de los sliders
131
+ private recalculateFromSliders(): void {
132
+ this.baseAmount = this.sliderBase;
133
+ this.projectedAmount = this.sliderProjected - this.sliderBase;
134
+ this.totalAmount = this.sliderProjected;
135
+
136
+ this.updateGauge();
137
+ this.emitSummary();
138
+ }
139
+
140
+ private updateGauge(): void {
141
+ const thresholds = this.thresholds ?? DEFAULT_THRESHOLDS;
142
+ this.activeColors = this.getZoneColors(this.totalAmount, thresholds);
143
+
144
+ this.trackArcPath = this.buildArcPath(this.ANGLE_START, this.ANGLE_END);
145
+ this.totalArcPath = this.buildArcPath(this.ANGLE_START, this.valueToAngle(this.totalAmount));
146
+ this.baseArcPath = this.buildArcPath(this.ANGLE_START, this.valueToAngle(this.baseAmount));
147
+
148
+ this.dotBasePos = this.polar(this.valueToAngle(this.baseAmount));
149
+ this.dotTotalPos = this.polar(this.valueToAngle(this.totalAmount));
150
+
151
+ // El punto de proyección solo aparece si va delante del real y no llegó al borde
152
+ this.dotTotalVisible = this.totalAmount > this.baseAmount && this.totalAmount < this.limit;
153
+
154
+ this.limitTextPos = this.polar(this.ANGLE_END, this.R + 20);
155
+
156
+ this.excess = Math.max(0, this.totalAmount - this.limit);
157
+ this.limitExceeded.emit(this.excess > this.EXCESS_TOLERANCE);
158
+
159
+ this.colorChange.emit({
160
+ darkColor: this.activeColors.dark,
161
+ lightColor: this.activeColors.light,
162
+ grayColor: '#E8EAEF',
163
+ limitReached: this.totalAmount >= this.limit,
164
+ });
165
+ }
166
+
167
+ private emitSummary(): void {
168
+ this.cpmChange.emit({
169
+ baseAmount: this.baseAmount,
170
+ projectedAmount: this.projectedAmount,
171
+ totalAmount: this.totalAmount,
172
+ limit: this.limit,
173
+ });
174
+ }
175
+
176
+ // Clampea el valor al límite para que el arco no desborde visualmente
177
+ private valueToAngle(value: number): number {
178
+ const clamped = Math.min(value, this.limit);
179
+ return Math.PI - (clamped / this.limit) * Math.PI;
180
+ }
181
+
182
+ private polar(angle: number, radius: number = this.R): SvgPoint {
183
+ return {
184
+ x: this.CX + radius * Math.cos(angle),
185
+ y: this.CY - radius * Math.sin(angle),
186
+ };
187
+ }
188
+
189
+ private buildArcPath(a1: number, a2: number): string {
190
+ const start = this.polar(a1);
191
+ const end = this.polar(a2);
192
+ const large = (a1 - a2) > Math.PI ? 1 : 0;
193
+ return `M ${start.x} ${start.y} A ${this.R} ${this.R} 0 ${large} 1 ${end.x} ${end.y}`;
194
+ }
195
+
196
+ private getZoneColors(value: number, t: CpmThresholds): ZoneColor {
197
+ const pct = value / this.limit;
198
+ if (pct < t.zone1Max) return ZONE_COLORS['zone1'];
199
+ if (pct < t.zone2Max) return ZONE_COLORS['zone2'];
200
+ if (pct < t.zone3Max) return ZONE_COLORS['zone3'];
201
+ return ZONE_COLORS['zone4'];
202
+ }
203
+ }
@@ -0,0 +1,19 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { LibeyNgCpmIndicatorComponent } from './libey-ng-cpm-indicator.component';
4
+ import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
5
+
6
+
7
+
8
+ @NgModule({
9
+ declarations: [
10
+ LibeyNgCpmIndicatorComponent
11
+ ],
12
+ imports: [
13
+ CommonModule
14
+ ],
15
+ exports: [
16
+ LibeyNgCpmIndicatorComponent
17
+ ]
18
+ })
19
+ export class LibeyNgCpmIndicatorModule { }
@@ -0,0 +1,9 @@
1
+ .d-inline-flex {
2
+ display: inline-flex;
3
+ }
4
+
5
+ button:disabled {
6
+ svg path {
7
+ fill: #ABBED1 !important;
8
+ }
9
+ }
@@ -0,0 +1,16 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { LibeyNgIconsComponent } from './libey-ng-icons/libey-ng-icons.component';
4
+
5
+ @NgModule({
6
+ declarations: [
7
+ LibeyNgIconsComponent
8
+ ],
9
+ imports: [
10
+ CommonModule
11
+ ],
12
+ exports: [
13
+ LibeyNgIconsComponent
14
+ ]
15
+ })
16
+ export class IconsModule { }