@c80/ui 1.0.57 → 1.0.62
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/index.js +13 -8
- package/esm2022/index.js.map +1 -1
- package/esm2022/lib/action-list/action-list.component.js +7 -0
- package/esm2022/lib/action-list/action-list.component.js.map +1 -1
- package/esm2022/lib/action-list/action-list.types.js.map +1 -1
- package/esm2022/lib/card-level/card-level.component.js +4 -3
- package/esm2022/lib/card-level/card-level.component.js.map +1 -1
- package/esm2022/lib/card-level/card-level.interface.js.map +1 -1
- package/esm2022/lib/card-level/index.js.map +1 -1
- package/esm2022/lib/error-notification/error-notification.component.js +41 -0
- package/esm2022/lib/error-notification/error-notification.component.js.map +1 -0
- package/esm2022/lib/error-notification/error-notification.types.js +2 -0
- package/esm2022/lib/error-notification/error-notification.types.js.map +1 -0
- package/esm2022/lib/error-notification/index.js +3 -0
- package/esm2022/lib/error-notification/index.js.map +1 -0
- package/esm2022/lib/header/header.component.js +8 -2
- package/esm2022/lib/header/header.component.js.map +1 -1
- package/esm2022/lib/header/header.types.js.map +1 -1
- package/esm2022/lib/icon/icon.component.js +11 -5
- package/esm2022/lib/icon/icon.component.js.map +1 -1
- package/esm2022/lib/icon/icon.definitions.js +108 -2
- package/esm2022/lib/icon/icon.definitions.js.map +1 -1
- package/esm2022/lib/icon/icon.types.js.map +1 -1
- package/esm2022/lib/icon/icon.utils.js +7 -0
- package/esm2022/lib/icon/icon.utils.js.map +1 -1
- package/esm2022/lib/icon/theme.service.js +20 -0
- package/esm2022/lib/icon/theme.service.js.map +1 -1
- package/esm2022/lib/info-list/info-list.component.js +3 -0
- package/esm2022/lib/info-list/info-list.component.js.map +1 -1
- package/esm2022/lib/input-field/input-field.component.js +19 -2
- package/esm2022/lib/input-field/input-field.component.js.map +1 -1
- package/esm2022/lib/input-search/c80-input-search.component.js +26 -0
- package/esm2022/lib/input-search/c80-input-search.component.js.map +1 -0
- package/esm2022/lib/input-search/index.js +2 -0
- package/esm2022/lib/input-search/index.js.map +1 -0
- package/esm2022/lib/modal/index.js.map +1 -1
- package/esm2022/lib/modal/modal.component.js +59 -2
- package/esm2022/lib/modal/modal.component.js.map +1 -1
- package/esm2022/lib/modal/modal.service.js +60 -3
- package/esm2022/lib/modal/modal.service.js.map +1 -1
- package/esm2022/lib/modal/modal.types.js +2 -0
- package/esm2022/lib/modal/modal.types.js.map +1 -0
- package/esm2022/lib/profile-stats/profile-stats.component.js +6 -2
- package/esm2022/lib/profile-stats/profile-stats.component.js.map +1 -1
- package/esm2022/lib/profile-stats/profile-stats.types.js.map +1 -1
- package/esm2022/lib/rating-display/index.js +2 -0
- package/esm2022/lib/rating-display/index.js.map +1 -0
- package/esm2022/lib/rating-display/rating-display.component.js +24 -0
- package/esm2022/lib/rating-display/rating-display.component.js.map +1 -0
- package/esm2022/lib/rating-stars/index.js +2 -0
- package/esm2022/lib/rating-stars/index.js.map +1 -0
- package/esm2022/lib/rating-stars/rating-stars.component.js +33 -0
- package/esm2022/lib/rating-stars/rating-stars.component.js.map +1 -0
- package/esm2022/lib/select/index.js +1 -1
- package/esm2022/lib/select/index.js.map +1 -1
- package/esm2022/lib/select/select.component.js +31 -1
- package/esm2022/lib/select/select.component.js.map +1 -1
- package/esm2022/lib/select/select.types.js +2 -0
- package/esm2022/lib/select/select.types.js.map +1 -0
- package/esm2022/lib/snackbar/index.js.map +1 -1
- package/esm2022/lib/snackbar/snackbar.component.js +19 -2
- package/esm2022/lib/snackbar/snackbar.component.js.map +1 -1
- package/esm2022/lib/snackbar/snackbar.service.js +9 -0
- package/esm2022/lib/snackbar/snackbar.service.js.map +1 -1
- package/esm2022/lib/snackbar/snackbar.types.js +2 -0
- package/esm2022/lib/snackbar/{snackbar.model.js.map → snackbar.types.js.map} +1 -1
- package/esm2022/lib/spinner/index.js +2 -0
- package/esm2022/lib/spinner/index.js.map +1 -0
- package/esm2022/lib/spinner/spinner.component.js +22 -0
- package/esm2022/lib/spinner/spinner.component.js.map +1 -0
- package/esm2022/lib/stat-card/index.js.map +1 -1
- package/esm2022/lib/stat-card/stat-card.component.js +3 -0
- package/esm2022/lib/stat-card/stat-card.component.js.map +1 -1
- package/esm2022/lib/stat-card/stat-card.types.js +2 -0
- package/esm2022/lib/stat-card/stat-card.types.js.map +1 -0
- package/esm2022/lib/tab/c80-tab.component.js +19 -2
- package/esm2022/lib/tab/c80-tab.component.js.map +1 -1
- package/esm2022/lib/tab/c80-tab.types.js +2 -0
- package/esm2022/lib/tab/c80-tab.types.js.map +1 -0
- package/esm2022/lib/tab/directives/c80-tab-item.directive.js +3 -0
- package/esm2022/lib/tab/directives/c80-tab-item.directive.js.map +1 -1
- package/esm2022/lib/tab/directives/c80-tab-label.directive.js +3 -0
- 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/index.js +2 -0
- package/esm2022/lib/table/index.js.map +1 -1
- package/esm2022/lib/table/table-column-visibility.service.js +27 -34
- package/esm2022/lib/table/table-column-visibility.service.js.map +1 -1
- 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 +18 -10
- package/esm2022/lib/table/table-data-converter.service.js.map +1 -1
- package/esm2022/lib/table/table-data-utils.service.js +18 -4
- package/esm2022/lib/table/table-data-utils.service.js.map +1 -1
- package/esm2022/lib/table/table-dto-mapper.service.js +98 -0
- package/esm2022/lib/table/table-dto-mapper.service.js.map +1 -0
- package/esm2022/lib/table/table-pagination.service.js +79 -0
- package/esm2022/lib/table/table-pagination.service.js.map +1 -0
- package/esm2022/lib/table/table-selection.service.js +14 -3
- package/esm2022/lib/table/table-selection.service.js.map +1 -1
- package/esm2022/lib/table/table.component.js +124 -22
- package/esm2022/lib/table/table.component.js.map +1 -1
- package/esm2022/lib/table/table.types.js.map +1 -1
- package/esm2022/lib/table/table.utils.js +10 -2
- package/esm2022/lib/table/table.utils.js.map +1 -1
- package/index.d.ts +13 -8
- package/lib/action-list/action-list.component.d.ts +7 -0
- package/lib/action-list/action-list.types.d.ts +2 -1
- package/lib/card-level/card-level.component.d.ts +4 -1
- package/lib/error-notification/error-notification.component.d.ts +20 -0
- package/lib/error-notification/error-notification.types.d.ts +4 -0
- package/lib/error-notification/index.d.ts +2 -0
- package/lib/header/header.component.d.ts +7 -1
- package/lib/header/header.types.d.ts +2 -0
- package/lib/icon/icon.component.d.ts +8 -0
- package/lib/icon/icon.types.d.ts +2 -0
- package/lib/icon/icon.utils.d.ts +7 -0
- package/lib/icon/theme.service.d.ts +17 -0
- package/lib/info-list/info-list.component.d.ts +3 -0
- package/lib/input-field/input-field.component.d.ts +17 -0
- package/lib/input-search/c80-input-search.component.d.ts +16 -0
- package/lib/input-search/index.d.ts +1 -0
- package/lib/modal/index.d.ts +1 -0
- package/lib/modal/modal.component.d.ts +58 -16
- package/lib/modal/modal.service.d.ts +73 -4
- package/lib/modal/modal.types.d.ts +15 -0
- package/lib/profile-stats/profile-stats.component.d.ts +4 -0
- package/lib/profile-stats/profile-stats.types.d.ts +6 -2
- package/lib/rating-display/index.d.ts +1 -0
- package/lib/rating-display/rating-display.component.d.ts +12 -0
- package/lib/rating-stars/index.d.ts +1 -0
- package/lib/rating-stars/rating-stars.component.d.ts +19 -0
- package/lib/select/index.d.ts +1 -1
- package/lib/select/select.component.d.ts +29 -1
- package/lib/snackbar/index.d.ts +1 -1
- package/lib/snackbar/snackbar.component.d.ts +18 -1
- package/lib/snackbar/snackbar.service.d.ts +10 -1
- package/lib/spinner/index.d.ts +1 -0
- package/lib/spinner/spinner.component.d.ts +12 -0
- package/lib/stat-card/index.d.ts +1 -0
- package/lib/stat-card/stat-card.component.d.ts +4 -7
- package/lib/stat-card/stat-card.types.d.ts +7 -0
- package/lib/tab/c80-tab.component.d.ts +17 -0
- package/lib/tab/directives/c80-tab-item.directive.d.ts +3 -0
- package/lib/tab/directives/c80-tab-label.directive.d.ts +3 -0
- package/lib/tab/index.d.ts +1 -1
- package/lib/table/index.d.ts +2 -0
- package/lib/table/table-column-visibility.service.d.ts +19 -6
- package/lib/table/table-crud-state.service.d.ts +23 -13
- package/lib/table/table-data-converter.service.d.ts +2 -0
- package/lib/table/table-data-utils.service.d.ts +7 -0
- package/lib/table/table-dto-mapper.service.d.ts +34 -0
- package/lib/table/table-pagination.service.d.ts +41 -0
- package/lib/table/table-selection.service.d.ts +14 -12
- package/lib/table/table.component.d.ts +27 -3
- package/lib/table/table.types.d.ts +17 -1
- package/lib/table/table.utils.d.ts +4 -1
- package/package.json +1 -1
- package/esm2022/lib/select/select.model.js +0 -2
- package/esm2022/lib/select/select.model.js.map +0 -1
- package/esm2022/lib/snackbar/snackbar.model.js +0 -2
- package/esm2022/lib/tab/c80-tab.model.js +0 -2
- package/esm2022/lib/tab/c80-tab.model.js.map +0 -1
- /package/lib/select/{select.model.d.ts → select.types.d.ts} +0 -0
- /package/lib/snackbar/{snackbar.model.d.ts → snackbar.types.d.ts} +0 -0
- /package/lib/tab/{c80-tab.model.d.ts → c80-tab.types.d.ts} +0 -0
|
@@ -2,11 +2,17 @@ import { Component, computed, effect, inject, ChangeDetectionStrategy } from '@a
|
|
|
2
2
|
import { ModalService } from './modal.service';
|
|
3
3
|
import { IconComponent } from './../icon';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
5
8
|
export class ModalComponent {
|
|
6
9
|
modalService = inject(ModalService);
|
|
7
10
|
isOpen = this.modalService.modalState.isOpen;
|
|
8
11
|
config = this.modalService.modalState.config;
|
|
9
12
|
isVisible = computed(() => this.isOpen(), ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
10
16
|
constructor() {
|
|
11
17
|
effect(() => {
|
|
12
18
|
if (this.isOpen()) {
|
|
@@ -21,26 +27,49 @@ export class ModalComponent {
|
|
|
21
27
|
}
|
|
22
28
|
});
|
|
23
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Maneja la confirmación del modal
|
|
32
|
+
*/
|
|
24
33
|
onConfirm() {
|
|
25
34
|
this.modalService.handleResult({ action: 'confirm', confirmed: true });
|
|
26
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Maneja la cancelación del modal
|
|
38
|
+
*/
|
|
27
39
|
onCancel() {
|
|
28
40
|
this.modalService.handleResult({ action: 'cancel', confirmed: false });
|
|
29
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Maneja la respuesta afirmativa del modal
|
|
44
|
+
*/
|
|
30
45
|
onYes() {
|
|
31
46
|
this.modalService.handleResult({ action: 'yes', confirmed: true });
|
|
32
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Maneja la respuesta negativa del modal
|
|
50
|
+
*/
|
|
33
51
|
onNo() {
|
|
34
52
|
this.modalService.handleResult({ action: 'no', confirmed: false });
|
|
35
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Cierra el modal actual
|
|
56
|
+
*/
|
|
36
57
|
closeModal() {
|
|
37
58
|
this.modalService.closeModal();
|
|
38
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Maneja el clic en el backdrop del modal
|
|
62
|
+
* @param event - Evento de clic
|
|
63
|
+
*/
|
|
39
64
|
onBackdropClick(event) {
|
|
40
65
|
if (event.target === event.currentTarget) {
|
|
41
66
|
this.closeModal();
|
|
42
67
|
}
|
|
43
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
*
|
|
71
|
+
* @returns Clase CSS del botón primario según el tipo de modal
|
|
72
|
+
*/
|
|
44
73
|
getPrimaryButtonClass() {
|
|
45
74
|
const configValue = this.config();
|
|
46
75
|
switch (configValue.type) {
|
|
@@ -55,33 +84,61 @@ export class ModalComponent {
|
|
|
55
84
|
return 'btn-info';
|
|
56
85
|
}
|
|
57
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
*
|
|
89
|
+
* @returns true si debe mostrar botones Sí/No
|
|
90
|
+
*/
|
|
58
91
|
showYesNoButtons() {
|
|
59
92
|
return this.config().type === 'yesNo';
|
|
60
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
*
|
|
96
|
+
* @returns true si debe mostrar botones Confirmar/Cancelar
|
|
97
|
+
*/
|
|
61
98
|
showConfirmButtons() {
|
|
62
99
|
const type = this.config().type;
|
|
63
100
|
return type === 'confirm' || type === 'warning' || type === 'error';
|
|
64
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
*
|
|
104
|
+
* @returns true si debe mostrar botón OK
|
|
105
|
+
*/
|
|
65
106
|
showOkButton() {
|
|
66
107
|
return this.config().type === 'info';
|
|
67
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
*
|
|
111
|
+
* @returns Texto del botón de confirmación
|
|
112
|
+
*/
|
|
68
113
|
getConfirmText() {
|
|
69
114
|
return this.config().confirmText ?? 'Confirmar';
|
|
70
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
*
|
|
118
|
+
* @returns Texto del botón de cancelar
|
|
119
|
+
*/
|
|
71
120
|
getCancelText() {
|
|
72
121
|
return this.config().cancelText ?? 'Cancelar';
|
|
73
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
*
|
|
125
|
+
* @returns Texto del botón Sí
|
|
126
|
+
*/
|
|
74
127
|
getYesText() {
|
|
75
128
|
return this.config().yesText ?? 'Sí';
|
|
76
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
*
|
|
132
|
+
* @returns Texto del botón No
|
|
133
|
+
*/
|
|
77
134
|
getNoText() {
|
|
78
135
|
return this.config().noText ?? 'No';
|
|
79
136
|
}
|
|
80
137
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
81
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.10", type: ModalComponent, isStandalone: true, selector: "c80-modal", ngImport: i0, template: "<!-- Modal Backdrop -->\n@if (isOpen()) {\n<div class=\"modal-backdrop\" [class.show]=\"isVisible()\" tabindex=\"-1\" (click)=\"onBackdropClick($event)\" (keydown.escape)=\"closeModal()\">\n\n <!-- Modal Container -->\n <dialog class=\"modal-container\" [class.show]=\"isVisible()\" [attr.aria-labelledby]=\"'modal-title'\" [open]=\"isVisible()\">\n\n <!-- Modal Header -->\n <div class=\"modal-header\">\n <h4 class=\"modal-title\" id=\"modal-title\">{{ config().title }}</h4>\n <c80-icon [button]=\"true\" icon=\"close\" (iconClick)=\"closeModal()\" title=\"Cerrar\"
|
|
138
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.10", type: ModalComponent, isStandalone: true, selector: "c80-modal", ngImport: i0, template: "<!-- Modal Backdrop -->\n@if (isOpen()) {\n<div class=\"modal-backdrop\" [class.show]=\"isVisible()\" tabindex=\"-1\" (click)=\"onBackdropClick($event)\" (keydown.escape)=\"closeModal()\">\n\n <!-- Modal Container -->\n <dialog class=\"modal-container\" [class.show]=\"isVisible()\" [attr.aria-labelledby]=\"'modal-title'\" [open]=\"isVisible()\">\n\n <!-- Modal Header -->\n <div class=\"modal-header\">\n <h4 class=\"modal-title\" id=\"modal-title\">{{ config().title }}</h4>\n <c80-icon [button]=\"true\" icon=\"close\" (iconClick)=\"closeModal()\" title=\"Cerrar\" />\n </div>\n\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <p class=\"modal-message\">{{ config().message }}</p>\n </div>\n\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n\n <!-- Info Modal - Solo OK -->\n @if (showOkButton()) {\n <c80-icon [button]=\"true\" icon=\"check\" textRight=\"OK\" (iconClick)=\"onConfirm()\" [border]=\"true\" />\n }\n\n <!-- Yes/No Modal -->\n @if (showYesNoButtons()) {\n <c80-icon [button]=\"true\" icon=\"check\" [textRight]=\"getYesText()\" (iconClick)=\"onYes()\" [border]=\"true\" />\n <c80-icon [button]=\"true\" icon=\"cancel\" [textRight]=\"getNoText()\" (iconClick)=\"onNo()\" [border]=\"true\" />\n }\n\n <!-- Confirm Modal -->\n @if (showConfirmButtons()) {\n <c80-icon [button]=\"true\" icon=\"check\" [textRight]=\"getConfirmText()\" (iconClick)=\"onConfirm()\" [border]=\"true\" />\n <c80-icon [button]=\"true\" icon=\"cancel\" [textRight]=\"getCancelText()\" (iconClick)=\"onCancel()\" [border]=\"true\" />\n }\n\n </div>\n </dialog>\n</div>\n}", styles: [".modal-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:1100;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s ease-in-out;outline:none}.modal-backdrop.show{opacity:1}.modal-container{background:var(--color-bg-primary);border-radius:8px;box-shadow:0 4px 20px #00000026;border:1px solid var(--color-border-default);max-width:400px;width:90%;max-height:90vh;overflow:hidden;transform:scale(.9) translateY(-10px);transition:all .15s ease-out;position:relative;padding:0}.modal-container.show{transform:scale(1) translateY(0)}.modal-container::backdrop{background:transparent}.modal-header{display:flex;align-items:center;gap:8px;padding:16px 20px 12px;border-bottom:1px solid var(--color-border-default);background:var(--color-bg-secondary)}.modal-header .modal-title{flex:1;margin:0;font-size:16px;font-weight:600;color:var(--color-text-primary);line-height:1.3}.modal-body{padding:16px 20px}.modal-body .modal-message{margin:0;font-size:14px;line-height:1.5;color:var(--color-text-primary);white-space:pre-line}.modal-footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 20px 16px;background:var(--color-bg-secondary);border-top:1px solid var(--color-border-default)}@media(max-width:768px){.modal-container{width:95%;margin:10px}.modal-header{padding:12px 16px 8px}.modal-header .modal-title{font-size:15px}.modal-body{padding:12px 16px}.modal-body .modal-message{font-size:13px}.modal-footer{padding:8px 16px 12px;flex-direction:column}}\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 });
|
|
82
139
|
}
|
|
83
140
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ModalComponent, decorators: [{
|
|
84
141
|
type: Component,
|
|
85
|
-
args: [{ selector: 'c80-modal', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Modal Backdrop -->\n@if (isOpen()) {\n<div class=\"modal-backdrop\" [class.show]=\"isVisible()\" tabindex=\"-1\" (click)=\"onBackdropClick($event)\" (keydown.escape)=\"closeModal()\">\n\n <!-- Modal Container -->\n <dialog class=\"modal-container\" [class.show]=\"isVisible()\" [attr.aria-labelledby]=\"'modal-title'\" [open]=\"isVisible()\">\n\n <!-- Modal Header -->\n <div class=\"modal-header\">\n <h4 class=\"modal-title\" id=\"modal-title\">{{ config().title }}</h4>\n <c80-icon [button]=\"true\" icon=\"close\" (iconClick)=\"closeModal()\" title=\"Cerrar\"
|
|
142
|
+
args: [{ selector: 'c80-modal', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Modal Backdrop -->\n@if (isOpen()) {\n<div class=\"modal-backdrop\" [class.show]=\"isVisible()\" tabindex=\"-1\" (click)=\"onBackdropClick($event)\" (keydown.escape)=\"closeModal()\">\n\n <!-- Modal Container -->\n <dialog class=\"modal-container\" [class.show]=\"isVisible()\" [attr.aria-labelledby]=\"'modal-title'\" [open]=\"isVisible()\">\n\n <!-- Modal Header -->\n <div class=\"modal-header\">\n <h4 class=\"modal-title\" id=\"modal-title\">{{ config().title }}</h4>\n <c80-icon [button]=\"true\" icon=\"close\" (iconClick)=\"closeModal()\" title=\"Cerrar\" />\n </div>\n\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <p class=\"modal-message\">{{ config().message }}</p>\n </div>\n\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n\n <!-- Info Modal - Solo OK -->\n @if (showOkButton()) {\n <c80-icon [button]=\"true\" icon=\"check\" textRight=\"OK\" (iconClick)=\"onConfirm()\" [border]=\"true\" />\n }\n\n <!-- Yes/No Modal -->\n @if (showYesNoButtons()) {\n <c80-icon [button]=\"true\" icon=\"check\" [textRight]=\"getYesText()\" (iconClick)=\"onYes()\" [border]=\"true\" />\n <c80-icon [button]=\"true\" icon=\"cancel\" [textRight]=\"getNoText()\" (iconClick)=\"onNo()\" [border]=\"true\" />\n }\n\n <!-- Confirm Modal -->\n @if (showConfirmButtons()) {\n <c80-icon [button]=\"true\" icon=\"check\" [textRight]=\"getConfirmText()\" (iconClick)=\"onConfirm()\" [border]=\"true\" />\n <c80-icon [button]=\"true\" icon=\"cancel\" [textRight]=\"getCancelText()\" (iconClick)=\"onCancel()\" [border]=\"true\" />\n }\n\n </div>\n </dialog>\n</div>\n}", styles: [".modal-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:1100;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s ease-in-out;outline:none}.modal-backdrop.show{opacity:1}.modal-container{background:var(--color-bg-primary);border-radius:8px;box-shadow:0 4px 20px #00000026;border:1px solid var(--color-border-default);max-width:400px;width:90%;max-height:90vh;overflow:hidden;transform:scale(.9) translateY(-10px);transition:all .15s ease-out;position:relative;padding:0}.modal-container.show{transform:scale(1) translateY(0)}.modal-container::backdrop{background:transparent}.modal-header{display:flex;align-items:center;gap:8px;padding:16px 20px 12px;border-bottom:1px solid var(--color-border-default);background:var(--color-bg-secondary)}.modal-header .modal-title{flex:1;margin:0;font-size:16px;font-weight:600;color:var(--color-text-primary);line-height:1.3}.modal-body{padding:16px 20px}.modal-body .modal-message{margin:0;font-size:14px;line-height:1.5;color:var(--color-text-primary);white-space:pre-line}.modal-footer{display:flex;justify-content:flex-end;gap:8px;padding:12px 20px 16px;background:var(--color-bg-secondary);border-top:1px solid var(--color-border-default)}@media(max-width:768px){.modal-container{width:95%;margin:10px}.modal-header{padding:12px 16px 8px}.modal-header .modal-title{font-size:15px}.modal-body{padding:12px 16px}.modal-body .modal-message{font-size:13px}.modal-footer{padding:8px 16px 12px;flex-direction:column}}\n"] }]
|
|
86
143
|
}], ctorParameters: () => [] });
|
|
87
144
|
//# sourceMappingURL=modal.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/modal/modal.component.ts","../../../../../libs/ui/src/lib/modal/modal.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;;
|
|
1
|
+
{"version":3,"file":"modal.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/modal/modal.component.ts","../../../../../libs/ui/src/lib/modal/modal.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;;AAE1C;;GAEG;AAUH,MAAM,OAAO,cAAc;IACR,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IAE5C,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC;IAC7C,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC;IAC7C,SAAS,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,qDAAC,CAAC;IAEnD;;OAEG;IACH;QACE,MAAM,CAAC,GAAG,EAAE;YACV,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;gBAClB,iDAAiD;gBACjD,sBAAsB;gBACtB,UAAU,CAAC,GAAG,EAAE;oBACd,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CACrC,iBAAiB,CACH,CAAC;oBACjB,IAAI,QAAQ,EAAE,CAAC;wBACb,QAAQ,CAAC,KAAK,EAAE,CAAC;oBACnB,CAAC;gBACH,CAAC,EAAE,GAAG,CAAC,CAAC;YACV,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,SAAS;QACP,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;IACjC,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,KAAY;QAC1B,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,aAAa,EAAE,CAAC;YACzC,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,qBAAqB;QACnB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAClC,QAAQ,WAAW,CAAC,IAAI,EAAE,CAAC;YACzB,KAAK,SAAS;gBACZ,OAAO,aAAa,CAAC;YACvB,KAAK,OAAO;gBACV,OAAO,YAAY,CAAC;YACtB,KAAK,SAAS,CAAC;YACf,KAAK,OAAO;gBACV,OAAO,aAAa,CAAC;YACvB;gBACE,OAAO,UAAU,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC;IACxC,CAAC;IAED;;;OAGG;IACH,kBAAkB;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC;QAChC,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,OAAO,CAAC;IACtE,CAAC;IAED;;;OAGG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,WAAW,IAAI,WAAW,CAAC;IAClD,CAAC;IAED;;;OAGG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,IAAI,UAAU,CAAC;IAChD,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,IAAI,IAAI,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,IAAI,IAAI,CAAC;IACtC,CAAC;wGAlJU,cAAc;4FAAd,cAAc,qEChB3B,2pDAyCC,unDD9BW,aAAa;;4FAKZ,cAAc;kBAT1B,SAAS;+BAEE,WAAW,cACT,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { Component, computed, effect, inject, ChangeDetectionStrategy } from '@angular/core';\nimport { ModalService } from './modal.service';\nimport { IconComponent } from './../icon';\n\n/**\n *\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'c80-modal',\n standalone: true,\n imports: [IconComponent],\n templateUrl: './modal.component.html',\n styleUrl: './modal.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ModalComponent {\n private readonly modalService = inject(ModalService);\n\n readonly isOpen = this.modalService.modalState.isOpen;\n readonly config = this.modalService.modalState.config;\n readonly isVisible = computed(() => this.isOpen());\n\n /**\n *\n */\n constructor() {\n effect(() => {\n if (this.isOpen()) {\n // Auto-focus modal when opened for accessibility\n /* v8 ignore next 8 */\n setTimeout(() => {\n const backdrop = document.querySelector(\n '.modal-backdrop'\n ) as HTMLElement;\n if (backdrop) {\n backdrop.focus();\n }\n }, 100);\n }\n });\n }\n\n /**\n * Maneja la confirmación del modal\n */\n onConfirm(): void {\n this.modalService.handleResult({ action: 'confirm', confirmed: true });\n }\n\n /**\n * Maneja la cancelación del modal\n */\n onCancel(): void {\n this.modalService.handleResult({ action: 'cancel', confirmed: false });\n }\n\n /**\n * Maneja la respuesta afirmativa del modal\n */\n onYes(): void {\n this.modalService.handleResult({ action: 'yes', confirmed: true });\n }\n\n /**\n * Maneja la respuesta negativa del modal\n */\n onNo(): void {\n this.modalService.handleResult({ action: 'no', confirmed: false });\n }\n\n /**\n * Cierra el modal actual\n */\n closeModal(): void {\n this.modalService.closeModal();\n }\n\n /**\n * Maneja el clic en el backdrop del modal\n * @param event - Evento de clic\n */\n onBackdropClick(event: Event): void {\n if (event.target === event.currentTarget) {\n this.closeModal();\n }\n }\n\n /**\n *\n * @returns Clase CSS del botón primario según el tipo de modal\n */\n getPrimaryButtonClass(): string {\n const configValue = this.config();\n switch (configValue.type) {\n case 'warning':\n return 'btn-warning';\n case 'error':\n return 'btn-danger';\n case 'confirm':\n case 'yesNo':\n return 'btn-primary';\n default:\n return 'btn-info';\n }\n }\n\n /**\n *\n * @returns true si debe mostrar botones Sí/No\n */\n showYesNoButtons(): boolean {\n return this.config().type === 'yesNo';\n }\n\n /**\n *\n * @returns true si debe mostrar botones Confirmar/Cancelar\n */\n showConfirmButtons(): boolean {\n const type = this.config().type;\n return type === 'confirm' || type === 'warning' || type === 'error';\n }\n\n /**\n *\n * @returns true si debe mostrar botón OK\n */\n showOkButton(): boolean {\n return this.config().type === 'info';\n }\n\n /**\n *\n * @returns Texto del botón de confirmación\n */\n getConfirmText(): string {\n return this.config().confirmText ?? 'Confirmar';\n }\n\n /**\n *\n * @returns Texto del botón de cancelar\n */\n getCancelText(): string {\n return this.config().cancelText ?? 'Cancelar';\n }\n\n /**\n *\n * @returns Texto del botón Sí\n */\n getYesText(): string {\n return this.config().yesText ?? 'Sí';\n }\n\n /**\n *\n * @returns Texto del botón No\n */\n getNoText(): string {\n return this.config().noText ?? 'No';\n }\n}\n","<!-- Modal Backdrop -->\n@if (isOpen()) {\n<div class=\"modal-backdrop\" [class.show]=\"isVisible()\" tabindex=\"-1\" (click)=\"onBackdropClick($event)\" (keydown.escape)=\"closeModal()\">\n\n <!-- Modal Container -->\n <dialog class=\"modal-container\" [class.show]=\"isVisible()\" [attr.aria-labelledby]=\"'modal-title'\" [open]=\"isVisible()\">\n\n <!-- Modal Header -->\n <div class=\"modal-header\">\n <h4 class=\"modal-title\" id=\"modal-title\">{{ config().title }}</h4>\n <c80-icon [button]=\"true\" icon=\"close\" (iconClick)=\"closeModal()\" title=\"Cerrar\" />\n </div>\n\n <!-- Modal Body -->\n <div class=\"modal-body\">\n <p class=\"modal-message\">{{ config().message }}</p>\n </div>\n\n <!-- Modal Footer -->\n <div class=\"modal-footer\">\n\n <!-- Info Modal - Solo OK -->\n @if (showOkButton()) {\n <c80-icon [button]=\"true\" icon=\"check\" textRight=\"OK\" (iconClick)=\"onConfirm()\" [border]=\"true\" />\n }\n\n <!-- Yes/No Modal -->\n @if (showYesNoButtons()) {\n <c80-icon [button]=\"true\" icon=\"check\" [textRight]=\"getYesText()\" (iconClick)=\"onYes()\" [border]=\"true\" />\n <c80-icon [button]=\"true\" icon=\"cancel\" [textRight]=\"getNoText()\" (iconClick)=\"onNo()\" [border]=\"true\" />\n }\n\n <!-- Confirm Modal -->\n @if (showConfirmButtons()) {\n <c80-icon [button]=\"true\" icon=\"check\" [textRight]=\"getConfirmText()\" (iconClick)=\"onConfirm()\" [border]=\"true\" />\n <c80-icon [button]=\"true\" icon=\"cancel\" [textRight]=\"getCancelText()\" (iconClick)=\"onCancel()\" [border]=\"true\" />\n }\n\n </div>\n </dialog>\n</div>\n}"]}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Injectable, signal } from '@angular/core';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
3
6
|
export class ModalService {
|
|
4
7
|
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
5
8
|
config = signal({
|
|
@@ -12,6 +15,10 @@ export class ModalService {
|
|
|
12
15
|
isOpen: this.isOpen.asReadonly(),
|
|
13
16
|
config: this.config.asReadonly(),
|
|
14
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @param config
|
|
21
|
+
*/
|
|
15
22
|
async showModal(config) {
|
|
16
23
|
this.config.set(config);
|
|
17
24
|
this.isOpen.set(true);
|
|
@@ -19,7 +26,17 @@ export class ModalService {
|
|
|
19
26
|
this.resolvePromise = resolve;
|
|
20
27
|
});
|
|
21
28
|
}
|
|
22
|
-
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @param options
|
|
32
|
+
* @param options.title
|
|
33
|
+
* @param options.message
|
|
34
|
+
* @param options.confirmText
|
|
35
|
+
* @param options.cancelText
|
|
36
|
+
* @returns Promise que resuelve true si se confirmó
|
|
37
|
+
*/
|
|
38
|
+
async confirm(options) {
|
|
39
|
+
const { title, message, confirmText = 'Confirmar', cancelText = 'Cancelar' } = options;
|
|
23
40
|
return this.showModal({
|
|
24
41
|
title,
|
|
25
42
|
message,
|
|
@@ -28,7 +45,17 @@ export class ModalService {
|
|
|
28
45
|
cancelText,
|
|
29
46
|
}).then((result) => result.confirmed);
|
|
30
47
|
}
|
|
31
|
-
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param options
|
|
51
|
+
* @param options.title
|
|
52
|
+
* @param options.message
|
|
53
|
+
* @param options.yesText
|
|
54
|
+
* @param options.noText
|
|
55
|
+
* @returns Promise que resuelve true si se eligió Sí
|
|
56
|
+
*/
|
|
57
|
+
async yesNo(options) {
|
|
58
|
+
const { title, message, yesText = 'Sí', noText = 'No' } = options;
|
|
32
59
|
return this.showModal({
|
|
33
60
|
title,
|
|
34
61
|
message,
|
|
@@ -37,6 +64,12 @@ export class ModalService {
|
|
|
37
64
|
noText,
|
|
38
65
|
}).then((result) => result.action === 'yes');
|
|
39
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @param title
|
|
70
|
+
* @param message
|
|
71
|
+
* @returns Promise que resuelve cuando se cierra el modal
|
|
72
|
+
*/
|
|
40
73
|
async info(title, message) {
|
|
41
74
|
return this.showModal({
|
|
42
75
|
title,
|
|
@@ -44,7 +77,17 @@ export class ModalService {
|
|
|
44
77
|
type: 'info',
|
|
45
78
|
}).then(() => void 0);
|
|
46
79
|
}
|
|
47
|
-
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* @param options
|
|
83
|
+
* @param options.title
|
|
84
|
+
* @param options.message
|
|
85
|
+
* @param options.confirmText
|
|
86
|
+
* @param options.cancelText
|
|
87
|
+
* @returns Promise que resuelve true si se confirmó
|
|
88
|
+
*/
|
|
89
|
+
async warning(options) {
|
|
90
|
+
const { title, message, confirmText = 'Entendido', cancelText = 'Cancelar' } = options;
|
|
48
91
|
return this.showModal({
|
|
49
92
|
title,
|
|
50
93
|
message,
|
|
@@ -53,6 +96,13 @@ export class ModalService {
|
|
|
53
96
|
cancelText,
|
|
54
97
|
}).then((result) => result.confirmed);
|
|
55
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
*
|
|
101
|
+
* @param title
|
|
102
|
+
* @param message
|
|
103
|
+
* @param confirmText
|
|
104
|
+
* @returns Promise que resuelve true si se confirmó
|
|
105
|
+
*/
|
|
56
106
|
async error(title, message, confirmText = 'Entendido') {
|
|
57
107
|
return this.showModal({
|
|
58
108
|
title,
|
|
@@ -61,6 +111,10 @@ export class ModalService {
|
|
|
61
111
|
confirmText,
|
|
62
112
|
}).then(() => void 0);
|
|
63
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Maneja el resultado del modal y resuelve la promesa
|
|
116
|
+
* @param result - Resultado de la acción del modal
|
|
117
|
+
*/
|
|
64
118
|
handleResult(result) {
|
|
65
119
|
if (this.resolvePromise) {
|
|
66
120
|
this.resolvePromise(result);
|
|
@@ -68,6 +122,9 @@ export class ModalService {
|
|
|
68
122
|
}
|
|
69
123
|
this.closeModal();
|
|
70
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Cierra el modal actual
|
|
127
|
+
*/
|
|
71
128
|
closeModal() {
|
|
72
129
|
this.isOpen.set(false);
|
|
73
130
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.service.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/modal/modal.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;
|
|
1
|
+
{"version":3,"file":"modal.service.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/modal/modal.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, signal } from '@angular/core';\nimport type { ModalConfig, ModalResult } from './modal.types';\n\n/**\n *\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class ModalService {\n private readonly isOpen = signal(false);\n private readonly config = signal<ModalConfig>({\n title: '',\n message: '',\n type: 'info',\n });\n\n private resolvePromise?: (result: ModalResult) => void;\n\n readonly modalState = {\n isOpen: this.isOpen.asReadonly(),\n config: this.config.asReadonly(),\n };\n\n /**\n *\n * @param config\n */\n async showModal(config: ModalConfig): Promise<ModalResult> {\n this.config.set(config);\n this.isOpen.set(true);\n\n return new Promise<ModalResult>((resolve) => {\n this.resolvePromise = resolve;\n });\n }\n\n /**\n *\n * @param options\n * @param options.title\n * @param options.message\n * @param options.confirmText\n * @param options.cancelText\n * @returns Promise que resuelve true si se confirmó\n */\n async confirm(options: {\n title: string;\n message: string;\n confirmText?: string;\n cancelText?: string;\n }): Promise<boolean> {\n const { title, message, confirmText = 'Confirmar', cancelText = 'Cancelar' } = options;\n return this.showModal({\n title,\n message,\n type: 'confirm',\n confirmText,\n cancelText,\n }).then((result) => result.confirmed);\n }\n\n /**\n *\n * @param options\n * @param options.title\n * @param options.message\n * @param options.yesText\n * @param options.noText\n * @returns Promise que resuelve true si se eligió Sí\n */\n async yesNo(options: {\n title: string;\n message: string;\n yesText?: string;\n noText?: string;\n }): Promise<boolean> {\n const { title, message, yesText = 'Sí', noText = 'No' } = options;\n return this.showModal({\n title,\n message,\n type: 'yesNo',\n yesText,\n noText,\n }).then((result) => result.action === 'yes');\n }\n\n /**\n *\n * @param title\n * @param message\n * @returns Promise que resuelve cuando se cierra el modal\n */\n async info(title: string, message: string): Promise<void> {\n return this.showModal({\n title,\n message,\n type: 'info',\n }).then(() => void 0);\n }\n\n /**\n *\n * @param options\n * @param options.title\n * @param options.message\n * @param options.confirmText\n * @param options.cancelText\n * @returns Promise que resuelve true si se confirmó\n */\n async warning(options: {\n title: string;\n message: string;\n confirmText?: string;\n cancelText?: string;\n }): Promise<boolean> {\n const { title, message, confirmText = 'Entendido', cancelText = 'Cancelar' } = options;\n return this.showModal({\n title,\n message,\n type: 'warning',\n confirmText,\n cancelText,\n }).then((result) => result.confirmed);\n }\n\n /**\n *\n * @param title\n * @param message\n * @param confirmText\n * @returns Promise que resuelve true si se confirmó\n */\n async error(\n title: string,\n message: string,\n confirmText = 'Entendido'\n ): Promise<void> {\n return this.showModal({\n title,\n message,\n type: 'error',\n confirmText,\n }).then(() => void 0);\n }\n\n /**\n * Maneja el resultado del modal y resuelve la promesa\n * @param result - Resultado de la acción del modal\n */\n handleResult(result: ModalResult): void {\n if (this.resolvePromise) {\n this.resolvePromise(result);\n this.resolvePromise = undefined;\n }\n this.closeModal();\n }\n\n /**\n * Cierra el modal actual\n */\n closeModal(): void {\n this.isOpen.set(false);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal.types.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/modal/modal.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ModalType = 'info' | 'confirm' | 'yesNo' | 'warning' | 'error';\n\nexport interface ModalConfig {\n title: string;\n message: string;\n type?: ModalType;\n confirmText?: string;\n cancelText?: string;\n yesText?: string;\n noText?: string;\n showCancel?: boolean;\n}\n\nexport interface ModalResult {\n action: 'confirm' | 'cancel' | 'yes' | 'no';\n confirmed: boolean;\n}\n"]}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Componente para mostrar estadísticas del usuario
|
|
5
|
+
* Soporta valores con etiquetas o botones de acción
|
|
6
|
+
*/
|
|
3
7
|
export class ProfileStatsComponent {
|
|
4
8
|
stats = input.required(...(ngDevMode ? [{ debugName: "stats" }] : []));
|
|
5
9
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ProfileStatsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.10", type: ProfileStatsComponent, isStandalone: true, selector: "c80-profile-stats", inputs: { stats: { classPropertyName: "stats", publicName: "stats", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"stats\">\n @for (stat of stats(); track $index) {\n <div class=\"stats__item\">\n <span class=\"stats__value\">{{ stat.value }}</span>\n <span class=\"stats__label\">{{ stat.label }}</span>\n </div>\n }\n</div>", styles: [".stats{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--spacing-md);text-align:center}.stats__item{display:flex;flex-direction:column;align-items:center;gap:var(--spacing-xs)}.stats__value{font-size:1.25rem;font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:1}.stats__label{font-size:.8125rem;color:var(--color-text-secondary);text-transform:lowercase}@media(max-width:768px){.stats{gap:var(--spacing-sm)}.stats__value{font-size:1.125rem}.stats__label{font-size:.75rem}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.10", type: ProfileStatsComponent, isStandalone: true, selector: "c80-profile-stats", inputs: { stats: { classPropertyName: "stats", publicName: "stats", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"stats\">\n @for (stat of stats(); track $index) {\n <div class=\"stats__item\" [class.stats__item--centered]=\"!stat.label && !stat.button\">\n <span class=\"stats__value\">{{ stat.value }}</span>\n @if (stat.button) {\n <button class=\"stats__button\" (click)=\"stat.button.onClick()\">\n {{ stat.button.text }}\n </button>\n } @else if (stat.label) {\n <span class=\"stats__label\">{{ stat.label }}</span>\n }\n </div>\n }\n</div>", styles: [".stats{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--spacing-md);text-align:center}.stats__item{display:flex;flex-direction:column;align-items:center;gap:var(--spacing-xs)}.stats__item--centered{justify-content:center}.stats__value{font-size:1.25rem;font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:1}.stats__label{font-size:.8125rem;color:var(--color-text-secondary);text-transform:lowercase}.stats__button{padding:3px 20%;font-size:.8125rem;font-weight:700;color:var(--color-primary);background:transparent;border:1px solid var(--color-primary);border-radius:var(--radius-sm);cursor:pointer;transition:all .2s ease;text-transform:lowercase}@media(max-width:768px){.stats{gap:var(--spacing-sm)}.stats__value{font-size:1.125rem}.stats__label{font-size:.75rem}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7
11
|
}
|
|
8
12
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ProfileStatsComponent, decorators: [{
|
|
9
13
|
type: Component,
|
|
10
|
-
args: [{ selector: 'c80-profile-stats', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"stats\">\n @for (stat of stats(); track $index) {\n <div class=\"stats__item\">\n <span class=\"stats__value\">{{ stat.value }}</span>\n <span class=\"stats__label\">{{ stat.label }}</span>\n </div>\n }\n</div>", styles: [".stats{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--spacing-md);text-align:center}.stats__item{display:flex;flex-direction:column;align-items:center;gap:var(--spacing-xs)}.stats__value{font-size:1.25rem;font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:1}.stats__label{font-size:.8125rem;color:var(--color-text-secondary);text-transform:lowercase}@media(max-width:768px){.stats{gap:var(--spacing-sm)}.stats__value{font-size:1.125rem}.stats__label{font-size:.75rem}}\n"] }]
|
|
14
|
+
args: [{ selector: 'c80-profile-stats', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"stats\">\n @for (stat of stats(); track $index) {\n <div class=\"stats__item\" [class.stats__item--centered]=\"!stat.label && !stat.button\">\n <span class=\"stats__value\">{{ stat.value }}</span>\n @if (stat.button) {\n <button class=\"stats__button\" (click)=\"stat.button.onClick()\">\n {{ stat.button.text }}\n </button>\n } @else if (stat.label) {\n <span class=\"stats__label\">{{ stat.label }}</span>\n }\n </div>\n }\n</div>", styles: [".stats{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--spacing-md);text-align:center}.stats__item{display:flex;flex-direction:column;align-items:center;gap:var(--spacing-xs)}.stats__item--centered{justify-content:center}.stats__value{font-size:1.25rem;font-weight:var(--font-weight-bold);color:var(--color-text-primary);line-height:1}.stats__label{font-size:.8125rem;color:var(--color-text-secondary);text-transform:lowercase}.stats__button{padding:3px 20%;font-size:.8125rem;font-weight:700;color:var(--color-primary);background:transparent;border:1px solid var(--color-primary);border-radius:var(--radius-sm);cursor:pointer;transition:all .2s ease;text-transform:lowercase}@media(max-width:768px){.stats{gap:var(--spacing-sm)}.stats__value{font-size:1.125rem}.stats__label{font-size:.75rem}}\n"] }]
|
|
11
15
|
}], propDecorators: { stats: [{ type: i0.Input, args: [{ isSignal: true, alias: "stats", required: true }] }] } });
|
|
12
16
|
//# sourceMappingURL=profile-stats.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-stats.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/profile-stats/profile-stats.component.ts","../../../../../libs/ui/src/lib/profile-stats/profile-stats.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;;
|
|
1
|
+
{"version":3,"file":"profile-stats.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/profile-stats/profile-stats.component.ts","../../../../../libs/ui/src/lib/profile-stats/profile-stats.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;;AAG1E;;;GAGG;AASH,MAAM,OAAO,qBAAqB;IAC9B,KAAK,GAAG,KAAK,CAAC,QAAQ,gDAAc,CAAC;wGAD5B,qBAAqB;4FAArB,qBAAqB,gNCflC,ugBAaM;;4FDEO,qBAAqB;kBARjC,SAAS;+BAEI,mBAAmB,cACjB,IAAI,mBAGC,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\nimport type { StatItem } from './profile-stats.types';\n\n/**\n * Componente para mostrar estadísticas del usuario\n * Soporta valores con etiquetas o botones de acción\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'c80-profile-stats',\n standalone: true,\n templateUrl: './profile-stats.component.html',\n styleUrl: './profile-stats.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class ProfileStatsComponent {\n stats = input.required<StatItem[]>();\n}","<div class=\"stats\">\n @for (stat of stats(); track $index) {\n <div class=\"stats__item\" [class.stats__item--centered]=\"!stat.label && !stat.button\">\n <span class=\"stats__value\">{{ stat.value }}</span>\n @if (stat.button) {\n <button class=\"stats__button\" (click)=\"stat.button.onClick()\">\n {{ stat.button.text }}\n </button>\n } @else if (stat.label) {\n <span class=\"stats__label\">{{ stat.label }}</span>\n }\n </div>\n }\n</div>"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-stats.types.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/profile-stats/profile-stats.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface StatItem {\n label
|
|
1
|
+
{"version":3,"file":"profile-stats.types.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/profile-stats/profile-stats.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface StatItem {\n value?: number | string;\n label?: string;\n button?: {\n text: string;\n onClick: () => void;\n };\n}"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/rating-display/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC","sourcesContent":["export * from './rating-display.component';\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
2
|
+
import { IconComponent } from '../icon';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
export class RatingDisplayComponent {
|
|
8
|
+
rating = input(0, ...(ngDevMode ? [{ debugName: "rating" }] : []));
|
|
9
|
+
size = input(0.1, ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
10
|
+
spacing = input(-22, ...(ngDevMode ? [{ debugName: "spacing" }] : []));
|
|
11
|
+
stars = computed(() => {
|
|
12
|
+
const rating = Math.round(this.rating());
|
|
13
|
+
return Array.from({ length: rating });
|
|
14
|
+
}, ...(ngDevMode ? [{ debugName: "stars" }] : []));
|
|
15
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: RatingDisplayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.10", type: RatingDisplayComponent, isStandalone: true, selector: "c80-rating-display", inputs: { rating: { classPropertyName: "rating", publicName: "rating", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, spacing: { classPropertyName: "spacing", publicName: "spacing", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--spacing.px": "spacing()" } }, ngImport: i0, template: "<div class=\"rating-display\">\n @for (star of stars(); track $index) {\n <c80-icon icon=\"starFilled\" [size]=\"size()\" color=\"warn\" class=\"rating-display__star\" />\n }\n</div>", styles: [":host{--spacing: -22px}.rating-display{display:flex;align-items:center;pointer-events:none}.rating-display__star{margin-left:var(--spacing)}.rating-display__star:first-child{margin-left: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 });
|
|
17
|
+
}
|
|
18
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: RatingDisplayComponent, decorators: [{
|
|
19
|
+
type: Component,
|
|
20
|
+
args: [{ selector: 'c80-rating-display', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
21
|
+
'[style.--spacing.px]': 'spacing()'
|
|
22
|
+
}, template: "<div class=\"rating-display\">\n @for (star of stars(); track $index) {\n <c80-icon icon=\"starFilled\" [size]=\"size()\" color=\"warn\" class=\"rating-display__star\" />\n }\n</div>", styles: [":host{--spacing: -22px}.rating-display{display:flex;align-items:center;pointer-events:none}.rating-display__star{margin-left:var(--spacing)}.rating-display__star:first-child{margin-left:0}\n"] }]
|
|
23
|
+
}], propDecorators: { rating: [{ type: i0.Input, args: [{ isSignal: true, alias: "rating", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], spacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "spacing", required: false }] }] } });
|
|
24
|
+
//# sourceMappingURL=rating-display.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rating-display.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/rating-display/rating-display.component.ts","../../../../../libs/ui/src/lib/rating-display/rating-display.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAExC;;GAEG;AAaH,MAAM,OAAO,sBAAsB;IAC/B,MAAM,GAAG,KAAK,CAAS,CAAC,kDAAC,CAAC;IAC1B,IAAI,GAAG,KAAK,CAAS,GAAG,gDAAC,CAAC;IAC1B,OAAO,GAAG,KAAK,CAAS,CAAC,EAAE,mDAAC,CAAC;IAEV,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC,iDAAC,CAAC;wGARM,sBAAsB;4FAAtB,sBAAsB,qgBClBnC,iMAIM,wPDMQ,aAAa;;4FAQd,sBAAsB;kBAZlC,SAAS;+BAEI,oBAAoB,cAClB,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM,QACzC;wBACF,sBAAsB,EAAE,WAAW;qBACtC","sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\nimport { IconComponent } from '../icon';\n\n/**\n *\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'c80-rating-display',\n standalone: true,\n imports: [IconComponent],\n templateUrl: './rating-display.component.html',\n styleUrl: './rating-display.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[style.--spacing.px]': 'spacing()'\n }\n})\nexport class RatingDisplayComponent {\n rating = input<number>(0);\n size = input<number>(0.1);\n spacing = input<number>(-22);\n\n protected readonly stars = computed(() => {\n const rating = Math.round(this.rating());\n return Array.from({ length: rating });\n });\n}\n","<div class=\"rating-display\">\n @for (star of stars(); track $index) {\n <c80-icon icon=\"starFilled\" [size]=\"size()\" color=\"warn\" class=\"rating-display__star\" />\n }\n</div>"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/rating-stars/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC","sourcesContent":["export * from './rating-stars.component';\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';
|
|
2
|
+
import { IconComponent } from '../icon';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
export class RatingStarsComponent {
|
|
8
|
+
rating = input(0, ...(ngDevMode ? [{ debugName: "rating" }] : []));
|
|
9
|
+
showLabel = input(false, ...(ngDevMode ? [{ debugName: "showLabel" }] : []));
|
|
10
|
+
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
|
|
11
|
+
ratingChange = output();
|
|
12
|
+
currentRating = computed(() => this.rating(), ...(ngDevMode ? [{ debugName: "currentRating" }] : []));
|
|
13
|
+
stars = computed(() => {
|
|
14
|
+
const rating = this.currentRating();
|
|
15
|
+
return Array.from({ length: 5 }, (_, i) => i < rating);
|
|
16
|
+
}, ...(ngDevMode ? [{ debugName: "stars" }] : []));
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @param rating
|
|
20
|
+
*/
|
|
21
|
+
onStarClick(rating) {
|
|
22
|
+
if (this.readonly())
|
|
23
|
+
return;
|
|
24
|
+
this.ratingChange.emit(rating);
|
|
25
|
+
}
|
|
26
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: RatingStarsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
27
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.10", type: RatingStarsComponent, isStandalone: true, selector: "c80-rating-stars", inputs: { rating: { classPropertyName: "rating", publicName: "rating", isSignal: true, isRequired: false, transformFunction: null }, showLabel: { classPropertyName: "showLabel", publicName: "showLabel", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { ratingChange: "ratingChange" }, ngImport: i0, template: "<div class=\"rating-stars\">\n @for (star of stars(); track $index) {\n <c80-icon button [icon]=\"star ? 'starFilled' : 'star'\" [size]=\"1.5\" [color]=\"star ? 'warn' : undefined\" (iconClick)=\"onStarClick($index + 1)\" class=\"rating-stars__star\" [class.rating-stars__star--filled]=\"star\"\n [class.rating-stars__star--empty]=\"!star\" [title]=\"($index + 1) + ' estrella' + ($index > 0 ? 's' : '')\" />\n }\n @if (showLabel()) {\n <span class=\"rating-stars__label\">{{ currentRating() }}/5</span>\n }\n</div>", styles: [".rating-stars{display:flex;align-items:center;gap:var(--spacing-xs)}.rating-stars__star{cursor:pointer;transition:transform .2s ease;-webkit-user-select:none;user-select:none}.rating-stars__star:hover{transform:scale(1.2)}.rating-stars__star:active{transform:scale(.9)}.rating-stars__star--empty{opacity:.3}.rating-stars__label{margin-left:var(--spacing-sm);font-size:.875rem;color:var(--color-text-secondary)}@media(max-width:768px){.rating-stars{gap:var(--spacing-xs)}.rating-stars__star:hover{transform:scale(1.15)}}\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 });
|
|
28
|
+
}
|
|
29
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: RatingStarsComponent, decorators: [{
|
|
30
|
+
type: Component,
|
|
31
|
+
args: [{ selector: 'c80-rating-stars', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"rating-stars\">\n @for (star of stars(); track $index) {\n <c80-icon button [icon]=\"star ? 'starFilled' : 'star'\" [size]=\"1.5\" [color]=\"star ? 'warn' : undefined\" (iconClick)=\"onStarClick($index + 1)\" class=\"rating-stars__star\" [class.rating-stars__star--filled]=\"star\"\n [class.rating-stars__star--empty]=\"!star\" [title]=\"($index + 1) + ' estrella' + ($index > 0 ? 's' : '')\" />\n }\n @if (showLabel()) {\n <span class=\"rating-stars__label\">{{ currentRating() }}/5</span>\n }\n</div>", styles: [".rating-stars{display:flex;align-items:center;gap:var(--spacing-xs)}.rating-stars__star{cursor:pointer;transition:transform .2s ease;-webkit-user-select:none;user-select:none}.rating-stars__star:hover{transform:scale(1.2)}.rating-stars__star:active{transform:scale(.9)}.rating-stars__star--empty{opacity:.3}.rating-stars__label{margin-left:var(--spacing-sm);font-size:.875rem;color:var(--color-text-secondary)}@media(max-width:768px){.rating-stars{gap:var(--spacing-xs)}.rating-stars__star:hover{transform:scale(1.15)}}\n"] }]
|
|
32
|
+
}], propDecorators: { rating: [{ type: i0.Input, args: [{ isSignal: true, alias: "rating", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], ratingChange: [{ type: i0.Output, args: ["ratingChange"] }] } });
|
|
33
|
+
//# sourceMappingURL=rating-stars.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rating-stars.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/rating-stars/rating-stars.component.ts","../../../../../libs/ui/src/lib/rating-stars/rating-stars.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;;AAExC;;GAEG;AAUH,MAAM,OAAO,oBAAoB;IAC7B,MAAM,GAAG,KAAK,CAAS,CAAC,kDAAC,CAAC;IAC1B,SAAS,GAAG,KAAK,CAAU,KAAK,qDAAC,CAAC;IAClC,QAAQ,GAAG,KAAK,CAAU,KAAK,oDAAC,CAAC;IAEjC,YAAY,GAAG,MAAM,EAAU,CAAC;IAEb,aAAa,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,yDAAC,CAAC;IAE9C,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;IAC3D,CAAC,iDAAC,CAAC;IAEH;;;OAGG;IACO,WAAW,CAAC,MAAc;QAChC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE,OAAO;QAC5B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;wGArBQ,oBAAoB;4FAApB,oBAAoB,mgBCfjC,8hBAQM,mkBDEQ,aAAa;;4FAKd,oBAAoB;kBAThC,SAAS;+BAEI,kBAAkB,cAChB,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';\nimport { IconComponent } from '../icon';\n\n/**\n *\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'c80-rating-stars',\n standalone: true,\n imports: [IconComponent],\n templateUrl: './rating-stars.component.html',\n styleUrl: './rating-stars.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class RatingStarsComponent {\n rating = input<number>(0);\n showLabel = input<boolean>(false);\n readonly = input<boolean>(false);\n\n ratingChange = output<number>();\n\n protected readonly currentRating = computed(() => this.rating());\n\n protected readonly stars = computed(() => {\n const rating = this.currentRating();\n return Array.from({ length: 5 }, (_, i) => i < rating);\n });\n\n /**\n *\n * @param rating\n */\n protected onStarClick(rating: number): void {\n if (this.readonly()) return;\n this.ratingChange.emit(rating);\n }\n}\n","<div class=\"rating-stars\">\n @for (star of stars(); track $index) {\n <c80-icon button [icon]=\"star ? 'starFilled' : 'star'\" [size]=\"1.5\" [color]=\"star ? 'warn' : undefined\" (iconClick)=\"onStarClick($index + 1)\" class=\"rating-stars__star\" [class.rating-stars__star--filled]=\"star\"\n [class.rating-stars__star--empty]=\"!star\" [title]=\"($index + 1) + ' estrella' + ($index > 0 ? 's' : '')\" />\n }\n @if (showLabel()) {\n <span class=\"rating-stars__label\">{{ currentRating() }}/5</span>\n }\n</div>"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/select/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC","sourcesContent":["export * from './select.
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/select/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC","sourcesContent":["export * from './select.types';\nexport * from './select.component';\n"]}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ChangeDetectionStrategy, Component, computed, input, output, signal, viewChild } from '@angular/core';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
let uniqueIdCounter = 0;
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
4
7
|
export class SelectComponent {
|
|
5
8
|
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
6
9
|
/* v8 ignore next */
|
|
@@ -28,12 +31,18 @@ export class SelectComponent {
|
|
|
28
31
|
controlId = `c80-select-${++uniqueIdCounter}`;
|
|
29
32
|
searchInput = viewChild('searchInput', ...(ngDevMode ? [{ debugName: "searchInput" }] : []));
|
|
30
33
|
filteredOptions = computed(() => {
|
|
31
|
-
const term = this.
|
|
34
|
+
const term = this.normalizeString(this.searchTerm());
|
|
32
35
|
if (!term || !this.filterable()) {
|
|
33
36
|
return this.options();
|
|
34
37
|
}
|
|
35
38
|
return this.options().filter(opt => opt.label.toLowerCase().includes(term));
|
|
36
39
|
}, ...(ngDevMode ? [{ debugName: "filteredOptions" }] : []));
|
|
40
|
+
normalizeString(str) {
|
|
41
|
+
return str.toLowerCase().trim();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
37
46
|
toggleDropdown() {
|
|
38
47
|
if (this.disabled() || this.loading()) {
|
|
39
48
|
return;
|
|
@@ -51,6 +60,10 @@ export class SelectComponent {
|
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
* @param option
|
|
66
|
+
*/
|
|
54
67
|
selectOption(option) {
|
|
55
68
|
if (option.disabled) {
|
|
56
69
|
return;
|
|
@@ -58,10 +71,17 @@ export class SelectComponent {
|
|
|
58
71
|
this.valueChange.emit(option.value);
|
|
59
72
|
this.isOpen.set(false);
|
|
60
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
*
|
|
76
|
+
*/
|
|
61
77
|
selectNull() {
|
|
62
78
|
this.valueChange.emit(null);
|
|
63
79
|
this.isOpen.set(false);
|
|
64
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
*
|
|
83
|
+
* @returns Etiqueta del valor seleccionado o placeholder
|
|
84
|
+
*/
|
|
65
85
|
getSelectedLabel() {
|
|
66
86
|
const currentValue = this.value();
|
|
67
87
|
if (currentValue === null || currentValue === undefined) {
|
|
@@ -70,13 +90,23 @@ export class SelectComponent {
|
|
|
70
90
|
const selected = this.options().find(opt => opt.value === currentValue);
|
|
71
91
|
return selected?.label ?? this.placeholder();
|
|
72
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
*/
|
|
73
96
|
closeDropdown() {
|
|
74
97
|
this.isOpen.set(false);
|
|
75
98
|
this.clearSearch();
|
|
76
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
*
|
|
102
|
+
* @param term
|
|
103
|
+
*/
|
|
77
104
|
onSearchChange(term) {
|
|
78
105
|
this.searchTerm.set(term);
|
|
79
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
*
|
|
109
|
+
*/
|
|
80
110
|
clearSearch() {
|
|
81
111
|
this.searchTerm.set('');
|
|
82
112
|
}
|