@c80/ui 1.1.2 → 2.0.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.
- package/esm2022/lib/action-list/action-list.component.js +5 -5
- package/esm2022/lib/action-list/action-list.component.js.map +1 -1
- package/esm2022/lib/action-list/action-list.types.js +0 -1
- package/esm2022/lib/card-level/card-level.component.js +12 -12
- package/esm2022/lib/card-level/card-level.component.js.map +1 -1
- package/esm2022/lib/card-level/card-level.interface.js +0 -1
- package/esm2022/lib/error-notification/error-notification.component.js +5 -5
- package/esm2022/lib/error-notification/error-notification.component.js.map +1 -1
- package/esm2022/lib/error-notification/error-notification.types.js +0 -1
- package/esm2022/lib/header/header.component.js +5 -5
- package/esm2022/lib/header/header.component.js.map +1 -1
- package/esm2022/lib/header/header.types.js +0 -1
- package/esm2022/lib/icon/icon.component.js +26 -26
- package/esm2022/lib/icon/icon.component.js.map +1 -1
- package/esm2022/lib/icon/icon.definitions.js.map +1 -1
- package/esm2022/lib/icon/icon.types.js +0 -1
- package/esm2022/lib/icon/theme.service.js +4 -4
- package/esm2022/lib/icon/theme.service.js.map +1 -1
- package/esm2022/lib/info-list/info-list.component.js +4 -4
- package/esm2022/lib/info-list/info-list.component.js.map +1 -1
- package/esm2022/lib/info-list/info-list.types.js +0 -1
- package/esm2022/lib/info-message/info-message.component.js +6 -6
- package/esm2022/lib/info-message/info-message.component.js.map +1 -1
- package/esm2022/lib/info-message/info-message.types.js +0 -1
- package/esm2022/lib/input-field/input-field.component.js +11 -11
- package/esm2022/lib/input-field/input-field.component.js.map +1 -1
- package/esm2022/lib/input-search/c80-input-search.component.js +5 -5
- package/esm2022/lib/input-search/c80-input-search.component.js.map +1 -1
- package/esm2022/lib/legal-disclaimer/legal-disclaimer.component.js +4 -4
- package/esm2022/lib/legal-disclaimer/legal-disclaimer.component.js.map +1 -1
- package/esm2022/lib/modal/modal.component.js +4 -4
- package/esm2022/lib/modal/modal.component.js.map +1 -1
- package/esm2022/lib/modal/modal.service.js +5 -5
- package/esm2022/lib/modal/modal.service.js.map +1 -1
- package/esm2022/lib/modal/modal.types.js +0 -1
- package/esm2022/lib/navigation-card/navigation-card.component.js +5 -5
- package/esm2022/lib/navigation-card/navigation-card.component.js.map +1 -1
- package/esm2022/lib/navigation-card/navigation-card.types.js +0 -1
- package/esm2022/lib/profile-stats/profile-stats.component.js +4 -4
- package/esm2022/lib/profile-stats/profile-stats.component.js.map +1 -1
- package/esm2022/lib/profile-stats/profile-stats.types.js +0 -1
- package/esm2022/lib/rating-display/rating-display.component.js +7 -7
- package/esm2022/lib/rating-display/rating-display.component.js.map +1 -1
- package/esm2022/lib/rating-stars/rating-stars.component.js +8 -8
- package/esm2022/lib/rating-stars/rating-stars.component.js.map +1 -1
- package/esm2022/lib/select/select.component.js +17 -17
- package/esm2022/lib/select/select.component.js.map +1 -1
- package/esm2022/lib/select/select.types.js +0 -1
- package/esm2022/lib/snackbar/snackbar.component.js +6 -6
- package/esm2022/lib/snackbar/snackbar.component.js.map +1 -1
- package/esm2022/lib/snackbar/snackbar.service.js +3 -3
- package/esm2022/lib/snackbar/snackbar.types.js +0 -1
- package/esm2022/lib/spinner/spinner.component.js +7 -7
- package/esm2022/lib/spinner/spinner.component.js.map +1 -1
- package/esm2022/lib/stat-card/stat-card.component.js +5 -5
- package/esm2022/lib/stat-card/stat-card.component.js.map +1 -1
- package/esm2022/lib/stat-card/stat-card.types.js +0 -1
- package/esm2022/lib/tab/c80-tab.component.js +6 -6
- package/esm2022/lib/tab/c80-tab.component.js.map +1 -1
- package/esm2022/lib/tab/c80-tab.types.js +0 -1
- package/esm2022/lib/tab/directives/c80-tab-item.directive.js +3 -3
- package/esm2022/lib/tab/directives/c80-tab-label.directive.js +3 -3
- package/esm2022/lib/table/table-column-visibility.service.js +3 -3
- package/esm2022/lib/table/table-crud-state.service.js +7 -7
- package/esm2022/lib/table/table-crud-state.service.js.map +1 -1
- package/esm2022/lib/table/table-data-converter.service.js +3 -3
- package/esm2022/lib/table/table-data-utils.service.js +3 -3
- package/esm2022/lib/table/table-dto-mapper.service.js +3 -3
- package/esm2022/lib/table/table-pagination.service.js +10 -10
- package/esm2022/lib/table/table-pagination.service.js.map +1 -1
- package/esm2022/lib/table/table-selection.service.js +6 -6
- package/esm2022/lib/table/table-selection.service.js.map +1 -1
- package/esm2022/lib/table/table.component.js +26 -26
- package/esm2022/lib/table/table.component.js.map +1 -1
- package/esm2022/lib/table/table.types.js +0 -1
- package/package.json +4 -3
|
@@ -5,8 +5,8 @@ import * as i0 from "@angular/core";
|
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
7
|
export class ActionListComponent {
|
|
8
|
-
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
9
|
-
actions = input([], ...(ngDevMode ? [{ debugName: "actions" }] : []));
|
|
8
|
+
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
9
|
+
actions = input([], ...(ngDevMode ? [{ debugName: "actions" }] : /* istanbul ignore next */ []));
|
|
10
10
|
actionClick = output();
|
|
11
11
|
/**
|
|
12
12
|
*
|
|
@@ -20,10 +20,10 @@ export class ActionListComponent {
|
|
|
20
20
|
action.action();
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
24
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
23
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ActionListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
24
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ActionListComponent, isStandalone: true, selector: "c80-action-list", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: "<div class=\"action-list\">\n @if (title()) {\n <h2 class=\"action-list__title\">{{ title() }}</h2>\n }\n\n @for (action of actions(); track $index) {\n <button class=\"action-list__item\" [class.action-list__item--danger]=\"action.isDanger\" [class.action-list__item--navigable]=\"action.isNavigable\" (click)=\"onActionClick(action)\">\n\n <div class=\"action-list__info\">\n <span class=\"action-list__label\">{{ action.label }}</span>\n @if (action.description) {\n <span class=\"action-list__description\">{{ action.description }}</span>\n }\n </div>\n\n @if (action.icon || action.isNavigable) {\n <c80-icon [button]=\"!action.isNavigable\" [icon]=\"action.icon || (action.isNavigable ? 'arrowRight' : '')\" [color]=\"action.isDanger ? 'warn' : undefined\" [title]=\"action.label\" />\n }\n </button>\n }\n</div>", styles: [".action-list__title{font-size:.875rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--color-text-secondary);margin:1rem 0px .4rem}.action-list__item{display:flex;justify-content:space-between;align-items:center;padding:1rem;background:var(--color-surface);border-radius:var(--radius-lg);margin-bottom:.75rem;border:none;width:100%;text-align:left;cursor:pointer;transition:all var(--transition-base)}.action-list__item:hover{transform:translate(2px);background:var(--color-bg-dark)}.action-list__item:last-child{margin-bottom:0}.action-list__item--danger .action-list__label{color:var(--color-accent)}.action-list__item--navigable:hover{transform:translate(2px);background:var(--color-bg-dark)}.action-list__info{display:flex;flex-direction:column;gap:.25rem}.action-list__label{font-size:1rem;font-weight:500;color:var(--color-text-primary)}.action-list__description{font-size:.875rem;color:var(--color-text-secondary)}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "c80-icon", inputs: ["icon", "color", "customColor", "disabled", "size", "button", "border", "type", "textLeft", "textRight", "dark"], outputs: ["iconClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
25
25
|
}
|
|
26
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
26
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ActionListComponent, decorators: [{
|
|
27
27
|
type: Component,
|
|
28
28
|
args: [{ selector: 'c80-action-list', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"action-list\">\n @if (title()) {\n <h2 class=\"action-list__title\">{{ title() }}</h2>\n }\n\n @for (action of actions(); track $index) {\n <button class=\"action-list__item\" [class.action-list__item--danger]=\"action.isDanger\" [class.action-list__item--navigable]=\"action.isNavigable\" (click)=\"onActionClick(action)\">\n\n <div class=\"action-list__info\">\n <span class=\"action-list__label\">{{ action.label }}</span>\n @if (action.description) {\n <span class=\"action-list__description\">{{ action.description }}</span>\n }\n </div>\n\n @if (action.icon || action.isNavigable) {\n <c80-icon [button]=\"!action.isNavigable\" [icon]=\"action.icon || (action.isNavigable ? 'arrowRight' : '')\" [color]=\"action.isDanger ? 'warn' : undefined\" [title]=\"action.label\" />\n }\n </button>\n }\n</div>", styles: [".action-list__title{font-size:.875rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--color-text-secondary);margin:1rem 0px .4rem}.action-list__item{display:flex;justify-content:space-between;align-items:center;padding:1rem;background:var(--color-surface);border-radius:var(--radius-lg);margin-bottom:.75rem;border:none;width:100%;text-align:left;cursor:pointer;transition:all var(--transition-base)}.action-list__item:hover{transform:translate(2px);background:var(--color-bg-dark)}.action-list__item:last-child{margin-bottom:0}.action-list__item--danger .action-list__label{color:var(--color-accent)}.action-list__item--navigable:hover{transform:translate(2px);background:var(--color-bg-dark)}.action-list__info{display:flex;flex-direction:column;gap:.25rem}.action-list__label{font-size:1rem;font-weight:500;color:var(--color-text-primary)}.action-list__description{font-size:.875rem;color:var(--color-text-secondary)}\n"] }]
|
|
29
29
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-list.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/action-list/action-list.component.ts","../../../../../libs/ui/src/lib/action-list/action-list.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAElF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAExC;;GAEG;
|
|
1
|
+
{"version":3,"file":"action-list.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/action-list/action-list.component.ts","../../../../../libs/ui/src/lib/action-list/action-list.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAElF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAExC;;GAEG;AASH,MAAM,OAAO,mBAAmB;IAC5B,KAAK,GAAG,KAAK,CAAS,EAAE,4EAAC,CAAC;IAC1B,OAAO,GAAG,KAAK,CAAe,EAAE,8EAAC,CAAC;IAElC,WAAW,GAAG,MAAM,EAAU,CAAC;IAE/B;;;OAGG;IACO,aAAa,CAAC,MAAkB;QACtC,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACpC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;aAAM,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC7C,MAAM,CAAC,MAAM,EAAE,CAAC;QACpB,CAAC;IACL,CAAC;wGAhBQ,mBAAmB;4FAAnB,mBAAmB,sXCfhC,w5BAoBM,8+BDVQ,aAAa;;4FAKd,mBAAmB;kBAR/B,SAAS;+BACI,iBAAiB,cACf,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { Component, input, output, ChangeDetectionStrategy } from '@angular/core';\r\nimport type { ActionItem } from './action-list.types';\r\nimport { IconComponent } from '../icon';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-action-list',\r\n standalone: true,\r\n imports: [IconComponent],\r\n templateUrl: './action-list.component.html',\r\n styleUrl: './action-list.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class ActionListComponent {\r\n title = input<string>('');\r\n actions = input<ActionItem[]>([]);\r\n\r\n actionClick = output<string>();\r\n\r\n /**\r\n *\r\n * @param action\r\n */\r\n protected onActionClick(action: ActionItem): void {\r\n if (typeof action.action === 'string') {\r\n this.actionClick.emit(action.action);\r\n } else if (typeof action.action === 'function') {\r\n action.action();\r\n }\r\n }\r\n}","<div class=\"action-list\">\n @if (title()) {\n <h2 class=\"action-list__title\">{{ title() }}</h2>\n }\n\n @for (action of actions(); track $index) {\n <button class=\"action-list__item\" [class.action-list__item--danger]=\"action.isDanger\" [class.action-list__item--navigable]=\"action.isNavigable\" (click)=\"onActionClick(action)\">\n\n <div class=\"action-list__info\">\n <span class=\"action-list__label\">{{ action.label }}</span>\n @if (action.description) {\n <span class=\"action-list__description\">{{ action.description }}</span>\n }\n </div>\n\n @if (action.icon || action.isNavigable) {\n <c80-icon [button]=\"!action.isNavigable\" [icon]=\"action.icon || (action.isNavigable ? 'arrowRight' : '')\" [color]=\"action.isDanger ? 'warn' : undefined\" [title]=\"action.label\" />\n }\n </button>\n }\n</div>"]}
|
|
@@ -5,39 +5,39 @@ import * as i0 from "@angular/core";
|
|
|
5
5
|
*/
|
|
6
6
|
export class CardLevelComponent {
|
|
7
7
|
/* v8 ignore next */
|
|
8
|
-
cardLevelData = input.required(...(ngDevMode ? [{ debugName: "cardLevelData" }] : []));
|
|
8
|
+
cardLevelData = input.required(...(ngDevMode ? [{ debugName: "cardLevelData" }] : /* istanbul ignore next */ []));
|
|
9
9
|
/* v8 ignore next */
|
|
10
|
-
size = input(1, ...(ngDevMode ? [{ debugName: "size" }] : [])); // Multiplicador del tamaño base (220px)
|
|
10
|
+
size = input(1, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ [])); // Multiplicador del tamaño base (220px)
|
|
11
11
|
// ID único generado para el componente
|
|
12
12
|
/* v8 ignore next 5 */
|
|
13
13
|
generatedId = computed(() => {
|
|
14
14
|
const label = this.cardLevelData().label.toLowerCase().replaceAll(/\s+/g, '-');
|
|
15
15
|
const randomNum = Math.floor(Math.random() * 10000);
|
|
16
16
|
return `${label}-${randomNum}`;
|
|
17
|
-
}, ...(ngDevMode ? [{ debugName: "generatedId" }] : []));
|
|
17
|
+
}, ...(ngDevMode ? [{ debugName: "generatedId" }] : /* istanbul ignore next */ []));
|
|
18
18
|
// Ancho calculado de la card
|
|
19
19
|
/* v8 ignore next 4 */
|
|
20
20
|
cardWidth = computed(() => {
|
|
21
21
|
const baseWidth = 140;
|
|
22
22
|
const calculatedWidth = baseWidth * this.size();
|
|
23
23
|
return `${calculatedWidth}px`;
|
|
24
|
-
}, ...(ngDevMode ? [{ debugName: "cardWidth" }] : []));
|
|
24
|
+
}, ...(ngDevMode ? [{ debugName: "cardWidth" }] : /* istanbul ignore next */ []));
|
|
25
25
|
// Detecta si el rango es bidireccional (min negativo, max positivo)
|
|
26
26
|
/* v8 ignore next 4 */
|
|
27
27
|
isBidirectional = computed(() => {
|
|
28
28
|
const data = this.cardLevelData();
|
|
29
29
|
return data.min < 0 && data.max > 0;
|
|
30
|
-
}, ...(ngDevMode ? [{ debugName: "isBidirectional" }] : []));
|
|
30
|
+
}, ...(ngDevMode ? [{ debugName: "isBidirectional" }] : /* istanbul ignore next */ []));
|
|
31
31
|
// Calcula el porcentaje de fill para barras bidireccionales
|
|
32
32
|
/* v8 ignore next 4 */
|
|
33
33
|
bidirectionalFillPercent = computed(() => {
|
|
34
34
|
const data = this.cardLevelData();
|
|
35
35
|
const totalRange = data.max - data.min;
|
|
36
36
|
return Math.abs(data.value / totalRange) * 100;
|
|
37
|
-
}, ...(ngDevMode ? [{ debugName: "bidirectionalFillPercent" }] : []));
|
|
37
|
+
}, ...(ngDevMode ? [{ debugName: "bidirectionalFillPercent" }] : /* istanbul ignore next */ []));
|
|
38
38
|
// Determina la dirección del fill (left/right)
|
|
39
39
|
/* v8 ignore next 3 */
|
|
40
|
-
fillDirection = computed(() => this.cardLevelData().value >= 0 ? 'right' : 'left', ...(ngDevMode ? [{ debugName: "fillDirection" }] : []));
|
|
40
|
+
fillDirection = computed(() => this.cardLevelData().value >= 0 ? 'right' : 'left', ...(ngDevMode ? [{ debugName: "fillDirection" }] : /* istanbul ignore next */ []));
|
|
41
41
|
// Color según el valor y umbrales
|
|
42
42
|
/* v8 ignore next 11 */
|
|
43
43
|
fillColor = computed(() => {
|
|
@@ -52,12 +52,12 @@ export class CardLevelComponent {
|
|
|
52
52
|
return 'var(--color-warning)';
|
|
53
53
|
}
|
|
54
54
|
return 'var(--color-success)';
|
|
55
|
-
}, ...(ngDevMode ? [{ debugName: "fillColor" }] : []));
|
|
56
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
57
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
55
|
+
}, ...(ngDevMode ? [{ debugName: "fillColor" }] : /* istanbul ignore next */ []));
|
|
56
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CardLevelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
57
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", 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>\r\n", 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}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
58
58
|
}
|
|
59
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
59
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CardLevelComponent, decorators: [{
|
|
60
60
|
type: Component,
|
|
61
|
-
args: [{ selector: 'c80-card-level', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "
|
|
61
|
+
args: [{ selector: 'c80-card-level', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, 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>\r\n", 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}\n"] }]
|
|
62
62
|
}], propDecorators: { cardLevelData: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardLevelData", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
63
63
|
//# sourceMappingURL=card-level.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card-level.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/card-level/card-level.component.ts","../../../../../libs/ui/src/lib/card-level/card-level.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;;AAGpF;;GAEG;
|
|
1
|
+
{"version":3,"file":"card-level.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/card-level/card-level.component.ts","../../../../../libs/ui/src/lib/card-level/card-level.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;;AAGpF;;GAEG;AASH,MAAM,OAAO,kBAAkB;IAC7B,oBAAoB;IACpB,aAAa,GAAG,KAAK,CAAC,QAAQ,mFAAiB,CAAC;IAChD,oBAAoB;IACpB,IAAI,GAAG,KAAK,CAAS,CAAC,2EAAC,CAAC,CAAC,wCAAwC;IAEjE,uCAAuC;IACvC,sBAAsB;IACb,WAAW,GAAG,QAAQ,CAAC,GAAG,EAAE;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC;QACpD,OAAO,GAAG,KAAK,IAAI,SAAS,EAAE,CAAC;IACjC,CAAC,kFAAC,CAAC;IAEH,6BAA6B;IAC7B,sBAAsB;IACb,SAAS,GAAG,QAAQ,CAAC,GAAG,EAAE;QACjC,MAAM,SAAS,GAAG,GAAG,CAAC;QACtB,MAAM,eAAe,GAAG,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAChD,OAAO,GAAG,eAAe,IAAI,CAAC;IAChC,CAAC,gFAAC,CAAC;IAEH,oEAAoE;IACpE,sBAAsB;IACtB,eAAe,GAAG,QAAQ,CAAC,GAAG,EAAE;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;IACtC,CAAC,sFAAC,CAAC;IAEH,4DAA4D;IAC5D,sBAAsB;IACtB,wBAAwB,GAAG,QAAQ,CAAC,GAAG,EAAE;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACvC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC;IACjD,CAAC,+FAAC,CAAC;IAEH,+CAA+C;IAC/C,sBAAsB;IACtB,aAAa,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,oFAAC,CAAC;IAEnF,kCAAkC;IAClC,uBAAuB;IACvB,SAAS,GAAG,QAAQ,CAAC,GAAG,EAAE;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;YACxB,OAAO,qBAAqB,CAAC;QAC/B,CAAC;QACD,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;YACvB,OAAO,sBAAsB,CAAC;QAChC,CAAC;QACD,OAAO,sBAAsB,CAAC;IAChC,CAAC,gFAAC,CAAC;wGAxDQ,kBAAkB;4FAAlB,kBAAkB,0VCd/B,koCAwBA;;4FDVa,kBAAkB;kBAR9B,SAAS;+BACE,gBAAgB,cACd,IAAI,WACP,EAAE,mBAGM,uBAAuB,CAAC,MAAM","sourcesContent":["import { Component, input, computed, ChangeDetectionStrategy } from '@angular/core';\r\nimport type { CardLevelData } from './card-level.interface';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-card-level',\r\n standalone: true,\r\n imports: [],\r\n templateUrl: './card-level.component.html',\r\n styleUrl: './card-level.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class CardLevelComponent {\r\n /* v8 ignore next */\r\n cardLevelData = input.required<CardLevelData>();\r\n /* v8 ignore next */\r\n size = input<number>(1); // Multiplicador del tamaño base (220px)\r\n\r\n // ID único generado para el componente\r\n /* v8 ignore next 5 */\r\n readonly generatedId = computed(() => {\r\n const label = this.cardLevelData().label.toLowerCase().replaceAll(/\\s+/g, '-');\r\n const randomNum = Math.floor(Math.random() * 10000);\r\n return `${label}-${randomNum}`;\r\n });\r\n\r\n // Ancho calculado de la card\r\n /* v8 ignore next 4 */\r\n readonly cardWidth = computed(() => {\r\n const baseWidth = 140;\r\n const calculatedWidth = baseWidth * this.size();\r\n return `${calculatedWidth}px`;\r\n });\r\n\r\n // Detecta si el rango es bidireccional (min negativo, max positivo)\r\n /* v8 ignore next 4 */\r\n isBidirectional = computed(() => {\r\n const data = this.cardLevelData();\r\n return data.min < 0 && data.max > 0;\r\n });\r\n\r\n // Calcula el porcentaje de fill para barras bidireccionales\r\n /* v8 ignore next 4 */\r\n bidirectionalFillPercent = computed(() => {\r\n const data = this.cardLevelData();\r\n const totalRange = data.max - data.min;\r\n return Math.abs(data.value / totalRange) * 100;\r\n });\r\n\r\n // Determina la dirección del fill (left/right)\r\n /* v8 ignore next 3 */\r\n fillDirection = computed(() => this.cardLevelData().value >= 0 ? 'right' : 'left');\r\n\r\n // Color según el valor y umbrales\r\n /* v8 ignore next 11 */\r\n fillColor = computed(() => {\r\n const data = this.cardLevelData();\r\n const absValue = Math.abs(data.value);\r\n const absHigh = Math.abs(data.high);\r\n const absLow = Math.abs(data.low);\r\n\r\n if (absValue >= absHigh) {\r\n return 'var(--color-danger)';\r\n }\r\n if (absValue >= absLow) {\r\n return 'var(--color-warning)';\r\n }\r\n return 'var(--color-success)';\r\n });\r\n}\r\n","<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ándar 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>\r\n"]}
|
|
@@ -5,7 +5,7 @@ import * as i0 from "@angular/core";
|
|
|
5
5
|
* Componente reutilizable para mostrar mensajes de error
|
|
6
6
|
*/
|
|
7
7
|
export class ErrorNotificationComponent {
|
|
8
|
-
config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
8
|
+
config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
|
|
9
9
|
dismiss = output();
|
|
10
10
|
/**
|
|
11
11
|
* Divide el mensaje en oraciones separadas por '. '
|
|
@@ -24,17 +24,17 @@ export class ErrorNotificationComponent {
|
|
|
24
24
|
}
|
|
25
25
|
// Agregar punto a todas las partes excepto la última
|
|
26
26
|
return parts.map((part, index) => index === parts.length - 1 ? part : `${part}.`);
|
|
27
|
-
}, ...(ngDevMode ? [{ debugName: "sentences" }] : []));
|
|
27
|
+
}, ...(ngDevMode ? [{ debugName: "sentences" }] : /* istanbul ignore next */ []));
|
|
28
28
|
/**
|
|
29
29
|
* Emite evento de cierre
|
|
30
30
|
*/
|
|
31
31
|
onDismiss() {
|
|
32
32
|
this.dismiss.emit();
|
|
33
33
|
}
|
|
34
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
35
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
34
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ErrorNotificationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
35
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ErrorNotificationComponent, isStandalone: true, selector: "c80-error-notification", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { dismiss: "dismiss" }, ngImport: i0, template: "<div class=\"error-notification\">\n <div class=\"error-notification__content\">\n <c80-icon icon=\"error\" [size]=\"1.2\" />\n <div class=\"error-notification__message\">\n @for (sentence of sentences(); track $index) {\n <p>{{ sentence }}</p>\n }\n </div>\n </div>\n @if (config().dismissible !== false) {\n <c80-icon icon=\"close\" [size]=\"0.8\" (click)=\"onDismiss()\" (keydown.enter)=\"onDismiss()\" class=\"error-notification__close\" aria-label=\"Cerrar notificaci\u00F3n\" />\n }\n</div>", styles: [".error-notification{display:flex;align-items:center;justify-content:space-between;gap:var(--spacing-sm);padding:var(--spacing-md);background:#8b000014;border:1px solid rgba(139,68,68,.2);border-radius:var(--border-radius-lg);color:#8b0000;animation:slideDown .3s cubic-bezier(.4,0,.2,1)}.error-notification p{margin:0;font-size:.875rem;line-height:1.5;font-weight:var(--font-weight-medium)}.error-notification__message{display:flex;flex-direction:column}.error-notification__content{display:flex;align-items:center;gap:var(--spacing-sm);flex:1}.error-notification__content c80-icon{flex-shrink:0}.error-notification__close{flex-shrink:0;cursor:pointer;opacity:.7;transition:opacity .2s}.error-notification__close:hover{opacity:1}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "c80-icon", inputs: ["icon", "color", "customColor", "disabled", "size", "button", "border", "type", "textLeft", "textRight", "dark"], outputs: ["iconClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
36
36
|
}
|
|
37
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
37
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ErrorNotificationComponent, decorators: [{
|
|
38
38
|
type: Component,
|
|
39
39
|
args: [{ selector: 'c80-error-notification', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"error-notification\">\n <div class=\"error-notification__content\">\n <c80-icon icon=\"error\" [size]=\"1.2\" />\n <div class=\"error-notification__message\">\n @for (sentence of sentences(); track $index) {\n <p>{{ sentence }}</p>\n }\n </div>\n </div>\n @if (config().dismissible !== false) {\n <c80-icon icon=\"close\" [size]=\"0.8\" (click)=\"onDismiss()\" (keydown.enter)=\"onDismiss()\" class=\"error-notification__close\" aria-label=\"Cerrar notificaci\u00F3n\" />\n }\n</div>", styles: [".error-notification{display:flex;align-items:center;justify-content:space-between;gap:var(--spacing-sm);padding:var(--spacing-md);background:#8b000014;border:1px solid rgba(139,68,68,.2);border-radius:var(--border-radius-lg);color:#8b0000;animation:slideDown .3s cubic-bezier(.4,0,.2,1)}.error-notification p{margin:0;font-size:.875rem;line-height:1.5;font-weight:var(--font-weight-medium)}.error-notification__message{display:flex;flex-direction:column}.error-notification__content{display:flex;align-items:center;gap:var(--spacing-sm);flex:1}.error-notification__content c80-icon{flex-shrink:0}.error-notification__close{flex-shrink:0;cursor:pointer;opacity:.7;transition:opacity .2s}.error-notification__close:hover{opacity:1}@keyframes slideDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}\n"] }]
|
|
40
40
|
}], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }] } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-notification.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/error-notification/error-notification.component.ts","../../../../../libs/ui/src/lib/error-notification/error-notification.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAGxC;;GAEG;
|
|
1
|
+
{"version":3,"file":"error-notification.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/error-notification/error-notification.component.ts","../../../../../libs/ui/src/lib/error-notification/error-notification.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAGxC;;GAEG;AASH,MAAM,OAAO,0BAA0B;IACnC,MAAM,GAAG,KAAK,CAAC,QAAQ,4EAA2B,CAAC;IAEnD,OAAO,GAAG,MAAM,EAAQ,CAAC;IAEzB;;;OAGG;IACgB,SAAS,GAAG,QAAQ,CAAC,GAAG,EAAE;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC;QACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,8CAA8C;QAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;QAED,wEAAwE;QACxE,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;QACtD,CAAC;QAED,qDAAqD;QACrD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAC7B,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CACjD,CAAC;IACN,CAAC,gFAAC,CAAC;IAEH;;OAEG;IACO,SAAS;QACf,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;wGAlCQ,0BAA0B;4FAA1B,0BAA0B,yPCfvC,ujBAYM,y3BDFQ,aAAa;;4FAKd,0BAA0B;kBARtC,SAAS;+BACI,wBAAwB,cACtB,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\nimport type { ErrorNotificationConfig } from './error-notification.types';\r\n\r\n/**\r\n * Componente reutilizable para mostrar mensajes de error\r\n */\r\n@Component({\r\n selector: 'c80-error-notification',\r\n standalone: true,\r\n imports: [IconComponent],\r\n templateUrl: './error-notification.component.html',\r\n styleUrl: './error-notification.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class ErrorNotificationComponent {\r\n config = input.required<ErrorNotificationConfig>();\r\n\r\n dismiss = output<void>();\r\n\r\n /**\r\n * Divide el mensaje en oraciones separadas por '. '\r\n * Excluye la última oración si termina en punto\r\n */\r\n protected readonly sentences = computed(() => {\r\n const message = this.config().message;\r\n const parts = message.split('. ');\r\n\r\n // Si solo hay una parte, devolverla como está\r\n if (parts.length === 1) {\r\n return [message];\r\n }\r\n\r\n // Si la última parte está vacía (mensaje terminaba en '. '), eliminarla\r\n if (parts.at(-1) === '') {\r\n return parts.slice(0, -1).map(part => `${part}.`);\r\n }\r\n\r\n // Agregar punto a todas las partes excepto la última\r\n return parts.map((part, index) =>\r\n index === parts.length - 1 ? part : `${part}.`\r\n );\r\n });\r\n\r\n /**\r\n * Emite evento de cierre\r\n */\r\n protected onDismiss(): void {\r\n this.dismiss.emit();\r\n }\r\n}\r\n","<div class=\"error-notification\">\n <div class=\"error-notification__content\">\n <c80-icon icon=\"error\" [size]=\"1.2\" />\n <div class=\"error-notification__message\">\n @for (sentence of sentences(); track $index) {\n <p>{{ sentence }}</p>\n }\n </div>\n </div>\n @if (config().dismissible !== false) {\n <c80-icon icon=\"close\" [size]=\"0.8\" (click)=\"onDismiss()\" (keydown.enter)=\"onDismiss()\" class=\"error-notification__close\" aria-label=\"Cerrar notificación\" />\n }\n</div>"]}
|
|
@@ -7,18 +7,18 @@ import * as i0 from "@angular/core";
|
|
|
7
7
|
*/
|
|
8
8
|
export class HeaderComponent {
|
|
9
9
|
location = inject(Location);
|
|
10
|
-
config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
11
|
-
backIcon = input('chevronLeft', ...(ngDevMode ? [{ debugName: "backIcon" }] : []));
|
|
10
|
+
config = input.required(...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
|
|
11
|
+
backIcon = input('chevronLeft', ...(ngDevMode ? [{ debugName: "backIcon" }] : /* istanbul ignore next */ []));
|
|
12
12
|
/**
|
|
13
13
|
*
|
|
14
14
|
*/
|
|
15
15
|
onBackClick() {
|
|
16
16
|
this.location.back();
|
|
17
17
|
}
|
|
18
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
19
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
18
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
19
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: HeaderComponent, isStandalone: true, selector: "c80-header", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, backIcon: { classPropertyName: "backIcon", publicName: "backIcon", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<header class=\"header\" [class.header--no-border]=\"config().showBorder === false\">\n @if (config().showBackButton !== false) {\n <c80-icon button [icon]=\"backIcon()\" [size]=\"1.2\" (iconClick)=\"onBackClick()\" title=\"Volver\" class=\"header__back-btn\" />\n }\n <h1 class=\"header__title\">{{ config().title }}</h1>\n <div class=\"header__actions\">\n <ng-content />\n </div>\n</header>", styles: [".header{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-bottom:1rem;padding:1rem;border-bottom:1px solid var(--color-border)}.header--no-border{border-bottom:none}.header__back-btn{flex-shrink:0}.header__title{font-size:1.5rem;font-weight:600;color:var(--color-text-primary);margin:0;-webkit-user-select:none;user-select:none}.header__actions{display:flex;align-items:center;gap:var(--spacing-sm);flex-shrink:0;margin-left:auto}@media(max-width:768px){.header{padding:.75rem;gap:.75rem;margin-bottom:.5rem}.header__title{font-size:1.25rem}}\n"], dependencies: [{ kind: "component", type: IconComponent, selector: "c80-icon", inputs: ["icon", "color", "customColor", "disabled", "size", "button", "border", "type", "textLeft", "textRight", "dark"], outputs: ["iconClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
20
20
|
}
|
|
21
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
21
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HeaderComponent, decorators: [{
|
|
22
22
|
type: Component,
|
|
23
23
|
args: [{ selector: 'c80-header', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<header class=\"header\" [class.header--no-border]=\"config().showBorder === false\">\n @if (config().showBackButton !== false) {\n <c80-icon button [icon]=\"backIcon()\" [size]=\"1.2\" (iconClick)=\"onBackClick()\" title=\"Volver\" class=\"header__back-btn\" />\n }\n <h1 class=\"header__title\">{{ config().title }}</h1>\n <div class=\"header__actions\">\n <ng-content />\n </div>\n</header>", styles: [".header{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin-bottom:1rem;padding:1rem;border-bottom:1px solid var(--color-border)}.header--no-border{border-bottom:none}.header__back-btn{flex-shrink:0}.header__title{font-size:1.5rem;font-weight:600;color:var(--color-text-primary);margin:0;-webkit-user-select:none;user-select:none}.header__actions{display:flex;align-items:center;gap:var(--spacing-sm);flex-shrink:0;margin-left:auto}@media(max-width:768px){.header{padding:.75rem;gap:.75rem;margin-bottom:.5rem}.header__title{font-size:1.25rem}}\n"] }]
|
|
24
24
|
}], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], backIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "backIcon", required: false }] }] } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"header.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/header/header.component.ts","../../../../../libs/ui/src/lib/header/header.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAIxC;;GAEG;
|
|
1
|
+
{"version":3,"file":"header.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/header/header.component.ts","../../../../../libs/ui/src/lib/header/header.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAIxC;;GAEG;AASH,MAAM,OAAO,eAAe;IACP,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,MAAM,GAAG,KAAK,CAAC,QAAQ,4EAAgB,CAAC;IACxC,QAAQ,GAAG,KAAK,CAAW,aAAa,+EAAC,CAAC;IAE1C;;OAEG;IACO,WAAW;QACjB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;wGAXQ,eAAe;4FAAf,eAAe,6UCjB5B,oaAQS,snBDIK,aAAa;;4FAKd,eAAe;kBAR3B,SAAS;+BACI,YAAY,cACV,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { Location } from '@angular/common';\r\nimport { ChangeDetectionStrategy, Component, inject, input } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\nimport type { IconType } from '../icon';\r\nimport type { HeaderConfig } from './header.types';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-header',\r\n standalone: true,\r\n imports: [IconComponent],\r\n templateUrl: './header.component.html',\r\n styleUrl: './header.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class HeaderComponent {\r\n private readonly location = inject(Location);\r\n\r\n config = input.required<HeaderConfig>();\r\n backIcon = input<IconType>('chevronLeft');\r\n\r\n /**\r\n *\r\n */\r\n protected onBackClick(): void {\r\n this.location.back();\r\n }\r\n}","<header class=\"header\" [class.header--no-border]=\"config().showBorder === false\">\n @if (config().showBackButton !== false) {\n <c80-icon button [icon]=\"backIcon()\" [size]=\"1.2\" (iconClick)=\"onBackClick()\" title=\"Volver\" class=\"header__back-btn\" />\n }\n <h1 class=\"header__title\">{{ config().title }}</h1>\n <div class=\"header__actions\">\n <ng-content />\n </div>\n</header>"]}
|
|
@@ -11,30 +11,30 @@ import * as i0 from "@angular/core";
|
|
|
11
11
|
export class IconComponent {
|
|
12
12
|
themeService = inject(ThemeService);
|
|
13
13
|
/* v8 ignore next */
|
|
14
|
-
icon = input('check', ...(ngDevMode ? [{ debugName: "icon" }] : [])); // Tipo de icono a mostrar
|
|
14
|
+
icon = input('check', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ [])); // Tipo de icono a mostrar
|
|
15
15
|
/* v8 ignore next */
|
|
16
|
-
color = input(undefined, ...(ngDevMode ? [{ debugName: "color" }] : [])); // Color del icono (primary, secondary, warn, success)
|
|
16
|
+
color = input(undefined, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ [])); // Color del icono (primary, secondary, warn, success)
|
|
17
17
|
/* v8 ignore next */
|
|
18
|
-
customColor = input(undefined, ...(ngDevMode ? [{ debugName: "customColor" }] : [])); // Color personalizado (sobrescribe color)
|
|
18
|
+
customColor = input(undefined, ...(ngDevMode ? [{ debugName: "customColor" }] : /* istanbul ignore next */ [])); // Color personalizado (sobrescribe color)
|
|
19
19
|
/* v8 ignore next */
|
|
20
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : [])); // Estado deshabilitado
|
|
20
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ [])); // Estado deshabilitado
|
|
21
21
|
/* v8 ignore next */
|
|
22
|
-
size = input(1, ...(ngDevMode ? [{ debugName: "size" }] : [])); // Multiplicador de tamaño (1 = 24px)
|
|
22
|
+
size = input(1, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ [])); // Multiplicador de tamaño (1 = 24px)
|
|
23
23
|
/* v8 ignore next */
|
|
24
|
-
button = input(false, ...(ngDevMode ?
|
|
24
|
+
button = input(false, { ...(ngDevMode ? { debugName: "button" } : /* istanbul ignore next */ {}), transform: transformToBoolean }); // Renderiza como botón clickeable
|
|
25
25
|
/* v8 ignore next */
|
|
26
|
-
border = input(false, ...(ngDevMode ?
|
|
26
|
+
border = input(false, { ...(ngDevMode ? { debugName: "border" } : /* istanbul ignore next */ {}), transform: transformToBoolean }); // Agrega borde al wrapper
|
|
27
27
|
/* v8 ignore next */
|
|
28
|
-
type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : [])); // Tipo de botón (button, submit, reset)
|
|
28
|
+
type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ [])); // Tipo de botón (button, submit, reset)
|
|
29
29
|
/* v8 ignore next */
|
|
30
|
-
textLeft = input(undefined, ...(ngDevMode ? [{ debugName: "textLeft" }] : [])); // Texto a la izquierda del icono
|
|
30
|
+
textLeft = input(undefined, ...(ngDevMode ? [{ debugName: "textLeft" }] : /* istanbul ignore next */ [])); // Texto a la izquierda del icono
|
|
31
31
|
/* v8 ignore next */
|
|
32
|
-
textRight = input(undefined, ...(ngDevMode ? [{ debugName: "textRight" }] : [])); // Texto a la derecha del icono
|
|
32
|
+
textRight = input(undefined, ...(ngDevMode ? [{ debugName: "textRight" }] : /* istanbul ignore next */ [])); // Texto a la derecha del icono
|
|
33
33
|
/* v8 ignore next */
|
|
34
|
-
dark = input(false, ...(ngDevMode ?
|
|
34
|
+
dark = input(false, { ...(ngDevMode ? { debugName: "dark" } : /* istanbul ignore next */ {}), transform: transformToBoolean }); // Modo oscuro
|
|
35
35
|
iconClick = output(); // Evento emitido al hacer click (solo si button=true)
|
|
36
|
-
iconSize = computed(() => BASE_ICON_SIZE * this.size(), ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
|
|
37
|
-
isDarkMode = computed(() => this.dark() || this.themeService.isDark(), ...(ngDevMode ? [{ debugName: "isDarkMode" }] : []));
|
|
36
|
+
iconSize = computed(() => BASE_ICON_SIZE * this.size(), ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
|
|
37
|
+
isDarkMode = computed(() => this.dark() || this.themeService.isDark(), ...(ngDevMode ? [{ debugName: "isDarkMode" }] : /* istanbul ignore next */ []));
|
|
38
38
|
iconColor = computed(() => {
|
|
39
39
|
if (this.disabled())
|
|
40
40
|
return DISABLED_COLOR;
|
|
@@ -47,7 +47,7 @@ export class IconComponent {
|
|
|
47
47
|
return this.themeService.isDark() ? THEME_DARK_COLOR : THEME_LIGHT_COLOR;
|
|
48
48
|
}
|
|
49
49
|
return BASE_ICON_COLORS[colorType] ?? DEFAULT_ICON_COLOR;
|
|
50
|
-
}, ...(ngDevMode ? [{ debugName: "iconColor" }] : []));
|
|
50
|
+
}, ...(ngDevMode ? [{ debugName: "iconColor" }] : /* istanbul ignore next */ []));
|
|
51
51
|
iconOpacity = computed(() => {
|
|
52
52
|
if (this.disabled())
|
|
53
53
|
return DISABLED_OPACITY;
|
|
@@ -55,15 +55,15 @@ export class IconComponent {
|
|
|
55
55
|
const colorType = this.color();
|
|
56
56
|
const isOpacityReducedColor = colorType && OPACITY_REDUCED_COLORS.includes(colorType);
|
|
57
57
|
return !hasCustomColor && isOpacityReducedColor ? SECONDARY_WARN_OPACITY : DEFAULT_OPACITY;
|
|
58
|
-
}, ...(ngDevMode ? [{ debugName: "iconOpacity" }] : []));
|
|
58
|
+
}, ...(ngDevMode ? [{ debugName: "iconOpacity" }] : /* istanbul ignore next */ []));
|
|
59
59
|
// Optimización: Un solo lookup a ICON_DEFINITIONS
|
|
60
|
-
iconDefinition = computed(() => ICON_DEFINITIONS[this.icon()] ?? ICON_DEFINITIONS['default'], ...(ngDevMode ? [{ debugName: "iconDefinition" }] : []));
|
|
61
|
-
iconPath = computed(() => this.iconDefinition().path, ...(ngDevMode ? [{ debugName: "iconPath" }] : []));
|
|
62
|
-
additionalShapes = computed(() => this.iconDefinition().additionalShapes ?? [], ...(ngDevMode ? [{ debugName: "additionalShapes" }] : []));
|
|
63
|
-
shouldFillIcon = computed(() => shouldIconUseFill(this.icon()), ...(ngDevMode ? [{ debugName: "shouldFillIcon" }] : []));
|
|
64
|
-
multiColorIcon = computed(() => this.iconDefinition().multiColor, ...(ngDevMode ? [{ debugName: "multiColorIcon" }] : []));
|
|
65
|
-
hasMultiPaths = computed(() => this.multiColorIcon() !== undefined, ...(ngDevMode ? [{ debugName: "hasMultiPaths" }] : []));
|
|
66
|
-
iconStrokeWidth = computed(() => this.iconDefinition().strokeWidth ?? SVG_STROKE_ATTRS.strokeWidth, ...(ngDevMode ? [{ debugName: "iconStrokeWidth" }] : []));
|
|
60
|
+
iconDefinition = computed(() => ICON_DEFINITIONS[this.icon()] ?? ICON_DEFINITIONS['default'], ...(ngDevMode ? [{ debugName: "iconDefinition" }] : /* istanbul ignore next */ []));
|
|
61
|
+
iconPath = computed(() => this.iconDefinition().path, ...(ngDevMode ? [{ debugName: "iconPath" }] : /* istanbul ignore next */ []));
|
|
62
|
+
additionalShapes = computed(() => this.iconDefinition().additionalShapes ?? [], ...(ngDevMode ? [{ debugName: "additionalShapes" }] : /* istanbul ignore next */ []));
|
|
63
|
+
shouldFillIcon = computed(() => shouldIconUseFill(this.icon()), ...(ngDevMode ? [{ debugName: "shouldFillIcon" }] : /* istanbul ignore next */ []));
|
|
64
|
+
multiColorIcon = computed(() => this.iconDefinition().multiColor, ...(ngDevMode ? [{ debugName: "multiColorIcon" }] : /* istanbul ignore next */ []));
|
|
65
|
+
hasMultiPaths = computed(() => this.multiColorIcon() !== undefined, ...(ngDevMode ? [{ debugName: "hasMultiPaths" }] : /* istanbul ignore next */ []));
|
|
66
|
+
iconStrokeWidth = computed(() => this.iconDefinition().strokeWidth ?? SVG_STROKE_ATTRS.strokeWidth, ...(ngDevMode ? [{ debugName: "iconStrokeWidth" }] : /* istanbul ignore next */ []));
|
|
67
67
|
// Exponer constantes SVG al template
|
|
68
68
|
svgStrokeAttrs = SVG_STROKE_ATTRS;
|
|
69
69
|
/**
|
|
@@ -75,11 +75,11 @@ export class IconComponent {
|
|
|
75
75
|
this.iconClick.emit(event);
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
79
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
78
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
79
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: IconComponent, 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 }, dark: { classPropertyName: "dark", publicName: "dark", 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()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\" [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 || null\" [attr.stroke]=\"iconColor()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\"\r\n [attr.fill]=\"shape.fill === 'color' ? iconColor() : 'none'\" />\r\n } @else if (shape.type === 'path') {\r\n <path [attr.d]=\"shape.d\" [attr.stroke]=\"iconColor()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\" [attr.stroke-linecap]=\"svgStrokeAttrs.strokeLinecap\" [attr.stroke-linejoin]=\"svgStrokeAttrs.strokeLinejoin\"\r\n [attr.fill]=\"shape.fill === 'color' ? iconColor() : 'none'\" />\r\n }\r\n }\r\n\r\n @if (hasMultiPaths()) {\r\n <!-- Iconos con m\u00FAltiples paths y colores personalizados -->\r\n @for (path of multiColorIcon()!.paths; track $index) {\r\n <path [attr.d]=\"path\" [attr.fill]=\"multiColorIcon()!.colors[$index] || iconColor()\" stroke=\"none\" />\r\n }\r\n } @else {\r\n <!-- Iconos con un solo path -->\r\n <path [attr.d]=\"iconPath()\" [attr.stroke]=\"iconColor()\" [attr.fill]=\"shouldFillIcon() ? iconColor() : 'none'\" [attr.stroke-width]=\"iconStrokeWidth()\" [attr.stroke-linecap]=\"svgStrokeAttrs.strokeLinecap\"\r\n [attr.stroke-linejoin]=\"svgStrokeAttrs.strokeLinejoin\" />\r\n }\r\n </svg>\r\n</ng-template>\r\n\r\n<ng-template #textContent>\r\n @if (textLeft()) {\r\n <span class=\"icon-text ms-3\">{{ 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 me-3\">{{ 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()\" [class.dark-mode]=\"isDarkMode()\" (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()\" [class.dark-mode]=\"isDarkMode()\">\r\n <ng-container *ngTemplateOutlet=\"textContent\" />\r\n</span>\r\n}", styles: [":host{--icon-border-color: #e5e7eb;--icon-border-color-hover: #d1d5db;--icon-border-color-disabled: #f3f4f6;--icon-bg-hover: #f3f4f6;--icon-bg-active: #e5e7eb;--icon-text-color: #111827;--icon-border-radius: 4px;--icon-transition: .2s}:host .dark-mode{--icon-border-color: #374151;--icon-border-color-hover: #4b5563;--icon-border-color-disabled: #1f2937;--icon-bg-hover: #374151;--icon-bg-active: #4b5563;--icon-text-color: #f9fafb}:host .icon-wrapper{display:inline-flex;align-items:center;gap:8px;background:transparent;padding:0;border:none;outline:none;cursor:pointer;transition:opacity var(--icon-transition)}:host button.icon-wrapper:focus-visible{outline:none;outline-offset:2px;border-radius:var(--icon-border-radius)}: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 var(--icon-transition);box-sizing:border-box}:host button.icon-wrapper:hover:not(:disabled) .icon-content{background:var(--icon-bg-hover)}:host button.icon-wrapper:active:not(:disabled) .icon-content{background:var(--icon-bg-active)}:host .icon-text{font-size:14px;line-height:1;white-space:nowrap;-webkit-user-select:none;user-select:none;color:var(--icon-text-color)}:host .icon-wrapper-border{border:1px solid var(--icon-border-color);border-radius:var(--icon-border-radius);padding:4px 8px}:host button.icon-wrapper-border:hover:not(:disabled){border-color:var(--icon-border-color-hover)}:host button.icon-wrapper-border:disabled{border-color:var(--icon-border-color-disabled)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
80
80
|
}
|
|
81
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
81
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: IconComponent, decorators: [{
|
|
82
82
|
type: Component,
|
|
83
|
-
args: [{ selector: 'c80-icon', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #svgContent>\n
|
|
83
|
+
args: [{ selector: 'c80-icon', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, 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()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\" [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 || null\" [attr.stroke]=\"iconColor()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\"\r\n [attr.fill]=\"shape.fill === 'color' ? iconColor() : 'none'\" />\r\n } @else if (shape.type === 'path') {\r\n <path [attr.d]=\"shape.d\" [attr.stroke]=\"iconColor()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\" [attr.stroke-linecap]=\"svgStrokeAttrs.strokeLinecap\" [attr.stroke-linejoin]=\"svgStrokeAttrs.strokeLinejoin\"\r\n [attr.fill]=\"shape.fill === 'color' ? iconColor() : 'none'\" />\r\n }\r\n }\r\n\r\n @if (hasMultiPaths()) {\r\n <!-- Iconos con m\u00FAltiples paths y colores personalizados -->\r\n @for (path of multiColorIcon()!.paths; track $index) {\r\n <path [attr.d]=\"path\" [attr.fill]=\"multiColorIcon()!.colors[$index] || iconColor()\" stroke=\"none\" />\r\n }\r\n } @else {\r\n <!-- Iconos con un solo path -->\r\n <path [attr.d]=\"iconPath()\" [attr.stroke]=\"iconColor()\" [attr.fill]=\"shouldFillIcon() ? iconColor() : 'none'\" [attr.stroke-width]=\"iconStrokeWidth()\" [attr.stroke-linecap]=\"svgStrokeAttrs.strokeLinecap\"\r\n [attr.stroke-linejoin]=\"svgStrokeAttrs.strokeLinejoin\" />\r\n }\r\n </svg>\r\n</ng-template>\r\n\r\n<ng-template #textContent>\r\n @if (textLeft()) {\r\n <span class=\"icon-text ms-3\">{{ 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 me-3\">{{ 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()\" [class.dark-mode]=\"isDarkMode()\" (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()\" [class.dark-mode]=\"isDarkMode()\">\r\n <ng-container *ngTemplateOutlet=\"textContent\" />\r\n</span>\r\n}", styles: [":host{--icon-border-color: #e5e7eb;--icon-border-color-hover: #d1d5db;--icon-border-color-disabled: #f3f4f6;--icon-bg-hover: #f3f4f6;--icon-bg-active: #e5e7eb;--icon-text-color: #111827;--icon-border-radius: 4px;--icon-transition: .2s}:host .dark-mode{--icon-border-color: #374151;--icon-border-color-hover: #4b5563;--icon-border-color-disabled: #1f2937;--icon-bg-hover: #374151;--icon-bg-active: #4b5563;--icon-text-color: #f9fafb}:host .icon-wrapper{display:inline-flex;align-items:center;gap:8px;background:transparent;padding:0;border:none;outline:none;cursor:pointer;transition:opacity var(--icon-transition)}:host button.icon-wrapper:focus-visible{outline:none;outline-offset:2px;border-radius:var(--icon-border-radius)}: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 var(--icon-transition);box-sizing:border-box}:host button.icon-wrapper:hover:not(:disabled) .icon-content{background:var(--icon-bg-hover)}:host button.icon-wrapper:active:not(:disabled) .icon-content{background:var(--icon-bg-active)}:host .icon-text{font-size:14px;line-height:1;white-space:nowrap;-webkit-user-select:none;user-select:none;color:var(--icon-text-color)}:host .icon-wrapper-border{border:1px solid var(--icon-border-color);border-radius:var(--icon-border-radius);padding:4px 8px}:host button.icon-wrapper-border:hover:not(:disabled){border-color:var(--icon-border-color-hover)}:host button.icon-wrapper-border:disabled{border-color:var(--icon-border-color-disabled)}\n"] }]
|
|
84
84
|
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], customColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "customColor", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], button: [{ type: i0.Input, args: [{ isSignal: true, alias: "button", required: false }] }], border: [{ type: i0.Input, args: [{ isSignal: true, alias: "border", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], textLeft: [{ type: i0.Input, args: [{ isSignal: true, alias: "textLeft", required: false }] }], textRight: [{ type: i0.Input, args: [{ isSignal: true, alias: "textRight", required: false }] }], dark: [{ type: i0.Input, args: [{ isSignal: true, alias: "dark", required: false }] }], iconClick: [{ type: i0.Output, args: ["iconClick"] }] } });
|
|
85
85
|
//# sourceMappingURL=icon.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/icon/icon.component.ts","../../../../../libs/ui/src/lib/icon/icon.component.html"],"names":[],"mappings":"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","sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport { Component, input, output, computed, ChangeDetectionStrategy, inject } from '@angular/core';\nimport {\n BASE_ICON_SIZE,\n BASE_ICON_COLORS,\n DISABLED_COLOR,\n DEFAULT_ICON_COLOR,\n DISABLED_OPACITY,\n SECONDARY_WARN_OPACITY,\n DEFAULT_OPACITY,\n OPACITY_REDUCED_COLORS,\n SVG_STROKE_ATTRS,\n THEME_DARK_COLOR,\n THEME_LIGHT_COLOR,\n} from './icon.constants';\nimport { ICON_DEFINITIONS } from './icon.definitions';\nimport type { ColorType, ButtonType, IconType } from './icon.types';\nimport { transformToBoolean, shouldIconUseFill } from './icon.utils';\nimport { ThemeService } from './theme.service';\n\n\n/**\n *\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'c80-icon',\n standalone: true,\n imports: [NgTemplateOutlet],\n templateUrl: './icon.component.html',\n styleUrls: ['./icon.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class IconComponent {\n private readonly themeService = inject(ThemeService);\n\n /* v8 ignore next */\n readonly icon = input<IconType>('check'); // Tipo de icono a mostrar\n /* v8 ignore next */\n readonly color = input<ColorType | undefined>(undefined); // Color del icono (primary, secondary, warn, success)\n /* v8 ignore next */\n readonly customColor = input<string | undefined>(undefined); // Color personalizado (sobrescribe color)\n /* v8 ignore next */\n readonly disabled = input(false); // Estado deshabilitado\n /* v8 ignore next */\n readonly size = input(1); // Multiplicador de tamaño (1 = 24px)\n /* v8 ignore next */\n readonly button = input(false, { transform: transformToBoolean }); // Renderiza como botón clickeable\n /* v8 ignore next */\n readonly border = input(false, { transform: transformToBoolean }); // Agrega borde al wrapper\n /* v8 ignore next */\n readonly type = input<ButtonType>('button'); // Tipo de botón (button, submit, reset)\n /* v8 ignore next */\n readonly textLeft = input<string | undefined>(undefined); // Texto a la izquierda del icono\n /* v8 ignore next */\n readonly textRight = input<string | undefined>(undefined); // Texto a la derecha del icono\n /* v8 ignore next */\n readonly dark = input(false, { transform: transformToBoolean }); // Modo oscuro\n\n readonly iconClick = output<Event>(); // Evento emitido al hacer click (solo si button=true)\n\n readonly iconSize = computed(() => BASE_ICON_SIZE * this.size());\n\n readonly isDarkMode = computed(() => this.dark() || this.themeService.isDark());\n\n readonly iconColor = computed(() => {\n if (this.disabled()) return DISABLED_COLOR;\n\n const custom = this.customColor();\n if (custom) return custom;\n\n const colorType = this.color();\n\n // Si no hay color específico, usar color adaptativo al tema\n if (!colorType) {\n return this.themeService.isDark() ? THEME_DARK_COLOR : THEME_LIGHT_COLOR;\n }\n\n return BASE_ICON_COLORS[colorType] ?? DEFAULT_ICON_COLOR;\n });\n\n readonly iconOpacity = computed(() => {\n if (this.disabled()) return DISABLED_OPACITY;\n\n const hasCustomColor = this.customColor() !== undefined;\n const colorType = this.color();\n const isOpacityReducedColor = colorType && OPACITY_REDUCED_COLORS.includes(colorType);\n\n return !hasCustomColor && isOpacityReducedColor ? SECONDARY_WARN_OPACITY : DEFAULT_OPACITY;\n });\n\n // Optimización: Un solo lookup a ICON_DEFINITIONS\n readonly iconDefinition = computed(() => ICON_DEFINITIONS[this.icon()] ?? ICON_DEFINITIONS['default']);\n\n readonly iconPath = computed(() => this.iconDefinition().path);\n\n readonly additionalShapes = computed(() => this.iconDefinition().additionalShapes ?? []);\n\n readonly shouldFillIcon = computed(() => shouldIconUseFill(this.icon()));\n\n readonly multiColorIcon = computed(() => this.iconDefinition().multiColor);\n\n readonly hasMultiPaths = computed(() => this.multiColorIcon() !== undefined);\n\n readonly iconStrokeWidth = computed(() => this.iconDefinition().strokeWidth ?? SVG_STROKE_ATTRS.strokeWidth);\n\n // Exponer constantes SVG al template\n readonly svgStrokeAttrs = SVG_STROKE_ATTRS;\n\n /**\n *\n * @param event\n */\n onButtonClick(event: Event): void {\n if (!this.disabled()) {\n this.iconClick.emit(event);\n }\n }\n}\n","<ng-template #svgContent>\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <svg [attr.width]=\"iconSize()\" [attr.height]=\"iconSize()\" viewBox=\"0 0 24 24\" fill=\"none\" [style.opacity]=\"iconOpacity()\">\n @for (shape of additionalShapes(); track $index) {\n @if (shape.type === 'circle') {\n <circle [attr.cx]=\"shape.cx\" [attr.cy]=\"shape.cy\" [attr.r]=\"shape.r\" [attr.stroke]=\"iconColor()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\" [attr.fill]=\"shape.fill === 'color' ? iconColor() : 'none'\" />\n } @else if (shape.type === 'rect') {\n <rect [attr.x]=\"shape.x\" [attr.y]=\"shape.y\" [attr.width]=\"shape.width\" [attr.height]=\"shape.height\" [attr.rx]=\"shape.rx || null\" [attr.stroke]=\"iconColor()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\"\n [attr.fill]=\"shape.fill === 'color' ? iconColor() : 'none'\" />\n } @else if (shape.type === 'path') {\n <path [attr.d]=\"shape.d\" [attr.stroke]=\"iconColor()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\" [attr.stroke-linecap]=\"svgStrokeAttrs.strokeLinecap\" [attr.stroke-linejoin]=\"svgStrokeAttrs.strokeLinejoin\"\n [attr.fill]=\"shape.fill === 'color' ? iconColor() : 'none'\" />\n }\n }\n\n @if (hasMultiPaths()) {\n <!-- Iconos con múltiples paths y colores personalizados -->\n @for (path of multiColorIcon()!.paths; track $index) {\n <path [attr.d]=\"path\" [attr.fill]=\"multiColorIcon()!.colors[$index] || iconColor()\" stroke=\"none\" />\n }\n } @else {\n <!-- Iconos con un solo path -->\n <path [attr.d]=\"iconPath()\" [attr.stroke]=\"iconColor()\" [attr.fill]=\"shouldFillIcon() ? iconColor() : 'none'\" [attr.stroke-width]=\"iconStrokeWidth()\" [attr.stroke-linecap]=\"svgStrokeAttrs.strokeLinecap\"\n [attr.stroke-linejoin]=\"svgStrokeAttrs.strokeLinejoin\" />\n }\n </svg>\n</ng-template>\n\n<ng-template #textContent>\n @if (textLeft()) {\n <span class=\"icon-text ms-3\">{{ textLeft() }}</span>\n }\n <!-- eslint-disable-next-line @angular-eslint/template/no-inline-styles -->\n <span class=\"icon-content\" [style.width.px]=\"iconSize() + 8\" [style.height.px]=\"iconSize() + 8\">\n <ng-container *ngTemplateOutlet=\"svgContent\" />\n </span>\n @if (textRight()) {\n <span class=\"icon-text me-3\">{{ textRight() }}</span>\n }\n</ng-template>\n\n@if (button()) {\n<button [type]=\"type()\" [disabled]=\"disabled()\" class=\"icon-wrapper\" [class.icon-wrapper-border]=\"border()\" [class.dark-mode]=\"isDarkMode()\" (click)=\"onButtonClick($event)\">\n <ng-container *ngTemplateOutlet=\"textContent\" />\n</button>\n} @else {\n<span class=\"icon-wrapper\" [class.icon-wrapper-border]=\"border()\" [class.dark-mode]=\"isDarkMode()\">\n <ng-container *ngTemplateOutlet=\"textContent\" />\n</span>\n}"]}
|
|
1
|
+
{"version":3,"file":"icon.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/icon/icon.component.ts","../../../../../libs/ui/src/lib/icon/icon.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACpG,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;;AAG/C;;GAEG;AASH,MAAM,OAAO,aAAa;IACP,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IAErD,oBAAoB;IACX,IAAI,GAAG,KAAK,CAAW,OAAO,2EAAC,CAAC,CAAC,0BAA0B;IACpE,oBAAoB;IACX,KAAK,GAAG,KAAK,CAAwB,SAAS,4EAAC,CAAC,CAAC,sDAAsD;IAChH,oBAAoB;IACX,WAAW,GAAG,KAAK,CAAqB,SAAS,kFAAC,CAAC,CAAC,0CAA0C;IACvG,oBAAoB;IACX,QAAQ,GAAG,KAAK,CAAC,KAAK,+EAAC,CAAC,CAAC,uBAAuB;IACzD,oBAAoB;IACX,IAAI,GAAG,KAAK,CAAC,CAAC,2EAAC,CAAC,CAAC,qCAAqC;IAC/D,oBAAoB;IACX,MAAM,GAAG,KAAK,CAAC,KAAK,8EAAI,SAAS,EAAE,kBAAkB,GAAG,CAAC,CAAC,kCAAkC;IACrG,oBAAoB;IACX,MAAM,GAAG,KAAK,CAAC,KAAK,8EAAI,SAAS,EAAE,kBAAkB,GAAG,CAAC,CAAC,0BAA0B;IAC7F,oBAAoB;IACX,IAAI,GAAG,KAAK,CAAa,QAAQ,2EAAC,CAAC,CAAC,wCAAwC;IACrF,oBAAoB;IACX,QAAQ,GAAG,KAAK,CAAqB,SAAS,+EAAC,CAAC,CAAC,iCAAiC;IAC3F,oBAAoB;IACX,SAAS,GAAG,KAAK,CAAqB,SAAS,gFAAC,CAAC,CAAC,+BAA+B;IAC1F,oBAAoB;IACX,IAAI,GAAG,KAAK,CAAC,KAAK,4EAAI,SAAS,EAAE,kBAAkB,GAAG,CAAC,CAAC,cAAc;IAEtE,SAAS,GAAG,MAAM,EAAS,CAAC,CAAC,sDAAsD;IAEnF,QAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,cAAc,GAAG,IAAI,CAAC,IAAI,EAAE,+EAAC,CAAC;IAExD,UAAU,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,iFAAC,CAAC;IAEvE,SAAS,GAAG,QAAQ,CAAC,GAAG,EAAE;QACjC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE,OAAO,cAAc,CAAC;QAE3C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAE/B,4DAA4D;QAC5D,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,iBAAiB,CAAC;QAC3E,CAAC;QAED,OAAO,gBAAgB,CAAC,SAAS,CAAC,IAAI,kBAAkB,CAAC;IAC3D,CAAC,gFAAC,CAAC;IAEM,WAAW,GAAG,QAAQ,CAAC,GAAG,EAAE;QACnC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE,OAAO,gBAAgB,CAAC;QAE7C,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC;QACxD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,qBAAqB,GAAG,SAAS,IAAI,sBAAsB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAEtF,OAAO,CAAC,cAAc,IAAI,qBAAqB,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,eAAe,CAAC;IAC7F,CAAC,kFAAC,CAAC;IAEH,kDAAkD;IACzC,cAAc,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,gBAAgB,CAAC,SAAS,CAAC,qFAAC,CAAC;IAE9F,QAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,+EAAC,CAAC;IAEtD,gBAAgB,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,gBAAgB,IAAI,EAAE,uFAAC,CAAC;IAEhF,cAAc,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,qFAAC,CAAC;IAEhE,cAAc,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,UAAU,qFAAC,CAAC;IAElE,aAAa,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,SAAS,oFAAC,CAAC;IAEpE,eAAe,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,WAAW,IAAI,gBAAgB,CAAC,WAAW,sFAAC,CAAC;IAE7G,qCAAqC;IAC5B,cAAc,GAAG,gBAAgB,CAAC;IAE3C;;;OAGG;IACH,aAAa,CAAC,KAAY;QACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACrB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;wGApFU,aAAa;4FAAb,aAAa,u8CChC1B,8sFA+CC,oqDDpBW,gBAAgB;;4FAKf,aAAa;kBARzB,SAAS;+BACE,UAAU,cACR,IAAI,WACP,CAAC,gBAAgB,CAAC,mBAGV,uBAAuB,CAAC,MAAM","sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\r\nimport { Component, input, output, computed, ChangeDetectionStrategy, inject } from '@angular/core';\r\nimport {\r\n BASE_ICON_SIZE,\r\n BASE_ICON_COLORS,\r\n DISABLED_COLOR,\r\n DEFAULT_ICON_COLOR,\r\n DISABLED_OPACITY,\r\n SECONDARY_WARN_OPACITY,\r\n DEFAULT_OPACITY,\r\n OPACITY_REDUCED_COLORS,\r\n SVG_STROKE_ATTRS,\r\n THEME_DARK_COLOR,\r\n THEME_LIGHT_COLOR,\r\n} from './icon.constants';\r\nimport { ICON_DEFINITIONS } from './icon.definitions';\r\nimport type { ColorType, ButtonType, IconType } from './icon.types';\r\nimport { transformToBoolean, shouldIconUseFill } from './icon.utils';\r\nimport { ThemeService } from './theme.service';\r\n\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-icon',\r\n standalone: true,\r\n imports: [NgTemplateOutlet],\r\n templateUrl: './icon.component.html',\r\n styleUrls: ['./icon.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class IconComponent {\r\n private readonly themeService = inject(ThemeService);\r\n\r\n /* v8 ignore next */\r\n readonly icon = input<IconType>('check'); // Tipo de icono a mostrar\r\n /* v8 ignore next */\r\n readonly color = input<ColorType | undefined>(undefined); // Color del icono (primary, secondary, warn, success)\r\n /* v8 ignore next */\r\n readonly customColor = input<string | undefined>(undefined); // Color personalizado (sobrescribe color)\r\n /* v8 ignore next */\r\n readonly disabled = input(false); // Estado deshabilitado\r\n /* v8 ignore next */\r\n readonly size = input(1); // Multiplicador de tamaño (1 = 24px)\r\n /* v8 ignore next */\r\n readonly button = input(false, { transform: transformToBoolean }); // Renderiza como botón clickeable\r\n /* v8 ignore next */\r\n readonly border = input(false, { transform: transformToBoolean }); // Agrega borde al wrapper\r\n /* v8 ignore next */\r\n readonly type = input<ButtonType>('button'); // Tipo de botón (button, submit, reset)\r\n /* v8 ignore next */\r\n readonly textLeft = input<string | undefined>(undefined); // Texto a la izquierda del icono\r\n /* v8 ignore next */\r\n readonly textRight = input<string | undefined>(undefined); // Texto a la derecha del icono\r\n /* v8 ignore next */\r\n readonly dark = input(false, { transform: transformToBoolean }); // Modo oscuro\r\n\r\n readonly iconClick = output<Event>(); // Evento emitido al hacer click (solo si button=true)\r\n\r\n readonly iconSize = computed(() => BASE_ICON_SIZE * this.size());\r\n\r\n readonly isDarkMode = computed(() => this.dark() || this.themeService.isDark());\r\n\r\n readonly iconColor = computed(() => {\r\n if (this.disabled()) return DISABLED_COLOR;\r\n\r\n const custom = this.customColor();\r\n if (custom) return custom;\r\n\r\n const colorType = this.color();\r\n\r\n // Si no hay color específico, usar color adaptativo al tema\r\n if (!colorType) {\r\n return this.themeService.isDark() ? THEME_DARK_COLOR : THEME_LIGHT_COLOR;\r\n }\r\n\r\n return BASE_ICON_COLORS[colorType] ?? DEFAULT_ICON_COLOR;\r\n });\r\n\r\n readonly iconOpacity = computed(() => {\r\n if (this.disabled()) return DISABLED_OPACITY;\r\n\r\n const hasCustomColor = this.customColor() !== undefined;\r\n const colorType = this.color();\r\n const isOpacityReducedColor = colorType && OPACITY_REDUCED_COLORS.includes(colorType);\r\n\r\n return !hasCustomColor && isOpacityReducedColor ? SECONDARY_WARN_OPACITY : DEFAULT_OPACITY;\r\n });\r\n\r\n // Optimización: Un solo lookup a ICON_DEFINITIONS\r\n readonly iconDefinition = computed(() => ICON_DEFINITIONS[this.icon()] ?? ICON_DEFINITIONS['default']);\r\n\r\n readonly iconPath = computed(() => this.iconDefinition().path);\r\n\r\n readonly additionalShapes = computed(() => this.iconDefinition().additionalShapes ?? []);\r\n\r\n readonly shouldFillIcon = computed(() => shouldIconUseFill(this.icon()));\r\n\r\n readonly multiColorIcon = computed(() => this.iconDefinition().multiColor);\r\n\r\n readonly hasMultiPaths = computed(() => this.multiColorIcon() !== undefined);\r\n\r\n readonly iconStrokeWidth = computed(() => this.iconDefinition().strokeWidth ?? SVG_STROKE_ATTRS.strokeWidth);\r\n\r\n // Exponer constantes SVG al template\r\n readonly svgStrokeAttrs = SVG_STROKE_ATTRS;\r\n\r\n /**\r\n *\r\n * @param event\r\n */\r\n onButtonClick(event: Event): void {\r\n if (!this.disabled()) {\r\n this.iconClick.emit(event);\r\n }\r\n }\r\n}\r\n","<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()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\" [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 || null\" [attr.stroke]=\"iconColor()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\"\r\n [attr.fill]=\"shape.fill === 'color' ? iconColor() : 'none'\" />\r\n } @else if (shape.type === 'path') {\r\n <path [attr.d]=\"shape.d\" [attr.stroke]=\"iconColor()\" [attr.stroke-width]=\"svgStrokeAttrs.strokeWidth\" [attr.stroke-linecap]=\"svgStrokeAttrs.strokeLinecap\" [attr.stroke-linejoin]=\"svgStrokeAttrs.strokeLinejoin\"\r\n [attr.fill]=\"shape.fill === 'color' ? iconColor() : 'none'\" />\r\n }\r\n }\r\n\r\n @if (hasMultiPaths()) {\r\n <!-- Iconos con múltiples paths y colores personalizados -->\r\n @for (path of multiColorIcon()!.paths; track $index) {\r\n <path [attr.d]=\"path\" [attr.fill]=\"multiColorIcon()!.colors[$index] || iconColor()\" stroke=\"none\" />\r\n }\r\n } @else {\r\n <!-- Iconos con un solo path -->\r\n <path [attr.d]=\"iconPath()\" [attr.stroke]=\"iconColor()\" [attr.fill]=\"shouldFillIcon() ? iconColor() : 'none'\" [attr.stroke-width]=\"iconStrokeWidth()\" [attr.stroke-linecap]=\"svgStrokeAttrs.strokeLinecap\"\r\n [attr.stroke-linejoin]=\"svgStrokeAttrs.strokeLinejoin\" />\r\n }\r\n </svg>\r\n</ng-template>\r\n\r\n<ng-template #textContent>\r\n @if (textLeft()) {\r\n <span class=\"icon-text ms-3\">{{ 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 me-3\">{{ 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()\" [class.dark-mode]=\"isDarkMode()\" (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()\" [class.dark-mode]=\"isDarkMode()\">\r\n <ng-container *ngTemplateOutlet=\"textContent\" />\r\n</span>\r\n}"]}
|