@c80/ui 1.0.44 → 1.0.45

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 (78) hide show
  1. package/c80-ui.d.ts +5 -0
  2. package/esm2022/c80-ui.js +5 -0
  3. package/esm2022/c80-ui.js.map +1 -0
  4. package/esm2022/index.js +6 -0
  5. package/esm2022/index.js.map +1 -0
  6. package/esm2022/lib/card-level/card-level.component.js +56 -0
  7. package/esm2022/lib/card-level/card-level.component.js.map +1 -0
  8. package/esm2022/lib/card-level/card-level.interface.js +2 -0
  9. package/esm2022/lib/card-level/card-level.interface.js.map +1 -0
  10. package/esm2022/lib/card-level/index.js +3 -0
  11. package/esm2022/lib/card-level/index.js.map +1 -0
  12. package/esm2022/lib/icon/icon.component.js +48 -0
  13. package/esm2022/lib/icon/icon.component.js.map +1 -0
  14. package/esm2022/lib/icon/icon.constants.js +237 -0
  15. package/esm2022/lib/icon/icon.constants.js.map +1 -0
  16. package/esm2022/lib/icon/icon.types.js +2 -0
  17. package/esm2022/lib/icon/icon.types.js.map +1 -0
  18. package/esm2022/lib/icon/icon.utils.js +4 -0
  19. package/esm2022/lib/icon/icon.utils.js.map +1 -0
  20. package/esm2022/lib/icon/index.js +4 -0
  21. package/esm2022/lib/icon/index.js.map +1 -0
  22. package/esm2022/lib/modal/index.js +3 -0
  23. package/esm2022/lib/modal/index.js.map +1 -0
  24. package/esm2022/lib/modal/modal.component.js +86 -0
  25. package/esm2022/lib/modal/modal.component.js.map +1 -0
  26. package/esm2022/lib/modal/modal.service.js +83 -0
  27. package/esm2022/lib/modal/modal.service.js.map +1 -0
  28. package/esm2022/lib/stat-card/index.js +2 -0
  29. package/esm2022/lib/stat-card/index.js.map +1 -0
  30. package/esm2022/lib/stat-card/stat-card.component.js +13 -0
  31. package/esm2022/lib/stat-card/stat-card.component.js.map +1 -0
  32. package/esm2022/lib/table/index.js +9 -0
  33. package/esm2022/lib/table/index.js.map +1 -0
  34. package/esm2022/lib/table/table-column-visibility.service.js +105 -0
  35. package/esm2022/lib/table/table-column-visibility.service.js.map +1 -0
  36. package/esm2022/lib/table/table-crud-state.service.js +115 -0
  37. package/esm2022/lib/table/table-crud-state.service.js.map +1 -0
  38. package/esm2022/lib/table/table-data-converter.service.js +145 -0
  39. package/esm2022/lib/table/table-data-converter.service.js.map +1 -0
  40. package/esm2022/lib/table/table-data-utils.service.js +193 -0
  41. package/esm2022/lib/table/table-data-utils.service.js.map +1 -0
  42. package/esm2022/lib/table/table-selection.service.js +121 -0
  43. package/esm2022/lib/table/table-selection.service.js.map +1 -0
  44. package/esm2022/lib/table/table.component.js +413 -0
  45. package/esm2022/lib/table/table.component.js.map +1 -0
  46. package/esm2022/lib/table/table.types.js +5 -0
  47. package/esm2022/lib/table/table.types.js.map +1 -0
  48. package/esm2022/lib/table/table.utils.js +107 -0
  49. package/esm2022/lib/table/table.utils.js.map +1 -0
  50. package/lib/icon/icon.component.d.ts +2 -2
  51. package/lib/modal/index.d.ts +2 -3
  52. package/lib/stat-card/stat-card.component.d.ts +2 -2
  53. package/lib/table/table.component.d.ts +10 -13
  54. package/package.json +7 -9
  55. package/esm2022/c80-ui.mjs +0 -5
  56. package/esm2022/index.mjs +0 -6
  57. package/esm2022/lib/card-level/card-level.component.mjs +0 -57
  58. package/esm2022/lib/card-level/card-level.interface.mjs +0 -2
  59. package/esm2022/lib/card-level/index.mjs +0 -3
  60. package/esm2022/lib/icon/icon.component.mjs +0 -49
  61. package/esm2022/lib/icon/icon.constants.mjs +0 -237
  62. package/esm2022/lib/icon/icon.types.mjs +0 -2
  63. package/esm2022/lib/icon/icon.utils.mjs +0 -4
  64. package/esm2022/lib/icon/index.mjs +0 -4
  65. package/esm2022/lib/modal/index.mjs +0 -3
  66. package/esm2022/lib/modal/modal.component.mjs +0 -86
  67. package/esm2022/lib/modal/modal.service.mjs +0 -83
  68. package/esm2022/lib/stat-card/index.mjs +0 -2
  69. package/esm2022/lib/stat-card/stat-card.component.mjs +0 -16
  70. package/esm2022/lib/table/index.mjs +0 -9
  71. package/esm2022/lib/table/table-column-visibility.service.mjs +0 -105
  72. package/esm2022/lib/table/table-crud-state.service.mjs +0 -115
  73. package/esm2022/lib/table/table-data-converter.service.mjs +0 -145
  74. package/esm2022/lib/table/table-data-utils.service.mjs +0 -193
  75. package/esm2022/lib/table/table-selection.service.mjs +0 -121
  76. package/esm2022/lib/table/table.component.mjs +0 -432
  77. package/esm2022/lib/table/table.types.mjs +0 -5
  78. package/esm2022/lib/table/table.utils.mjs +0 -107
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Transform function para convertir valores string/boolean a boolean
3
+ * Usado en @Input() con transform para habilitar sintaxis de atributos booleanos
4
+ * @example [searchable]="true" o simplemente searchable
5
+ */
6
+ export function booleanAttribute(value) {
7
+ return value === '' || value === true || value === 'true';
8
+ }
9
+ /**
10
+ * Extrae mensaje de error de forma segura desde un objeto unknown
11
+ * @param err - Error desconocido (puede ser Error, string, object, etc.)
12
+ * @returns Mensaje de error legible
13
+ */
14
+ export function getErrorMessage(err) {
15
+ const error = err;
16
+ return error?.message || 'Error al cargar datos';
17
+ }
18
+ /**
19
+ * Obtiene el valor de un input HTML según el tipo de columna
20
+ * IMPORTANTE: Convierte el valor al tipo correcto antes de retornarlo
21
+ * @param event - Evento del input
22
+ * @param col - Definición de columna (opcional)
23
+ * @returns Valor extraído y convertido según el tipo de columna
24
+ */
25
+ export function getInputValue(event, col) {
26
+ if (col?.type === 'boolean') {
27
+ return event.target.checked;
28
+ }
29
+ const target = event.target;
30
+ const rawValue = target?.value;
31
+ if (!col) {
32
+ return rawValue;
33
+ }
34
+ return convertInputValueByType(rawValue, col.type);
35
+ }
36
+ /**
37
+ * Convierte un valor de input según el tipo de columna especificado
38
+ * @param rawValue - Valor crudo del input (string)
39
+ * @param type - Tipo de columna
40
+ * @returns Valor convertido al tipo apropiado
41
+ */
42
+ function convertInputValueByType(rawValue, type) {
43
+ if (!type || type === 'string' || type === 'password' || type === 'date') {
44
+ return rawValue;
45
+ }
46
+ if (type === 'integer' || type === 'number') {
47
+ return convertToNumber(rawValue, type === 'integer');
48
+ }
49
+ if (type === 'enum') {
50
+ return convertEnumValue(rawValue);
51
+ }
52
+ return rawValue;
53
+ }
54
+ /**
55
+ * Convierte string a number o integer
56
+ */
57
+ function convertToNumber(value, isInteger) {
58
+ if (value === '' || value === null || value === undefined) {
59
+ return undefined;
60
+ }
61
+ const num = Number(value);
62
+ if (Number.isNaN(num)) {
63
+ return undefined;
64
+ }
65
+ return isInteger ? Math.floor(num) : num;
66
+ }
67
+ /**
68
+ * Convierte valor de enum (intenta convertir a número si es posible)
69
+ */
70
+ function convertEnumValue(value) {
71
+ const num = Number(value);
72
+ return Number.isNaN(num) ? value : num;
73
+ }
74
+ /**
75
+ * Extrae el ID de una fila para usar como trackBy en ngFor
76
+ * @param index - Índice de la fila
77
+ * @param row - Fila de datos
78
+ * @returns ID como string o índice como fallback
79
+ */
80
+ export function trackById(index, row) {
81
+ const id = row && typeof row === 'object' && 'id' in row
82
+ ? row['id']
83
+ : undefined;
84
+ return typeof id === 'string' ? id : index;
85
+ }
86
+ /**
87
+ * Verifica si una acción debe mostrarse para una fila específica
88
+ * CREATE se excluye porque se maneja con el botón "+" en el header
89
+ * @param action - Acción a verificar
90
+ * @param row - Fila de datos
91
+ * @returns true si la acción debe mostrarse
92
+ */
93
+ export function shouldShowAction(action, row) {
94
+ if (action.name === 'create') {
95
+ return false;
96
+ }
97
+ return !action.condition || action.condition(row);
98
+ }
99
+ /**
100
+ * Obtiene el tooltip de una acción (usa tooltip personalizado o name por defecto)
101
+ * @param action - Acción
102
+ * @returns Texto del tooltip
103
+ */
104
+ export function getActionTooltip(action) {
105
+ return action.tooltip || action.name;
106
+ }
107
+ //# sourceMappingURL=table.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.utils.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/table/table.utils.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAuB;IACtD,OAAO,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC;AAC5D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,MAAM,KAAK,GAAG,GAA2B,CAAC;IAC1C,OAAO,KAAK,EAAE,OAAO,IAAI,uBAAuB,CAAC;AACnD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,KAAY,EAAE,GAAoB;IAC9D,IAAI,GAAG,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAQ,KAAK,CAAC,MAA2B,CAAC,OAAO,CAAC;IACpD,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAA8C,CAAC;IACpE,MAAM,QAAQ,GAAG,MAAM,EAAE,KAAK,CAAC;IAE/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,uBAAuB,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;AACrD,CAAC;AAED;;;;;GAKG;AACH,SAAS,uBAAuB,CAC9B,QAAgB,EAChB,IAAiF;IAEjF,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACzE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,eAAe,CAAC,QAAQ,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,KAAa,EAAE,SAAkB;IACxD,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1D,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,KAAa;IACrC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAoC,KAAa,EAAE,GAAM;IAChF,MAAM,EAAE,GAAG,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,IAAI,IAAI,GAAG;QACtD,CAAC,CAAE,GAA+B,CAAC,IAAI,CAAC;QACxC,CAAC,CAAC,SAAS,CAAC;IACd,OAAO,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAyB,EACzB,GAAM;IAEN,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAyB;IACxD,OAAO,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC;AACvC,CAAC","sourcesContent":["import type { C80TableColDef, CustomTableAction } from './table.types';\n\n/**\n * Transform function para convertir valores string/boolean a boolean\n * Usado en @Input() con transform para habilitar sintaxis de atributos booleanos\n * @example [searchable]=\"true\" o simplemente searchable\n */\nexport function booleanAttribute(value: boolean | string): boolean {\n return value === '' || value === true || value === 'true';\n}\n\n/**\n * Extrae mensaje de error de forma segura desde un objeto unknown\n * @param err - Error desconocido (puede ser Error, string, object, etc.)\n * @returns Mensaje de error legible\n */\nexport function getErrorMessage(err: unknown): string {\n const error = err as { message?: string };\n return error?.message || 'Error al cargar datos';\n}\n\n/**\n * Obtiene el valor de un input HTML según el tipo de columna\n * IMPORTANTE: Convierte el valor al tipo correcto antes de retornarlo\n * @param event - Evento del input\n * @param col - Definición de columna (opcional)\n * @returns Valor extraído y convertido según el tipo de columna\n */\nexport function getInputValue(event: Event, col?: C80TableColDef): unknown {\n if (col?.type === 'boolean') {\n return (event.target as HTMLInputElement).checked;\n }\n\n const target = event.target as HTMLInputElement | HTMLSelectElement;\n const rawValue = target?.value;\n\n if (!col) {\n return rawValue;\n }\n\n return convertInputValueByType(rawValue, col.type);\n}\n\n/**\n * Convierte un valor de input según el tipo de columna especificado\n * @param rawValue - Valor crudo del input (string)\n * @param type - Tipo de columna\n * @returns Valor convertido al tipo apropiado\n */\nfunction convertInputValueByType(\n rawValue: string,\n type?: 'string' | 'number' | 'integer' | 'boolean' | 'password' | 'enum' | 'date'\n): unknown {\n if (!type || type === 'string' || type === 'password' || type === 'date') {\n return rawValue;\n }\n\n if (type === 'integer' || type === 'number') {\n return convertToNumber(rawValue, type === 'integer');\n }\n\n if (type === 'enum') {\n return convertEnumValue(rawValue);\n }\n\n return rawValue;\n}\n\n/**\n * Convierte string a number o integer\n */\nfunction convertToNumber(value: string, isInteger: boolean): number | undefined {\n if (value === '' || value === null || value === undefined) {\n return undefined;\n }\n const num = Number(value);\n if (Number.isNaN(num)) {\n return undefined;\n }\n return isInteger ? Math.floor(num) : num;\n}\n\n/**\n * Convierte valor de enum (intenta convertir a número si es posible)\n */\nfunction convertEnumValue(value: string): string | number {\n const num = Number(value);\n return Number.isNaN(num) ? value : num;\n}\n\n/**\n * Extrae el ID de una fila para usar como trackBy en ngFor\n * @param index - Índice de la fila\n * @param row - Fila de datos\n * @returns ID como string o índice como fallback\n */\nexport function trackById<T extends Record<string, unknown>>(index: number, row: T): string | number {\n const id = row && typeof row === 'object' && 'id' in row\n ? (row as Record<string, unknown>)['id']\n : undefined;\n return typeof id === 'string' ? id : index;\n}\n\n/**\n * Verifica si una acción debe mostrarse para una fila específica\n * CREATE se excluye porque se maneja con el botón \"+\" en el header\n * @param action - Acción a verificar\n * @param row - Fila de datos\n * @returns true si la acción debe mostrarse\n */\nexport function shouldShowAction<T extends Record<string, unknown>>(\n action: CustomTableAction,\n row: T\n): boolean {\n if (action.name === 'create') {\n return false;\n }\n return !action.condition || action.condition(row);\n}\n\n/**\n * Obtiene el tooltip de una acción (usa tooltip personalizado o name por defecto)\n * @param action - Acción\n * @returns Texto del tooltip\n */\nexport function getActionTooltip(action: CustomTableAction): string {\n return action.tooltip || action.name;\n}\n"]}
@@ -14,9 +14,9 @@ export declare class C80IconComponent {
14
14
  readonly iconClick: import("@angular/core").OutputEmitterRef<Event>;
15
15
  readonly iconSize: import("@angular/core").Signal<number>;
16
16
  readonly iconColor: import("@angular/core").Signal<string>;
17
- readonly iconOpacity: import("@angular/core").Signal<1 | 0.5 | 0.7>;
17
+ readonly iconOpacity: import("@angular/core").Signal<0.5 | 0.7 | 1>;
18
18
  readonly iconPath: import("@angular/core").Signal<string>;
19
- readonly additionalShapes: import("@angular/core").Signal<import("./icon.types").ShapeAttributes[]>;
19
+ readonly additionalShapes: import("@angular/core").Signal<import("@c80/ui").ShapeAttributes[]>;
20
20
  onButtonClick(event: Event): void;
21
21
  static ɵfac: i0.ɵɵFactoryDeclaration<C80IconComponent, never>;
22
22
  static ɵcmp: i0.ɵɵComponentDeclaration<C80IconComponent, "c80-icon", never, { "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "customColor": { "alias": "customColor"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "button": { "alias": "button"; "required": false; "isSignal": true; }; "border": { "alias": "border"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "textLeft": { "alias": "textLeft"; "required": false; "isSignal": true; }; "textRight": { "alias": "textRight"; "required": false; "isSignal": true; }; }, { "iconClick": "iconClick"; }, never, never, true, never>;
@@ -1,3 +1,2 @@
1
- export { C80ModalComponent } from './modal.component';
2
- export { ModalService } from './modal.service';
3
- export type { ModalConfig, ModalResult, ModalType } from './modal.component';
1
+ export * from './modal.component';
2
+ export * from './modal.service';
@@ -7,7 +7,7 @@ export interface CardDef {
7
7
  count: number;
8
8
  }
9
9
  export declare class C80StatCardComponent {
10
- cards: CardDef[];
10
+ readonly cards: import("@angular/core").InputSignal<CardDef[]>;
11
11
  static ɵfac: i0.ɵɵFactoryDeclaration<C80StatCardComponent, never>;
12
- static ɵcmp: i0.ɵɵComponentDeclaration<C80StatCardComponent, "c80-stat-card", never, { "cards": { "alias": "cards"; "required": false; }; }, {}, never, never, true, never>;
12
+ static ɵcmp: i0.ɵɵComponentDeclaration<C80StatCardComponent, "c80-stat-card", never, { "cards": { "alias": "cards"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
13
13
  }
@@ -132,15 +132,15 @@ import * as i0 from "@angular/core";
132
132
  private readonly dataConverter;
133
133
  private readonly selectionService;
134
134
  private readonly crudService;
135
- data$: Observable<T[]>;
136
- columns: C80TableColDef[];
137
- inputValues$?: Observable<Partial<T>>;
138
- customActions: CustomTableAction[];
139
- size: number;
140
- multiple: boolean;
141
- searchable: boolean;
142
- allowSelection: boolean;
143
- noConfirm: boolean;
135
+ readonly data$: import("@angular/core").InputSignal<Observable<T[]>>;
136
+ readonly columns: import("@angular/core").InputSignal<C80TableColDef[]>;
137
+ readonly inputValues$: import("@angular/core").InputSignal<Observable<Partial<T>> | undefined>;
138
+ readonly customActions: import("@angular/core").InputSignal<CustomTableAction[]>;
139
+ readonly size: import("@angular/core").InputSignal<number>;
140
+ readonly multiple: import("@angular/core").InputSignal<boolean>;
141
+ readonly searchable: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
142
+ readonly allowSelection: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
143
+ readonly noConfirm: import("@angular/core").InputSignalWithTransform<boolean, string | boolean>;
144
144
  readonly actionClick: import("@angular/core").OutputEmitterRef<{
145
145
  action: string;
146
146
  row: T;
@@ -247,8 +247,5 @@ import * as i0 from "@angular/core";
247
247
  isColumnVisibleInHeader(column: C80TableColDef): boolean;
248
248
  isColumnVisibleForRow(column: C80TableColDef, row: T): boolean;
249
249
  static ɵfac: i0.ɵɵFactoryDeclaration<C80TableComponent<any>, never>;
250
- static ɵcmp: i0.ɵɵComponentDeclaration<C80TableComponent<any>, "c80-table", never, { "data$": { "alias": "data$"; "required": false; }; "columns": { "alias": "columns"; "required": false; }; "inputValues$": { "alias": "inputValues$"; "required": false; }; "customActions": { "alias": "customActions"; "required": false; }; "size": { "alias": "size"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "searchable": { "alias": "searchable"; "required": false; }; "allowSelection": { "alias": "allowSelection"; "required": false; }; "noConfirm": { "alias": "noConfirm"; "required": false; }; }, { "actionClick": "actionClick"; "searchTerm": "searchTerm"; "errorEvent": "errorEvent"; "selectable": "selectable"; }, never, never, true, never>;
251
- static ngAcceptInputType_searchable: boolean | string;
252
- static ngAcceptInputType_allowSelection: boolean | string;
253
- static ngAcceptInputType_noConfirm: boolean | string;
250
+ static ɵcmp: i0.ɵɵComponentDeclaration<C80TableComponent<any>, "c80-table", never, { "data$": { "alias": "data$"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "inputValues$": { "alias": "inputValues$"; "required": false; "isSignal": true; }; "customActions": { "alias": "customActions"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "allowSelection": { "alias": "allowSelection"; "required": false; "isSignal": true; }; "noConfirm": { "alias": "noConfirm"; "required": false; "isSignal": true; }; }, { "actionClick": "actionClick"; "searchTerm": "searchTerm"; "errorEvent": "errorEvent"; "selectable": "selectable"; }, never, never, true, never>;
254
251
  }
package/package.json CHANGED
@@ -1,23 +1,21 @@
1
1
  {
2
2
  "name": "@c80/ui",
3
- "version": "1.0.44",
3
+ "version": "1.0.45",
4
4
  "peerDependencies": {
5
- "@angular/core": "^18.2.0",
5
+ "@angular/core": "^20.3.9",
6
6
  "rxjs": "~7.8.0",
7
- "@angular/common": "~18.2.0"
7
+ "@angular/common": "~20.3.9"
8
8
  },
9
9
  "sideEffects": false,
10
- "module": "esm2022/c80-ui.mjs",
11
- "typings": "index.d.ts",
10
+ "module": "esm2022/c80-ui.js",
11
+ "typings": "c80-ui.d.ts",
12
12
  "exports": {
13
13
  "./package.json": {
14
14
  "default": "./package.json"
15
15
  },
16
16
  ".": {
17
- "types": "./index.d.ts",
18
- "esm2022": "./esm2022/c80-ui.mjs",
19
- "esm": "./esm2022/c80-ui.mjs",
20
- "default": "./esm2022/c80-ui.mjs"
17
+ "types": "./c80-ui.d.ts",
18
+ "default": "./esm2022/c80-ui.js"
21
19
  }
22
20
  },
23
21
  "dependencies": {
@@ -1,5 +0,0 @@
1
- /**
2
- * Generated bundle index. Do not edit.
3
- */
4
- export * from './index';
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYzgwLXVpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vbGlicy91aS9zcmMvYzgwLXVpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxTQUFTLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vaW5kZXgnO1xuIl19
package/esm2022/index.mjs DELETED
@@ -1,6 +0,0 @@
1
- export * from './lib/table';
2
- export * from './lib/icon';
3
- export * from './lib/stat-card';
4
- export * from './lib/card-level';
5
- export * from './lib/modal';
6
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWJzL3VpL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsa0JBQWtCLENBQUM7QUFDakMsY0FBYyxhQUFhLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2xpYi90YWJsZSc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9pY29uJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL3N0YXQtY2FyZCc7XG5leHBvcnQgKiBmcm9tICcuL2xpYi9jYXJkLWxldmVsJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGFsJztcbiJdfQ==
@@ -1,57 +0,0 @@
1
- import { Component, input, computed } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import * as i0 from "@angular/core";
4
- export class CardLevelComponent {
5
- cardLevelData = input.required();
6
- size = input(1); // Multiplicador del tamaño base (220px)
7
- _generatedId;
8
- get generatedId() {
9
- if (!this._generatedId) {
10
- const label = this.cardLevelData().label.toLowerCase().replaceAll(/\s+/g, '-');
11
- const randomNum = Math.floor(Math.random() * 10000);
12
- this._generatedId = `${label}-${randomNum}`;
13
- }
14
- return this._generatedId;
15
- }
16
- get cardWidth() {
17
- const baseWidth = 140;
18
- const calculatedWidth = baseWidth * this.size();
19
- return `${calculatedWidth}px`;
20
- }
21
- // Detecta si el rango es bidireccional (min negativo, max positivo)
22
- isBidirectional = computed(() => {
23
- const data = this.cardLevelData();
24
- return data.min < 0 && data.max > 0;
25
- });
26
- // Calcula el porcentaje de fill para barras bidireccionales
27
- bidirectionalFillPercent = computed(() => {
28
- const data = this.cardLevelData();
29
- const totalRange = data.max - data.min;
30
- return Math.abs(data.value / totalRange) * 100;
31
- });
32
- // Determina la dirección del fill (left/right)
33
- fillDirection = computed(() => {
34
- return this.cardLevelData().value >= 0 ? 'right' : 'left';
35
- });
36
- // Color según el valor y umbrales
37
- fillColor = computed(() => {
38
- const data = this.cardLevelData();
39
- const absValue = Math.abs(data.value);
40
- const absHigh = Math.abs(data.high);
41
- const absLow = Math.abs(data.low);
42
- if (absValue >= absHigh) {
43
- return 'var(--color-danger)';
44
- }
45
- if (absValue >= absLow) {
46
- return 'var(--color-warning)';
47
- }
48
- return 'var(--color-success)';
49
- });
50
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CardLevelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
51
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CardLevelComponent, isStandalone: true, selector: "c80-card-level", inputs: { cardLevelData: { classPropertyName: "cardLevelData", publicName: "cardLevelData", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"card-level-container\" [style.width]=\"cardWidth\">\r\n <label [for]=\"generatedId\">\r\n <strong>{{ cardLevelData().label }}</strong>\r\n\r\n <span class=\"value-display\">\r\n @if (isBidirectional()) {\r\n <!-- Barra bidireccional desde el centro -->\r\n <div class=\"bidirectional-meter\">\r\n <div class=\"meter-track\">\r\n <div class=\"center-line\"></div>\r\n <div class=\"meter-fill\" [class.fill-left]=\"fillDirection() === 'left'\" [class.fill-right]=\"fillDirection() === 'right'\" [style.width.%]=\"bidirectionalFillPercent()\" [style.background]=\"fillColor()\">\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- Meter est\u00E1ndar para rangos unidireccionales -->\r\n <meter [id]=\"generatedId\" [optimum]=\"cardLevelData().optimum\" [min]=\"cardLevelData().min\" [max]=\"cardLevelData().max\" [low]=\"cardLevelData().low\" [high]=\"cardLevelData().high\" [value]=\"cardLevelData().value\">\r\n </meter>\r\n }\r\n\r\n {{ cardLevelData().value }}{{ cardLevelData().unit }}\r\n </span>\r\n </label>\r\n</div>", styles: [".card-level-container{background:#fff;border-radius:5px;padding:8px;margin:4px;box-shadow:0 4px 6px #0000001a,0 1px 3px #00000014;min-width:100px;flex:1}.card-level-container label{display:flex;flex-direction:column;margin:0}.card-level-container label strong{font-size:12px;font-weight:600;color:#2d3748;text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px}.card-level-container label .value-display{font-size:12px;font-weight:600;color:#1a202c;text-align:center;padding:0 5px;background:#4299e11a;border-radius:5px}.card-level-container label .bidirectional-meter{width:100%;margin-bottom:4px}.card-level-container label .bidirectional-meter .meter-track{position:relative;width:100%;height:10px;background:#e2e8f0;border-radius:12px;box-shadow:inset 0 2px 4px #0000001a;overflow:hidden}.card-level-container label .bidirectional-meter .meter-track .center-line{position:absolute;left:50%;top:0;bottom:0;width:4px;background:#4a5568;transform:translate(-50%);z-index:1}.card-level-container label .bidirectional-meter .meter-track .meter-fill{position:absolute;top:0;bottom:0;border-radius:5px}.card-level-container label .bidirectional-meter .meter-track .meter-fill.fill-right{left:50%}.card-level-container label .bidirectional-meter .meter-track .meter-fill.fill-left{right:50%}.card-level-container label meter{width:100%;border-radius:12px;border:none;background:#e2e8f0;margin-bottom:4px}.card-level-container label meter::-webkit-meter-bar{background:#e2e8f0;border-radius:12px;box-shadow:inset 0 2px 4px #0000001a}.card-level-container label meter::-webkit-meter-optimum-value{background:linear-gradient(90deg,#48bb78,#38a169);border-radius:12px}.card-level-container label meter::-webkit-meter-suboptimum-value{background:linear-gradient(90deg,#ed8936,#dd6b20);border-radius:12px}.card-level-container label meter::-webkit-meter-even-less-good-value{background:linear-gradient(90deg,#f56565,#e53e3e);border-radius:12px}.card-level-container label meter::-moz-meter-bar{background:linear-gradient(90deg,#48bb78,#38a169);border-radius:12px}:host{--color-success: linear-gradient(90deg, #48bb78, #38a169);--color-warning: linear-gradient(90deg, #ed8936, #dd6b20);--color-danger: linear-gradient(90deg, #f56565, #e53e3e)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
52
- }
53
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CardLevelComponent, decorators: [{
54
- type: Component,
55
- args: [{ selector: 'c80-card-level', standalone: true, imports: [CommonModule], template: "<div class=\"card-level-container\" [style.width]=\"cardWidth\">\r\n <label [for]=\"generatedId\">\r\n <strong>{{ cardLevelData().label }}</strong>\r\n\r\n <span class=\"value-display\">\r\n @if (isBidirectional()) {\r\n <!-- Barra bidireccional desde el centro -->\r\n <div class=\"bidirectional-meter\">\r\n <div class=\"meter-track\">\r\n <div class=\"center-line\"></div>\r\n <div class=\"meter-fill\" [class.fill-left]=\"fillDirection() === 'left'\" [class.fill-right]=\"fillDirection() === 'right'\" [style.width.%]=\"bidirectionalFillPercent()\" [style.background]=\"fillColor()\">\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- Meter est\u00E1ndar para rangos unidireccionales -->\r\n <meter [id]=\"generatedId\" [optimum]=\"cardLevelData().optimum\" [min]=\"cardLevelData().min\" [max]=\"cardLevelData().max\" [low]=\"cardLevelData().low\" [high]=\"cardLevelData().high\" [value]=\"cardLevelData().value\">\r\n </meter>\r\n }\r\n\r\n {{ cardLevelData().value }}{{ cardLevelData().unit }}\r\n </span>\r\n </label>\r\n</div>", styles: [".card-level-container{background:#fff;border-radius:5px;padding:8px;margin:4px;box-shadow:0 4px 6px #0000001a,0 1px 3px #00000014;min-width:100px;flex:1}.card-level-container label{display:flex;flex-direction:column;margin:0}.card-level-container label strong{font-size:12px;font-weight:600;color:#2d3748;text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px}.card-level-container label .value-display{font-size:12px;font-weight:600;color:#1a202c;text-align:center;padding:0 5px;background:#4299e11a;border-radius:5px}.card-level-container label .bidirectional-meter{width:100%;margin-bottom:4px}.card-level-container label .bidirectional-meter .meter-track{position:relative;width:100%;height:10px;background:#e2e8f0;border-radius:12px;box-shadow:inset 0 2px 4px #0000001a;overflow:hidden}.card-level-container label .bidirectional-meter .meter-track .center-line{position:absolute;left:50%;top:0;bottom:0;width:4px;background:#4a5568;transform:translate(-50%);z-index:1}.card-level-container label .bidirectional-meter .meter-track .meter-fill{position:absolute;top:0;bottom:0;border-radius:5px}.card-level-container label .bidirectional-meter .meter-track .meter-fill.fill-right{left:50%}.card-level-container label .bidirectional-meter .meter-track .meter-fill.fill-left{right:50%}.card-level-container label meter{width:100%;border-radius:12px;border:none;background:#e2e8f0;margin-bottom:4px}.card-level-container label meter::-webkit-meter-bar{background:#e2e8f0;border-radius:12px;box-shadow:inset 0 2px 4px #0000001a}.card-level-container label meter::-webkit-meter-optimum-value{background:linear-gradient(90deg,#48bb78,#38a169);border-radius:12px}.card-level-container label meter::-webkit-meter-suboptimum-value{background:linear-gradient(90deg,#ed8936,#dd6b20);border-radius:12px}.card-level-container label meter::-webkit-meter-even-less-good-value{background:linear-gradient(90deg,#f56565,#e53e3e);border-radius:12px}.card-level-container label meter::-moz-meter-bar{background:linear-gradient(90deg,#48bb78,#38a169);border-radius:12px}:host{--color-success: linear-gradient(90deg, #48bb78, #38a169);--color-warning: linear-gradient(90deg, #ed8936, #dd6b20);--color-danger: linear-gradient(90deg, #f56565, #e53e3e)}\n"] }]
56
- }] });
57
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FyZC1sZXZlbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL3VpL3NyYy9saWIvY2FyZC1sZXZlbC9jYXJkLWxldmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL2xpYnMvdWkvc3JjL2xpYi9jYXJkLWxldmVsL2NhcmQtbGV2ZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7QUFXL0MsTUFBTSxPQUFPLGtCQUFrQjtJQUM3QixhQUFhLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBaUIsQ0FBQztJQUNoRCxJQUFJLEdBQUcsS0FBSyxDQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsd0NBQXdDO0lBRXpELFlBQVksQ0FBVTtJQUU5QixJQUFJLFdBQVc7UUFDYixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3ZCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztZQUMvRSxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQztZQUNwRCxJQUFJLENBQUMsWUFBWSxHQUFHLEdBQUcsS0FBSyxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQzlDLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztJQUVELElBQUksU0FBUztRQUNYLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQztRQUN0QixNQUFNLGVBQWUsR0FBRyxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2hELE9BQU8sR0FBRyxlQUFlLElBQUksQ0FBQztJQUNoQyxDQUFDO0lBRUQsb0VBQW9FO0lBQ3BFLGVBQWUsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1FBQzlCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNsQyxPQUFPLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDO0lBQ3RDLENBQUMsQ0FBQyxDQUFDO0lBRUgsNERBQTREO0lBQzVELHdCQUF3QixHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7UUFDdkMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2xDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUN2QyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssR0FBRyxVQUFVLENBQUMsR0FBRyxHQUFHLENBQUM7SUFDakQsQ0FBQyxDQUFDLENBQUM7SUFFSCwrQ0FBK0M7SUFDL0MsYUFBYSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7UUFDNUIsT0FBTyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDNUQsQ0FBQyxDQUFDLENBQUM7SUFFSCxrQ0FBa0M7SUFDbEMsU0FBUyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7UUFDeEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2xDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRWxDLElBQUksUUFBUSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ3hCLE9BQU8scUJBQXFCLENBQUM7UUFDL0IsQ0FBQztRQUNELElBQUksUUFBUSxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ3ZCLE9BQU8sc0JBQXNCLENBQUM7UUFDaEMsQ0FBQztRQUNELE9BQU8sc0JBQXNCLENBQUM7SUFDaEMsQ0FBQyxDQUFDLENBQUM7d0dBckRRLGtCQUFrQjs0RkFBbEIsa0JBQWtCLDBWQ1ovQix3bkNBdUJNLDB2RURmTSxZQUFZOzs0RkFJWCxrQkFBa0I7a0JBUjlCLFNBQVM7K0JBRUUsZ0JBQWdCLGNBQ2QsSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBpbnB1dCwgY29tcHV0ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgQ2FyZExldmVsRGF0YSB9IGZyb20gJy4vY2FyZC1sZXZlbC5pbnRlcmZhY2UnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9jb21wb25lbnQtc2VsZWN0b3JcclxuICBzZWxlY3RvcjogJ2M4MC1jYXJkLWxldmVsJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9jYXJkLWxldmVsLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybDogJy4vY2FyZC1sZXZlbC5jb21wb25lbnQuc2NzcydcclxufSlcclxuZXhwb3J0IGNsYXNzIENhcmRMZXZlbENvbXBvbmVudCB7XHJcbiAgY2FyZExldmVsRGF0YSA9IGlucHV0LnJlcXVpcmVkPENhcmRMZXZlbERhdGE+KCk7XHJcbiAgc2l6ZSA9IGlucHV0PG51bWJlcj4oMSk7IC8vIE11bHRpcGxpY2Fkb3IgZGVsIHRhbWHDsW8gYmFzZSAoMjIwcHgpXHJcblxyXG4gIHByaXZhdGUgX2dlbmVyYXRlZElkPzogc3RyaW5nO1xyXG5cclxuICBnZXQgZ2VuZXJhdGVkSWQoKTogc3RyaW5nIHtcclxuICAgIGlmICghdGhpcy5fZ2VuZXJhdGVkSWQpIHtcclxuICAgICAgY29uc3QgbGFiZWwgPSB0aGlzLmNhcmRMZXZlbERhdGEoKS5sYWJlbC50b0xvd2VyQ2FzZSgpLnJlcGxhY2VBbGwoL1xccysvZywgJy0nKTtcclxuICAgICAgY29uc3QgcmFuZG9tTnVtID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwMDApO1xyXG4gICAgICB0aGlzLl9nZW5lcmF0ZWRJZCA9IGAke2xhYmVsfS0ke3JhbmRvbU51bX1gO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXMuX2dlbmVyYXRlZElkO1xyXG4gIH1cclxuXHJcbiAgZ2V0IGNhcmRXaWR0aCgpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgYmFzZVdpZHRoID0gMTQwO1xyXG4gICAgY29uc3QgY2FsY3VsYXRlZFdpZHRoID0gYmFzZVdpZHRoICogdGhpcy5zaXplKCk7XHJcbiAgICByZXR1cm4gYCR7Y2FsY3VsYXRlZFdpZHRofXB4YDtcclxuICB9XHJcblxyXG4gIC8vIERldGVjdGEgc2kgZWwgcmFuZ28gZXMgYmlkaXJlY2Npb25hbCAobWluIG5lZ2F0aXZvLCBtYXggcG9zaXRpdm8pXHJcbiAgaXNCaWRpcmVjdGlvbmFsID0gY29tcHV0ZWQoKCkgPT4ge1xyXG4gICAgY29uc3QgZGF0YSA9IHRoaXMuY2FyZExldmVsRGF0YSgpO1xyXG4gICAgcmV0dXJuIGRhdGEubWluIDwgMCAmJiBkYXRhLm1heCA+IDA7XHJcbiAgfSk7XHJcblxyXG4gIC8vIENhbGN1bGEgZWwgcG9yY2VudGFqZSBkZSBmaWxsIHBhcmEgYmFycmFzIGJpZGlyZWNjaW9uYWxlc1xyXG4gIGJpZGlyZWN0aW9uYWxGaWxsUGVyY2VudCA9IGNvbXB1dGVkKCgpID0+IHtcclxuICAgIGNvbnN0IGRhdGEgPSB0aGlzLmNhcmRMZXZlbERhdGEoKTtcclxuICAgIGNvbnN0IHRvdGFsUmFuZ2UgPSBkYXRhLm1heCAtIGRhdGEubWluO1xyXG4gICAgcmV0dXJuIE1hdGguYWJzKGRhdGEudmFsdWUgLyB0b3RhbFJhbmdlKSAqIDEwMDtcclxuICB9KTtcclxuXHJcbiAgLy8gRGV0ZXJtaW5hIGxhIGRpcmVjY2nDs24gZGVsIGZpbGwgKGxlZnQvcmlnaHQpXHJcbiAgZmlsbERpcmVjdGlvbiA9IGNvbXB1dGVkKCgpID0+IHtcclxuICAgIHJldHVybiB0aGlzLmNhcmRMZXZlbERhdGEoKS52YWx1ZSA+PSAwID8gJ3JpZ2h0JyA6ICdsZWZ0JztcclxuICB9KTtcclxuXHJcbiAgLy8gQ29sb3Igc2Vnw7puIGVsIHZhbG9yIHkgdW1icmFsZXNcclxuICBmaWxsQ29sb3IgPSBjb21wdXRlZCgoKSA9PiB7XHJcbiAgICBjb25zdCBkYXRhID0gdGhpcy5jYXJkTGV2ZWxEYXRhKCk7XHJcbiAgICBjb25zdCBhYnNWYWx1ZSA9IE1hdGguYWJzKGRhdGEudmFsdWUpO1xyXG4gICAgY29uc3QgYWJzSGlnaCA9IE1hdGguYWJzKGRhdGEuaGlnaCk7XHJcbiAgICBjb25zdCBhYnNMb3cgPSBNYXRoLmFicyhkYXRhLmxvdyk7XHJcblxyXG4gICAgaWYgKGFic1ZhbHVlID49IGFic0hpZ2gpIHtcclxuICAgICAgcmV0dXJuICd2YXIoLS1jb2xvci1kYW5nZXIpJztcclxuICAgIH1cclxuICAgIGlmIChhYnNWYWx1ZSA+PSBhYnNMb3cpIHtcclxuICAgICAgcmV0dXJuICd2YXIoLS1jb2xvci13YXJuaW5nKSc7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gJ3ZhcigtLWNvbG9yLXN1Y2Nlc3MpJztcclxuICB9KTtcclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwiY2FyZC1sZXZlbC1jb250YWluZXJcIiBbc3R5bGUud2lkdGhdPVwiY2FyZFdpZHRoXCI+XHJcbiAgPGxhYmVsIFtmb3JdPVwiZ2VuZXJhdGVkSWRcIj5cclxuICAgIDxzdHJvbmc+e3sgY2FyZExldmVsRGF0YSgpLmxhYmVsIH19PC9zdHJvbmc+XHJcblxyXG4gICAgPHNwYW4gY2xhc3M9XCJ2YWx1ZS1kaXNwbGF5XCI+XHJcbiAgICAgIEBpZiAoaXNCaWRpcmVjdGlvbmFsKCkpIHtcclxuICAgICAgPCEtLSBCYXJyYSBiaWRpcmVjY2lvbmFsIGRlc2RlIGVsIGNlbnRybyAtLT5cclxuICAgICAgPGRpdiBjbGFzcz1cImJpZGlyZWN0aW9uYWwtbWV0ZXJcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibWV0ZXItdHJhY2tcIj5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjZW50ZXItbGluZVwiPjwvZGl2PlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm1ldGVyLWZpbGxcIiBbY2xhc3MuZmlsbC1sZWZ0XT1cImZpbGxEaXJlY3Rpb24oKSA9PT0gJ2xlZnQnXCIgW2NsYXNzLmZpbGwtcmlnaHRdPVwiZmlsbERpcmVjdGlvbigpID09PSAncmlnaHQnXCIgW3N0eWxlLndpZHRoLiVdPVwiYmlkaXJlY3Rpb25hbEZpbGxQZXJjZW50KClcIiBbc3R5bGUuYmFja2dyb3VuZF09XCJmaWxsQ29sb3IoKVwiPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICB9IEBlbHNlIHtcclxuICAgICAgPCEtLSBNZXRlciBlc3TDoW5kYXIgcGFyYSByYW5nb3MgdW5pZGlyZWNjaW9uYWxlcyAtLT5cclxuICAgICAgPG1ldGVyIFtpZF09XCJnZW5lcmF0ZWRJZFwiIFtvcHRpbXVtXT1cImNhcmRMZXZlbERhdGEoKS5vcHRpbXVtXCIgW21pbl09XCJjYXJkTGV2ZWxEYXRhKCkubWluXCIgW21heF09XCJjYXJkTGV2ZWxEYXRhKCkubWF4XCIgW2xvd109XCJjYXJkTGV2ZWxEYXRhKCkubG93XCIgW2hpZ2hdPVwiY2FyZExldmVsRGF0YSgpLmhpZ2hcIiBbdmFsdWVdPVwiY2FyZExldmVsRGF0YSgpLnZhbHVlXCI+XHJcbiAgICAgIDwvbWV0ZXI+XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHt7IGNhcmRMZXZlbERhdGEoKS52YWx1ZSB9fXt7IGNhcmRMZXZlbERhdGEoKS51bml0IH19XHJcbiAgICA8L3NwYW4+XHJcbiAgPC9sYWJlbD5cclxuPC9kaXY+Il19
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FyZC1sZXZlbC5pbnRlcmZhY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL3VpL3NyYy9saWIvY2FyZC1sZXZlbC9jYXJkLWxldmVsLmludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGludGVyZmFjZSBDYXJkTGV2ZWxEYXRhIHtcclxuICBsYWJlbDogc3RyaW5nO1xyXG4gIHZhbHVlOiBudW1iZXI7XHJcbiAgbWluOiBudW1iZXI7XHJcbiAgbWF4OiBudW1iZXI7XHJcbiAgb3B0aW11bTogbnVtYmVyO1xyXG4gIGxvdzogbnVtYmVyO1xyXG4gIGhpZ2g6IG51bWJlcjtcclxuICB1bml0OiBzdHJpbmc7XHJcbn1cclxuIl19
@@ -1,3 +0,0 @@
1
- export * from './card-level.component';
2
- export * from './card-level.interface';
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL3VpL3NyYy9saWIvY2FyZC1sZXZlbC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsd0JBQXdCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2NhcmQtbGV2ZWwuY29tcG9uZW50JztcclxuZXhwb3J0ICogZnJvbSAnLi9jYXJkLWxldmVsLmludGVyZmFjZSc7XHJcbiJdfQ==
@@ -1,49 +0,0 @@
1
- import { Component, input, output, computed } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { BASE_ICON_SIZE, BASE_ICON_COLORS, DISABLED_COLOR, DEFAULT_ICON_COLOR, DISABLED_OPACITY, SECONDARY_WARN_OPACITY, DEFAULT_OPACITY, ICON_PATHS, ICON_ADDITIONAL_SHAPES, } from './icon.constants';
4
- import { transformToBoolean } from './icon.utils';
5
- import * as i0 from "@angular/core";
6
- import * as i1 from "@angular/common";
7
- export class C80IconComponent {
8
- icon = input('check'); // Tipo de icono a mostrar
9
- color = input('primary'); // Color del icono (primary, secondary, warn, success)
10
- customColor = input(undefined); // Color personalizado (sobrescribe color)
11
- disabled = input(false); // Estado deshabilitado
12
- size = input(1); // Multiplicador de tamaño (1 = 24px)
13
- button = input(false, { transform: transformToBoolean }); // Renderiza como botón clickeable
14
- border = input(false, { transform: transformToBoolean }); // Agrega borde al wrapper
15
- type = input('button'); // Tipo de botón (button, submit, reset)
16
- textLeft = input(undefined); // Texto a la izquierda del icono
17
- textRight = input(undefined); // Texto a la derecha del icono
18
- iconClick = output(); // Evento emitido al hacer click (solo si button=true)
19
- iconSize = computed(() => BASE_ICON_SIZE * this.size());
20
- iconColor = computed(() => {
21
- if (this.disabled())
22
- return DISABLED_COLOR;
23
- const custom = this.customColor();
24
- if (custom)
25
- return custom;
26
- return BASE_ICON_COLORS[this.color()] ?? DEFAULT_ICON_COLOR;
27
- });
28
- iconOpacity = computed(() => {
29
- if (this.disabled())
30
- return DISABLED_OPACITY;
31
- const hasCustomColor = this.customColor() !== undefined;
32
- const isSecondaryOrWarn = ['secondary', 'warn'].includes(this.color());
33
- return !hasCustomColor && isSecondaryOrWarn ? SECONDARY_WARN_OPACITY : DEFAULT_OPACITY;
34
- });
35
- iconPath = computed(() => ICON_PATHS[this.icon()] ?? ICON_PATHS['default']);
36
- additionalShapes = computed(() => ICON_ADDITIONAL_SHAPES[this.icon()] ?? []);
37
- onButtonClick(event) {
38
- if (!this.disabled()) {
39
- this.iconClick.emit(event);
40
- }
41
- }
42
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C80IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
43
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: C80IconComponent, isStandalone: true, selector: "c80-icon", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, customColor: { classPropertyName: "customColor", publicName: "customColor", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, button: { classPropertyName: "button", publicName: "button", isSignal: true, isRequired: false, transformFunction: null }, border: { classPropertyName: "border", publicName: "border", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, textLeft: { classPropertyName: "textLeft", publicName: "textLeft", isSignal: true, isRequired: false, transformFunction: null }, textRight: { classPropertyName: "textRight", publicName: "textRight", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { iconClick: "iconClick" }, ngImport: i0, template: "<ng-template #svgContent>\r\n <svg [attr.width]=\"iconSize()\" [attr.height]=\"iconSize()\" viewBox=\"0 0 24 24\" fill=\"none\" [style.opacity]=\"iconOpacity()\">\r\n @for (shape of additionalShapes(); track $index) {\r\n @if (shape.type === 'circle') {\r\n <circle [attr.cx]=\"shape['cx']\" [attr.cy]=\"shape['cy']\" [attr.r]=\"shape['r']\" [attr.stroke]=\"iconColor()\" stroke-width=\"2\" [attr.fill]=\"shape['fill'] === 'color' ? iconColor() : 'none'\" />\r\n } @else if (shape.type === 'rect') {\r\n <rect [attr.x]=\"shape['x']\" [attr.y]=\"shape['y']\" [attr.width]=\"shape['width']\" [attr.height]=\"shape['height']\" [attr.rx]=\"shape['rx']\" [attr.stroke]=\"iconColor()\" stroke-width=\"2\" fill=\"none\" />\r\n } @else if (shape.type === 'path') {\r\n <path [attr.d]=\"shape['d']\" [attr.stroke]=\"iconColor()\" stroke-width=\"2\" [attr.fill]=\"shape['fill'] === 'color' ? iconColor() : 'none'\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n }\r\n }\r\n <path [attr.d]=\"iconPath()\" [attr.stroke]=\"iconColor()\" [attr.fill]=\"icon() === 'delete' ? iconColor() : 'none'\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n</ng-template>\r\n\r\n<ng-template #textContent>\r\n @if (textLeft()) {\r\n <span class=\"icon-text\" style=\"margin-left: 12px\">{{ textLeft() }}</span>\r\n }\r\n <span class=\"icon-content\" [style.width.px]=\"iconSize() + 8\" [style.height.px]=\"iconSize() + 8\">\r\n <ng-container *ngTemplateOutlet=\"svgContent\" />\r\n </span>\r\n @if (textRight()) {\r\n <span class=\"icon-text\" style=\"margin-right: 12px\">{{ textRight() }}</span>\r\n }\r\n</ng-template>\r\n\r\n@if (button()) {\r\n<button [type]=\"type()\" [disabled]=\"disabled()\" class=\"icon-wrapper\" [class.icon-wrapper-border]=\"border()\" (click)=\"onButtonClick($event)\">\r\n <ng-container *ngTemplateOutlet=\"textContent\" />\r\n</button>\r\n} @else {\r\n<span class=\"icon-wrapper\" [class.icon-wrapper-border]=\"border()\">\r\n <ng-container *ngTemplateOutlet=\"textContent\" />\r\n</span>\r\n}", styles: [":host .icon-wrapper{display:inline-flex;align-items:center;gap:8px;background:transparent;padding:0;border:none;outline:none;cursor:pointer;transition:opacity .2s}:host button.icon-wrapper:focus-visible{outline:2px solid #1976d2;outline-offset:2px;border-radius:4px}:host button.icon-wrapper:disabled{opacity:.5;cursor:default}:host .icon-content{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;min-width:0;min-height:0;padding:4px;margin:0 4px;transition:background .2s;box-sizing:border-box}:host button.icon-wrapper:hover:not(:disabled) .icon-content{background:#1976d214}:host button.icon-wrapper:active:not(:disabled) .icon-content{background:#1976d229}:host .icon-text{font-size:14px;line-height:1;white-space:nowrap;-webkit-user-select:none;user-select:none}:host .icon-wrapper-border{border:1px solid rgba(0,0,0,.23);border-radius:4px;padding:4px 8px}:host button.icon-wrapper-border:hover:not(:disabled){border-color:#000000de}:host button.icon-wrapper-border:disabled{border-color:#0000001f}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
44
- }
45
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C80IconComponent, decorators: [{
46
- type: Component,
47
- args: [{ selector: 'c80-icon', standalone: true, imports: [CommonModule], template: "<ng-template #svgContent>\r\n <svg [attr.width]=\"iconSize()\" [attr.height]=\"iconSize()\" viewBox=\"0 0 24 24\" fill=\"none\" [style.opacity]=\"iconOpacity()\">\r\n @for (shape of additionalShapes(); track $index) {\r\n @if (shape.type === 'circle') {\r\n <circle [attr.cx]=\"shape['cx']\" [attr.cy]=\"shape['cy']\" [attr.r]=\"shape['r']\" [attr.stroke]=\"iconColor()\" stroke-width=\"2\" [attr.fill]=\"shape['fill'] === 'color' ? iconColor() : 'none'\" />\r\n } @else if (shape.type === 'rect') {\r\n <rect [attr.x]=\"shape['x']\" [attr.y]=\"shape['y']\" [attr.width]=\"shape['width']\" [attr.height]=\"shape['height']\" [attr.rx]=\"shape['rx']\" [attr.stroke]=\"iconColor()\" stroke-width=\"2\" fill=\"none\" />\r\n } @else if (shape.type === 'path') {\r\n <path [attr.d]=\"shape['d']\" [attr.stroke]=\"iconColor()\" stroke-width=\"2\" [attr.fill]=\"shape['fill'] === 'color' ? iconColor() : 'none'\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n }\r\n }\r\n <path [attr.d]=\"iconPath()\" [attr.stroke]=\"iconColor()\" [attr.fill]=\"icon() === 'delete' ? iconColor() : 'none'\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n</ng-template>\r\n\r\n<ng-template #textContent>\r\n @if (textLeft()) {\r\n <span class=\"icon-text\" style=\"margin-left: 12px\">{{ textLeft() }}</span>\r\n }\r\n <span class=\"icon-content\" [style.width.px]=\"iconSize() + 8\" [style.height.px]=\"iconSize() + 8\">\r\n <ng-container *ngTemplateOutlet=\"svgContent\" />\r\n </span>\r\n @if (textRight()) {\r\n <span class=\"icon-text\" style=\"margin-right: 12px\">{{ textRight() }}</span>\r\n }\r\n</ng-template>\r\n\r\n@if (button()) {\r\n<button [type]=\"type()\" [disabled]=\"disabled()\" class=\"icon-wrapper\" [class.icon-wrapper-border]=\"border()\" (click)=\"onButtonClick($event)\">\r\n <ng-container *ngTemplateOutlet=\"textContent\" />\r\n</button>\r\n} @else {\r\n<span class=\"icon-wrapper\" [class.icon-wrapper-border]=\"border()\">\r\n <ng-container *ngTemplateOutlet=\"textContent\" />\r\n</span>\r\n}", styles: [":host .icon-wrapper{display:inline-flex;align-items:center;gap:8px;background:transparent;padding:0;border:none;outline:none;cursor:pointer;transition:opacity .2s}:host button.icon-wrapper:focus-visible{outline:2px solid #1976d2;outline-offset:2px;border-radius:4px}:host button.icon-wrapper:disabled{opacity:.5;cursor:default}:host .icon-content{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;min-width:0;min-height:0;padding:4px;margin:0 4px;transition:background .2s;box-sizing:border-box}:host button.icon-wrapper:hover:not(:disabled) .icon-content{background:#1976d214}:host button.icon-wrapper:active:not(:disabled) .icon-content{background:#1976d229}:host .icon-text{font-size:14px;line-height:1;white-space:nowrap;-webkit-user-select:none;user-select:none}:host .icon-wrapper-border{border:1px solid rgba(0,0,0,.23);border-radius:4px;padding:4px 8px}:host button.icon-wrapper-border:hover:not(:disabled){border-color:#000000de}:host button.icon-wrapper-border:disabled{border-color:#0000001f}\n"] }]
48
- }] });
49
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWNvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL3VpL3NyYy9saWIvaWNvbi9pY29uLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL2xpYnMvdWkvc3JjL2xpYi9pY29uL2ljb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUNMLGNBQWMsRUFDZCxnQkFBZ0IsRUFDaEIsY0FBYyxFQUNkLGtCQUFrQixFQUNsQixnQkFBZ0IsRUFDaEIsc0JBQXNCLEVBQ3RCLGVBQWUsRUFDZixVQUFVLEVBQ1Ysc0JBQXNCLEdBQ3ZCLE1BQU0sa0JBQWtCLENBQUM7QUFFMUIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sY0FBYyxDQUFDOzs7QUFVbEQsTUFBTSxPQUFPLGdCQUFnQjtJQUNsQixJQUFJLEdBQUcsS0FBSyxDQUFXLE9BQU8sQ0FBQyxDQUFDLENBQUMsMEJBQTBCO0lBQzNELEtBQUssR0FBRyxLQUFLLENBQVksU0FBUyxDQUFDLENBQUMsQ0FBQyxzREFBc0Q7SUFDM0YsV0FBVyxHQUFHLEtBQUssQ0FBcUIsU0FBUyxDQUFDLENBQUMsQ0FBQywwQ0FBMEM7SUFDOUYsUUFBUSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLHVCQUF1QjtJQUNoRCxJQUFJLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMscUNBQXFDO0lBQ3RELE1BQU0sR0FBRyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLENBQUMsQ0FBQyxDQUFDLGtDQUFrQztJQUM1RixNQUFNLEdBQUcsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLFNBQVMsRUFBRSxrQkFBa0IsRUFBRSxDQUFDLENBQUMsQ0FBQywwQkFBMEI7SUFDcEYsSUFBSSxHQUFHLEtBQUssQ0FBYSxRQUFRLENBQUMsQ0FBQyxDQUFDLHdDQUF3QztJQUM1RSxRQUFRLEdBQUcsS0FBSyxDQUFxQixTQUFTLENBQUMsQ0FBQyxDQUFDLGlDQUFpQztJQUNsRixTQUFTLEdBQUcsS0FBSyxDQUFxQixTQUFTLENBQUMsQ0FBQyxDQUFDLCtCQUErQjtJQUVqRixTQUFTLEdBQUcsTUFBTSxFQUFTLENBQUMsQ0FBQyxzREFBc0Q7SUFFbkYsUUFBUSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFFeEQsU0FBUyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7UUFDakMsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQUUsT0FBTyxjQUFjLENBQUM7UUFFM0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2xDLElBQUksTUFBTTtZQUFFLE9BQU8sTUFBTSxDQUFDO1FBRTFCLE9BQU8sZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLElBQUksa0JBQWtCLENBQUM7SUFDOUQsQ0FBQyxDQUFDLENBQUM7SUFFTSxXQUFXLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtRQUNuQyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFBRSxPQUFPLGdCQUFnQixDQUFDO1FBRTdDLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsS0FBSyxTQUFTLENBQUM7UUFDeEQsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFFdkUsT0FBTyxDQUFDLGNBQWMsSUFBSSxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQztJQUN6RixDQUFDLENBQUMsQ0FBQztJQUVNLFFBQVEsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQzVFLGdCQUFnQixHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUV0RixhQUFhLENBQUMsS0FBWTtRQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDN0IsQ0FBQztJQUNILENBQUM7d0dBekNVLGdCQUFnQjs0RkFBaEIsZ0JBQWdCLGsxQ0N4QjdCLGdqRUFtQ0Msb2tDRGZXLFlBQVk7OzRGQUlYLGdCQUFnQjtrQkFSNUIsU0FBUzsrQkFFRSxVQUFVLGNBQ1IsSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBpbnB1dCwgb3V0cHV0LCBjb21wdXRlZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7XG4gIEJBU0VfSUNPTl9TSVpFLFxuICBCQVNFX0lDT05fQ09MT1JTLFxuICBESVNBQkxFRF9DT0xPUixcbiAgREVGQVVMVF9JQ09OX0NPTE9SLFxuICBESVNBQkxFRF9PUEFDSVRZLFxuICBTRUNPTkRBUllfV0FSTl9PUEFDSVRZLFxuICBERUZBVUxUX09QQUNJVFksXG4gIElDT05fUEFUSFMsXG4gIElDT05fQURESVRJT05BTF9TSEFQRVMsXG59IGZyb20gJy4vaWNvbi5jb25zdGFudHMnO1xuaW1wb3J0IHR5cGUgeyBJY29uVHlwZSwgQ29sb3JUeXBlLCBCdXR0b25UeXBlIH0gZnJvbSAnLi9pY29uLnR5cGVzJztcbmltcG9ydCB7IHRyYW5zZm9ybVRvQm9vbGVhbiB9IGZyb20gJy4vaWNvbi51dGlscyc7XG5cbkBDb21wb25lbnQoe1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGFuZ3VsYXItZXNsaW50L2NvbXBvbmVudC1zZWxlY3RvclxuICBzZWxlY3RvcjogJ2M4MC1pY29uJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9pY29uLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vaWNvbi5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBDODBJY29uQ29tcG9uZW50IHtcbiAgcmVhZG9ubHkgaWNvbiA9IGlucHV0PEljb25UeXBlPignY2hlY2snKTsgLy8gVGlwbyBkZSBpY29ubyBhIG1vc3RyYXJcbiAgcmVhZG9ubHkgY29sb3IgPSBpbnB1dDxDb2xvclR5cGU+KCdwcmltYXJ5Jyk7IC8vIENvbG9yIGRlbCBpY29ubyAocHJpbWFyeSwgc2Vjb25kYXJ5LCB3YXJuLCBzdWNjZXNzKVxuICByZWFkb25seSBjdXN0b21Db2xvciA9IGlucHV0PHN0cmluZyB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTsgLy8gQ29sb3IgcGVyc29uYWxpemFkbyAoc29icmVzY3JpYmUgY29sb3IpXG4gIHJlYWRvbmx5IGRpc2FibGVkID0gaW5wdXQoZmFsc2UpOyAvLyBFc3RhZG8gZGVzaGFiaWxpdGFkb1xuICByZWFkb25seSBzaXplID0gaW5wdXQoMSk7IC8vIE11bHRpcGxpY2Fkb3IgZGUgdGFtYcOxbyAoMSA9IDI0cHgpXG4gIHJlYWRvbmx5IGJ1dHRvbiA9IGlucHV0KGZhbHNlLCB7IHRyYW5zZm9ybTogdHJhbnNmb3JtVG9Cb29sZWFuIH0pOyAvLyBSZW5kZXJpemEgY29tbyBib3TDs24gY2xpY2tlYWJsZVxuICByZWFkb25seSBib3JkZXIgPSBpbnB1dChmYWxzZSwgeyB0cmFuc2Zvcm06IHRyYW5zZm9ybVRvQm9vbGVhbiB9KTsgLy8gQWdyZWdhIGJvcmRlIGFsIHdyYXBwZXJcbiAgcmVhZG9ubHkgdHlwZSA9IGlucHV0PEJ1dHRvblR5cGU+KCdidXR0b24nKTsgLy8gVGlwbyBkZSBib3TDs24gKGJ1dHRvbiwgc3VibWl0LCByZXNldClcbiAgcmVhZG9ubHkgdGV4dExlZnQgPSBpbnB1dDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7IC8vIFRleHRvIGEgbGEgaXpxdWllcmRhIGRlbCBpY29ub1xuICByZWFkb25seSB0ZXh0UmlnaHQgPSBpbnB1dDxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7IC8vIFRleHRvIGEgbGEgZGVyZWNoYSBkZWwgaWNvbm9cblxuICByZWFkb25seSBpY29uQ2xpY2sgPSBvdXRwdXQ8RXZlbnQ+KCk7IC8vIEV2ZW50byBlbWl0aWRvIGFsIGhhY2VyIGNsaWNrIChzb2xvIHNpIGJ1dHRvbj10cnVlKVxuXG4gIHJlYWRvbmx5IGljb25TaXplID0gY29tcHV0ZWQoKCkgPT4gQkFTRV9JQ09OX1NJWkUgKiB0aGlzLnNpemUoKSk7XG5cbiAgcmVhZG9ubHkgaWNvbkNvbG9yID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKCkpIHJldHVybiBESVNBQkxFRF9DT0xPUjtcblxuICAgIGNvbnN0IGN1c3RvbSA9IHRoaXMuY3VzdG9tQ29sb3IoKTtcbiAgICBpZiAoY3VzdG9tKSByZXR1cm4gY3VzdG9tO1xuXG4gICAgcmV0dXJuIEJBU0VfSUNPTl9DT0xPUlNbdGhpcy5jb2xvcigpXSA/PyBERUZBVUxUX0lDT05fQ09MT1I7XG4gIH0pO1xuXG4gIHJlYWRvbmx5IGljb25PcGFjaXR5ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKCkpIHJldHVybiBESVNBQkxFRF9PUEFDSVRZO1xuXG4gICAgY29uc3QgaGFzQ3VzdG9tQ29sb3IgPSB0aGlzLmN1c3RvbUNvbG9yKCkgIT09IHVuZGVmaW5lZDtcbiAgICBjb25zdCBpc1NlY29uZGFyeU9yV2FybiA9IFsnc2Vjb25kYXJ5JywgJ3dhcm4nXS5pbmNsdWRlcyh0aGlzLmNvbG9yKCkpO1xuXG4gICAgcmV0dXJuICFoYXNDdXN0b21Db2xvciAmJiBpc1NlY29uZGFyeU9yV2FybiA/IFNFQ09OREFSWV9XQVJOX09QQUNJVFkgOiBERUZBVUxUX09QQUNJVFk7XG4gIH0pO1xuXG4gIHJlYWRvbmx5IGljb25QYXRoID0gY29tcHV0ZWQoKCkgPT4gSUNPTl9QQVRIU1t0aGlzLmljb24oKV0gPz8gSUNPTl9QQVRIU1snZGVmYXVsdCddKTtcbiAgcmVhZG9ubHkgYWRkaXRpb25hbFNoYXBlcyA9IGNvbXB1dGVkKCgpID0+IElDT05fQURESVRJT05BTF9TSEFQRVNbdGhpcy5pY29uKCldID8/IFtdKTtcblxuICBvbkJ1dHRvbkNsaWNrKGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5kaXNhYmxlZCgpKSB7XG4gICAgICB0aGlzLmljb25DbGljay5lbWl0KGV2ZW50KTtcbiAgICB9XG4gIH1cbn1cbiIsIjxuZy10ZW1wbGF0ZSAjc3ZnQ29udGVudD5cclxuICA8c3ZnIFthdHRyLndpZHRoXT1cImljb25TaXplKClcIiBbYXR0ci5oZWlnaHRdPVwiaWNvblNpemUoKVwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIFtzdHlsZS5vcGFjaXR5XT1cImljb25PcGFjaXR5KClcIj5cclxuICAgIEBmb3IgKHNoYXBlIG9mIGFkZGl0aW9uYWxTaGFwZXMoKTsgdHJhY2sgJGluZGV4KSB7XHJcbiAgICBAaWYgKHNoYXBlLnR5cGUgPT09ICdjaXJjbGUnKSB7XHJcbiAgICA8Y2lyY2xlIFthdHRyLmN4XT1cInNoYXBlWydjeCddXCIgW2F0dHIuY3ldPVwic2hhcGVbJ2N5J11cIiBbYXR0ci5yXT1cInNoYXBlWydyJ11cIiBbYXR0ci5zdHJva2VdPVwiaWNvbkNvbG9yKClcIiBzdHJva2Utd2lkdGg9XCIyXCIgW2F0dHIuZmlsbF09XCJzaGFwZVsnZmlsbCddID09PSAnY29sb3InID8gaWNvbkNvbG9yKCkgOiAnbm9uZSdcIiAvPlxyXG4gICAgfSBAZWxzZSBpZiAoc2hhcGUudHlwZSA9PT0gJ3JlY3QnKSB7XHJcbiAgICA8cmVjdCBbYXR0ci54XT1cInNoYXBlWyd4J11cIiBbYXR0ci55XT1cInNoYXBlWyd5J11cIiBbYXR0ci53aWR0aF09XCJzaGFwZVsnd2lkdGgnXVwiIFthdHRyLmhlaWdodF09XCJzaGFwZVsnaGVpZ2h0J11cIiBbYXR0ci5yeF09XCJzaGFwZVsncngnXVwiIFthdHRyLnN0cm9rZV09XCJpY29uQ29sb3IoKVwiIHN0cm9rZS13aWR0aD1cIjJcIiBmaWxsPVwibm9uZVwiIC8+XHJcbiAgICB9IEBlbHNlIGlmIChzaGFwZS50eXBlID09PSAncGF0aCcpIHtcclxuICAgIDxwYXRoIFthdHRyLmRdPVwic2hhcGVbJ2QnXVwiIFthdHRyLnN0cm9rZV09XCJpY29uQ29sb3IoKVwiIHN0cm9rZS13aWR0aD1cIjJcIiBbYXR0ci5maWxsXT1cInNoYXBlWydmaWxsJ10gPT09ICdjb2xvcicgPyBpY29uQ29sb3IoKSA6ICdub25lJ1wiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICB9XHJcbiAgICB9XHJcbiAgICA8cGF0aCBbYXR0ci5kXT1cImljb25QYXRoKClcIiBbYXR0ci5zdHJva2VdPVwiaWNvbkNvbG9yKClcIiBbYXR0ci5maWxsXT1cImljb24oKSA9PT0gJ2RlbGV0ZScgPyBpY29uQ29sb3IoKSA6ICdub25lJ1wiIHN0cm9rZS13aWR0aD1cIjJcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gIDwvc3ZnPlxyXG48L25nLXRlbXBsYXRlPlxyXG5cclxuPG5nLXRlbXBsYXRlICN0ZXh0Q29udGVudD5cclxuICBAaWYgKHRleHRMZWZ0KCkpIHtcclxuICA8c3BhbiBjbGFzcz1cImljb24tdGV4dFwiIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEycHhcIj57eyB0ZXh0TGVmdCgpIH19PC9zcGFuPlxyXG4gIH1cclxuICA8c3BhbiBjbGFzcz1cImljb24tY29udGVudFwiIFtzdHlsZS53aWR0aC5weF09XCJpY29uU2l6ZSgpICsgOFwiIFtzdHlsZS5oZWlnaHQucHhdPVwiaWNvblNpemUoKSArIDhcIj5cclxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJzdmdDb250ZW50XCIgLz5cclxuICA8L3NwYW4+XHJcbiAgQGlmICh0ZXh0UmlnaHQoKSkge1xyXG4gIDxzcGFuIGNsYXNzPVwiaWNvbi10ZXh0XCIgc3R5bGU9XCJtYXJnaW4tcmlnaHQ6IDEycHhcIj57eyB0ZXh0UmlnaHQoKSB9fTwvc3Bhbj5cclxuICB9XHJcbjwvbmctdGVtcGxhdGU+XHJcblxyXG5AaWYgKGJ1dHRvbigpKSB7XHJcbjxidXR0b24gW3R5cGVdPVwidHlwZSgpXCIgW2Rpc2FibGVkXT1cImRpc2FibGVkKClcIiBjbGFzcz1cImljb24td3JhcHBlclwiIFtjbGFzcy5pY29uLXdyYXBwZXItYm9yZGVyXT1cImJvcmRlcigpXCIgKGNsaWNrKT1cIm9uQnV0dG9uQ2xpY2soJGV2ZW50KVwiPlxyXG4gIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0ZXh0Q29udGVudFwiIC8+XHJcbjwvYnV0dG9uPlxyXG59IEBlbHNlIHtcclxuPHNwYW4gY2xhc3M9XCJpY29uLXdyYXBwZXJcIiBbY2xhc3MuaWNvbi13cmFwcGVyLWJvcmRlcl09XCJib3JkZXIoKVwiPlxyXG4gIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0ZXh0Q29udGVudFwiIC8+XHJcbjwvc3Bhbj5cclxufSJdfQ==