ngx-sumax-erp-components 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/esm2022/lib/sumax-dashboard/cards/smx-dash-card-basic/smx-dash-card-basic.component.mjs +45 -0
  2. package/esm2022/lib/sumax-dashboard/cards/smx-dash-card-doughnut-ext-labels/smx-dash-card-doughnut-ext-labels.component.mjs +273 -0
  3. package/esm2022/lib/sumax-dashboard/cards/smx-dash-card-kpi-legend/smx-dash-card-kpi-legend.component.mjs +125 -0
  4. package/esm2022/lib/sumax-dashboard/cards/smx-dash-card-legend-chart/smx-dash-card-legend-chart.component.mjs +292 -0
  5. package/esm2022/lib/sumax-dashboard/cards/smx-dash-card-legend-chart-select/smx-dash-card-legend-chart-select.component.mjs +276 -0
  6. package/esm2022/lib/sumax-dashboard/cards/smx-dash-card-legend-chart-tabs/smx-dash-card-legend-chart-tabs.component.mjs +226 -0
  7. package/esm2022/lib/sumax-dashboard/cards/smx-dash-card-metric-list/smx-dash-card-metric-list.component.mjs +80 -0
  8. package/esm2022/lib/sumax-dashboard/cards/smx-dash-card-ranking/smx-dash-card-ranking.component.mjs +98 -0
  9. package/esm2022/lib/sumax-dashboard/cards/smx-dash-card-table/smx-dash-card-table.component.mjs +294 -0
  10. package/esm2022/lib/sumax-dashboard/models/chart-data.mjs +2 -0
  11. package/esm2022/lib/sumax-dashboard/smx-dash-body/smx-dash-body.component.mjs +31 -0
  12. package/esm2022/lib/sumax-dashboard/smx-dash-grid/smx-dash-grid.component.mjs +271 -0
  13. package/esm2022/lib/sumax-dashboard/smx-dash-head/smx-dash-head.component.mjs +76 -0
  14. package/esm2022/lib/sumax-dashboard/smx-dash-head-filters/smx-dash-head-filters.component.mjs +476 -0
  15. package/esm2022/lib/sumax-dashboard/smx-dash-head-title/smx-dash-head-title.component.mjs +23 -0
  16. package/esm2022/lib/sumax-dashboard/smx-dash-head-widgets/smx-dash-head-widgets.component.mjs +21 -0
  17. package/esm2022/lib/sumax-dashboard/sumax-dashboard.component.mjs +191 -0
  18. package/esm2022/lib/sumax-dashboard/types/types.mjs +15 -0
  19. package/esm2022/lib/sumax-dashboard/utils/chart-setup.mjs +46 -0
  20. package/esm2022/lib/sumax-dashboard/utils/dashboard-integration.utils.mjs +124 -0
  21. package/esm2022/public-api.mjs +17 -4
  22. package/fesm2022/ngx-sumax-erp-components.mjs +2913 -13
  23. package/fesm2022/ngx-sumax-erp-components.mjs.map +1 -1
  24. package/lib/sumax-dashboard/cards/smx-dash-card-basic/smx-dash-card-basic.component.d.ts +25 -0
  25. package/lib/sumax-dashboard/cards/smx-dash-card-doughnut-ext-labels/smx-dash-card-doughnut-ext-labels.component.d.ts +66 -0
  26. package/lib/sumax-dashboard/cards/smx-dash-card-kpi-legend/smx-dash-card-kpi-legend.component.d.ts +40 -0
  27. package/lib/sumax-dashboard/cards/smx-dash-card-legend-chart/smx-dash-card-legend-chart.component.d.ts +109 -0
  28. package/lib/sumax-dashboard/cards/smx-dash-card-legend-chart-select/smx-dash-card-legend-chart-select.component.d.ts +91 -0
  29. package/lib/sumax-dashboard/cards/smx-dash-card-legend-chart-tabs/smx-dash-card-legend-chart-tabs.component.d.ts +77 -0
  30. package/lib/sumax-dashboard/cards/smx-dash-card-metric-list/smx-dash-card-metric-list.component.d.ts +48 -0
  31. package/lib/sumax-dashboard/cards/smx-dash-card-ranking/smx-dash-card-ranking.component.d.ts +48 -0
  32. package/lib/sumax-dashboard/cards/smx-dash-card-table/smx-dash-card-table.component.d.ts +78 -0
  33. package/lib/sumax-dashboard/models/chart-data.d.ts +23 -0
  34. package/lib/sumax-dashboard/smx-dash-body/smx-dash-body.component.d.ts +25 -0
  35. package/lib/sumax-dashboard/smx-dash-grid/smx-dash-grid.component.d.ts +52 -0
  36. package/lib/sumax-dashboard/smx-dash-head/smx-dash-head.component.d.ts +39 -0
  37. package/lib/sumax-dashboard/smx-dash-head-filters/smx-dash-head-filters.component.d.ts +114 -0
  38. package/lib/sumax-dashboard/smx-dash-head-title/smx-dash-head-title.component.d.ts +9 -0
  39. package/lib/sumax-dashboard/smx-dash-head-widgets/smx-dash-head-widgets.component.d.ts +11 -0
  40. package/lib/sumax-dashboard/sumax-dashboard.component.d.ts +120 -0
  41. package/lib/sumax-dashboard/types/types.d.ts +148 -0
  42. package/lib/sumax-dashboard/utils/chart-setup.d.ts +39 -0
  43. package/lib/sumax-dashboard/utils/dashboard-integration.utils.d.ts +53 -0
  44. package/package.json +1 -1
  45. package/public-api.d.ts +16 -3
@@ -0,0 +1,45 @@
1
+ import { CommonModule } from "@angular/common";
2
+ import { ChangeDetectionStrategy, Component, Input } from "@angular/core";
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/common";
5
+ export class SmxDashCardBasicComponent {
6
+ constructor() {
7
+ /** Título del widget. Puede estar vacío si `showTitle` es `false`. @default "" */
8
+ this.title = "";
9
+ /** Controla la visibilidad del título en la cabecera del card. @default true */
10
+ this.showTitle = true;
11
+ /** Estilos CSS inline adicionales para el elemento del título. @default {} */
12
+ this.titleStyle = {};
13
+ /** Alineación horizontal del título. Propagado desde `extra.titleHAlign`. @default "center" */
14
+ this.titleHAlign = "center";
15
+ /** Alineación vertical del contenido. Propagado desde `extra.contentVAlign`. @default "center" */
16
+ this.contentVAlign = "center";
17
+ /** Alineación horizontal del contenido. Propagado desde `extra.contentHAlign`. @default "center" */
18
+ this.contentHAlign = "center";
19
+ }
20
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmxDashCardBasicComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
21
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: SmxDashCardBasicComponent, isStandalone: true, selector: "smx-dash-card-basic", inputs: { title: "title", showTitle: "showTitle", titleStyle: "titleStyle", titleHAlign: "titleHAlign", contentVAlign: "contentVAlign", contentHAlign: "contentHAlign", value: "value", formatters: "formatters", i18n: "i18n" }, ngImport: i0, template: "<div class=\"smx-card-basic\">\n <div class=\"smx-card-basic-title\" *ngIf=\"showTitle\" [ngStyle]=\"titleStyle\">{{ title }}</div>\n <div class=\"smx-card-basic-value\">{{ value ?? \"Sin datos\" }}</div>\n</div>\n", styles: [".smx-card-basic{display:grid;gap:6px;place-items:center;width:100%;height:100%}.smx-card-basic-title{font-size:13px;opacity:.8}.smx-card-basic-value{font-size:22px;font-weight:600}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
22
+ }
23
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmxDashCardBasicComponent, decorators: [{
24
+ type: Component,
25
+ args: [{ selector: "smx-dash-card-basic", standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"smx-card-basic\">\n <div class=\"smx-card-basic-title\" *ngIf=\"showTitle\" [ngStyle]=\"titleStyle\">{{ title }}</div>\n <div class=\"smx-card-basic-value\">{{ value ?? \"Sin datos\" }}</div>\n</div>\n", styles: [".smx-card-basic{display:grid;gap:6px;place-items:center;width:100%;height:100%}.smx-card-basic-title{font-size:13px;opacity:.8}.smx-card-basic-value{font-size:22px;font-weight:600}\n"] }]
26
+ }], propDecorators: { title: [{
27
+ type: Input
28
+ }], showTitle: [{
29
+ type: Input
30
+ }], titleStyle: [{
31
+ type: Input
32
+ }], titleHAlign: [{
33
+ type: Input
34
+ }], contentVAlign: [{
35
+ type: Input
36
+ }], contentHAlign: [{
37
+ type: Input
38
+ }], value: [{
39
+ type: Input
40
+ }], formatters: [{
41
+ type: Input
42
+ }], i18n: [{
43
+ type: Input
44
+ }] } });
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic214LWRhc2gtY2FyZC1iYXNpYy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc3VtYXgtZXJwLWNvbXBvbmVudC9zcmMvbGliL3N1bWF4LWRhc2hib2FyZC9jYXJkcy9zbXgtZGFzaC1jYXJkLWJhc2ljL3NteC1kYXNoLWNhcmQtYmFzaWMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXN1bWF4LWVycC1jb21wb25lbnQvc3JjL2xpYi9zdW1heC1kYXNoYm9hcmQvY2FyZHMvc214LWRhc2gtY2FyZC1iYXNpYy9zbXgtZGFzaC1jYXJkLWJhc2ljLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQzs7O0FBVTFFLE1BQU0sT0FBTyx5QkFBeUI7SUFSdEM7UUFTRSxrRkFBa0Y7UUFDekUsVUFBSyxHQUFHLEVBQUUsQ0FBQztRQUNwQixnRkFBZ0Y7UUFDdkUsY0FBUyxHQUFHLElBQUksQ0FBQztRQUMxQiw4RUFBOEU7UUFDckUsZUFBVSxHQUEyQixFQUFFLENBQUM7UUFDakQsK0ZBQStGO1FBQ3RGLGdCQUFXLEdBQWdDLFFBQVEsQ0FBQztRQUM3RCxrR0FBa0c7UUFDekYsa0JBQWEsR0FBZ0MsUUFBUSxDQUFDO1FBQy9ELG9HQUFvRztRQUMzRixrQkFBYSxHQUFnQyxRQUFRLENBQUM7S0FPaEU7K0dBbkJZLHlCQUF5QjttR0FBekIseUJBQXlCLGlUQ1h0QywwTkFJQSwrT0RFWSxZQUFZOzs0RkFLWCx5QkFBeUI7a0JBUnJDLFNBQVM7K0JBQ0UscUJBQXFCLGNBQ25CLElBQUksV0FDUCxDQUFDLFlBQVksQ0FBQyxtQkFHTix1QkFBdUIsQ0FBQyxNQUFNOzhCQUl0QyxLQUFLO3NCQUFiLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsYUFBYTtzQkFBckIsS0FBSztnQkFFRyxhQUFhO3NCQUFyQixLQUFLO2dCQUVHLEtBQUs7c0JBQWIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcbmltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIElucHV0IH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcInNteC1kYXNoLWNhcmQtYmFzaWNcIixcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIHRlbXBsYXRlVXJsOiBcIi4vc214LWRhc2gtY2FyZC1iYXNpYy5jb21wb25lbnQuaHRtbFwiLFxuICBzdHlsZVVybHM6IFtcIi4vc214LWRhc2gtY2FyZC1iYXNpYy5jb21wb25lbnQuc2Nzc1wiXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFNteERhc2hDYXJkQmFzaWNDb21wb25lbnQge1xuICAvKiogVMOtdHVsbyBkZWwgd2lkZ2V0LiBQdWVkZSBlc3RhciB2YWPDrW8gc2kgYHNob3dUaXRsZWAgZXMgYGZhbHNlYC4gQGRlZmF1bHQgXCJcIiAqL1xuICBASW5wdXQoKSB0aXRsZSA9IFwiXCI7XG4gIC8qKiBDb250cm9sYSBsYSB2aXNpYmlsaWRhZCBkZWwgdMOtdHVsbyBlbiBsYSBjYWJlY2VyYSBkZWwgY2FyZC4gQGRlZmF1bHQgdHJ1ZSAqL1xuICBASW5wdXQoKSBzaG93VGl0bGUgPSB0cnVlO1xuICAvKiogRXN0aWxvcyBDU1MgaW5saW5lIGFkaWNpb25hbGVzIHBhcmEgZWwgZWxlbWVudG8gZGVsIHTDrXR1bG8uIEBkZWZhdWx0IHt9ICovXG4gIEBJbnB1dCgpIHRpdGxlU3R5bGU6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgLyoqIEFsaW5lYWNpw7NuIGhvcml6b250YWwgZGVsIHTDrXR1bG8uIFByb3BhZ2FkbyBkZXNkZSBgZXh0cmEudGl0bGVIQWxpZ25gLiBAZGVmYXVsdCBcImNlbnRlclwiICovXG4gIEBJbnB1dCgpIHRpdGxlSEFsaWduOiBcImxlZnRcIiB8IFwiY2VudGVyXCIgfCBcInJpZ2h0XCIgPSBcImNlbnRlclwiO1xuICAvKiogQWxpbmVhY2nDs24gdmVydGljYWwgZGVsIGNvbnRlbmlkby4gUHJvcGFnYWRvIGRlc2RlIGBleHRyYS5jb250ZW50VkFsaWduYC4gQGRlZmF1bHQgXCJjZW50ZXJcIiAqL1xuICBASW5wdXQoKSBjb250ZW50VkFsaWduOiBcInRvcFwiIHwgXCJjZW50ZXJcIiB8IFwiYm90dG9tXCIgPSBcImNlbnRlclwiO1xuICAvKiogQWxpbmVhY2nDs24gaG9yaXpvbnRhbCBkZWwgY29udGVuaWRvLiBQcm9wYWdhZG8gZGVzZGUgYGV4dHJhLmNvbnRlbnRIQWxpZ25gLiBAZGVmYXVsdCBcImNlbnRlclwiICovXG4gIEBJbnB1dCgpIGNvbnRlbnRIQWxpZ246IFwibGVmdFwiIHwgXCJjZW50ZXJcIiB8IFwicmlnaHRcIiA9IFwiY2VudGVyXCI7XG4gIC8qKiBWYWxvciBwcmluY2lwYWwgYSBtb3N0cmFyIGVuIGVsIGNhcmQgKHRleHRvIG8gbsO6bWVybykuICovXG4gIEBJbnB1dCgpIHZhbHVlPzogc3RyaW5nIHwgbnVtYmVyO1xuICAvKiogTWFwYSBkZSBmdW5jaW9uZXMgZGUgZm9ybWF0ZW8gcHJvcGFnYWRvIGRlc2RlIGVsIGdyaWQgKHVzbyBpbnRlcm5vIC8gZXh0ZW5zaWJsZSkuICovXG4gIEBJbnB1dCgpIGZvcm1hdHRlcnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAvKiogSW50ZXJuYWNpb25hbGl6YWNpw7NuIHByb3BhZ2FkYSBkZXNkZSBlbCBncmlkLiAqL1xuICBASW5wdXQoKSBpMThuPzogeyBtb250aHM/OiBzdHJpbmdbXSB9O1xufVxuIiwiPGRpdiBjbGFzcz1cInNteC1jYXJkLWJhc2ljXCI+XG4gIDxkaXYgY2xhc3M9XCJzbXgtY2FyZC1iYXNpYy10aXRsZVwiICpuZ0lmPVwic2hvd1RpdGxlXCIgW25nU3R5bGVdPVwidGl0bGVTdHlsZVwiPnt7IHRpdGxlIH19PC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJzbXgtY2FyZC1iYXNpYy12YWx1ZVwiPnt7IHZhbHVlID8/IFwiU2luIGRhdG9zXCIgfX08L2Rpdj5cbjwvZGl2PlxuIl19
@@ -0,0 +1,273 @@
1
+ import { CommonModule } from "@angular/common";
2
+ import { ChangeDetectionStrategy, Component, Input, ViewChild } from "@angular/core";
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/common";
5
+ export class SmxDashCardDoughnutExtLabelsComponent {
6
+ constructor() {
7
+ /** Título del widget. @default "" */
8
+ this.title = "";
9
+ /** Controla la visibilidad del título. @default false */
10
+ this.showTitle = false;
11
+ /** Estilos CSS inline adicionales para el elemento del título. @default {} */
12
+ this.titleStyle = {};
13
+ /** Alineación horizontal del título. @default "center" */
14
+ this.titleHAlign = "center";
15
+ /** Alineación vertical del contenido. @default "center" */
16
+ this.contentVAlign = "center";
17
+ /** Alineación horizontal del contenido. @default "center" */
18
+ this.contentHAlign = "center";
19
+ /** Items del gráfico doughnut. Cada item tiene `label`, `value` y `color`. @default [] */
20
+ this.items = [];
21
+ /** Controla la visibilidad de la leyenda nativa lateral de Chart.js. @default false */
22
+ this.legendVisible = false;
23
+ /** Ancho fijo del canvas en píxeles (0 = automático basado en el contenedor). @default 0 */
24
+ this.chartWidth = 0;
25
+ /** Alto fijo del canvas en píxeles (0 = automático basado en el contenedor). @default 0 */
26
+ this.chartHeight = 0;
27
+ /** Opciones de formateo numérico para los valores en leyenda y resumen. @default {} */
28
+ this.numberFormat = {};
29
+ /** Items de la leyenda inferior (debajo del gráfico). Cada item tiene `label`, `value` y `color` opcional. @default [] */
30
+ this.bottomLegendItems = [];
31
+ /** Items del bloque resumen. Cada item tiene `label` y `value`. @default [] */
32
+ this.summaryItems = [];
33
+ /** Estilos CSS inline adicionales para el contenedor de la leyenda inferior. @default {} */
34
+ this.bottomLegendStyle = {};
35
+ /** Estilos CSS inline adicionales para el bloque de resumen. @default {} */
36
+ this.summaryStyle = {};
37
+ }
38
+ ngOnChanges() {
39
+ this._initW = undefined;
40
+ this._initH = undefined;
41
+ this._draw();
42
+ }
43
+ ngAfterViewInit() {
44
+ this._draw();
45
+ }
46
+ /** Formatea un valor numérico usando `numberFormat`. Si `numberFormat` está vacío, retorna el valor como string sin modificar. */
47
+ fmtValue(v) {
48
+ const num = Number(v ?? 0);
49
+ if (!Object.keys(this.numberFormat).length)
50
+ return String(v ?? "");
51
+ const locale = this.numberFormat.locale ?? "es-PE";
52
+ return num.toLocaleString(locale, {
53
+ useGrouping: this.numberFormat.useGrouping ?? true,
54
+ minimumFractionDigits: this.numberFormat.minimumFractionDigits ?? 0,
55
+ maximumFractionDigits: this.numberFormat.maximumFractionDigits ?? 2,
56
+ });
57
+ }
58
+ async _draw() {
59
+ const el = this.canvas?.nativeElement;
60
+ if (!el)
61
+ return;
62
+ const ctx = el.getContext("2d");
63
+ if (!ctx)
64
+ return;
65
+ const ChartGlobal = globalThis.Chart;
66
+ if (ChartGlobal) {
67
+ this._drawChartMode(el, ChartGlobal);
68
+ return;
69
+ }
70
+ this._drawCanvasFallback(el, ctx);
71
+ }
72
+ _drawChartMode(el, ChartGlobal) {
73
+ if (this.chart && this.chart.destroy) {
74
+ this.chart.destroy();
75
+ }
76
+ if (!this._initW) {
77
+ this._initW = this.chartWidth !== "auto" && this.chartWidth > 0 ? this.chartWidth : Math.max(300, Math.ceil(el.clientWidth || 360));
78
+ }
79
+ if (!this._initH) {
80
+ this._initH =
81
+ this.chartHeight !== "auto" && this.chartHeight > 0 ? this.chartHeight : Math.max(200, Math.ceil(el.clientHeight || 240));
82
+ }
83
+ el.width = this._initW;
84
+ el.height = this._initH;
85
+ const labels = (this.items ?? []).map((x) => x.label);
86
+ const data = (this.items ?? []).map((x) => x.value ?? 0);
87
+ const bg = (this.items ?? []).map((x) => x.color || "#3f51b5");
88
+ const ChartCtor = ChartGlobal;
89
+ const extLabels = {
90
+ id: "extLabels",
91
+ afterDatasetsDraw: (chart) => {
92
+ const meta = chart.getDatasetMeta(0);
93
+ const items = labels.map((l, i) => ({ label: l, value: data[i], color: bg[i] }));
94
+ const c = chart.ctx;
95
+ c.save();
96
+ c.font = "12px Arial";
97
+ c.textBaseline = "middle";
98
+ meta.data.forEach((el, i) => {
99
+ const mid = (el.startAngle + el.endAngle) / 2;
100
+ const r = el.outerRadius + 32;
101
+ const x = el.x;
102
+ const y = el.y;
103
+ let px = x + Math.cos(mid) * r;
104
+ let py = y + Math.sin(mid) * r;
105
+ const margin = 12;
106
+ const left = chart.chartArea.left + margin;
107
+ const right = chart.chartArea.right - margin;
108
+ const top = chart.chartArea.top + margin;
109
+ const bottom = chart.chartArea.bottom - margin;
110
+ if (px < left)
111
+ px = left;
112
+ if (px > right)
113
+ px = right;
114
+ if (py < top)
115
+ py = top;
116
+ if (py > bottom)
117
+ py = bottom;
118
+ c.fillStyle = items[i]?.color || "#424242";
119
+ const label = String(items[i]?.label ?? "");
120
+ const valueStr = this.fmtValue(items[i]?.value ?? 0);
121
+ const full = label + ": " + valueStr;
122
+ const cosv = Math.cos(mid);
123
+ if (Math.abs(cosv) > 0.45)
124
+ c.textAlign = cosv > 0 ? "left" : "right";
125
+ else
126
+ c.textAlign = "center";
127
+ let maxW;
128
+ if (c.textAlign === "left")
129
+ maxW = right - px;
130
+ else if (c.textAlign === "right")
131
+ maxW = px - left;
132
+ else
133
+ maxW = Math.min(right - px, px - left);
134
+ const needsWrap = c.measureText(full).width > Math.max(60, maxW - 6);
135
+ if (needsWrap) {
136
+ const line1 = label + ":";
137
+ const line2 = valueStr;
138
+ c.fillText(line1, px, py - 8);
139
+ c.fillText(line2, px, py + 8);
140
+ }
141
+ else {
142
+ c.fillText(full, px, py);
143
+ }
144
+ });
145
+ c.restore();
146
+ },
147
+ };
148
+ this.chart = new ChartCtor(el, {
149
+ type: "doughnut",
150
+ data: { labels, datasets: [{ data, backgroundColor: bg, radius: "65%" }] },
151
+ options: {
152
+ responsive: false,
153
+ // Compatibilidad Chart.js v2: lee options.legend en lugar de options.plugins.legend
154
+ legend: { display: this.legendVisible },
155
+ plugins: {
156
+ legend: { display: this.legendVisible },
157
+ tooltip: {
158
+ enabled: true,
159
+ ...(Object.keys(this.numberFormat).length
160
+ ? { callbacks: { label: (ctx) => `${ctx.label ?? ""}: ${this.fmtValue(ctx.raw ?? 0)}` } }
161
+ : {}),
162
+ },
163
+ },
164
+ layout: { padding: 32 },
165
+ cutout: "55%",
166
+ radius: "65%",
167
+ },
168
+ plugins: [extLabels],
169
+ });
170
+ }
171
+ _drawCanvasFallback(el, ctx) {
172
+ const w = el.width, h = el.height;
173
+ ctx.clearRect(0, 0, w, h);
174
+ const total = (this.items ?? []).reduce((acc, it) => acc + Number(it.value ?? 0), 0);
175
+ if (!total)
176
+ return;
177
+ const radius = Math.min(w, h) / 4.2;
178
+ const cx = w / 2, cy = h / 2;
179
+ let start = -Math.PI / 2;
180
+ for (const it of this.items) {
181
+ const frac = Number(it.value ?? 0) / total;
182
+ const end = start + frac * Math.PI * 2;
183
+ ctx.beginPath();
184
+ ctx.moveTo(cx, cy);
185
+ ctx.arc(cx, cy, radius, start, end);
186
+ ctx.closePath();
187
+ ctx.fillStyle = it.color || "#3f51b5";
188
+ ctx.fill();
189
+ const mid = (start + end) / 2;
190
+ const rr = radius + 28;
191
+ const px = cx + Math.cos(mid) * rr;
192
+ const py = cy + Math.sin(mid) * rr;
193
+ ctx.fillStyle = it.color || "#424242";
194
+ ctx.font = "12px Arial";
195
+ const cosv = Math.cos(mid);
196
+ if (Math.abs(cosv) > 0.45)
197
+ ctx.textAlign = cosv > 0 ? "left" : "right";
198
+ else
199
+ ctx.textAlign = "center";
200
+ ctx.textBaseline = "middle";
201
+ const full = `${it.label}: ${it.value ?? 0}`;
202
+ const left = 12;
203
+ const right = w - 12;
204
+ let maxW;
205
+ if (ctx.textAlign === "left")
206
+ maxW = right - px;
207
+ else if (ctx.textAlign === "right")
208
+ maxW = px - left;
209
+ else
210
+ maxW = Math.min(right - px, px - left);
211
+ const needsWrap = ctx.measureText(full).width > Math.max(60, maxW - 6);
212
+ if (needsWrap) {
213
+ const line1 = `${it.label}:`;
214
+ const line2 = `${it.value ?? 0}`;
215
+ ctx.fillText(line1, px, py - 8);
216
+ ctx.fillText(line2, px, py + 8);
217
+ }
218
+ else {
219
+ ctx.fillText(full, px, py);
220
+ }
221
+ start = end;
222
+ }
223
+ ctx.globalCompositeOperation = "destination-out";
224
+ ctx.beginPath();
225
+ ctx.arc(cx, cy, radius * 0.55, 0, Math.PI * 2);
226
+ ctx.fill();
227
+ ctx.globalCompositeOperation = "source-over";
228
+ }
229
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmxDashCardDoughnutExtLabelsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
230
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: SmxDashCardDoughnutExtLabelsComponent, isStandalone: true, selector: "smx-dash-card-doughnut-ext-labels", inputs: { title: "title", showTitle: "showTitle", titleStyle: "titleStyle", titleHAlign: "titleHAlign", contentVAlign: "contentVAlign", contentHAlign: "contentHAlign", items: "items", legendVisible: "legendVisible", formatters: "formatters", i18n: "i18n", chartWidth: "chartWidth", chartHeight: "chartHeight", numberFormat: "numberFormat", bottomLegendItems: "bottomLegendItems", summaryItems: "summaryItems", bottomLegendStyle: "bottomLegendStyle", summaryStyle: "summaryStyle" }, viewQueries: [{ propertyName: "canvas", first: true, predicate: ["canvas"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smx-card-doughnut-wrap\" [class.smx-auto-mode]=\"chartWidth === 'auto' || chartHeight === 'auto'\">\n <div *ngIf=\"showTitle && title\" class=\"smx-card-inner-title\" [ngStyle]=\"titleStyle\" [style.text-align]=\"titleHAlign\">{{ title }}</div>\n <div\n class=\"graphic\"\n [class.smx-auto-chart]=\"chartWidth === 'auto' || chartHeight === 'auto'\"\n [style.justify-content]=\"contentHAlign === 'left' ? 'flex-start' : contentHAlign === 'right' ? 'flex-end' : 'center'\"\n [style.align-items]=\"contentVAlign === 'top' ? 'flex-start' : contentVAlign === 'bottom' ? 'flex-end' : 'center'\">\n <canvas\n #canvas\n [style.width]=\"chartWidth !== 'auto' && chartWidth > 0 ? chartWidth + 'px' : null\"\n [style.height]=\"chartHeight !== 'auto' && chartHeight > 0 ? chartHeight + 'px' : null\">\n </canvas>\n </div>\n <div *ngIf=\"bottomLegendItems.length > 0\" class=\"bottom-legend\" [ngStyle]=\"bottomLegendStyle\">\n <div *ngFor=\"let item of bottomLegendItems\" class=\"bottom-legend-item\">\n <span *ngIf=\"item.color\" class=\"legend-dot\" [style.background]=\"item.color\"></span>\n <span class=\"legend-label\">{{ item.label }}</span>\n <span class=\"legend-value\">{{ fmtValue(item.value) }}</span>\n </div>\n </div>\n <ng-container *ngIf=\"summaryItems.length > 0\">\n <div class=\"summary-separator\"></div>\n <div class=\"summary-section\" [ngStyle]=\"summaryStyle\">\n <div *ngFor=\"let s of summaryItems\" class=\"summary-item\">\n <span class=\"summary-label\">{{ s.label }}</span>\n <span class=\"summary-value\">{{ fmtValue(s.value) }}</span>\n </div>\n </div>\n </ng-container>\n</div>\n", styles: [":host{display:flex;flex-direction:column;min-height:0}.smx-card-doughnut-wrap{display:flex;flex-direction:column;flex:1;min-height:0}.smx-card-inner-title{flex-shrink:0;font-size:13px;font-weight:700;text-align:center;text-transform:uppercase;letter-spacing:.04em;color:#333;margin-bottom:8px;padding:0 4px}.graphic{flex:1;display:flex;justify-content:center;align-items:center;overflow:hidden;min-height:0}.bottom-legend{display:flex;flex-direction:column;gap:4px;padding:8px 12px 4px}.bottom-legend-item{display:flex;align-items:center;gap:6px;font-size:13px;color:#333}.legend-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0;display:inline-block}.legend-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.legend-value{font-weight:600;white-space:nowrap}.summary-separator{height:1px;background:#e0e0e0;margin:6px 12px}.summary-section{display:flex;flex-direction:column;gap:2px;padding:4px 12px 8px}.summary-item{display:flex;align-items:center;justify-content:space-between;font-size:13px;font-weight:700;color:#424242}.summary-label{flex:1}.summary-value{white-space:nowrap}.smx-auto-mode .graphic{flex:1;min-height:200px}.graphic.smx-auto-chart{flex:1;position:relative;overflow:hidden;width:100%;min-height:200px}.graphic.smx-auto-chart canvas{position:absolute;inset:0;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
231
+ }
232
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmxDashCardDoughnutExtLabelsComponent, decorators: [{
233
+ type: Component,
234
+ args: [{ selector: "smx-dash-card-doughnut-ext-labels", standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"smx-card-doughnut-wrap\" [class.smx-auto-mode]=\"chartWidth === 'auto' || chartHeight === 'auto'\">\n <div *ngIf=\"showTitle && title\" class=\"smx-card-inner-title\" [ngStyle]=\"titleStyle\" [style.text-align]=\"titleHAlign\">{{ title }}</div>\n <div\n class=\"graphic\"\n [class.smx-auto-chart]=\"chartWidth === 'auto' || chartHeight === 'auto'\"\n [style.justify-content]=\"contentHAlign === 'left' ? 'flex-start' : contentHAlign === 'right' ? 'flex-end' : 'center'\"\n [style.align-items]=\"contentVAlign === 'top' ? 'flex-start' : contentVAlign === 'bottom' ? 'flex-end' : 'center'\">\n <canvas\n #canvas\n [style.width]=\"chartWidth !== 'auto' && chartWidth > 0 ? chartWidth + 'px' : null\"\n [style.height]=\"chartHeight !== 'auto' && chartHeight > 0 ? chartHeight + 'px' : null\">\n </canvas>\n </div>\n <div *ngIf=\"bottomLegendItems.length > 0\" class=\"bottom-legend\" [ngStyle]=\"bottomLegendStyle\">\n <div *ngFor=\"let item of bottomLegendItems\" class=\"bottom-legend-item\">\n <span *ngIf=\"item.color\" class=\"legend-dot\" [style.background]=\"item.color\"></span>\n <span class=\"legend-label\">{{ item.label }}</span>\n <span class=\"legend-value\">{{ fmtValue(item.value) }}</span>\n </div>\n </div>\n <ng-container *ngIf=\"summaryItems.length > 0\">\n <div class=\"summary-separator\"></div>\n <div class=\"summary-section\" [ngStyle]=\"summaryStyle\">\n <div *ngFor=\"let s of summaryItems\" class=\"summary-item\">\n <span class=\"summary-label\">{{ s.label }}</span>\n <span class=\"summary-value\">{{ fmtValue(s.value) }}</span>\n </div>\n </div>\n </ng-container>\n</div>\n", styles: [":host{display:flex;flex-direction:column;min-height:0}.smx-card-doughnut-wrap{display:flex;flex-direction:column;flex:1;min-height:0}.smx-card-inner-title{flex-shrink:0;font-size:13px;font-weight:700;text-align:center;text-transform:uppercase;letter-spacing:.04em;color:#333;margin-bottom:8px;padding:0 4px}.graphic{flex:1;display:flex;justify-content:center;align-items:center;overflow:hidden;min-height:0}.bottom-legend{display:flex;flex-direction:column;gap:4px;padding:8px 12px 4px}.bottom-legend-item{display:flex;align-items:center;gap:6px;font-size:13px;color:#333}.legend-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0;display:inline-block}.legend-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.legend-value{font-weight:600;white-space:nowrap}.summary-separator{height:1px;background:#e0e0e0;margin:6px 12px}.summary-section{display:flex;flex-direction:column;gap:2px;padding:4px 12px 8px}.summary-item{display:flex;align-items:center;justify-content:space-between;font-size:13px;font-weight:700;color:#424242}.summary-label{flex:1}.summary-value{white-space:nowrap}.smx-auto-mode .graphic{flex:1;min-height:200px}.graphic.smx-auto-chart{flex:1;position:relative;overflow:hidden;width:100%;min-height:200px}.graphic.smx-auto-chart canvas{position:absolute;inset:0;width:100%;height:100%}\n"] }]
235
+ }], propDecorators: { title: [{
236
+ type: Input
237
+ }], showTitle: [{
238
+ type: Input
239
+ }], titleStyle: [{
240
+ type: Input
241
+ }], titleHAlign: [{
242
+ type: Input
243
+ }], contentVAlign: [{
244
+ type: Input
245
+ }], contentHAlign: [{
246
+ type: Input
247
+ }], items: [{
248
+ type: Input
249
+ }], legendVisible: [{
250
+ type: Input
251
+ }], formatters: [{
252
+ type: Input
253
+ }], i18n: [{
254
+ type: Input
255
+ }], chartWidth: [{
256
+ type: Input
257
+ }], chartHeight: [{
258
+ type: Input
259
+ }], numberFormat: [{
260
+ type: Input
261
+ }], bottomLegendItems: [{
262
+ type: Input
263
+ }], summaryItems: [{
264
+ type: Input
265
+ }], bottomLegendStyle: [{
266
+ type: Input
267
+ }], summaryStyle: [{
268
+ type: Input
269
+ }], canvas: [{
270
+ type: ViewChild,
271
+ args: ["canvas", { static: false }]
272
+ }] } });
273
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic214LWRhc2gtY2FyZC1kb3VnaG51dC1leHQtbGFiZWxzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zdW1heC1lcnAtY29tcG9uZW50L3NyYy9saWIvc3VtYXgtZGFzaGJvYXJkL2NhcmRzL3NteC1kYXNoLWNhcmQtZG91Z2hudXQtZXh0LWxhYmVscy9zbXgtZGFzaC1jYXJkLWRvdWdobnV0LWV4dC1sYWJlbHMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXN1bWF4LWVycC1jb21wb25lbnQvc3JjL2xpYi9zdW1heC1kYXNoYm9hcmQvY2FyZHMvc214LWRhc2gtY2FyZC1kb3VnaG51dC1leHQtbGFiZWxzL3NteC1kYXNoLWNhcmQtZG91Z2hudXQtZXh0LWxhYmVscy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFpQix1QkFBdUIsRUFBRSxTQUFTLEVBQWMsS0FBSyxFQUFhLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7O0FBVzNILE1BQU0sT0FBTyxxQ0FBcUM7SUFSbEQ7UUFTRSxxQ0FBcUM7UUFDNUIsVUFBSyxHQUFHLEVBQUUsQ0FBQztRQUNwQix5REFBeUQ7UUFDaEQsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUMzQiw4RUFBOEU7UUFDckUsZUFBVSxHQUEyQixFQUFFLENBQUM7UUFDakQsMERBQTBEO1FBQ2pELGdCQUFXLEdBQWdDLFFBQVEsQ0FBQztRQUM3RCwyREFBMkQ7UUFDbEQsa0JBQWEsR0FBZ0MsUUFBUSxDQUFDO1FBQy9ELDZEQUE2RDtRQUNwRCxrQkFBYSxHQUFnQyxRQUFRLENBQUM7UUFDL0QsMEZBQTBGO1FBQ2pGLFVBQUssR0FBMkIsRUFBRSxDQUFDO1FBQzVDLHVGQUF1RjtRQUM5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LHNyQkNabEQsNnFEQThCQSwrMkNEdkJZLFlBQVk7OzRGQUtYLHFDQUFxQztrQkFSakQsU0FBUzsrQkFDRSxtQ0FBbUMsY0FDakMsSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDLG1CQUdOLHVCQUF1QixDQUFDLE1BQU07OEJBSXRDLEtBQUs7c0JBQWIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxhQUFhO3NCQUFyQixLQUFLO2dCQUVHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBRUcsS0FBSztzQkFBYixLQUFLO2dCQUVHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUcsaUJBQWlCO3NCQUF6QixLQUFLO2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUcsaUJBQWlCO3NCQUF6QixLQUFLO2dCQUVHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ2tDLE1BQU07c0JBQTdDLFNBQVM7dUJBQUMsUUFBUSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcbmltcG9ydCB7IEFmdGVyVmlld0luaXQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIEVsZW1lbnRSZWYsIElucHV0LCBPbkNoYW5nZXMsIFZpZXdDaGlsZCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IFBpZUl0ZW0gfSBmcm9tIFwiLi4vLi4vdHlwZXMvdHlwZXNcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcInNteC1kYXNoLWNhcmQtZG91Z2hudXQtZXh0LWxhYmVsc1wiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgdGVtcGxhdGVVcmw6IFwiLi9zbXgtZGFzaC1jYXJkLWRvdWdobnV0LWV4dC1sYWJlbHMuY29tcG9uZW50Lmh0bWxcIixcbiAgc3R5bGVVcmxzOiBbXCIuL3NteC1kYXNoLWNhcmQtZG91Z2hudXQtZXh0LWxhYmVscy5jb21wb25lbnQuc2Nzc1wiXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFNteERhc2hDYXJkRG91Z2hudXRFeHRMYWJlbHNDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQge1xuICAvKiogVMOtdHVsbyBkZWwgd2lkZ2V0LiBAZGVmYXVsdCBcIlwiICovXG4gIEBJbnB1dCgpIHRpdGxlID0gXCJcIjtcbiAgLyoqIENvbnRyb2xhIGxhIHZpc2liaWxpZGFkIGRlbCB0w610dWxvLiBAZGVmYXVsdCBmYWxzZSAqL1xuICBASW5wdXQoKSBzaG93VGl0bGUgPSBmYWxzZTtcbiAgLyoqIEVzdGlsb3MgQ1NTIGlubGluZSBhZGljaW9uYWxlcyBwYXJhIGVsIGVsZW1lbnRvIGRlbCB0w610dWxvLiBAZGVmYXVsdCB7fSAqL1xuICBASW5wdXQoKSB0aXRsZVN0eWxlOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gIC8qKiBBbGluZWFjacOzbiBob3Jpem9udGFsIGRlbCB0w610dWxvLiBAZGVmYXVsdCBcImNlbnRlclwiICovXG4gIEBJbnB1dCgpIHRpdGxlSEFsaWduOiBcImxlZnRcIiB8IFwiY2VudGVyXCIgfCBcInJpZ2h0XCIgPSBcImNlbnRlclwiO1xuICAvKiogQWxpbmVhY2nDs24gdmVydGljYWwgZGVsIGNvbnRlbmlkby4gQGRlZmF1bHQgXCJjZW50ZXJcIiAqL1xuICBASW5wdXQoKSBjb250ZW50VkFsaWduOiBcInRvcFwiIHwgXCJjZW50ZXJcIiB8IFwiYm90dG9tXCIgPSBcImNlbnRlclwiO1xuICAvKiogQWxpbmVhY2nDs24gaG9yaXpvbnRhbCBkZWwgY29udGVuaWRvLiBAZGVmYXVsdCBcImNlbnRlclwiICovXG4gIEBJbnB1dCgpIGNvbnRlbnRIQWxpZ246IFwibGVmdFwiIHwgXCJjZW50ZXJcIiB8IFwicmlnaHRcIiA9IFwiY2VudGVyXCI7XG4gIC8qKiBJdGVtcyBkZWwgZ3LDoWZpY28gZG91Z2hudXQuIENhZGEgaXRlbSB0aWVuZSBgbGFiZWxgLCBgdmFsdWVgIHkgYGNvbG9yYC4gQGRlZmF1bHQgW10gKi9cbiAgQElucHV0KCkgaXRlbXM6IFJlYWRvbmx5QXJyYXk8UGllSXRlbT4gPSBbXTtcbiAgLyoqIENvbnRyb2xhIGxhIHZpc2liaWxpZGFkIGRlIGxhIGxleWVuZGEgbmF0aXZhIGxhdGVyYWwgZGUgQ2hhcnQuanMuIEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIGxlZ2VuZFZpc2libGUgPSBmYWxzZTtcbiAgLyoqIE1hcGEgZGUgZnVuY2lvbmVzIGRlIGZvcm1hdGVvIHByb3BhZ2FkbyBkZXNkZSBlbCBncmlkLiAqL1xuICBASW5wdXQoKSBmb3JtYXR0ZXJzPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgLyoqIEludGVybmFjaW9uYWxpemFjacOzbiBwcm9wYWdhZGEgZGVzZGUgZWwgZ3JpZC4gKi9cbiAgQElucHV0KCkgaTE4bj86IHsgbW9udGhzPzogc3RyaW5nW10gfTtcbiAgLyoqIEFuY2hvIGZpam8gZGVsIGNhbnZhcyBlbiBww614ZWxlcyAoMCA9IGF1dG9tw6F0aWNvIGJhc2FkbyBlbiBlbCBjb250ZW5lZG9yKS4gQGRlZmF1bHQgMCAqL1xuICBASW5wdXQoKSBjaGFydFdpZHRoOiBudW1iZXIgfCBcImF1dG9cIiA9IDA7XG4gIC8qKiBBbHRvIGZpam8gZGVsIGNhbnZhcyBlbiBww614ZWxlcyAoMCA9IGF1dG9tw6F0aWNvIGJhc2FkbyBlbiBlbCBjb250ZW5lZG9yKS4gQGRlZmF1bHQgMCAqL1xuICBASW5wdXQoKSBjaGFydEhlaWdodDogbnVtYmVyIHwgXCJhdXRvXCIgPSAwO1xuICAvKiogT3BjaW9uZXMgZGUgZm9ybWF0ZW8gbnVtw6lyaWNvIHBhcmEgbG9zIHZhbG9yZXMgZW4gbGV5ZW5kYSB5IHJlc3VtZW4uIEBkZWZhdWx0IHt9ICovXG4gIEBJbnB1dCgpIG51bWJlckZvcm1hdDogeyB1c2VHcm91cGluZz86IGJvb2xlYW47IG1pbmltdW1GcmFjdGlvbkRpZ2l0cz86IG51bWJlcjsgbWF4aW11bUZyYWN0aW9uRGlnaXRzPzogbnVtYmVyOyBsb2NhbGU/OiBzdHJpbmcgfSA9IHt9O1xuICAvKiogSXRlbXMgZGUgbGEgbGV5ZW5kYSBpbmZlcmlvciAoZGViYWpvIGRlbCBncsOhZmljbykuIENhZGEgaXRlbSB0aWVuZSBgbGFiZWxgLCBgdmFsdWVgIHkgYGNvbG9yYCBvcGNpb25hbC4gQGRlZmF1bHQgW10gKi9cbiAgQElucHV0KCkgYm90dG9tTGVnZW5kSXRlbXM6IEFycmF5PHsgbGFiZWw6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB8IG51bWJlcjsgY29sb3I/OiBzdHJpbmcgfT4gPSBbXTtcbiAgLyoqIEl0ZW1zIGRlbCBibG9xdWUgcmVzdW1lbi4gQ2FkYSBpdGVtIHRpZW5lIGBsYWJlbGAgeSBgdmFsdWVgLiBAZGVmYXVsdCBbXSAqL1xuICBASW5wdXQoKSBzdW1tYXJ5SXRlbXM6IEFycmF5PHsgbGFiZWw6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB8IG51bWJlciB9PiA9IFtdO1xuICAvKiogRXN0aWxvcyBDU1MgaW5saW5lIGFkaWNpb25hbGVzIHBhcmEgZWwgY29udGVuZWRvciBkZSBsYSBsZXllbmRhIGluZmVyaW9yLiBAZGVmYXVsdCB7fSAqL1xuICBASW5wdXQoKSBib3R0b21MZWdlbmRTdHlsZTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAvKiogRXN0aWxvcyBDU1MgaW5saW5lIGFkaWNpb25hbGVzIHBhcmEgZWwgYmxvcXVlIGRlIHJlc3VtZW4uIEBkZWZhdWx0IHt9ICovXG4gIEBJbnB1dCgpIHN1bW1hcnlTdHlsZTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBAVmlld0NoaWxkKFwiY2FudmFzXCIsIHsgc3RhdGljOiBmYWxzZSB9KSBjYW52YXM/OiBFbGVtZW50UmVmPEhUTUxDYW52YXNFbGVtZW50PjtcbiAgcHJpdmF0ZSBjaGFydDogdW5rbm93bjtcbiAgcHJpdmF0ZSBfaW5pdFc/OiBudW1iZXI7XG4gIHByaXZhdGUgX2luaXRIPzogbnVtYmVyO1xuXG4gIG5nT25DaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMuX2luaXRXID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX2luaXRIID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuX2RyYXcoKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLl9kcmF3KCk7XG4gIH1cblxuICAvKiogRm9ybWF0ZWEgdW4gdmFsb3IgbnVtw6lyaWNvIHVzYW5kbyBgbnVtYmVyRm9ybWF0YC4gU2kgYG51bWJlckZvcm1hdGAgZXN0w6EgdmFjw61vLCByZXRvcm5hIGVsIHZhbG9yIGNvbW8gc3RyaW5nIHNpbiBtb2RpZmljYXIuICovXG4gIGZtdFZhbHVlKHY6IHVua25vd24pOiBzdHJpbmcge1xuICAgIGNvbnN0IG51bSA9IE51bWJlcih2ID8/IDApO1xuICAgIGlmICghT2JqZWN0LmtleXModGhpcy5udW1iZXJGb3JtYXQpLmxlbmd0aCkgcmV0dXJuIFN0cmluZyh2ID8/IFwiXCIpO1xuICAgIGNvbnN0IGxvY2FsZSA9IHRoaXMubnVtYmVyRm9ybWF0LmxvY2FsZSA/PyBcImVzLVBFXCI7XG4gICAgcmV0dXJuIG51bS50b0xvY2FsZVN0cmluZyhsb2NhbGUsIHtcbiAgICAgIHVzZUdyb3VwaW5nOiB0aGlzLm51bWJlckZvcm1hdC51c2VHcm91cGluZyA/PyB0cnVlLFxuICAgICAgbWluaW11bUZyYWN0aW9uRGlnaXRzOiB0aGlzLm51bWJlckZvcm1hdC5taW5pbXVtRnJhY3Rpb25EaWdpdHMgPz8gMCxcbiAgICAgIG1heGltdW1GcmFjdGlvbkRpZ2l0czogdGhpcy5udW1iZXJGb3JtYXQubWF4aW11bUZyYWN0aW9uRGlnaXRzID8/IDIsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIF9kcmF3KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGVsID0gdGhpcy5jYW52YXM/Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuICAgIGNvbnN0IGN0eCA9IGVsLmdldENvbnRleHQoXCIyZFwiKTtcbiAgICBpZiAoIWN0eCkgcmV0dXJuO1xuICAgIGNvbnN0IENoYXJ0R2xvYmFsID0gKGdsb2JhbFRoaXMgYXMgdW5rbm93biBhcyB7IENoYXJ0PzogdW5rbm93biB9KS5DaGFydDtcbiAgICBpZiAoQ2hhcnRHbG9iYWwpIHtcbiAgICAgIHRoaXMuX2RyYXdDaGFydE1vZGUoZWwsIENoYXJ0R2xvYmFsKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5fZHJhd0NhbnZhc0ZhbGxiYWNrKGVsLCBjdHgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZHJhd0NoYXJ0TW9kZShlbDogSFRNTENhbnZhc0VsZW1lbnQsIENoYXJ0R2xvYmFsOiB1bmtub3duKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY2hhcnQgJiYgKHRoaXMuY2hhcnQgYXMgeyBkZXN0cm95OiAoKSA9PiB2b2lkIH0pLmRlc3Ryb3kpIHtcbiAgICAgICh0aGlzLmNoYXJ0IGFzIHsgZGVzdHJveTogKCkgPT4gdm9pZCB9KS5kZXN0cm95KCk7XG4gICAgfVxuICAgIGlmICghdGhpcy5faW5pdFcpIHtcbiAgICAgIHRoaXMuX2luaXRXID0gdGhpcy5jaGFydFdpZHRoICE9PSBcImF1dG9cIiAmJiB0aGlzLmNoYXJ0V2lkdGggPiAwID8gdGhpcy5jaGFydFdpZHRoIDogTWF0aC5tYXgoMzAwLCBNYXRoLmNlaWwoZWwuY2xpZW50V2lkdGggfHwgMzYwKSk7XG4gICAgfVxuICAgIGlmICghdGhpcy5faW5pdEgpIHtcbiAgICAgIHRoaXMuX2luaXRIID1cbiAgICAgICAgdGhpcy5jaGFydEhlaWdodCAhPT0gXCJhdXRvXCIgJiYgdGhpcy5jaGFydEhlaWdodCA+IDAgPyB0aGlzLmNoYXJ0SGVpZ2h0IDogTWF0aC5tYXgoMjAwLCBNYXRoLmNlaWwoZWwuY2xpZW50SGVpZ2h0IHx8IDI0MCkpO1xuICAgIH1cbiAgICBlbC53aWR0aCA9IHRoaXMuX2luaXRXO1xuICAgIGVsLmhlaWdodCA9IHRoaXMuX2luaXRIO1xuICAgIGNvbnN0IGxhYmVscyA9ICh0aGlzLml0ZW1zID8/IFtdKS5tYXAoKHgpID0+IHgubGFiZWwpO1xuICAgIGNvbnN0IGRhdGEgPSAodGhpcy5pdGVtcyA/PyBbXSkubWFwKCh4KSA9PiB4LnZhbHVlID8/IDApO1xuICAgIGNvbnN0IGJnID0gKHRoaXMuaXRlbXMgPz8gW10pLm1hcCgoeCkgPT4gKHguY29sb3IgYXMgc3RyaW5nKSB8fCBcIiMzZjUxYjVcIik7XG4gICAgY29uc3QgQ2hhcnRDdG9yOiBhbnkgPSBDaGFydEdsb2JhbCBhcyBhbnk7XG4gICAgY29uc3QgZXh0TGFiZWxzID0ge1xuICAgICAgaWQ6IFwiZXh0TGFiZWxzXCIsXG4gICAgICBhZnRlckRhdGFzZXRzRHJhdzogKGNoYXJ0OiBhbnkpID0+IHtcbiAgICAgICAgY29uc3QgbWV0YSA9IGNoYXJ0LmdldERhdGFzZXRNZXRhKDApO1xuICAgICAgICBjb25zdCBpdGVtcyA9IGxhYmVscy5tYXAoKGwsIGkpID0+ICh7IGxhYmVsOiBsLCB2YWx1ZTogZGF0YVtpXSwgY29sb3I6IGJnW2ldIH0pKTtcbiAgICAgICAgY29uc3QgYyA9IGNoYXJ0LmN0eDtcbiAgICAgICAgYy5zYXZlKCk7XG4gICAgICAgIGMuZm9udCA9IFwiMTJweCBBcmlhbFwiO1xuICAgICAgICBjLnRleHRCYXNlbGluZSA9IFwibWlkZGxlXCI7XG4gICAgICAgIG1ldGEuZGF0YS5mb3JFYWNoKChlbDogYW55LCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgICBjb25zdCBtaWQgPSAoZWwuc3RhcnRBbmdsZSArIGVsLmVuZEFuZ2xlKSAvIDI7XG4gICAgICAgICAgY29uc3QgciA9IGVsLm91dGVyUmFkaXVzICsgMzI7XG4gICAgICAgICAgY29uc3QgeCA9IGVsLng7XG4gICAgICAgICAgY29uc3QgeSA9IGVsLnk7XG4gICAgICAgICAgbGV0IHB4ID0geCArIE1hdGguY29zKG1pZCkgKiByO1xuICAgICAgICAgIGxldCBweSA9IHkgKyBNYXRoLnNpbihtaWQpICogcjtcbiAgICAgICAgICBjb25zdCBtYXJnaW4gPSAxMjtcbiAgICAgICAgICBjb25zdCBsZWZ0ID0gY2hhcnQuY2hhcnRBcmVhLmxlZnQgKyBtYXJnaW47XG4gICAgICAgICAgY29uc3QgcmlnaHQgPSBjaGFydC5jaGFydEFyZWEucmlnaHQgLSBtYXJnaW47XG4gICAgICAgICAgY29uc3QgdG9wID0gY2hhcnQuY2hhcnRBcmVhLnRvcCArIG1hcmdpbjtcbiAgICAgICAgICBjb25zdCBib3R0b20gPSBjaGFydC5jaGFydEFyZWEuYm90dG9tIC0gbWFyZ2luO1xuICAgICAgICAgIGlmIChweCA8IGxlZnQpIHB4ID0gbGVmdDtcbiAgICAgICAgICBpZiAocHggPiByaWdodCkgcHggPSByaWdodDtcbiAgICAgICAgICBpZiAocHkgPCB0b3ApIHB5ID0gdG9wO1xuICAgICAgICAgIGlmIChweSA+IGJvdHRvbSkgcHkgPSBib3R0b207XG4gICAgICAgICAgYy5maWxsU3R5bGUgPSBpdGVtc1tpXT8uY29sb3IgfHwgXCIjNDI0MjQyXCI7XG4gICAgICAgICAgY29uc3QgbGFiZWwgPSBTdHJpbmcoaXRlbXNbaV0/LmxhYmVsID8/IFwiXCIpO1xuICAgICAgICAgIGNvbnN0IHZhbHVlU3RyID0gdGhpcy5mbXRWYWx1ZShpdGVtc1tpXT8udmFsdWUgPz8gMCk7XG4gICAgICAgICAgY29uc3QgZnVsbCA9IGxhYmVsICsgXCI6IFwiICsgdmFsdWVTdHI7XG4gICAgICAgICAgY29uc3QgY29zdiA9IE1hdGguY29zKG1pZCk7XG4gICAgICAgICAgaWYgKE1hdGguYWJzKGNvc3YpID4gMC40NSkgYy50ZXh0QWxpZ24gPSBjb3N2ID4gMCA/IFwibGVmdFwiIDogXCJyaWdodFwiO1xuICAgICAgICAgIGVsc2UgYy50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICAgIGxldCBtYXhXOiBudW1iZXI7XG4gICAgICAgICAgaWYgKGMudGV4dEFsaWduID09PSBcImxlZnRcIikgbWF4VyA9IHJpZ2h0IC0gcHg7XG4gICAgICAgICAgZWxzZSBpZiAoYy50ZXh0QWxpZ24gPT09IFwicmlnaHRcIikgbWF4VyA9IHB4IC0gbGVmdDtcbiAgICAgICAgICBlbHNlIG1heFcgPSBNYXRoLm1pbihyaWdodCAtIHB4LCBweCAtIGxlZnQpO1xuICAgICAgICAgIGNvbnN0IG5lZWRzV3JhcCA9IGMubWVhc3VyZVRleHQoZnVsbCkud2lkdGggPiBNYXRoLm1heCg2MCwgbWF4VyAtIDYpO1xuICAgICAgICAgIGlmIChuZWVkc1dyYXApIHtcbiAgICAgICAgICAgIGNvbnN0IGxpbmUxID0gbGFiZWwgKyBcIjpcIjtcbiAgICAgICAgICAgIGNvbnN0IGxpbmUyID0gdmFsdWVTdHI7XG4gICAgICAgICAgICBjLmZpbGxUZXh0KGxpbmUxLCBweCwgcHkgLSA4KTtcbiAgICAgICAgICAgIGMuZmlsbFRleHQobGluZTIsIHB4LCBweSArIDgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjLmZpbGxUZXh0KGZ1bGwsIHB4LCBweSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgYy5yZXN0b3JlKCk7XG4gICAgICB9LFxuICAgIH07XG4gICAgdGhpcy5jaGFydCA9IG5ldyBDaGFydEN0b3IoZWwsIHtcbiAgICAgIHR5cGU6IFwiZG91Z2hudXRcIixcbiAgICAgIGRhdGE6IHsgbGFiZWxzLCBkYXRhc2V0czogW3sgZGF0YSwgYmFja2dyb3VuZENvbG9yOiBiZywgcmFkaXVzOiBcIjY1JVwiIH1dIH0sXG4gICAgICBvcHRpb25zOiB7XG4gICAgICAgIHJlc3BvbnNpdmU6IGZhbHNlLFxuICAgICAgICAvLyBDb21wYXRpYmlsaWRhZCBDaGFydC5qcyB2MjogbGVlIG9wdGlvbnMubGVnZW5kIGVuIGx1Z2FyIGRlIG9wdGlvbnMucGx1Z2lucy5sZWdlbmRcbiAgICAgICAgbGVnZW5kOiB7IGRpc3BsYXk6IHRoaXMubGVnZW5kVmlzaWJsZSB9LFxuICAgICAgICBwbHVnaW5zOiB7XG4gICAgICAgICAgbGVnZW5kOiB7IGRpc3BsYXk6IHRoaXMubGVnZW5kVmlzaWJsZSB9LFxuICAgICAgICAgIHRvb2x0aXA6IHtcbiAgICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgICAuLi4oT2JqZWN0LmtleXModGhpcy5udW1iZXJGb3JtYXQpLmxlbmd0aFxuICAgICAgICAgICAgICA/IHsgY2FsbGJhY2tzOiB7IGxhYmVsOiAoY3R4OiBhbnkpID0+IGAke2N0eC5sYWJlbCA/PyBcIlwifTogJHt0aGlzLmZtdFZhbHVlKGN0eC5yYXcgPz8gMCl9YCB9IH1cbiAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgbGF5b3V0OiB7IHBhZGRpbmc6IDMyIH0sXG4gICAgICAgIGN1dG91dDogXCI1NSVcIixcbiAgICAgICAgcmFkaXVzOiBcIjY1JVwiLFxuICAgICAgfSBhcyBhbnksXG4gICAgICBwbHVnaW5zOiBbZXh0TGFiZWxzXSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2RyYXdDYW52YXNGYWxsYmFjayhlbDogSFRNTENhbnZhc0VsZW1lbnQsIGN0eDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEKTogdm9pZCB7XG4gICAgY29uc3QgdyA9IGVsLndpZHRoLFxuICAgICAgaCA9IGVsLmhlaWdodDtcbiAgICBjdHguY2xlYXJSZWN0KDAsIDAsIHcsIGgpO1xuICAgIGNvbnN0IHRvdGFsID0gKHRoaXMuaXRlbXMgPz8gW10pLnJlZHVjZSgoYWNjLCBpdCkgPT4gYWNjICsgTnVtYmVyKGl0LnZhbHVlID8/IDApLCAwKTtcbiAgICBpZiAoIXRvdGFsKSByZXR1cm47XG4gICAgY29uc3QgcmFkaXVzID0gTWF0aC5taW4odywgaCkgLyA0LjI7XG4gICAgY29uc3QgY3ggPSB3IC8gMixcbiAgICAgIGN5ID0gaCAvIDI7XG4gICAgbGV0IHN0YXJ0ID0gLU1hdGguUEkgLyAyO1xuICAgIGZvciAoY29uc3QgaXQgb2YgdGhpcy5pdGVtcykge1xuICAgICAgY29uc3QgZnJhYyA9IE51bWJlcihpdC52YWx1ZSA/PyAwKSAvIHRvdGFsO1xuICAgICAgY29uc3QgZW5kID0gc3RhcnQgKyBmcmFjICogTWF0aC5QSSAqIDI7XG4gICAgICBjdHguYmVnaW5QYXRoKCk7XG4gICAgICBjdHgubW92ZVRvKGN4LCBjeSk7XG4gICAgICBjdHguYXJjKGN4LCBjeSwgcmFkaXVzLCBzdGFydCwgZW5kKTtcbiAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSAoaXQuY29sb3IgYXMgc3RyaW5nKSB8fCBcIiMzZjUxYjVcIjtcbiAgICAgIGN0eC5maWxsKCk7XG4gICAgICBjb25zdCBtaWQgPSAoc3RhcnQgKyBlbmQpIC8gMjtcbiAgICAgIGNvbnN0IHJyID0gcmFkaXVzICsgMjg7XG4gICAgICBjb25zdCBweCA9IGN4ICsgTWF0aC5jb3MobWlkKSAqIHJyO1xuICAgICAgY29uc3QgcHkgPSBjeSArIE1hdGguc2luKG1pZCkgKiBycjtcbiAgICAgIGN0eC5maWxsU3R5bGUgPSAoaXQuY29sb3IgYXMgc3RyaW5nKSB8fCBcIiM0MjQyNDJcIjtcbiAgICAgIGN0eC5mb250ID0gXCIxMnB4IEFyaWFsXCI7XG4gICAgICBjb25zdCBjb3N2ID0gTWF0aC5jb3MobWlkKTtcbiAgICAgIGlmIChNYXRoLmFicyhjb3N2KSA+IDAuNDUpIGN0eC50ZXh0QWxpZ24gPSBjb3N2ID4gMCA/IFwibGVmdFwiIDogXCJyaWdodFwiO1xuICAgICAgZWxzZSBjdHgudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSBcIm1pZGRsZVwiO1xuICAgICAgY29uc3QgZnVsbCA9IGAke2l0LmxhYmVsfTogJHtpdC52YWx1ZSA/PyAwfWA7XG4gICAgICBjb25zdCBsZWZ0ID0gMTI7XG4gICAgICBjb25zdCByaWdodCA9IHcgLSAxMjtcbiAgICAgIGxldCBtYXhXOiBudW1iZXI7XG4gICAgICBpZiAoY3R4LnRleHRBbGlnbiA9PT0gXCJsZWZ0XCIpIG1heFcgPSByaWdodCAtIHB4O1xuICAgICAgZWxzZSBpZiAoY3R4LnRleHRBbGlnbiA9PT0gXCJyaWdodFwiKSBtYXhXID0gcHggLSBsZWZ0O1xuICAgICAgZWxzZSBtYXhXID0gTWF0aC5taW4ocmlnaHQgLSBweCwgcHggLSBsZWZ0KTtcbiAgICAgIGNvbnN0IG5lZWRzV3JhcCA9IGN0eC5tZWFzdXJlVGV4dChmdWxsKS53aWR0aCA+IE1hdGgubWF4KDYwLCBtYXhXIC0gNik7XG4gICAgICBpZiAobmVlZHNXcmFwKSB7XG4gICAgICAgIGNvbnN0IGxpbmUxID0gYCR7aXQubGFiZWx9OmA7XG4gICAgICAgIGNvbnN0IGxpbmUyID0gYCR7aXQudmFsdWUgPz8gMH1gO1xuICAgICAgICBjdHguZmlsbFRleHQobGluZTEsIHB4LCBweSAtIDgpO1xuICAgICAgICBjdHguZmlsbFRleHQobGluZTIsIHB4LCBweSArIDgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3R4LmZpbGxUZXh0KGZ1bGwsIHB4LCBweSk7XG4gICAgICB9XG4gICAgICBzdGFydCA9IGVuZDtcbiAgICB9XG4gICAgY3R4Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbiA9IFwiZGVzdGluYXRpb24tb3V0XCI7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIGN0eC5hcmMoY3gsIGN5LCByYWRpdXMgKiAwLjU1LCAwLCBNYXRoLlBJICogMik7XG4gICAgY3R4LmZpbGwoKTtcbiAgICBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gXCJzb3VyY2Utb3ZlclwiO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwic214LWNhcmQtZG91Z2hudXQtd3JhcFwiIFtjbGFzcy5zbXgtYXV0by1tb2RlXT1cImNoYXJ0V2lkdGggPT09ICdhdXRvJyB8fCBjaGFydEhlaWdodCA9PT0gJ2F1dG8nXCI+XG4gIDxkaXYgKm5nSWY9XCJzaG93VGl0bGUgJiYgdGl0bGVcIiBjbGFzcz1cInNteC1jYXJkLWlubmVyLXRpdGxlXCIgW25nU3R5bGVdPVwidGl0bGVTdHlsZVwiIFtzdHlsZS50ZXh0LWFsaWduXT1cInRpdGxlSEFsaWduXCI+e3sgdGl0bGUgfX08L2Rpdj5cbiAgPGRpdlxuICAgIGNsYXNzPVwiZ3JhcGhpY1wiXG4gICAgW2NsYXNzLnNteC1hdXRvLWNoYXJ0XT1cImNoYXJ0V2lkdGggPT09ICdhdXRvJyB8fCBjaGFydEhlaWdodCA9PT0gJ2F1dG8nXCJcbiAgICBbc3R5bGUuanVzdGlmeS1jb250ZW50XT1cImNvbnRlbnRIQWxpZ24gPT09ICdsZWZ0JyA/ICdmbGV4LXN0YXJ0JyA6IGNvbnRlbnRIQWxpZ24gPT09ICdyaWdodCcgPyAnZmxleC1lbmQnIDogJ2NlbnRlcidcIlxuICAgIFtzdHlsZS5hbGlnbi1pdGVtc109XCJjb250ZW50VkFsaWduID09PSAndG9wJyA/ICdmbGV4LXN0YXJ0JyA6IGNvbnRlbnRWQWxpZ24gPT09ICdib3R0b20nID8gJ2ZsZXgtZW5kJyA6ICdjZW50ZXInXCI+XG4gICAgPGNhbnZhc1xuICAgICAgI2NhbnZhc1xuICAgICAgW3N0eWxlLndpZHRoXT1cImNoYXJ0V2lkdGggIT09ICdhdXRvJyAmJiBjaGFydFdpZHRoID4gMCA/IGNoYXJ0V2lkdGggKyAncHgnIDogbnVsbFwiXG4gICAgICBbc3R5bGUuaGVpZ2h0XT1cImNoYXJ0SGVpZ2h0ICE9PSAnYXV0bycgJiYgY2hhcnRIZWlnaHQgPiAwID8gY2hhcnRIZWlnaHQgKyAncHgnIDogbnVsbFwiPlxuICAgIDwvY2FudmFzPlxuICA8L2Rpdj5cbiAgPGRpdiAqbmdJZj1cImJvdHRvbUxlZ2VuZEl0ZW1zLmxlbmd0aCA+IDBcIiBjbGFzcz1cImJvdHRvbS1sZWdlbmRcIiBbbmdTdHlsZV09XCJib3R0b21MZWdlbmRTdHlsZVwiPlxuICAgIDxkaXYgKm5nRm9yPVwibGV0IGl0ZW0gb2YgYm90dG9tTGVnZW5kSXRlbXNcIiBjbGFzcz1cImJvdHRvbS1sZWdlbmQtaXRlbVwiPlxuICAgICAgPHNwYW4gKm5nSWY9XCJpdGVtLmNvbG9yXCIgY2xhc3M9XCJsZWdlbmQtZG90XCIgW3N0eWxlLmJhY2tncm91bmRdPVwiaXRlbS5jb2xvclwiPjwvc3Bhbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwibGVnZW5kLWxhYmVsXCI+e3sgaXRlbS5sYWJlbCB9fTwvc3Bhbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwibGVnZW5kLXZhbHVlXCI+e3sgZm10VmFsdWUoaXRlbS52YWx1ZSkgfX08L3NwYW4+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwic3VtbWFyeUl0ZW1zLmxlbmd0aCA+IDBcIj5cbiAgICA8ZGl2IGNsYXNzPVwic3VtbWFyeS1zZXBhcmF0b3JcIj48L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwic3VtbWFyeS1zZWN0aW9uXCIgW25nU3R5bGVdPVwic3VtbWFyeVN0eWxlXCI+XG4gICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBzIG9mIHN1bW1hcnlJdGVtc1wiIGNsYXNzPVwic3VtbWFyeS1pdGVtXCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwic3VtbWFyeS1sYWJlbFwiPnt7IHMubGFiZWwgfX08L3NwYW4+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwic3VtbWFyeS12YWx1ZVwiPnt7IGZtdFZhbHVlKHMudmFsdWUpIH19PC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvbmctY29udGFpbmVyPlxuPC9kaXY+XG4iXX0=
@@ -0,0 +1,125 @@
1
+ import { CommonModule } from "@angular/common";
2
+ import { ChangeDetectionStrategy, Component, Input, ViewChild } from "@angular/core";
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/common";
5
+ export class SmxDashCardKpiLegendComponent {
6
+ constructor() {
7
+ /** Título del widget. @default "" */
8
+ this.title = "";
9
+ /** Controla la visibilidad del título. @default false */
10
+ this.showTitle = false;
11
+ /** Estilos CSS inline adicionales para el elemento del título. @default {} */
12
+ this.titleStyle = {};
13
+ /** Alineación horizontal del título. Propagado desde `extra.titleHAlign`. @default "center" */
14
+ this.titleHAlign = "center";
15
+ /** Alineación vertical del contenido. Propagado desde `extra.contentVAlign`. @default "center" */
16
+ this.contentVAlign = "center";
17
+ /** Alineación horizontal del contenido. Propagado desde `extra.contentHAlign`. @default "center" */
18
+ this.contentHAlign = "center";
19
+ /** KPI principal: valor numérico o texto a mostrar prominentemente. @default "" */
20
+ this.value = "";
21
+ /** Items del gráfico de torta/leyenda inferior. Cada item tiene `label`, `value` y `color`. @default [] */
22
+ this.items = [];
23
+ }
24
+ ngOnChanges() {
25
+ this._drawSparkline();
26
+ }
27
+ ngAfterViewInit() {
28
+ this._drawSparkline();
29
+ }
30
+ async _drawSparkline() {
31
+ const el = this.spark?.nativeElement;
32
+ if (!el)
33
+ return;
34
+ const dataArr = (this.sparkline ?? []);
35
+ const ctx = el.getContext("2d");
36
+ if (!ctx)
37
+ return;
38
+ const ChartGlobal = globalThis.Chart;
39
+ if (ChartGlobal && dataArr.length > 0) {
40
+ if (this.chart && this.chart.destroy) {
41
+ this.chart.destroy();
42
+ }
43
+ const ChartCtor = ChartGlobal;
44
+ this.chart = new ChartCtor(el, {
45
+ type: "line",
46
+ data: {
47
+ labels: dataArr.map((_, i) => i),
48
+ datasets: [
49
+ {
50
+ data: dataArr,
51
+ borderColor: "#3f51b5",
52
+ backgroundColor: "rgba(63,81,181,0.15)",
53
+ tension: 0.3,
54
+ },
55
+ ],
56
+ },
57
+ options: {
58
+ responsive: false,
59
+ animation: { duration: 0 },
60
+ transitions: { active: { animation: { duration: 0 } }, resize: { animation: { duration: 0 } } },
61
+ plugins: { legend: { display: false }, tooltip: { enabled: false } },
62
+ scales: { x: { display: false }, y: { display: false } },
63
+ elements: { point: { radius: 0 } },
64
+ },
65
+ });
66
+ return;
67
+ }
68
+ const w = el.width, h = el.height;
69
+ ctx.clearRect(0, 0, w, h);
70
+ if (!dataArr.length)
71
+ return;
72
+ const min = Math.min(...dataArr);
73
+ const max = Math.max(...dataArr);
74
+ const range = max - min || 1;
75
+ const stepX = w / Math.max(1, dataArr.length - 1);
76
+ ctx.strokeStyle = "#3f51b5";
77
+ ctx.fillStyle = "rgba(63,81,181,0.15)";
78
+ ctx.beginPath();
79
+ dataArr.forEach((v, i) => {
80
+ const x = i * stepX;
81
+ const y = h - ((v - min) / range) * h;
82
+ if (i === 0)
83
+ ctx.moveTo(x, y);
84
+ else
85
+ ctx.lineTo(x, y);
86
+ });
87
+ ctx.stroke();
88
+ }
89
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmxDashCardKpiLegendComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
90
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.11", type: SmxDashCardKpiLegendComponent, isStandalone: true, selector: "smx-dash-card-kpi-legend", inputs: { title: "title", showTitle: "showTitle", titleStyle: "titleStyle", titleHAlign: "titleHAlign", contentVAlign: "contentVAlign", contentHAlign: "contentHAlign", value: "value", delta: "delta", periodLabel: "periodLabel", items: "items", sparkline: "sparkline", formatters: "formatters", i18n: "i18n" }, viewQueries: [{ propertyName: "spark", first: true, predicate: ["spark"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smx-card-kpi-wrap\">\n <div *ngIf=\"showTitle && title\" class=\"smx-card-inner-title\" [ngStyle]=\"titleStyle\">{{ title }}</div>\n <div class=\"kpi-row\">\n <div class=\"kpi-value\">{{ value }}</div>\n <div class=\"kpi-delta\" [class.pos]=\"(delta ?? 0) >= 0\" [class.neg]=\"(delta ?? 0) < 0\">\n <span class=\"delta\">{{ delta }}</span>\n <span class=\"period\" *ngIf=\"periodLabel\">{{ periodLabel }}</span>\n </div>\n </div>\n <div class=\"sparkline\">\n <canvas #spark width=\"120\" height=\"36\"></canvas>\n </div>\n <ul class=\"legend-list\">\n <li class=\"legend-item\" *ngFor=\"let it of items\">\n <span class=\"dot\" [style.background]=\"it.color || '#3f51b5'\"></span>\n <span class=\"label\">{{ it.label }}</span>\n <span class=\"value\">{{ it.value }}</span>\n </li>\n </ul>\n</div>\n", styles: [":host{display:block}.smx-card-kpi-wrap{display:block}.smx-card-inner-title{font-size:13px;font-weight:700;text-align:center;text-transform:uppercase;letter-spacing:.04em;color:#333;margin-bottom:8px;padding:0 4px}.kpi-row{display:flex;align-items:baseline;gap:12px;margin-bottom:8px}.kpi-value{font-size:24px;font-weight:700}.kpi-delta{font-size:12px;font-weight:600}.kpi-delta.pos{color:#43a047}.kpi-delta.neg{color:#e53935}.sparkline{margin:4px 0 8px}.legend-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.legend-item{display:flex;align-items:center;gap:8px}.dot{width:10px;height:10px;border-radius:50%;display:inline-block}.label{flex:1}.value{font-weight:600}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
91
+ }
92
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: SmxDashCardKpiLegendComponent, decorators: [{
93
+ type: Component,
94
+ args: [{ selector: "smx-dash-card-kpi-legend", standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"smx-card-kpi-wrap\">\n <div *ngIf=\"showTitle && title\" class=\"smx-card-inner-title\" [ngStyle]=\"titleStyle\">{{ title }}</div>\n <div class=\"kpi-row\">\n <div class=\"kpi-value\">{{ value }}</div>\n <div class=\"kpi-delta\" [class.pos]=\"(delta ?? 0) >= 0\" [class.neg]=\"(delta ?? 0) < 0\">\n <span class=\"delta\">{{ delta }}</span>\n <span class=\"period\" *ngIf=\"periodLabel\">{{ periodLabel }}</span>\n </div>\n </div>\n <div class=\"sparkline\">\n <canvas #spark width=\"120\" height=\"36\"></canvas>\n </div>\n <ul class=\"legend-list\">\n <li class=\"legend-item\" *ngFor=\"let it of items\">\n <span class=\"dot\" [style.background]=\"it.color || '#3f51b5'\"></span>\n <span class=\"label\">{{ it.label }}</span>\n <span class=\"value\">{{ it.value }}</span>\n </li>\n </ul>\n</div>\n", styles: [":host{display:block}.smx-card-kpi-wrap{display:block}.smx-card-inner-title{font-size:13px;font-weight:700;text-align:center;text-transform:uppercase;letter-spacing:.04em;color:#333;margin-bottom:8px;padding:0 4px}.kpi-row{display:flex;align-items:baseline;gap:12px;margin-bottom:8px}.kpi-value{font-size:24px;font-weight:700}.kpi-delta{font-size:12px;font-weight:600}.kpi-delta.pos{color:#43a047}.kpi-delta.neg{color:#e53935}.sparkline{margin:4px 0 8px}.legend-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}.legend-item{display:flex;align-items:center;gap:8px}.dot{width:10px;height:10px;border-radius:50%;display:inline-block}.label{flex:1}.value{font-weight:600}\n"] }]
95
+ }], propDecorators: { title: [{
96
+ type: Input
97
+ }], showTitle: [{
98
+ type: Input
99
+ }], titleStyle: [{
100
+ type: Input
101
+ }], titleHAlign: [{
102
+ type: Input
103
+ }], contentVAlign: [{
104
+ type: Input
105
+ }], contentHAlign: [{
106
+ type: Input
107
+ }], value: [{
108
+ type: Input
109
+ }], delta: [{
110
+ type: Input
111
+ }], periodLabel: [{
112
+ type: Input
113
+ }], items: [{
114
+ type: Input
115
+ }], sparkline: [{
116
+ type: Input
117
+ }], formatters: [{
118
+ type: Input
119
+ }], i18n: [{
120
+ type: Input
121
+ }], spark: [{
122
+ type: ViewChild,
123
+ args: ["spark", { static: false }]
124
+ }] } });
125
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic214LWRhc2gtY2FyZC1rcGktbGVnZW5kLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zdW1heC1lcnAtY29tcG9uZW50L3NyYy9saWIvc3VtYXgtZGFzaGJvYXJkL2NhcmRzL3NteC1kYXNoLWNhcmQta3BpLWxlZ2VuZC9zbXgtZGFzaC1jYXJkLWtwaS1sZWdlbmQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXN1bWF4LWVycC1jb21wb25lbnQvc3JjL2xpYi9zdW1heC1kYXNoYm9hcmQvY2FyZHMvc214LWRhc2gtY2FyZC1rcGktbGVnZW5kL3NteC1kYXNoLWNhcmQta3BpLWxlZ2VuZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFpQix1QkFBdUIsRUFBRSxTQUFTLEVBQWMsS0FBSyxFQUFhLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7O0FBVzNILE1BQU0sT0FBTyw2QkFBNkI7SUFSMUM7UUFTRSxxQ0FBcUM7UUFDNUIsVUFBSyxHQUFHLEVBQUUsQ0FBQztRQUNwQix5REFBeUQ7UUFDaEQsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUMzQiw4RUFBOEU7UUFDckUsZUFBVSxHQUEyQixFQUFFLENBQUM7UUFDakQsK0ZBQStGO1FBQ3RGLGdCQUFXLEdBQWdDLFFBQVEsQ0FBQztRQUM3RCxrR0FBa0c7UUFDekYsa0JBQWEsR0FBZ0MsUUFBUSxDQUFDO1FBQy9ELG9HQUFvRztRQUMzRixrQkFBYSxHQUFnQyxRQUFRLENBQUM7UUFDL0QsbUZBQW1GO1FBQzFFLFVBQUssR0FBb0IsRUFBRSxDQUFDO1FBS3JDLDJHQUEyRztRQUNsRyxVQUFLLEdBQTJCLEVBQUUsQ0FBQztLQXdFN0M7SUE5REMsV0FBVztRQUNU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S0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFDaUMsS0FBSztzQkFBM0MsU0FBUzt1QkFBQyxPQUFPLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRWxlbWVudFJlZiwgSW5wdXQsIE9uQ2hhbmdlcywgVmlld0NoaWxkIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB0eXBlIHsgUGllSXRlbSB9IGZyb20gXCIuLi8uLi90eXBlcy90eXBlc1wiO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwic214LWRhc2gtY2FyZC1rcGktbGVnZW5kXCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICB0ZW1wbGF0ZVVybDogXCIuL3NteC1kYXNoLWNhcmQta3BpLWxlZ2VuZC5jb21wb25lbnQuaHRtbFwiLFxuICBzdHlsZVVybHM6IFtcIi4vc214LWRhc2gtY2FyZC1rcGktbGVnZW5kLmNvbXBvbmVudC5zY3NzXCJdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgU214RGFzaENhcmRLcGlMZWdlbmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIEFmdGVyVmlld0luaXQge1xuICAvKiogVMOtdHVsbyBkZWwgd2lkZ2V0LiBAZGVmYXVsdCBcIlwiICovXG4gIEBJbnB1dCgpIHRpdGxlID0gXCJcIjtcbiAgLyoqIENvbnRyb2xhIGxhIHZpc2liaWxpZGFkIGRlbCB0w610dWxvLiBAZGVmYXVsdCBmYWxzZSAqL1xuICBASW5wdXQoKSBzaG93VGl0bGUgPSBmYWxzZTtcbiAgLyoqIEVzdGlsb3MgQ1NTIGlubGluZSBhZGljaW9uYWxlcyBwYXJhIGVsIGVsZW1lbnRvIGRlbCB0w610dWxvLiBAZGVmYXVsdCB7fSAqL1xuICBASW5wdXQoKSB0aXRsZVN0eWxlOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gIC8qKiBBbGluZWFjacOzbiBob3Jpem9udGFsIGRlbCB0w610dWxvLiBQcm9wYWdhZG8gZGVzZGUgYGV4dHJhLnRpdGxlSEFsaWduYC4gQGRlZmF1bHQgXCJjZW50ZXJcIiAqL1xuICBASW5wdXQoKSB0aXRsZUhBbGlnbjogXCJsZWZ0XCIgfCBcImNlbnRlclwiIHwgXCJyaWdodFwiID0gXCJjZW50ZXJcIjtcbiAgLyoqIEFsaW5lYWNpw7NuIHZlcnRpY2FsIGRlbCBjb250ZW5pZG8uIFByb3BhZ2FkbyBkZXNkZSBgZXh0cmEuY29udGVudFZBbGlnbmAuIEBkZWZhdWx0IFwiY2VudGVyXCIgKi9cbiAgQElucHV0KCkgY29udGVudFZBbGlnbjogXCJ0b3BcIiB8IFwiY2VudGVyXCIgfCBcImJvdHRvbVwiID0gXCJjZW50ZXJcIjtcbiAgLyoqIEFsaW5lYWNpw7NuIGhvcml6b250YWwgZGVsIGNvbnRlbmlkby4gUHJvcGFnYWRvIGRlc2RlIGBleHRyYS5jb250ZW50SEFsaWduYC4gQGRlZmF1bHQgXCJjZW50ZXJcIiAqL1xuICBASW5wdXQoKSBjb250ZW50SEFsaWduOiBcImxlZnRcIiB8IFwiY2VudGVyXCIgfCBcInJpZ2h0XCIgPSBcImNlbnRlclwiO1xuICAvKiogS1BJIHByaW5jaXBhbDogdmFsb3IgbnVtw6lyaWNvIG8gdGV4dG8gYSBtb3N0cmFyIHByb21pbmVudGVtZW50ZS4gQGRlZmF1bHQgXCJcIiAqL1xuICBASW5wdXQoKSB2YWx1ZTogbnVtYmVyIHwgc3RyaW5nID0gXCJcIjtcbiAgLyoqIFZhcmlhY2nDs24gcG9yY2VudHVhbCByZXNwZWN0byBhbCBwZXLDrW9kbyBhbnRlcmlvciAocG9zaXRpdm8gPSB2ZXJkZSwgbmVnYXRpdm8gPSByb2pvKS4gKi9cbiAgQElucHV0KCkgZGVsdGE/OiBudW1iZXI7XG4gIC8qKiBFdGlxdWV0YSBkZXNjcmlwdGl2YSBkZWwgcGVyw61vZG8gZGUgY29tcGFyYWNpw7NuIGRlbCBkZWx0YSAoZS5qLiBcInZzLiBtZXMgYW50ZXJpb3JcIikuICovXG4gIEBJbnB1dCgpIHBlcmlvZExhYmVsPzogc3RyaW5nO1xuICAvKiogSXRlbXMgZGVsIGdyw6FmaWNvIGRlIHRvcnRhL2xleWVuZGEgaW5mZXJpb3IuIENhZGEgaXRlbSB0aWVuZSBgbGFiZWxgLCBgdmFsdWVgIHkgYGNvbG9yYC4gQGRlZmF1bHQgW10gKi9cbiAgQElucHV0KCkgaXRlbXM6IFJlYWRvbmx5QXJyYXk8UGllSXRlbT4gPSBbXTtcbiAgLyoqIFNlcmllIGRlIGRhdG9zIHBhcmEgZWwgZ3LDoWZpY28gc3BhcmtsaW5lIChsw61uZWEgcGVxdWXDsWEpLiBAZGVmYXVsdCBbXSAqL1xuICBASW5wdXQoKSBzcGFya2xpbmU/OiBSZWFkb25seUFycmF5PG51bWJlcj47XG4gIC8qKiBNYXBhIGRlIGZ1bmNpb25lcyBkZSBmb3JtYXRlbyBwcm9wYWdhZG8gZGVzZGUgZWwgZ3JpZC4gKi9cbiAgQElucHV0KCkgZm9ybWF0dGVycz86IFJlY29yZDxzdHJpbmcsIGFueT47XG4gIC8qKiBJbnRlcm5hY2lvbmFsaXphY2nDs24gcHJvcGFnYWRhIGRlc2RlIGVsIGdyaWQuICovXG4gIEBJbnB1dCgpIGkxOG4/OiB7IG1vbnRocz86IHN0cmluZ1tdIH07XG4gIEBWaWV3Q2hpbGQoXCJzcGFya1wiLCB7IHN0YXRpYzogZmFsc2UgfSkgc3Bhcms/OiBFbGVtZW50UmVmPEhUTUxDYW52YXNFbGVtZW50PjtcbiAgcHJpdmF0ZSBjaGFydDogdW5rbm93bjtcblxuICBuZ09uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLl9kcmF3U3BhcmtsaW5lKCk7XG4gIH1cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHRoaXMuX2RyYXdTcGFya2xpbmUoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgX2RyYXdTcGFya2xpbmUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZWwgPSB0aGlzLnNwYXJrPy5uYXRpdmVFbGVtZW50O1xuICAgIGlmICghZWwpIHJldHVybjtcbiAgICBjb25zdCBkYXRhQXJyID0gKHRoaXMuc3BhcmtsaW5lID8/IFtdKSBhcyBudW1iZXJbXTtcbiAgICBjb25zdCBjdHggPSBlbC5nZXRDb250ZXh0KFwiMmRcIik7XG4gICAgaWYgKCFjdHgpIHJldHVybjtcbiAgICBjb25zdCBDaGFydEdsb2JhbCA9IChnbG9iYWxUaGlzIGFzIHVua25vd24gYXMgeyBDaGFydD86IHVua25vd24gfSkuQ2hhcnQ7XG4gICAgaWYgKENoYXJ0R2xvYmFsICYmIGRhdGFBcnIubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKHRoaXMuY2hhcnQgJiYgKHRoaXMuY2hhcnQgYXMgeyBkZXN0cm95OiAoKSA9PiB2b2lkIH0pLmRlc3Ryb3kpIHtcbiAgICAgICAgKHRoaXMuY2hhcnQgYXMgeyBkZXN0cm95OiAoKSA9PiB2b2lkIH0pLmRlc3Ryb3koKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IENoYXJ0Q3RvcjogYW55ID0gQ2hhcnRHbG9iYWwgYXMgYW55O1xuICAgICAgdGhpcy5jaGFydCA9IG5ldyBDaGFydEN0b3IoZWwsIHtcbiAgICAgICAgdHlwZTogXCJsaW5lXCIsXG4gICAgICAgIGRhdGE6IHtcbiAgICAgICAgICBsYWJlbHM6IGRhdGFBcnIubWFwKChfLCBpKSA9PiBpKSxcbiAgICAgICAgICBkYXRhc2V0czogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBkYXRhOiBkYXRhQXJyLFxuICAgICAgICAgICAgICBib3JkZXJDb2xvcjogXCIjM2Y1MWI1XCIsXG4gICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogXCJyZ2JhKDYzLDgxLDE4MSwwLjE1KVwiLFxuICAgICAgICAgICAgICB0ZW5zaW9uOiAwLjMsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICByZXNwb25zaXZlOiBmYWxzZSxcbiAgICAgICAgICBhbmltYXRpb246IHsgZHVyYXRpb246IDAgfSxcbiAgICAgICAgICB0cmFuc2l0aW9uczogeyBhY3RpdmU6IHsgYW5pbWF0aW9uOiB7IGR1cmF0aW9uOiAwIH0gfSwgcmVzaXplOiB7IGFuaW1hdGlvbjogeyBkdXJhdGlvbjogMCB9IH0gfSxcbiAgICAgICAgICBwbHVnaW5zOiB7IGxlZ2VuZDogeyBkaXNwbGF5OiBmYWxzZSB9LCB0b29sdGlwOiB7IGVuYWJsZWQ6IGZhbHNlIH0gfSxcbiAgICAgICAgICBzY2FsZXM6IHsgeDogeyBkaXNwbGF5OiBmYWxzZSB9LCB5OiB7IGRpc3BsYXk6IGZhbHNlIH0gfSxcbiAgICAgICAgICBlbGVtZW50czogeyBwb2ludDogeyByYWRpdXM6IDAgfSB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHcgPSBlbC53aWR0aCxcbiAgICAgIGggPSBlbC5oZWlnaHQ7XG4gICAgY3R4LmNsZWFyUmVjdCgwLCAwLCB3LCBoKTtcbiAgICBpZiAoIWRhdGFBcnIubGVuZ3RoKSByZXR1cm47XG4gICAgY29uc3QgbWluID0gTWF0aC5taW4oLi4uZGF0YUFycik7XG4gICAgY29uc3QgbWF4ID0gTWF0aC5tYXgoLi4uZGF0YUFycik7XG4gICAgY29uc3QgcmFuZ2UgPSBtYXggLSBtaW4gfHwgMTtcbiAgICBjb25zdCBzdGVwWCA9IHcgLyBNYXRoLm1heCgxLCBkYXRhQXJyLmxlbmd0aCAtIDEpO1xuICAgIGN0eC5zdHJva2VTdHlsZSA9IFwiIzNmNTFiNVwiO1xuICAgIGN0eC5maWxsU3R5bGUgPSBcInJnYmEoNjMsODEsMTgxLDAuMTUpXCI7XG4gICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgIGRhdGFBcnIuZm9yRWFjaCgodiwgaSkgPT4ge1xuICAgICAgY29uc3QgeCA9IGkgKiBzdGVwWDtcbiAgICAgIGNvbnN0IHkgPSBoIC0gKCh2IC0gbWluKSAvIHJhbmdlKSAqIGg7XG4gICAgICBpZiAoaSA9PT0gMCkgY3R4Lm1vdmVUbyh4LCB5KTtcbiAgICAgIGVsc2UgY3R4LmxpbmVUbyh4LCB5KTtcbiAgICB9KTtcbiAgICBjdHguc3Ryb2tlKCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJzbXgtY2FyZC1rcGktd3JhcFwiPlxuICA8ZGl2ICpuZ0lmPVwic2hvd1RpdGxlICYmIHRpdGxlXCIgY2xhc3M9XCJzbXgtY2FyZC1pbm5lci10aXRsZVwiIFtuZ1N0eWxlXT1cInRpdGxlU3R5bGVcIj57eyB0aXRsZSB9fTwvZGl2PlxuICA8ZGl2IGNsYXNzPVwia3BpLXJvd1wiPlxuICAgIDxkaXYgY2xhc3M9XCJrcGktdmFsdWVcIj57eyB2YWx1ZSB9fTwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJrcGktZGVsdGFcIiBbY2xhc3MucG9zXT1cIihkZWx0YSA/PyAwKSA+PSAwXCIgW2NsYXNzLm5lZ109XCIoZGVsdGEgPz8gMCkgPCAwXCI+XG4gICAgICA8c3BhbiBjbGFzcz1cImRlbHRhXCI+e3sgZGVsdGEgfX08L3NwYW4+XG4gICAgICA8c3BhbiBjbGFzcz1cInBlcmlvZFwiICpuZ0lmPVwicGVyaW9kTGFiZWxcIj57eyBwZXJpb2RMYWJlbCB9fTwvc3Bhbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJzcGFya2xpbmVcIj5cbiAgICA8Y2FudmFzICNzcGFyayB3aWR0aD1cIjEyMFwiIGhlaWdodD1cIjM2XCI+PC9jYW52YXM+XG4gIDwvZGl2PlxuICA8dWwgY2xhc3M9XCJsZWdlbmQtbGlzdFwiPlxuICAgIDxsaSBjbGFzcz1cImxlZ2VuZC1pdGVtXCIgKm5nRm9yPVwibGV0IGl0IG9mIGl0ZW1zXCI+XG4gICAgICA8c3BhbiBjbGFzcz1cImRvdFwiIFtzdHlsZS5iYWNrZ3JvdW5kXT1cIml0LmNvbG9yIHx8ICcjM2Y1MWI1J1wiPjwvc3Bhbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWxcIj57eyBpdC5sYWJlbCB9fTwvc3Bhbj5cbiAgICAgIDxzcGFuIGNsYXNzPVwidmFsdWVcIj57eyBpdC52YWx1ZSB9fTwvc3Bhbj5cbiAgICA8L2xpPlxuICA8L3VsPlxuPC9kaXY+XG4iXX0=