@c80/ui 1.1.2 → 2.0.1
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/README.md +49 -49
- package/esm2022/lib/action-list/action-list.component.js +6 -6
- 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 +13 -24
- 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 +6 -6
- 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 +6 -6
- 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 -37
- 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 +7 -4
- package/esm2022/lib/icon/theme.service.js.map +1 -1
- package/esm2022/lib/info-list/info-list.component.js +5 -5
- 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 +10 -15
- 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 +12 -12
- package/esm2022/lib/input-field/input-field.component.js.map +1 -1
- package/esm2022/lib/input-search/c80-input-search.component.js +6 -6
- package/esm2022/lib/input-search/c80-input-search.component.js.map +1 -1
- package/esm2022/lib/legal-disclaimer/legal-disclaimer.component.js +5 -5
- package/esm2022/lib/legal-disclaimer/legal-disclaimer.component.js.map +1 -1
- package/esm2022/lib/modal/modal.component.js +5 -7
- package/esm2022/lib/modal/modal.component.js.map +1 -1
- package/esm2022/lib/modal/modal.service.js +11 -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 +6 -6
- 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 +5 -5
- 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 +8 -8
- package/esm2022/lib/rating-display/rating-display.component.js.map +1 -1
- package/esm2022/lib/rating-stars/rating-stars.component.js +9 -10
- package/esm2022/lib/rating-stars/rating-stars.component.js.map +1 -1
- package/esm2022/lib/select/select.component.js +17 -28
- 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 +7 -9
- 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 -6
- 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 +9 -12
- package/esm2022/lib/tab/c80-tab.component.js.map +1 -1
- package/esm2022/lib/tab/directives/c80-tab-item.directive.js +3 -4
- package/esm2022/lib/tab/directives/c80-tab-item.directive.js.map +1 -1
- package/esm2022/lib/tab/directives/c80-tab-label.directive.js +3 -4
- package/esm2022/lib/tab/directives/c80-tab-label.directive.js.map +1 -1
- package/esm2022/lib/tab/index.js.map +1 -1
- 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 +28 -54
- package/esm2022/lib/table/table.component.js.map +1 -1
- package/esm2022/lib/table/table.types.js +0 -1
- package/lib/card-level/card-level.component.d.ts +1 -1
- package/lib/info-message/info-message.component.d.ts +2 -5
- package/lib/modal/modal.component.d.ts +0 -1
- package/lib/rating-stars/rating-stars.component.d.ts +0 -1
- package/lib/tab/c80-tab.component.d.ts +1 -2
- package/lib/tab/index.d.ts +0 -1
- package/package.json +4 -3
- package/esm2022/lib/tab/c80-tab.types.js +0 -2
- package/esm2022/lib/tab/c80-tab.types.js.map +0 -1
- package/lib/tab/c80-tab.types.d.ts +0 -4
package/README.md
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
# UI Library (`@c80/ui`)
|
|
3
2
|
|
|
4
3
|
Librería de componentes de interfaz de usuario reutilizables para Angular, diseñada para acelerar el desarrollo de aplicaciones con una experiencia visual consistente y componentes listos para producción.
|
|
@@ -24,9 +23,8 @@ Componente para mostrar íconos SVG personalizables, con soporte para distintos
|
|
|
24
23
|
<c80-icon icon="add" [size]="2"></c80-icon>
|
|
25
24
|
```
|
|
26
25
|
|
|
27
|
-
|
|
28
26
|
### `c80-table`
|
|
29
|
-
Componente de tabla editable y dinámica, con soporte para operaciones CRUD, definición de columnas, edición en línea y acciones integradas.
|
|
27
|
+
Componente de tabla editable y dinámica, con soporte para operaciones CRUD, definición de columnas, edición en línea y acciones integradas. Desacoplado: recibe los datos como observable y emite eventos para las acciones.
|
|
30
28
|
|
|
31
29
|
**Props principales:**
|
|
32
30
|
- `data$`: `Observable<T[]>` (observable con los datos a mostrar)
|
|
@@ -64,72 +62,74 @@ userColumns = [
|
|
|
64
62
|
];
|
|
65
63
|
|
|
66
64
|
users$: Observable<User[]> = this.userService.getAll();
|
|
65
|
+
```
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
### `c80-action-list`
|
|
68
|
+
Lista de acciones con título opcional, descripción e iconos. Emite el ID de la acción al hacer click (o ejecuta la función embebida en el `ActionItem`).
|
|
69
|
+
|
|
70
|
+
**Props principales:**
|
|
71
|
+
- `title`: `string` (título opcional de la sección)
|
|
72
|
+
- `actions`: `ActionItem[]` (acciones a mostrar)
|
|
73
|
+
- `actionClick`: `EventEmitter<string>` (emite el `action` string al hacer click; si `action` es una función, se ejecuta en lugar de emitir)
|
|
74
|
+
|
|
75
|
+
**ActionItem:**
|
|
76
|
+
```typescript
|
|
77
|
+
interface ActionItem {
|
|
78
|
+
label: string; // Texto principal
|
|
79
|
+
description?: string; // Texto secundario
|
|
80
|
+
icon?: IconType; // Icono a mostrar
|
|
81
|
+
action?: string | (() => void); // ID de acción a emitir, o función a ejecutar
|
|
82
|
+
isDanger?: boolean; // Estilo de peligro
|
|
83
|
+
isNavigable?: boolean; // Estilo de enlace de navegación
|
|
76
84
|
}
|
|
77
85
|
```
|
|
78
86
|
|
|
87
|
+
**Ejemplo de uso:**
|
|
88
|
+
```html
|
|
89
|
+
<c80-action-list
|
|
90
|
+
title="Mi sección"
|
|
91
|
+
[actions]="actions()"
|
|
92
|
+
(actionClick)="onActionClick($event)"></c80-action-list>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### `c80-input-field`
|
|
96
|
+
Campo de entrada (`text` | `email` | `password`) que mantiene la estética de `c80-info-list`, pensado para edición inline con consistencia visual. Maneja estados de focus/readonly y eventos de teclado.
|
|
97
|
+
|
|
98
|
+
**Outputs:**
|
|
99
|
+
- `valueChange`: `EventEmitter<string>` (emite cuando cambia el valor)
|
|
100
|
+
- `enterPressed`: `EventEmitter<void>` (emite al presionar Enter)
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<c80-input-field
|
|
104
|
+
(valueChange)="onValueChange($event)"
|
|
105
|
+
(enterPressed)="onSubmit()"></c80-input-field>
|
|
106
|
+
```
|
|
107
|
+
|
|
79
108
|
## Instalación y uso
|
|
80
|
-
Esta librería está pensada para
|
|
109
|
+
Esta librería está pensada para usarse dentro del monorepo Nx. Importa los componentes directamente desde el punto de entrada público:
|
|
81
110
|
|
|
82
111
|
```typescript
|
|
83
112
|
import { C80IconComponent, C80TableComponent } from '@c80/ui';
|
|
84
113
|
```
|
|
85
114
|
|
|
86
115
|
## Estructura del proyecto
|
|
87
|
-
- `src/lib
|
|
88
|
-
- `src/
|
|
89
|
-
- `src/index.ts`: Punto de entrada público de la librería
|
|
90
|
-
|
|
91
|
-
## Publicación y visualización en npm
|
|
92
|
-
Una vez publicada, la librería puede consultarse en:
|
|
93
|
-
https://www.npmjs.com/package/@c80/ui
|
|
116
|
+
- `src/lib/<componente>/`: un directorio por componente (`icon`, `table`, `action-list`, `input-field`, etc.)
|
|
117
|
+
- `src/index.ts`: punto de entrada público de la librería
|
|
94
118
|
|
|
95
119
|
## Desarrollo y contribución
|
|
96
|
-
1.
|
|
97
|
-
2.
|
|
98
|
-
3. Ejecuta pruebas y build local:
|
|
120
|
+
1. Realiza los cambios necesarios en los componentes o estilos.
|
|
121
|
+
2. Ejecuta la build local:
|
|
99
122
|
```sh
|
|
100
|
-
pnpm nx test ui
|
|
101
123
|
pnpm nx build ui
|
|
102
124
|
```
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
## Contacto y soporte
|
|
106
|
-
Para reportar errores, solicitar funcionalidades o recibir soporte, utiliza el sistema de issues del repositorio o contacta al equipo de desarrollo.
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
© 2025 c80. Todos los derechos reservados.
|
|
125
|
+
3. Realiza un PR siguiendo las convenciones del repositorio.
|
|
110
126
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
3. Ejecuta las pruebas y la build local:
|
|
114
|
-
```sh
|
|
115
|
-
pnpm nx test ui
|
|
116
|
-
pnpm nx build ui
|
|
117
|
-
```
|
|
118
|
-
4. Realiza un PR siguiendo las convenciones del repositorio.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
## Publicación y visualización en npm
|
|
122
|
-
Esta librería puede ser publicada y visualizada en el registro de npm para su distribución y consulta pública. Una vez publicada, puedes encontrarla buscando el nombre del paquete en [npmjs.com](https://www.npmjs.com/):
|
|
123
|
-
|
|
124
|
-
```
|
|
127
|
+
## Publicación en npm
|
|
128
|
+
Una vez publicada, la librería puede consultarse en:
|
|
125
129
|
https://www.npmjs.com/package/@c80/ui
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
Desde la página de npm podrás consultar la documentación, versiones, dependencias y descargar el paquete para su uso externo si así se habilita.
|
|
129
130
|
|
|
130
131
|
## Contacto y soporte
|
|
131
|
-
Para reportar errores, solicitar
|
|
132
|
+
Para reportar errores, solicitar funcionalidades o recibir soporte, utiliza el sistema de issues del repositorio o contacta al equipo de desarrollo.
|
|
132
133
|
|
|
133
134
|
---
|
|
134
135
|
© 2025 c80. Todos los derechos reservados.
|
|
135
|
-
|
|
@@ -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,11 +20,11 @@ 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
|
-
args: [{ selector: 'c80-action-list',
|
|
28
|
+
args: [{ selector: 'c80-action-list', 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"] }] } });
|
|
30
30
|
//# sourceMappingURL=action-list.component.js.map
|
|
@@ -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;AAQH,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,sXCdhC,w5BAoBM,8+BDXQ,aAAa;;4FAKd,mBAAmB;kBAP/B,SAAS;+BACI,iBAAiB,WAClB,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 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>"]}
|
|
@@ -1,45 +1,34 @@
|
|
|
1
1
|
import { Component, input, computed, ChangeDetectionStrategy } from '@angular/core';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
|
+
let uniqueIdCounter = 0;
|
|
3
4
|
/**
|
|
4
5
|
*
|
|
5
6
|
*/
|
|
6
7
|
export class CardLevelComponent {
|
|
7
|
-
/*
|
|
8
|
-
|
|
9
|
-
/* v8 ignore next */
|
|
10
|
-
size = input(1, ...(ngDevMode ? [{ debugName: "size" }] : [])); // Multiplicador del tamaño base (220px)
|
|
8
|
+
cardLevelData = input.required(...(ngDevMode ? [{ debugName: "cardLevelData" }] : /* istanbul ignore next */ []));
|
|
9
|
+
size = input(1, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ [])); // Multiplicador del tamaño base (220px)
|
|
11
10
|
// ID único generado para el componente
|
|
12
|
-
|
|
13
|
-
generatedId = computed(() => {
|
|
14
|
-
const label = this.cardLevelData().label.toLowerCase().replaceAll(/\s+/g, '-');
|
|
15
|
-
const randomNum = Math.floor(Math.random() * 10000);
|
|
16
|
-
return `${label}-${randomNum}`;
|
|
17
|
-
}, ...(ngDevMode ? [{ debugName: "generatedId" }] : []));
|
|
11
|
+
generatedId = `c80-card-level-${++uniqueIdCounter}`;
|
|
18
12
|
// Ancho calculado de la card
|
|
19
|
-
/* v8 ignore next 4 */
|
|
20
13
|
cardWidth = computed(() => {
|
|
21
14
|
const baseWidth = 140;
|
|
22
15
|
const calculatedWidth = baseWidth * this.size();
|
|
23
16
|
return `${calculatedWidth}px`;
|
|
24
|
-
}, ...(ngDevMode ? [{ debugName: "cardWidth" }] : []));
|
|
17
|
+
}, ...(ngDevMode ? [{ debugName: "cardWidth" }] : /* istanbul ignore next */ []));
|
|
25
18
|
// Detecta si el rango es bidireccional (min negativo, max positivo)
|
|
26
|
-
/* v8 ignore next 4 */
|
|
27
19
|
isBidirectional = computed(() => {
|
|
28
20
|
const data = this.cardLevelData();
|
|
29
21
|
return data.min < 0 && data.max > 0;
|
|
30
|
-
}, ...(ngDevMode ? [{ debugName: "isBidirectional" }] : []));
|
|
22
|
+
}, ...(ngDevMode ? [{ debugName: "isBidirectional" }] : /* istanbul ignore next */ []));
|
|
31
23
|
// Calcula el porcentaje de fill para barras bidireccionales
|
|
32
|
-
/* v8 ignore next 4 */
|
|
33
24
|
bidirectionalFillPercent = computed(() => {
|
|
34
25
|
const data = this.cardLevelData();
|
|
35
26
|
const totalRange = data.max - data.min;
|
|
36
27
|
return Math.abs(data.value / totalRange) * 100;
|
|
37
|
-
}, ...(ngDevMode ? [{ debugName: "bidirectionalFillPercent" }] : []));
|
|
28
|
+
}, ...(ngDevMode ? [{ debugName: "bidirectionalFillPercent" }] : /* istanbul ignore next */ []));
|
|
38
29
|
// Determina la dirección del fill (left/right)
|
|
39
|
-
/*
|
|
40
|
-
fillDirection = computed(() => this.cardLevelData().value >= 0 ? 'right' : 'left', ...(ngDevMode ? [{ debugName: "fillDirection" }] : []));
|
|
30
|
+
fillDirection = computed(() => this.cardLevelData().value >= 0 ? 'right' : 'left', ...(ngDevMode ? [{ debugName: "fillDirection" }] : /* istanbul ignore next */ []));
|
|
41
31
|
// Color según el valor y umbrales
|
|
42
|
-
/* v8 ignore next 11 */
|
|
43
32
|
fillColor = computed(() => {
|
|
44
33
|
const data = this.cardLevelData();
|
|
45
34
|
const absValue = Math.abs(data.value);
|
|
@@ -52,12 +41,12 @@ export class CardLevelComponent {
|
|
|
52
41
|
return 'var(--color-warning)';
|
|
53
42
|
}
|
|
54
43
|
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: "
|
|
44
|
+
}, ...(ngDevMode ? [{ debugName: "fillColor" }] : /* istanbul ignore next */ []));
|
|
45
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CardLevelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
46
|
+
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
47
|
}
|
|
59
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
48
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: CardLevelComponent, decorators: [{
|
|
60
49
|
type: Component,
|
|
61
|
-
args: [{ selector: 'c80-card-level',
|
|
50
|
+
args: [{ selector: 'c80-card-level', 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
51
|
}], propDecorators: { cardLevelData: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardLevelData", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
63
52
|
//# 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,IAAI,eAAe,GAAG,CAAC,CAAC;AAExB;;GAEG;AAQH,MAAM,OAAO,kBAAkB;IAC7B,aAAa,GAAG,KAAK,CAAC,QAAQ,mFAAiB,CAAC;IAChD,IAAI,GAAG,KAAK,CAAS,CAAC,2EAAC,CAAC,CAAC,wCAAwC;IAEjE,uCAAuC;IAC9B,WAAW,GAAG,kBAAkB,EAAE,eAAe,EAAE,CAAC;IAE7D,6BAA6B;IACpB,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,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,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,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,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;wGA5CQ,kBAAkB;4FAAlB,kBAAkB,0VCf/B,8nCAwBA;;4FDTa,kBAAkB;kBAP9B,SAAS;+BACE,gBAAgB,WACjB,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\nlet uniqueIdCounter = 0;\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-card-level',\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 cardLevelData = input.required<CardLevelData>();\r\n size = input<number>(1); // Multiplicador del tamaño base (220px)\r\n\r\n // ID único generado para el componente\r\n readonly generatedId = `c80-card-level-${++uniqueIdCounter}`;\r\n\r\n // Ancho calculado de la card\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 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 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 fillDirection = computed(() => this.cardLevelData().value >= 0 ? 'right' : 'left');\r\n\r\n // Color según el valor y umbrales\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,18 +24,18 @@ 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
|
-
args: [{ selector: 'c80-error-notification',
|
|
39
|
+
args: [{ selector: 'c80-error-notification', 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"] }] } });
|
|
41
41
|
//# sourceMappingURL=error-notification.component.js.map
|
|
@@ -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;AAQH,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,yPCdvC,ujBAYM,y3BDHQ,aAAa;;4FAKd,0BAA0B;kBAPtC,SAAS;+BACI,wBAAwB,WACzB,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 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,19 +7,19 @@ 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
|
-
args: [{ selector: 'c80-header',
|
|
23
|
+
args: [{ selector: 'c80-header', 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 }] }] } });
|
|
25
25
|
//# sourceMappingURL=header.component.js.map
|
|
@@ -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;AAQH,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,6UChB5B,oaAQS,snBDGK,aAAa;;4FAKd,eAAe;kBAP3B,SAAS;+BACI,YAAY,WACb,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 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>"]}
|