@c80/ui 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +59 -49
  2. package/esm2022/lib/action-list/action-list.component.js +1 -1
  3. package/esm2022/lib/action-list/action-list.component.js.map +1 -1
  4. package/esm2022/lib/card-level/card-level.component.js +4 -15
  5. package/esm2022/lib/card-level/card-level.component.js.map +1 -1
  6. package/esm2022/lib/error-notification/error-notification.component.js +1 -1
  7. package/esm2022/lib/error-notification/error-notification.component.js.map +1 -1
  8. package/esm2022/lib/header/header.component.js +1 -1
  9. package/esm2022/lib/header/header.component.js.map +1 -1
  10. package/esm2022/lib/icon/icon.component.js +1 -12
  11. package/esm2022/lib/icon/icon.component.js.map +1 -1
  12. package/esm2022/lib/icon/theme.service.js +3 -0
  13. package/esm2022/lib/icon/theme.service.js.map +1 -1
  14. package/esm2022/lib/info-list/info-list.component.js +1 -1
  15. package/esm2022/lib/info-list/info-list.component.js.map +1 -1
  16. package/esm2022/lib/info-message/info-message.component.js +5 -10
  17. package/esm2022/lib/info-message/info-message.component.js.map +1 -1
  18. package/esm2022/lib/input-field/input-field.component.js +17 -15
  19. package/esm2022/lib/input-field/input-field.component.js.map +1 -1
  20. package/esm2022/lib/input-search/c80-input-search.component.js +1 -1
  21. package/esm2022/lib/input-search/c80-input-search.component.js.map +1 -1
  22. package/esm2022/lib/legal-disclaimer/legal-disclaimer.component.js +1 -1
  23. package/esm2022/lib/legal-disclaimer/legal-disclaimer.component.js.map +1 -1
  24. package/esm2022/lib/modal/modal.component.js +3 -5
  25. package/esm2022/lib/modal/modal.component.js.map +1 -1
  26. package/esm2022/lib/modal/modal.service.js +6 -0
  27. package/esm2022/lib/modal/modal.service.js.map +1 -1
  28. package/esm2022/lib/navigation-card/navigation-card.component.js +1 -1
  29. package/esm2022/lib/navigation-card/navigation-card.component.js.map +1 -1
  30. package/esm2022/lib/profile-stats/profile-stats.component.js +1 -1
  31. package/esm2022/lib/profile-stats/profile-stats.component.js.map +1 -1
  32. package/esm2022/lib/rating-display/rating-display.component.js +1 -1
  33. package/esm2022/lib/rating-display/rating-display.component.js.map +1 -1
  34. package/esm2022/lib/rating-stars/rating-stars.component.js +3 -4
  35. package/esm2022/lib/rating-stars/rating-stars.component.js.map +1 -1
  36. package/esm2022/lib/select/select.component.js +1 -12
  37. package/esm2022/lib/select/select.component.js.map +1 -1
  38. package/esm2022/lib/snackbar/snackbar.component.js +1 -3
  39. package/esm2022/lib/snackbar/snackbar.component.js.map +1 -1
  40. package/esm2022/lib/stat-card/stat-card.component.js +1 -2
  41. package/esm2022/lib/stat-card/stat-card.component.js.map +1 -1
  42. package/esm2022/lib/tab/c80-tab.component.js +4 -7
  43. package/esm2022/lib/tab/c80-tab.component.js.map +1 -1
  44. package/esm2022/lib/tab/directives/c80-tab-item.directive.js +0 -1
  45. package/esm2022/lib/tab/directives/c80-tab-item.directive.js.map +1 -1
  46. package/esm2022/lib/tab/directives/c80-tab-label.directive.js +0 -1
  47. package/esm2022/lib/tab/directives/c80-tab-label.directive.js.map +1 -1
  48. package/esm2022/lib/tab/index.js.map +1 -1
  49. package/esm2022/lib/table/table.component.js +3 -29
  50. package/esm2022/lib/table/table.component.js.map +1 -1
  51. package/lib/card-level/card-level.component.d.ts +1 -1
  52. package/lib/info-message/info-message.component.d.ts +2 -5
  53. package/lib/input-field/input-field.component.d.ts +14 -10
  54. package/lib/modal/modal.component.d.ts +0 -1
  55. package/lib/rating-stars/rating-stars.component.d.ts +0 -1
  56. package/lib/tab/c80-tab.component.d.ts +1 -2
  57. package/lib/tab/index.d.ts +0 -1
  58. package/package.json +1 -1
  59. package/esm2022/lib/tab/c80-tab.types.js +0 -1
  60. package/esm2022/lib/tab/c80-tab.types.js.map +0 -1
  61. package/lib/tab/c80-tab.types.d.ts +0 -4
@@ -1,4 +1,4 @@
1
- import { ChangeDetectionStrategy, Component, input } from '@angular/core';
1
+ import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
2
2
  import { IconComponent } from '../icon';
3
3
  import * as i0 from "@angular/core";
4
4
  /**
@@ -8,18 +8,13 @@ export class InfoMessageComponent {
8
8
  message = input.required(...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
9
9
  level = input('info', ...(ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []));
10
10
  linkConfig = input(...(ngDevMode ? [undefined, { debugName: "linkConfig" }] : /* istanbul ignore next */ []));
11
- /**
12
- * Retorna el ícono según el nivel
13
- * @returns Nombre del ícono a mostrar
14
- */
15
- get icon() {
16
- return this.level() === 'warn' ? 'warning' : 'infoCircle';
17
- }
11
+ /** Ícono según el nivel del mensaje. */
12
+ icon = computed(() => this.level() === 'warn' ? 'warning' : 'infoCircle', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
18
13
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: InfoMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: InfoMessageComponent, isStandalone: true, selector: "c80-info-message", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, linkConfig: { classPropertyName: "linkConfig", publicName: "linkConfig", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"info-notification\" [attr.data-level]=\"level()\">\n <c80-icon [icon]=\"icon\" [size]=\"1.2\" color=\"secondary\" />\n <div class=\"info-notification__content\">\n <p>{{ message() }}</p>\n @if (linkConfig()) {\n <a [href]=\"linkConfig()!.link\" class=\"info-notification__link\" target=\"_blank\" rel=\"noopener noreferrer\">\n {{ linkConfig()!.text }}\n </a>\n }\n </div>\n</div>", styles: [".info-notification{display:flex;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-md);border:1px solid;border-radius:var(--border-radius-lg);font-size:.8125rem;-webkit-user-select:none;user-select:none}.info-notification__content{flex:1;display:flex;flex-direction:column;gap:var(--spacing-xs)}.info-notification p{margin:0;line-height:1.3}.info-notification__link{font-size:.8125rem;font-weight:var(--font-weight-medium);text-decoration:underline;transition:opacity .2s}.info-notification__link:hover{opacity:.7}.info-notification c80-icon{flex-shrink:0}.info-notification[data-level=info]{background:transparent;border-color:#6366f11a;color:var(--color-text-secondary)}.info-notification[data-level=warn]{background:#f59e0b0d;border-color:#f59e0b33;color:#d97706}.info-notification[data-level=warn] c80-icon{color:#f59e0b}\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 });
14
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: InfoMessageComponent, isStandalone: true, selector: "c80-info-message", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, linkConfig: { classPropertyName: "linkConfig", publicName: "linkConfig", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"info-notification\" [attr.data-level]=\"level()\">\n <c80-icon [icon]=\"icon()\" [size]=\"1.2\" color=\"secondary\" />\n <div class=\"info-notification__content\">\n <p>{{ message() }}</p>\n @if (linkConfig()) {\n <a [href]=\"linkConfig()!.link\" class=\"info-notification__link\" target=\"_blank\" rel=\"noopener noreferrer\">\n {{ linkConfig()!.text }}\n </a>\n }\n </div>\n</div>", styles: [".info-notification{display:flex;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-md);border:1px solid;border-radius:var(--border-radius-lg);font-size:.8125rem;-webkit-user-select:none;user-select:none}.info-notification__content{flex:1;display:flex;flex-direction:column;gap:var(--spacing-xs)}.info-notification p{margin:0;line-height:1.3}.info-notification__link{font-size:.8125rem;font-weight:var(--font-weight-medium);text-decoration:underline;transition:opacity .2s}.info-notification__link:hover{opacity:.7}.info-notification c80-icon{flex-shrink:0}.info-notification[data-level=info]{background:transparent;border-color:#6366f11a;color:var(--color-text-secondary)}.info-notification[data-level=warn]{background:#f59e0b0d;border-color:#f59e0b33;color:#d97706}.info-notification[data-level=warn] c80-icon{color:#f59e0b}\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
15
  }
21
16
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: InfoMessageComponent, decorators: [{
22
17
  type: Component,
23
- args: [{ selector: 'c80-info-message', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"info-notification\" [attr.data-level]=\"level()\">\n <c80-icon [icon]=\"icon\" [size]=\"1.2\" color=\"secondary\" />\n <div class=\"info-notification__content\">\n <p>{{ message() }}</p>\n @if (linkConfig()) {\n <a [href]=\"linkConfig()!.link\" class=\"info-notification__link\" target=\"_blank\" rel=\"noopener noreferrer\">\n {{ linkConfig()!.text }}\n </a>\n }\n </div>\n</div>", styles: [".info-notification{display:flex;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-md);border:1px solid;border-radius:var(--border-radius-lg);font-size:.8125rem;-webkit-user-select:none;user-select:none}.info-notification__content{flex:1;display:flex;flex-direction:column;gap:var(--spacing-xs)}.info-notification p{margin:0;line-height:1.3}.info-notification__link{font-size:.8125rem;font-weight:var(--font-weight-medium);text-decoration:underline;transition:opacity .2s}.info-notification__link:hover{opacity:.7}.info-notification c80-icon{flex-shrink:0}.info-notification[data-level=info]{background:transparent;border-color:#6366f11a;color:var(--color-text-secondary)}.info-notification[data-level=warn]{background:#f59e0b0d;border-color:#f59e0b33;color:#d97706}.info-notification[data-level=warn] c80-icon{color:#f59e0b}\n"] }]
18
+ args: [{ selector: 'c80-info-message', imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"info-notification\" [attr.data-level]=\"level()\">\n <c80-icon [icon]=\"icon()\" [size]=\"1.2\" color=\"secondary\" />\n <div class=\"info-notification__content\">\n <p>{{ message() }}</p>\n @if (linkConfig()) {\n <a [href]=\"linkConfig()!.link\" class=\"info-notification__link\" target=\"_blank\" rel=\"noopener noreferrer\">\n {{ linkConfig()!.text }}\n </a>\n }\n </div>\n</div>", styles: [".info-notification{display:flex;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-md);border:1px solid;border-radius:var(--border-radius-lg);font-size:.8125rem;-webkit-user-select:none;user-select:none}.info-notification__content{flex:1;display:flex;flex-direction:column;gap:var(--spacing-xs)}.info-notification p{margin:0;line-height:1.3}.info-notification__link{font-size:.8125rem;font-weight:var(--font-weight-medium);text-decoration:underline;transition:opacity .2s}.info-notification__link:hover{opacity:.7}.info-notification c80-icon{flex-shrink:0}.info-notification[data-level=info]{background:transparent;border-color:#6366f11a;color:var(--color-text-secondary)}.info-notification[data-level=warn]{background:#f59e0b0d;border-color:#f59e0b33;color:#d97706}.info-notification[data-level=warn] c80-icon{color:#f59e0b}\n"] }]
24
19
  }], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], linkConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkConfig", required: false }] }] } });
25
20
  //# sourceMappingURL=info-message.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"info-message.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/info-message/info-message.component.ts","../../../../../libs/ui/src/lib/info-message/info-message.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAIxC;;GAEG;AASH,MAAM,OAAO,oBAAoB;IAC7B,OAAO,GAAG,KAAK,CAAC,QAAQ,6EAAU,CAAC;IACnC,KAAK,GAAG,KAAK,CAAwB,MAAM,4EAAC,CAAC;IAC7C,UAAU,GAAG,KAAK,2FAAmB,CAAC;IAEtC;;;OAGG;IACH,IAAc,IAAI;QACd,OAAO,IAAI,CAAC,KAAK,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC;IAC9D,CAAC;wGAXQ,oBAAoB;4FAApB,oBAAoB,odChBjC,kcAUM,i4BDCQ,aAAa;;4FAKd,oBAAoB;kBARhC,SAAS;+BACI,kBAAkB,cAChB,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\nimport type { InfoNotificationLevel, InfoMessageLink } from './info-message.types';\r\n\r\n\r\n/**\r\n * Componente reutilizable para mostrar mensajes informativos o de advertencia\r\n */\r\n@Component({\r\n selector: 'c80-info-message',\r\n standalone: true,\r\n imports: [IconComponent],\r\n templateUrl: './info-message.component.html',\r\n styleUrl: './info-message.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class InfoMessageComponent {\r\n message = input.required<string>();\r\n level = input<InfoNotificationLevel>('info');\r\n linkConfig = input<InfoMessageLink>();\r\n\r\n /**\r\n * Retorna el ícono según el nivel\r\n * @returns Nombre del ícono a mostrar\r\n */\r\n protected get icon(): string {\r\n return this.level() === 'warn' ? 'warning' : 'infoCircle';\r\n }\r\n}\r\n","<div class=\"info-notification\" [attr.data-level]=\"level()\">\n <c80-icon [icon]=\"icon\" [size]=\"1.2\" color=\"secondary\" />\n <div class=\"info-notification__content\">\n <p>{{ message() }}</p>\n @if (linkConfig()) {\n <a [href]=\"linkConfig()!.link\" class=\"info-notification__link\" target=\"_blank\" rel=\"noopener noreferrer\">\n {{ linkConfig()!.text }}\n </a>\n }\n </div>\n</div>"]}
1
+ {"version":3,"file":"info-message.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/info-message/info-message.component.ts","../../../../../libs/ui/src/lib/info-message/info-message.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;;AAIxC;;GAEG;AAQH,MAAM,OAAO,oBAAoB;IAC7B,OAAO,GAAG,KAAK,CAAC,QAAQ,6EAAU,CAAC;IACnC,KAAK,GAAG,KAAK,CAAwB,MAAM,4EAAC,CAAC;IAC7C,UAAU,GAAG,KAAK,2FAAmB,CAAC;IAEtC,wCAAwC;IACrB,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,2EAAC,CAAC;wGANpF,oBAAoB;4FAApB,oBAAoB,odCfjC,ocAUM,i4BDAQ,aAAa;;4FAKd,oBAAoB;kBAPhC,SAAS;+BACI,kBAAkB,WACnB,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\nimport type { InfoNotificationLevel, InfoMessageLink } from './info-message.types';\r\n\r\n\r\n/**\r\n * Componente reutilizable para mostrar mensajes informativos o de advertencia\r\n */\r\n@Component({\r\n selector: 'c80-info-message',\r\n imports: [IconComponent],\r\n templateUrl: './info-message.component.html',\r\n styleUrl: './info-message.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class InfoMessageComponent {\r\n message = input.required<string>();\r\n level = input<InfoNotificationLevel>('info');\r\n linkConfig = input<InfoMessageLink>();\r\n\r\n /** Ícono según el nivel del mensaje. */\r\n protected readonly icon = computed(() => this.level() === 'warn' ? 'warning' : 'infoCircle');\r\n}\r\n","<div class=\"info-notification\" [attr.data-level]=\"level()\">\n <c80-icon [icon]=\"icon()\" [size]=\"1.2\" color=\"secondary\" />\n <div class=\"info-notification__content\">\n <p>{{ message() }}</p>\n @if (linkConfig()) {\n <a [href]=\"linkConfig()!.link\" class=\"info-notification__link\" target=\"_blank\" rel=\"noopener noreferrer\">\n {{ linkConfig()!.text }}\n </a>\n }\n </div>\n</div>"]}
@@ -1,17 +1,21 @@
1
- import { ChangeDetectionStrategy, Component, output, signal } from '@angular/core';
1
+ import { ChangeDetectionStrategy, Component, input, model, output, signal } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
3
  /**
4
+ * Campo de entrada inline configurable desde el padre (label, type, readonly, etc.).
4
5
  *
6
+ * `value` es un `model()`: soporta two-way binding `[(value)]` y conserva `.set()`.
7
+ * El output `valueChange` lo genera implicitamente el model (misma firma `string`
8
+ * que el output explicito que existia en 2.x); NO se redeclara para evitar la
9
+ * colision de nombres y la doble emision por cada tecla.
5
10
  */
6
11
  export class InputFieldComponent {
7
- label = signal('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
8
- value = signal('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
9
- placeholder = signal('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
10
- type = signal('text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
11
- maxLength = signal(undefined, ...(ngDevMode ? [{ debugName: "maxLength" }] : /* istanbul ignore next */ []));
12
- readonly = signal(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
13
- required = signal(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
14
- valueChange = output();
12
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
13
+ value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
14
+ placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
15
+ type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
16
+ maxLength = input(undefined, ...(ngDevMode ? [{ debugName: "maxLength" }] : /* istanbul ignore next */ []));
17
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
18
+ required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
15
19
  enterPressed = output();
16
20
  isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
17
21
  /**
@@ -19,9 +23,7 @@ export class InputFieldComponent {
19
23
  * @param event
20
24
  */
21
25
  onValueChange(event) {
22
- const newValue = event.target.value;
23
- this.value.set(newValue);
24
- this.valueChange.emit(newValue);
26
+ this.value.set(event.target.value);
25
27
  }
26
28
  /**
27
29
  *
@@ -45,10 +47,10 @@ export class InputFieldComponent {
45
47
  }
46
48
  }
47
49
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: InputFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
48
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.17", type: InputFieldComponent, isStandalone: true, selector: "c80-input-field", outputs: { valueChange: "valueChange", enterPressed: "enterPressed" }, ngImport: i0, template: "<div class=\"input-field\">\n <div class=\"input-field__item\">\n <span class=\"input-field__label\">{{ label() }}</span>\n <input class=\"input-field__input\" [class.input-field__input--focused]=\"isFocused()\" [type]=\"type()\" [value]=\"value()\" [placeholder]=\"placeholder()\" [attr.maxlength]=\"maxLength()\" [readonly]=\"readonly()\" [required]=\"required()\"\n (input)=\"onValueChange($event)\" (focus)=\"onFocus()\" (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" />\n </div>\n</div>", styles: [".input-field{width:100%}.input-field__item{display:flex;justify-content:space-between;align-items:center;padding:1rem;background:var(--color-surface);border-radius:.5rem;gap:1rem;transition:all var(--transition-base)}.input-field__item:hover{background:var(--color-bg-dark)}.input-field__label{color:var(--color-text-primary);min-width:fit-content;font-size:.875rem;font-weight:500}.input-field__input{flex:1;background:transparent;border:none;outline:none;color:var(--color-text-primary);text-align:right;padding:.5rem 0;min-width:0}.input-field__input::placeholder{color:var(--color-text-tertiary);font-style:italic}.input-field__input:focus{color:var(--color-primary)}.input-field__input[readonly]{cursor:default;color:var(--color-text-secondary)}.input-field__input--focused{color:var(--color-primary)}@media(max-width:768px){.input-field__item{padding:.75rem;gap:.75rem}.input-field__label,.input-field__input{font-size:.875rem}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
50
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: InputFieldComponent, isStandalone: true, selector: "c80-input-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", enterPressed: "enterPressed" }, ngImport: i0, template: "<div class=\"input-field\">\n <div class=\"input-field__item\">\n <span class=\"input-field__label\">{{ label() }}</span>\n <input class=\"input-field__input\" [class.input-field__input--focused]=\"isFocused()\" [type]=\"type()\" [value]=\"value()\" [placeholder]=\"placeholder()\" [attr.maxlength]=\"maxLength()\" [readonly]=\"readonly()\" [required]=\"required()\"\n (input)=\"onValueChange($event)\" (focus)=\"onFocus()\" (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" />\n </div>\n</div>", styles: [".input-field{width:100%}.input-field__item{display:flex;justify-content:space-between;align-items:center;padding:1rem;background:var(--color-surface);border-radius:.5rem;gap:1rem;transition:all var(--transition-base)}.input-field__item:hover{background:var(--color-bg-dark)}.input-field__label{color:var(--color-text-primary);min-width:fit-content;font-size:.875rem;font-weight:500}.input-field__input{flex:1;background:transparent;border:none;outline:none;color:var(--color-text-primary);text-align:right;padding:.5rem 0;min-width:0}.input-field__input::placeholder{color:var(--color-text-tertiary);font-style:italic}.input-field__input:focus{color:var(--color-primary)}.input-field__input[readonly]{cursor:default;color:var(--color-text-secondary)}.input-field__input--focused{color:var(--color-primary)}@media(max-width:768px){.input-field__item{padding:.75rem;gap:.75rem}.input-field__label,.input-field__input{font-size:.875rem}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
49
51
  }
50
52
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: InputFieldComponent, decorators: [{
51
53
  type: Component,
52
- args: [{ selector: 'c80-input-field', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"input-field\">\n <div class=\"input-field__item\">\n <span class=\"input-field__label\">{{ label() }}</span>\n <input class=\"input-field__input\" [class.input-field__input--focused]=\"isFocused()\" [type]=\"type()\" [value]=\"value()\" [placeholder]=\"placeholder()\" [attr.maxlength]=\"maxLength()\" [readonly]=\"readonly()\" [required]=\"required()\"\n (input)=\"onValueChange($event)\" (focus)=\"onFocus()\" (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" />\n </div>\n</div>", styles: [".input-field{width:100%}.input-field__item{display:flex;justify-content:space-between;align-items:center;padding:1rem;background:var(--color-surface);border-radius:.5rem;gap:1rem;transition:all var(--transition-base)}.input-field__item:hover{background:var(--color-bg-dark)}.input-field__label{color:var(--color-text-primary);min-width:fit-content;font-size:.875rem;font-weight:500}.input-field__input{flex:1;background:transparent;border:none;outline:none;color:var(--color-text-primary);text-align:right;padding:.5rem 0;min-width:0}.input-field__input::placeholder{color:var(--color-text-tertiary);font-style:italic}.input-field__input:focus{color:var(--color-primary)}.input-field__input[readonly]{cursor:default;color:var(--color-text-secondary)}.input-field__input--focused{color:var(--color-primary)}@media(max-width:768px){.input-field__item{padding:.75rem;gap:.75rem}.input-field__label,.input-field__input{font-size:.875rem}}\n"] }]
53
- }], propDecorators: { valueChange: [{ type: i0.Output, args: ["valueChange"] }], enterPressed: [{ type: i0.Output, args: ["enterPressed"] }] } });
54
+ args: [{ selector: 'c80-input-field', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"input-field\">\n <div class=\"input-field__item\">\n <span class=\"input-field__label\">{{ label() }}</span>\n <input class=\"input-field__input\" [class.input-field__input--focused]=\"isFocused()\" [type]=\"type()\" [value]=\"value()\" [placeholder]=\"placeholder()\" [attr.maxlength]=\"maxLength()\" [readonly]=\"readonly()\" [required]=\"required()\"\n (input)=\"onValueChange($event)\" (focus)=\"onFocus()\" (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" />\n </div>\n</div>", styles: [".input-field{width:100%}.input-field__item{display:flex;justify-content:space-between;align-items:center;padding:1rem;background:var(--color-surface);border-radius:.5rem;gap:1rem;transition:all var(--transition-base)}.input-field__item:hover{background:var(--color-bg-dark)}.input-field__label{color:var(--color-text-primary);min-width:fit-content;font-size:.875rem;font-weight:500}.input-field__input{flex:1;background:transparent;border:none;outline:none;color:var(--color-text-primary);text-align:right;padding:.5rem 0;min-width:0}.input-field__input::placeholder{color:var(--color-text-tertiary);font-style:italic}.input-field__input:focus{color:var(--color-primary)}.input-field__input[readonly]{cursor:default;color:var(--color-text-secondary)}.input-field__input--focused{color:var(--color-primary)}@media(max-width:768px){.input-field__item{padding:.75rem;gap:.75rem}.input-field__label,.input-field__input{font-size:.875rem}}\n"] }]
55
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], enterPressed: [{ type: i0.Output, args: ["enterPressed"] }] } });
54
56
  //# sourceMappingURL=input-field.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"input-field.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/input-field/input-field.component.ts","../../../../../libs/ui/src/lib/input-field/input-field.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;AAEnF;;GAEG;AASH,MAAM,OAAO,mBAAmB;IACnB,KAAK,GAAG,MAAM,CAAS,EAAE,4EAAC,CAAC;IAC3B,KAAK,GAAG,MAAM,CAAS,EAAE,4EAAC,CAAC;IAC3B,WAAW,GAAG,MAAM,CAAS,EAAE,kFAAC,CAAC;IACjC,IAAI,GAAG,MAAM,CAAgC,MAAM,2EAAC,CAAC;IACrD,SAAS,GAAG,MAAM,CAAqB,SAAS,gFAAC,CAAC;IAClD,QAAQ,GAAG,MAAM,CAAU,KAAK,+EAAC,CAAC;IAClC,QAAQ,GAAG,MAAM,CAAU,KAAK,+EAAC,CAAC;IAE3C,WAAW,GAAG,MAAM,EAAU,CAAC;IAC/B,YAAY,GAAG,MAAM,EAAQ,CAAC;IAEX,SAAS,GAAG,MAAM,CAAC,KAAK,gFAAC,CAAC;IAE7C;;;OAGG;IACO,aAAa,CAAC,KAAY;QAChC,MAAM,QAAQ,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACO,OAAO;QACb,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACO,MAAM;QACZ,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACO,SAAS,CAAC,KAAoB;QACpC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QAC7B,CAAC;IACL,CAAC;wGA9CQ,mBAAmB;4FAAnB,mBAAmB,kJCbhC,ihBAMM;;4FDOO,mBAAmB;kBAR/B,SAAS;+BACI,iBAAiB,cACf,IAAI,WACP,EAAE,mBAGM,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, output, signal } from '@angular/core';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-input-field',\r\n standalone: true,\r\n imports: [],\r\n templateUrl: './input-field.component.html',\r\n styleUrl: './input-field.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class InputFieldComponent {\r\n readonly label = signal<string>('');\r\n readonly value = signal<string>('');\r\n readonly placeholder = signal<string>('');\r\n readonly type = signal<'text' | 'email' | 'password'>('text');\r\n readonly maxLength = signal<number | undefined>(undefined);\r\n readonly readonly = signal<boolean>(false);\r\n readonly required = signal<boolean>(false);\r\n\r\n valueChange = output<string>();\r\n enterPressed = output<void>();\r\n\r\n protected readonly isFocused = signal(false);\r\n\r\n /**\r\n *\r\n * @param event\r\n */\r\n protected onValueChange(event: Event): void {\r\n const newValue = (event.target as HTMLInputElement).value;\r\n this.value.set(newValue);\r\n this.valueChange.emit(newValue);\r\n }\r\n\r\n /**\r\n *\r\n */\r\n protected onFocus(): void {\r\n this.isFocused.set(true);\r\n }\r\n\r\n /**\r\n *\r\n */\r\n protected onBlur(): void {\r\n this.isFocused.set(false);\r\n }\r\n\r\n /**\r\n *\r\n * @param event\r\n */\r\n protected onKeyDown(event: KeyboardEvent): void {\r\n if (event.key === 'Enter') {\r\n this.enterPressed.emit();\r\n }\r\n }\r\n}","<div class=\"input-field\">\n <div class=\"input-field__item\">\n <span class=\"input-field__label\">{{ label() }}</span>\n <input class=\"input-field__input\" [class.input-field__input--focused]=\"isFocused()\" [type]=\"type()\" [value]=\"value()\" [placeholder]=\"placeholder()\" [attr.maxlength]=\"maxLength()\" [readonly]=\"readonly()\" [required]=\"required()\"\n (input)=\"onValueChange($event)\" (focus)=\"onFocus()\" (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" />\n </div>\n</div>"]}
1
+ {"version":3,"file":"input-field.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/input-field/input-field.component.ts","../../../../../libs/ui/src/lib/input-field/input-field.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;AAEjG;;;;;;;GAOG;AAQH,MAAM,OAAO,mBAAmB;IACnB,KAAK,GAAG,KAAK,CAAS,EAAE,4EAAC,CAAC;IAC1B,KAAK,GAAG,KAAK,CAAS,EAAE,4EAAC,CAAC;IAC1B,WAAW,GAAG,KAAK,CAAS,EAAE,kFAAC,CAAC;IAChC,IAAI,GAAG,KAAK,CAA2C,MAAM,2EAAC,CAAC;IAC/D,SAAS,GAAG,KAAK,CAAqB,SAAS,gFAAC,CAAC;IACjD,QAAQ,GAAG,KAAK,CAAU,KAAK,+EAAC,CAAC;IACjC,QAAQ,GAAG,KAAK,CAAU,KAAK,+EAAC,CAAC;IAEjC,YAAY,GAAG,MAAM,EAAQ,CAAC;IAEpB,SAAS,GAAG,MAAM,CAAC,KAAK,gFAAC,CAAC;IAE7C;;;OAGG;IACO,aAAa,CAAC,KAAY;QAChC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAE,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACO,OAAO;QACb,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACO,MAAM;QACZ,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACO,SAAS,CAAC,KAAoB;QACpC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;QAC7B,CAAC;IACL,CAAC;wGA3CQ,mBAAmB;4FAAnB,mBAAmB,6gCCjBhC,ihBAMM;;4FDWO,mBAAmB;kBAP/B,SAAS;+BACI,iBAAiB,WAClB,EAAE,mBAGM,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, input, model, output, signal } from '@angular/core';\n\n/**\n * Campo de entrada inline configurable desde el padre (label, type, readonly, etc.).\n *\n * `value` es un `model()`: soporta two-way binding `[(value)]` y conserva `.set()`.\n * El output `valueChange` lo genera implicitamente el model (misma firma `string`\n * que el output explicito que existia en 2.x); NO se redeclara para evitar la\n * colision de nombres y la doble emision por cada tecla.\n */\n@Component({\n selector: 'c80-input-field',\n imports: [],\n templateUrl: './input-field.component.html',\n styleUrl: './input-field.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class InputFieldComponent {\n readonly label = input<string>('');\n readonly value = model<string>('');\n readonly placeholder = input<string>('');\n readonly type = input<'text' | 'email' | 'password' | 'number'>('text');\n readonly maxLength = input<number | undefined>(undefined);\n readonly readonly = input<boolean>(false);\n readonly required = input<boolean>(false);\n\n readonly enterPressed = output<void>();\n\n protected readonly isFocused = signal(false);\n\n /**\n *\n * @param event\n */\n protected onValueChange(event: Event): void {\n this.value.set((event.target as HTMLInputElement).value);\n }\n\n /**\n *\n */\n protected onFocus(): void {\n this.isFocused.set(true);\n }\n\n /**\n *\n */\n protected onBlur(): void {\n this.isFocused.set(false);\n }\n\n /**\n *\n * @param event\n */\n protected onKeyDown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n this.enterPressed.emit();\n }\n }\n}\n","<div class=\"input-field\">\n <div class=\"input-field__item\">\n <span class=\"input-field__label\">{{ label() }}</span>\n <input class=\"input-field__input\" [class.input-field__input--focused]=\"isFocused()\" [type]=\"type()\" [value]=\"value()\" [placeholder]=\"placeholder()\" [attr.maxlength]=\"maxLength()\" [readonly]=\"readonly()\" [required]=\"required()\"\n (input)=\"onValueChange($event)\" (focus)=\"onFocus()\" (blur)=\"onBlur()\" (keydown)=\"onKeyDown($event)\" />\n </div>\n</div>"]}
@@ -21,6 +21,6 @@ export class InputSearchComponent {
21
21
  }
22
22
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: InputSearchComponent, decorators: [{
23
23
  type: Component,
24
- args: [{ selector: 'c80-input-search', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"c80-input-search\">\n <c80-icon icon=\"search\" [button]=\"false\" [size]=\"1.2\" class=\"c80-input-search__icon\" />\n <input type=\"search\" class=\"c80-input-search__input\" [placeholder]=\"placeholder()\" [value]=\"value()\" (input)=\"onInput($event)\" autocomplete=\"off\" />\n</div>", styles: [".c80-input-search{display:flex;align-items:center;position:relative;background:var(--color-surface);border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:.25rem .75rem;border:1px solid var(--color-border);transition:box-shadow var(--transition-base);width:100%;min-height:48px}.c80-input-search__icon{margin-right:.5rem;color:var(--color-text-secondary);flex-shrink:0;font-size:1.2rem}.c80-input-search__input{border:none;outline:none;background:transparent;font-size:1rem;color:var(--color-text-primary);width:100%;padding:0;box-shadow:none;font-family:inherit}\n"] }]
24
+ args: [{ selector: 'c80-input-search', imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"c80-input-search\">\n <c80-icon icon=\"search\" [button]=\"false\" [size]=\"1.2\" class=\"c80-input-search__icon\" />\n <input type=\"search\" class=\"c80-input-search__input\" [placeholder]=\"placeholder()\" [value]=\"value()\" (input)=\"onInput($event)\" autocomplete=\"off\" />\n</div>", styles: [".c80-input-search{display:flex;align-items:center;position:relative;background:var(--color-surface);border-radius:var(--radius-md);box-shadow:var(--shadow-sm);padding:.25rem .75rem;border:1px solid var(--color-border);transition:box-shadow var(--transition-base);width:100%;min-height:48px}.c80-input-search__icon{margin-right:.5rem;color:var(--color-text-secondary);flex-shrink:0;font-size:1.2rem}.c80-input-search__input{border:none;outline:none;background:transparent;font-size:1rem;color:var(--color-text-primary);width:100%;padding:0;box-shadow:none;font-family:inherit}\n"] }]
25
25
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], inputChange: [{ type: i0.Output, args: ["inputChange"] }] } });
26
26
  //# sourceMappingURL=c80-input-search.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"c80-input-search.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/input-search/c80-input-search.component.ts","../../../../../libs/ui/src/lib/input-search/c80-input-search.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAExC;;GAEG;AASH,MAAM,OAAO,oBAAoB;IACpB,KAAK,GAAG,KAAK,CAAS,EAAE,4EAAC,CAAC;IAC1B,WAAW,GAAG,KAAK,CAAS,WAAW,kFAAC,CAAC;IACzC,WAAW,GAAG,MAAM,EAAU,CAAC;IAExC;;;OAGG;IACO,OAAO,CAAC,KAAY;QAC1B,MAAM,GAAG,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QACrD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;wGAZQ,oBAAoB;4FAApB,oBAAoB,mYCdjC,qTAGM,2nBDMQ,aAAa;;4FAKd,oBAAoB;kBARhC,SAAS;+BACI,kBAAkB,cAChB,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, input, output } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-input-search',\r\n standalone: true,\r\n imports: [IconComponent],\r\n templateUrl: './c80-input-search.component.html',\r\n styleUrl: './c80-input-search.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class InputSearchComponent {\r\n readonly value = input<string>('');\r\n readonly placeholder = input<string>('Buscar...');\r\n readonly inputChange = output<string>();\r\n\r\n /**\r\n *\r\n * @param event\r\n */\r\n protected onInput(event: Event): void {\r\n const val = (event.target as HTMLInputElement).value;\r\n this.inputChange.emit(val);\r\n }\r\n}\r\n","<div class=\"c80-input-search\">\n <c80-icon icon=\"search\" [button]=\"false\" [size]=\"1.2\" class=\"c80-input-search__icon\" />\n <input type=\"search\" class=\"c80-input-search__input\" [placeholder]=\"placeholder()\" [value]=\"value()\" (input)=\"onInput($event)\" autocomplete=\"off\" />\n</div>"]}
1
+ {"version":3,"file":"c80-input-search.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/input-search/c80-input-search.component.ts","../../../../../libs/ui/src/lib/input-search/c80-input-search.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAExC;;GAEG;AAQH,MAAM,OAAO,oBAAoB;IACpB,KAAK,GAAG,KAAK,CAAS,EAAE,4EAAC,CAAC;IAC1B,WAAW,GAAG,KAAK,CAAS,WAAW,kFAAC,CAAC;IACzC,WAAW,GAAG,MAAM,EAAU,CAAC;IAExC;;;OAGG;IACO,OAAO,CAAC,KAAY;QAC1B,MAAM,GAAG,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QACrD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;wGAZQ,oBAAoB;4FAApB,oBAAoB,mYCbjC,qTAGM,2nBDKQ,aAAa;;4FAKd,oBAAoB;kBAPhC,SAAS;+BACI,kBAAkB,WACnB,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, input, output } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-input-search',\r\n imports: [IconComponent],\r\n templateUrl: './c80-input-search.component.html',\r\n styleUrl: './c80-input-search.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class InputSearchComponent {\r\n readonly value = input<string>('');\r\n readonly placeholder = input<string>('Buscar...');\r\n readonly inputChange = output<string>();\r\n\r\n /**\r\n *\r\n * @param event\r\n */\r\n protected onInput(event: Event): void {\r\n const val = (event.target as HTMLInputElement).value;\r\n this.inputChange.emit(val);\r\n }\r\n}\r\n","<div class=\"c80-input-search\">\n <c80-icon icon=\"search\" [button]=\"false\" [size]=\"1.2\" class=\"c80-input-search__icon\" />\n <input type=\"search\" class=\"c80-input-search__input\" [placeholder]=\"placeholder()\" [value]=\"value()\" (input)=\"onInput($event)\" autocomplete=\"off\" />\n</div>"]}
@@ -16,6 +16,6 @@ export class LegalDisclaimerComponent {
16
16
  }
17
17
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: LegalDisclaimerComponent, decorators: [{
18
18
  type: Component,
19
- args: [{ selector: 'c80-legal-disclaimer', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<p class=\"legal-disclaimer\" [innerText]=\"text()\"></p>\n", styles: [".legal-disclaimer{margin:var(--spacing-lg) 0 0;padding:var(--spacing-sm) var(--spacing-md);max-width:600px;font-size:.75rem;line-height:1.4;color:var(--color-text-secondary);text-align:center;background:rgba(var(--color-primary-rgb),.05);border-left:3px solid var(--color-primary);border-radius:var(--radius-md);opacity:.8}@media(max-width:480px){.legal-disclaimer{font-size:.7rem;padding:var(--spacing-xs) var(--spacing-sm)}}\n"] }]
19
+ args: [{ selector: 'c80-legal-disclaimer', changeDetection: ChangeDetectionStrategy.OnPush, template: "<p class=\"legal-disclaimer\" [innerText]=\"text()\"></p>\n", styles: [".legal-disclaimer{margin:var(--spacing-lg) 0 0;padding:var(--spacing-sm) var(--spacing-md);max-width:600px;font-size:.75rem;line-height:1.4;color:var(--color-text-secondary);text-align:center;background:rgba(var(--color-primary-rgb),.05);border-left:3px solid var(--color-primary);border-radius:var(--radius-md);opacity:.8}@media(max-width:480px){.legal-disclaimer{font-size:.7rem;padding:var(--spacing-xs) var(--spacing-sm)}}\n"] }]
20
20
  }], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: false }] }] } });
21
21
  //# sourceMappingURL=legal-disclaimer.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"legal-disclaimer.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/legal-disclaimer/legal-disclaimer.component.ts","../../../../../libs/ui/src/lib/legal-disclaimer/legal-disclaimer.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;;AAE1E;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACjC,4KAA4K,CAAC;AAEjL;;;GAGG;AAQH,MAAM,OAAO,wBAAwB;IACxB,IAAI,GAAG,KAAK,CAAS,wBAAwB,2EAAC,CAAC;wGAD/C,wBAAwB;4FAAxB,wBAAwB,iNCpBrC,6DACA;;4FDmBa,wBAAwB;kBAPpC,SAAS;+BACI,sBAAsB,cACpB,IAAI,mBAGC,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\n\r\n/**\r\n * Texto legal genérico por defecto.\r\n * Neutro y sin dominio específico; las apps deben pasar su propio texto vía el input `text`.\r\n */\r\nexport const DEFAULT_LEGAL_DISCLAIMER =\r\n 'La información mostrada se proporciona únicamente con fines orientativos y puede no estar actualizada. El uso de esta aplicación es responsabilidad exclusiva del usuario.';\r\n\r\n/**\r\n * Componente reutilizable para mostrar avisos legales.\r\n * Por defecto muestra un texto genérico, personalizable mediante el input `text`.\r\n */\r\n@Component({\r\n selector: 'c80-legal-disclaimer',\r\n standalone: true,\r\n templateUrl: './legal-disclaimer.component.html',\r\n styleUrl: './legal-disclaimer.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class LegalDisclaimerComponent {\r\n readonly text = input<string>(DEFAULT_LEGAL_DISCLAIMER);\r\n}\r\n","<p class=\"legal-disclaimer\" [innerText]=\"text()\"></p>\n"]}
1
+ {"version":3,"file":"legal-disclaimer.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/legal-disclaimer/legal-disclaimer.component.ts","../../../../../libs/ui/src/lib/legal-disclaimer/legal-disclaimer.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;;AAE1E;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACjC,4KAA4K,CAAC;AAEjL;;;GAGG;AAOH,MAAM,OAAO,wBAAwB;IACxB,IAAI,GAAG,KAAK,CAAS,wBAAwB,2EAAC,CAAC;wGAD/C,wBAAwB;4FAAxB,wBAAwB,iNCnBrC,6DACA;;4FDkBa,wBAAwB;kBANpC,SAAS;+BACI,sBAAsB,mBAGf,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\n\r\n/**\r\n * Texto legal genérico por defecto.\r\n * Neutro y sin dominio específico; las apps deben pasar su propio texto vía el input `text`.\r\n */\r\nexport const DEFAULT_LEGAL_DISCLAIMER =\r\n 'La información mostrada se proporciona únicamente con fines orientativos y puede no estar actualizada. El uso de esta aplicación es responsabilidad exclusiva del usuario.';\r\n\r\n/**\r\n * Componente reutilizable para mostrar avisos legales.\r\n * Por defecto muestra un texto genérico, personalizable mediante el input `text`.\r\n */\r\n@Component({\r\n selector: 'c80-legal-disclaimer',\r\n templateUrl: './legal-disclaimer.component.html',\r\n styleUrl: './legal-disclaimer.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class LegalDisclaimerComponent {\r\n readonly text = input<string>(DEFAULT_LEGAL_DISCLAIMER);\r\n}\r\n","<p class=\"legal-disclaimer\" [innerText]=\"text()\"></p>\n"]}
@@ -1,4 +1,4 @@
1
- import { Component, computed, effect, inject, ChangeDetectionStrategy } from '@angular/core';
1
+ import { Component, effect, inject, ChangeDetectionStrategy } from '@angular/core';
2
2
  import { ModalService } from './modal.service';
3
3
  import { IconComponent } from './../icon';
4
4
  import * as i0 from "@angular/core";
@@ -9,7 +9,6 @@ export class ModalComponent {
9
9
  modalService = inject(ModalService);
10
10
  isOpen = this.modalService.modalState.isOpen;
11
11
  config = this.modalService.modalState.config;
12
- isVisible = computed(() => this.isOpen(), ...(ngDevMode ? [{ debugName: "isVisible" }] : /* istanbul ignore next */ []));
13
12
  /**
14
13
  *
15
14
  */
@@ -17,7 +16,6 @@ export class ModalComponent {
17
16
  effect(() => {
18
17
  if (this.isOpen()) {
19
18
  // Auto-focus modal when opened for accessibility
20
- /* v8 ignore next 8 */
21
19
  setTimeout(() => {
22
20
  const backdrop = document.querySelector('.modal-backdrop');
23
21
  if (backdrop) {
@@ -142,10 +140,10 @@ export class ModalComponent {
142
140
  return this.config().confirmText ?? 'OK';
143
141
  }
144
142
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
145
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", 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 @if (config().allowHtml) {\n <p class=\"modal-message\" [innerHTML]=\"config().message\"></p>\n } @else {\n <p class=\"modal-message\">{{ config().message }}</p>\n }\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]=\"getOkText()\" (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;flex-wrap:nowrap;justify-content:flex-end;gap:8px;padding:12px 20px 16px;background:var(--color-bg-secondary);border-top:1px solid var(--color-border-default)}.modal-footer c80-icon{flex-shrink:0}@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 });
143
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ModalComponent, isStandalone: true, selector: "c80-modal", ngImport: i0, template: "<!-- Modal Backdrop -->\n@if (isOpen()) {\n<div class=\"modal-backdrop\" [class.show]=\"isOpen()\" tabindex=\"-1\" (click)=\"onBackdropClick($event)\" (keydown.escape)=\"closeModal()\">\n\n <!-- Modal Container -->\n <dialog class=\"modal-container\" [class.show]=\"isOpen()\" [attr.aria-labelledby]=\"'modal-title'\" [open]=\"isOpen()\">\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 @if (config().allowHtml) {\n <p class=\"modal-message\" [innerHTML]=\"config().message\"></p>\n } @else {\n <p class=\"modal-message\">{{ config().message }}</p>\n }\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]=\"getOkText()\" (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;flex-wrap:nowrap;justify-content:flex-end;gap:8px;padding:12px 20px 16px;background:var(--color-bg-secondary);border-top:1px solid var(--color-border-default)}.modal-footer c80-icon{flex-shrink:0}@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 });
146
144
  }
147
145
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ModalComponent, decorators: [{
148
146
  type: Component,
149
- 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 @if (config().allowHtml) {\n <p class=\"modal-message\" [innerHTML]=\"config().message\"></p>\n } @else {\n <p class=\"modal-message\">{{ config().message }}</p>\n }\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]=\"getOkText()\" (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;flex-wrap:nowrap;justify-content:flex-end;gap:8px;padding:12px 20px 16px;background:var(--color-bg-secondary);border-top:1px solid var(--color-border-default)}.modal-footer c80-icon{flex-shrink:0}@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"] }]
147
+ args: [{ selector: 'c80-modal', imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Modal Backdrop -->\n@if (isOpen()) {\n<div class=\"modal-backdrop\" [class.show]=\"isOpen()\" tabindex=\"-1\" (click)=\"onBackdropClick($event)\" (keydown.escape)=\"closeModal()\">\n\n <!-- Modal Container -->\n <dialog class=\"modal-container\" [class.show]=\"isOpen()\" [attr.aria-labelledby]=\"'modal-title'\" [open]=\"isOpen()\">\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 @if (config().allowHtml) {\n <p class=\"modal-message\" [innerHTML]=\"config().message\"></p>\n } @else {\n <p class=\"modal-message\">{{ config().message }}</p>\n }\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]=\"getOkText()\" (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;flex-wrap:nowrap;justify-content:flex-end;gap:8px;padding:12px 20px 16px;background:var(--color-bg-secondary);border-top:1px solid var(--color-border-default)}.modal-footer c80-icon{flex-shrink:0}@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"] }]
150
148
  }], ctorParameters: () => [] });
151
149
  //# 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":"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","sourcesContent":["import { Component, computed, effect, inject, ChangeDetectionStrategy } from '@angular/core';\r\nimport { ModalService } from './modal.service';\r\nimport { IconComponent } from './../icon';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-modal',\r\n standalone: true,\r\n imports: [IconComponent],\r\n templateUrl: './modal.component.html',\r\n styleUrl: './modal.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class ModalComponent {\r\n private readonly modalService = inject(ModalService);\r\n\r\n readonly isOpen = this.modalService.modalState.isOpen;\r\n readonly config = this.modalService.modalState.config;\r\n readonly isVisible = computed(() => this.isOpen());\r\n\r\n /**\r\n *\r\n */\r\n constructor() {\r\n effect(() => {\r\n if (this.isOpen()) {\r\n // Auto-focus modal when opened for accessibility\r\n /* v8 ignore next 8 */\r\n setTimeout(() => {\r\n const backdrop = document.querySelector(\r\n '.modal-backdrop'\r\n ) as HTMLElement;\r\n if (backdrop) {\r\n backdrop.focus();\r\n }\r\n }, 100);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Maneja la confirmación del modal\r\n */\r\n onConfirm(): void {\r\n this.modalService.handleResult({ action: 'confirm', confirmed: true });\r\n }\r\n\r\n /**\r\n * Maneja la cancelación del modal\r\n */\r\n onCancel(): void {\r\n this.modalService.handleResult({ action: 'cancel', confirmed: false });\r\n }\r\n\r\n /**\r\n * Maneja la respuesta afirmativa del modal\r\n */\r\n onYes(): void {\r\n this.modalService.handleResult({ action: 'yes', confirmed: true });\r\n }\r\n\r\n /**\r\n * Maneja la respuesta negativa del modal\r\n */\r\n onNo(): void {\r\n this.modalService.handleResult({ action: 'no', confirmed: false });\r\n }\r\n\r\n /**\r\n * Cierra el modal actual\r\n */\r\n closeModal(): void {\r\n this.modalService.closeModal();\r\n }\r\n\r\n /**\r\n * Maneja el clic en el backdrop del modal\r\n * @param event - Evento de clic\r\n */\r\n onBackdropClick(event: Event): void {\r\n if (event.target === event.currentTarget) {\r\n this.closeModal();\r\n }\r\n }\r\n\r\n /**\r\n *\r\n * @returns Clase CSS del botón primario según el tipo de modal\r\n */\r\n getPrimaryButtonClass(): string {\r\n const configValue = this.config();\r\n switch (configValue.type) {\r\n case 'warning':\r\n return 'btn-warning';\r\n case 'error':\r\n return 'btn-danger';\r\n case 'confirm':\r\n case 'yesNo':\r\n return 'btn-primary';\r\n default:\r\n return 'btn-info';\r\n }\r\n }\r\n\r\n /**\r\n *\r\n * @returns true si debe mostrar botones Sí/No\r\n */\r\n showYesNoButtons(): boolean {\r\n return this.config().type === 'yesNo';\r\n }\r\n\r\n /**\r\n *\r\n * @returns true si debe mostrar botones Confirmar/Cancelar\r\n */\r\n showConfirmButtons(): boolean {\r\n const type = this.config().type;\r\n return type === 'confirm' || type === 'warning' || type === 'error';\r\n }\r\n\r\n /**\r\n *\r\n * @returns true si debe mostrar botón OK\r\n */\r\n showOkButton(): boolean {\r\n return this.config().type === 'info';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón de confirmación\r\n */\r\n getConfirmText(): string {\r\n return this.config().confirmText ?? 'Confirmar';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón de cancelar\r\n */\r\n getCancelText(): string {\r\n return this.config().cancelText ?? 'Cancelar';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón Sí\r\n */\r\n getYesText(): string {\r\n return this.config().yesText ?? 'Sí';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón No\r\n */\r\n getNoText(): string {\r\n return this.config().noText ?? 'No';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón OK\r\n */\r\n getOkText(): string {\r\n return this.config().confirmText ?? 'OK';\r\n }\r\n}\r\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 @if (config().allowHtml) {\n <p class=\"modal-message\" [innerHTML]=\"config().message\"></p>\n } @else {\n <p class=\"modal-message\">{{ config().message }}</p>\n }\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]=\"getOkText()\" (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
+ {"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":"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","sourcesContent":["import { Component, effect, inject, ChangeDetectionStrategy } from '@angular/core';\r\nimport { ModalService } from './modal.service';\r\nimport { IconComponent } from './../icon';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-modal',\r\n imports: [IconComponent],\r\n templateUrl: './modal.component.html',\r\n styleUrl: './modal.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class ModalComponent {\r\n private readonly modalService = inject(ModalService);\r\n\r\n readonly isOpen = this.modalService.modalState.isOpen;\r\n readonly config = this.modalService.modalState.config;\r\n\r\n /**\r\n *\r\n */\r\n constructor() {\r\n effect(() => {\r\n if (this.isOpen()) {\r\n // Auto-focus modal when opened for accessibility\r\n setTimeout(() => {\r\n const backdrop = document.querySelector(\r\n '.modal-backdrop'\r\n ) as HTMLElement;\r\n if (backdrop) {\r\n backdrop.focus();\r\n }\r\n }, 100);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Maneja la confirmación del modal\r\n */\r\n onConfirm(): void {\r\n this.modalService.handleResult({ action: 'confirm', confirmed: true });\r\n }\r\n\r\n /**\r\n * Maneja la cancelación del modal\r\n */\r\n onCancel(): void {\r\n this.modalService.handleResult({ action: 'cancel', confirmed: false });\r\n }\r\n\r\n /**\r\n * Maneja la respuesta afirmativa del modal\r\n */\r\n onYes(): void {\r\n this.modalService.handleResult({ action: 'yes', confirmed: true });\r\n }\r\n\r\n /**\r\n * Maneja la respuesta negativa del modal\r\n */\r\n onNo(): void {\r\n this.modalService.handleResult({ action: 'no', confirmed: false });\r\n }\r\n\r\n /**\r\n * Cierra el modal actual\r\n */\r\n closeModal(): void {\r\n this.modalService.closeModal();\r\n }\r\n\r\n /**\r\n * Maneja el clic en el backdrop del modal\r\n * @param event - Evento de clic\r\n */\r\n onBackdropClick(event: Event): void {\r\n if (event.target === event.currentTarget) {\r\n this.closeModal();\r\n }\r\n }\r\n\r\n /**\r\n *\r\n * @returns Clase CSS del botón primario según el tipo de modal\r\n */\r\n getPrimaryButtonClass(): string {\r\n const configValue = this.config();\r\n switch (configValue.type) {\r\n case 'warning':\r\n return 'btn-warning';\r\n case 'error':\r\n return 'btn-danger';\r\n case 'confirm':\r\n case 'yesNo':\r\n return 'btn-primary';\r\n default:\r\n return 'btn-info';\r\n }\r\n }\r\n\r\n /**\r\n *\r\n * @returns true si debe mostrar botones Sí/No\r\n */\r\n showYesNoButtons(): boolean {\r\n return this.config().type === 'yesNo';\r\n }\r\n\r\n /**\r\n *\r\n * @returns true si debe mostrar botones Confirmar/Cancelar\r\n */\r\n showConfirmButtons(): boolean {\r\n const type = this.config().type;\r\n return type === 'confirm' || type === 'warning' || type === 'error';\r\n }\r\n\r\n /**\r\n *\r\n * @returns true si debe mostrar botón OK\r\n */\r\n showOkButton(): boolean {\r\n return this.config().type === 'info';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón de confirmación\r\n */\r\n getConfirmText(): string {\r\n return this.config().confirmText ?? 'Confirmar';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón de cancelar\r\n */\r\n getCancelText(): string {\r\n return this.config().cancelText ?? 'Cancelar';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón Sí\r\n */\r\n getYesText(): string {\r\n return this.config().yesText ?? 'Sí';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón No\r\n */\r\n getNoText(): string {\r\n return this.config().noText ?? 'No';\r\n }\r\n\r\n /**\r\n *\r\n * @returns Texto del botón OK\r\n */\r\n getOkText(): string {\r\n return this.config().confirmText ?? 'OK';\r\n }\r\n}\r\n","<!-- Modal Backdrop -->\n@if (isOpen()) {\n<div class=\"modal-backdrop\" [class.show]=\"isOpen()\" tabindex=\"-1\" (click)=\"onBackdropClick($event)\" (keydown.escape)=\"closeModal()\">\n\n <!-- Modal Container -->\n <dialog class=\"modal-container\" [class.show]=\"isOpen()\" [attr.aria-labelledby]=\"'modal-title'\" [open]=\"isOpen()\">\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 @if (config().allowHtml) {\n <p class=\"modal-message\" [innerHTML]=\"config().message\"></p>\n } @else {\n <p class=\"modal-message\">{{ config().message }}</p>\n }\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]=\"getOkText()\" (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}"]}
@@ -20,6 +20,12 @@ export class ModalService {
20
20
  * @param config
21
21
  */
22
22
  async showModal(config) {
23
+ // Si ya hay un modal abierto esperando respuesta, resolvemos su promesa
24
+ // como cancelación antes de reemplazarla para no dejarla colgada.
25
+ if (this.resolvePromise) {
26
+ this.resolvePromise({ action: 'cancel', confirmed: false });
27
+ this.resolvePromise = undefined;
28
+ }
23
29
  this.config.set(config);
24
30
  this.isOpen.set(true);
25
31
  return new Promise((resolve) => {
@@ -1 +1 @@
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 * @param options.allowHtml\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 allowHtml?: boolean;\n }): Promise<boolean> {\n const { title, message, confirmText = 'Confirmar', cancelText = 'Cancelar', allowHtml } = options;\n return this.showModal({\n title,\n message,\n type: 'confirm',\n confirmText,\n cancelText,\n allowHtml,\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 * @param options.allowHtml\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 allowHtml?: boolean;\n }): Promise<boolean> {\n const { title, message, yesText = 'Sí', noText = 'No', allowHtml } = options;\n return this.showModal({\n title,\n message,\n type: 'yesNo',\n yesText,\n noText,\n allowHtml,\n }).then((result) => result.action === 'yes');\n }\n\n /**\n *\n * @param title\n * @param message\n * @param allowHtml\n * @param confirmText\n * @returns Promise que resuelve cuando se cierra el modal\n */\n async info(title: string, message: string, allowHtml?: boolean, confirmText?: string): Promise<void> {\n return this.showModal({\n title,\n message,\n type: 'info',\n allowHtml,\n confirmText,\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 * @param options.allowHtml\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 allowHtml?: boolean;\n }): Promise<boolean> {\n const { title, message, confirmText = 'Entendido', cancelText = 'Cancelar', allowHtml } = options;\n return this.showModal({\n title,\n message,\n type: 'warning',\n confirmText,\n cancelText,\n allowHtml,\n }).then((result) => result.confirmed);\n }\n\n /**\n *\n * @param title\n * @param message\n * @param confirmText\n * @param allowHtml\n * @returns Promise que resuelve true si se confirmó\n */\n async error(\n title: string,\n message: string,\n confirmText = 'Entendido',\n allowHtml?: boolean\n ): Promise<void> {\n return this.showModal({\n title,\n message,\n type: 'error',\n confirmText,\n allowHtml,\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"]}
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 // Si ya hay un modal abierto esperando respuesta, resolvemos su promesa\n // como cancelación antes de reemplazarla para no dejarla colgada.\n if (this.resolvePromise) {\n this.resolvePromise({ action: 'cancel', confirmed: false });\n this.resolvePromise = undefined;\n }\n\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 * @param options.allowHtml\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 allowHtml?: boolean;\n }): Promise<boolean> {\n const { title, message, confirmText = 'Confirmar', cancelText = 'Cancelar', allowHtml } = options;\n return this.showModal({\n title,\n message,\n type: 'confirm',\n confirmText,\n cancelText,\n allowHtml,\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 * @param options.allowHtml\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 allowHtml?: boolean;\n }): Promise<boolean> {\n const { title, message, yesText = 'Sí', noText = 'No', allowHtml } = options;\n return this.showModal({\n title,\n message,\n type: 'yesNo',\n yesText,\n noText,\n allowHtml,\n }).then((result) => result.action === 'yes');\n }\n\n /**\n *\n * @param title\n * @param message\n * @param allowHtml\n * @param confirmText\n * @returns Promise que resuelve cuando se cierra el modal\n */\n async info(title: string, message: string, allowHtml?: boolean, confirmText?: string): Promise<void> {\n return this.showModal({\n title,\n message,\n type: 'info',\n allowHtml,\n confirmText,\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 * @param options.allowHtml\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 allowHtml?: boolean;\n }): Promise<boolean> {\n const { title, message, confirmText = 'Entendido', cancelText = 'Cancelar', allowHtml } = options;\n return this.showModal({\n title,\n message,\n type: 'warning',\n confirmText,\n cancelText,\n allowHtml,\n }).then((result) => result.confirmed);\n }\n\n /**\n *\n * @param title\n * @param message\n * @param confirmText\n * @param allowHtml\n * @returns Promise que resuelve true si se confirmó\n */\n async error(\n title: string,\n message: string,\n confirmText = 'Entendido',\n allowHtml?: boolean\n ): Promise<void> {\n return this.showModal({\n title,\n message,\n type: 'error',\n confirmText,\n allowHtml,\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"]}
@@ -13,6 +13,6 @@ export class NavigationCardComponent {
13
13
  }
14
14
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NavigationCardComponent, decorators: [{
15
15
  type: Component,
16
- args: [{ selector: 'c80-navigation-card', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<button type=\"button\" class=\"nav-card\" [class.active]=\"active()\" (click)=\"onCardClick()\">\n <c80-icon [icon]=\"card().icon\" [size]=\"1.7\" class=\"card-icon\" />\n <h3 class=\"card-title\">{{ card().title }}</h3>\n</button>", styles: [".nav-card{background:var(--color-bg-primary);border:1px solid var(--color-border-default);border-radius:12px;padding:24px;cursor:pointer;transition:all .1s ease;display:flex;flex-direction:column;align-items:center;text-align:center;min-height:140px;justify-content:center;width:100%;font-family:inherit;font-size:inherit}.nav-card:hover{background:var(--color-bg-hover);box-shadow:var(--shadow-md);transform:translateY(-1px);border-color:var(--color-border-medium)}.nav-card.active{background:var(--color-bg-tertiary);border-color:var(--color-text-primary)}.nav-card:focus-visible{outline:none}.nav-card .card-icon{margin-bottom:12px;display:flex;justify-content:center;align-items:center}.nav-card .card-title{font-size:16px;font-weight:600;margin:0;color:var(--color-text-primary);transition:color .2s}@media(max-width:768px){.nav-card{min-height:120px;padding:20px}.nav-card .card-icon{font-size:40px;width:40px;height:40px}.nav-card .card-title{font-size:14px}}\n"] }]
16
+ args: [{ selector: 'c80-navigation-card', imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<button type=\"button\" class=\"nav-card\" [class.active]=\"active()\" (click)=\"onCardClick()\">\n <c80-icon [icon]=\"card().icon\" [size]=\"1.7\" class=\"card-icon\" />\n <h3 class=\"card-title\">{{ card().title }}</h3>\n</button>", styles: [".nav-card{background:var(--color-bg-primary);border:1px solid var(--color-border-default);border-radius:12px;padding:24px;cursor:pointer;transition:all .1s ease;display:flex;flex-direction:column;align-items:center;text-align:center;min-height:140px;justify-content:center;width:100%;font-family:inherit;font-size:inherit}.nav-card:hover{background:var(--color-bg-hover);box-shadow:var(--shadow-md);transform:translateY(-1px);border-color:var(--color-border-medium)}.nav-card.active{background:var(--color-bg-tertiary);border-color:var(--color-text-primary)}.nav-card:focus-visible{outline:none}.nav-card .card-icon{margin-bottom:12px;display:flex;justify-content:center;align-items:center}.nav-card .card-title{font-size:16px;font-weight:600;margin:0;color:var(--color-text-primary);transition:color .2s}@media(max-width:768px){.nav-card{min-height:120px;padding:20px}.nav-card .card-icon{font-size:40px;width:40px;height:40px}.nav-card .card-title{font-size:14px}}\n"] }]
17
17
  }], propDecorators: { card: [{ type: i0.Input, args: [{ isSignal: true, alias: "card", required: true }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], cardClick: [{ type: i0.Output, args: ["cardClick"] }] } });
18
18
  //# sourceMappingURL=navigation-card.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-card.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/navigation-card/navigation-card.component.ts","../../../../../libs/ui/src/lib/navigation-card/navigation-card.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAYxC,MAAM,OAAO,uBAAuB;IACvB,IAAI,GAAG,KAAK,CAAC,QAAQ,0EAAkB,CAAC;IACxC,MAAM,GAAG,KAAK,CAAU,KAAK,6EAAC,CAAC;IAC/B,SAAS,GAAG,MAAM,EAAkB,CAAC;IAE9C,WAAW;QACP,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;wGAPQ,uBAAuB;4FAAvB,uBAAuB,+WCbpC,gPAGS,kgCDKK,aAAa;;4FAKd,uBAAuB;kBARnC,SAAS;+BACI,qBAAqB,cACnB,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { Component, input, output, ChangeDetectionStrategy } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\nimport type { NavigationCard } from './navigation-card.types';\r\n\r\n\r\n@Component({\r\n selector: 'c80-navigation-card',\r\n standalone: true,\r\n imports: [IconComponent],\r\n templateUrl: './navigation-card.component.html',\r\n styleUrl: './navigation-card.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class NavigationCardComponent {\r\n readonly card = input.required<NavigationCard>();\r\n readonly active = input<boolean>(false);\r\n readonly cardClick = output<NavigationCard>();\r\n\r\n onCardClick(): void {\r\n this.cardClick.emit(this.card());\r\n }\r\n}\r\n","<button type=\"button\" class=\"nav-card\" [class.active]=\"active()\" (click)=\"onCardClick()\">\n <c80-icon [icon]=\"card().icon\" [size]=\"1.7\" class=\"card-icon\" />\n <h3 class=\"card-title\">{{ card().title }}</h3>\n</button>"]}
1
+ {"version":3,"file":"navigation-card.component.js","sourceRoot":"","sources":["../../../../../libs/ui/src/lib/navigation-card/navigation-card.component.ts","../../../../../libs/ui/src/lib/navigation-card/navigation-card.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;;AAWxC,MAAM,OAAO,uBAAuB;IACvB,IAAI,GAAG,KAAK,CAAC,QAAQ,0EAAkB,CAAC;IACxC,MAAM,GAAG,KAAK,CAAU,KAAK,6EAAC,CAAC;IAC/B,SAAS,GAAG,MAAM,EAAkB,CAAC;IAE9C,WAAW;QACP,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;wGAPQ,uBAAuB;4FAAvB,uBAAuB,+WCZpC,gPAGS,kgCDIK,aAAa;;4FAKd,uBAAuB;kBAPnC,SAAS;+BACI,qBAAqB,WACtB,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { Component, input, output, ChangeDetectionStrategy } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\nimport type { NavigationCard } from './navigation-card.types';\r\n\r\n\r\n@Component({\r\n selector: 'c80-navigation-card',\r\n imports: [IconComponent],\r\n templateUrl: './navigation-card.component.html',\r\n styleUrl: './navigation-card.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class NavigationCardComponent {\r\n readonly card = input.required<NavigationCard>();\r\n readonly active = input<boolean>(false);\r\n readonly cardClick = output<NavigationCard>();\r\n\r\n onCardClick(): void {\r\n this.cardClick.emit(this.card());\r\n }\r\n}\r\n","<button type=\"button\" class=\"nav-card\" [class.active]=\"active()\" (click)=\"onCardClick()\">\n <c80-icon [icon]=\"card().icon\" [size]=\"1.7\" class=\"card-icon\" />\n <h3 class=\"card-title\">{{ card().title }}</h3>\n</button>"]}
@@ -11,6 +11,6 @@ export class ProfileStatsComponent {
11
11
  }
12
12
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ProfileStatsComponent, decorators: [{
13
13
  type: Component,
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:capitalize}.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:capitalize}@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', 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:capitalize}.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:capitalize}@media(max-width:768px){.stats{gap:var(--spacing-sm)}.stats__value{font-size:1.125rem}.stats__label{font-size:.75rem}}\n"] }]
15
15
  }], propDecorators: { stats: [{ type: i0.Input, args: [{ isSignal: true, alias: "stats", required: true }] }] } });
16
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;;AAG1E;;;GAGG;AAQH,MAAM,OAAO,qBAAqB;IAC9B,KAAK,GAAG,KAAK,CAAC,QAAQ,2EAAc,CAAC;wGAD5B,qBAAqB;4FAArB,qBAAqB,gNCdlC,ugBAaM;;4FDCO,qBAAqB;kBAPjC,SAAS;+BACI,mBAAmB,cACjB,IAAI,mBAGC,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\nimport type { StatItem } from './profile-stats.types';\r\n\r\n/**\r\n * Componente para mostrar estadísticas del usuario\r\n * Soporta valores con etiquetas o botones de acción\r\n */\r\n@Component({\r\n selector: 'c80-profile-stats',\r\n standalone: true,\r\n templateUrl: './profile-stats.component.html',\r\n styleUrl: './profile-stats.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class ProfileStatsComponent {\r\n stats = input.required<StatItem[]>();\r\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
+ {"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;AAOH,MAAM,OAAO,qBAAqB;IAC9B,KAAK,GAAG,KAAK,CAAC,QAAQ,2EAAc,CAAC;wGAD5B,qBAAqB;4FAArB,qBAAqB,gNCblC,ugBAaM;;4FDAO,qBAAqB;kBANjC,SAAS;+BACI,mBAAmB,mBAGZ,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\nimport type { StatItem } from './profile-stats.types';\r\n\r\n/**\r\n * Componente para mostrar estadísticas del usuario\r\n * Soporta valores con etiquetas o botones de acción\r\n */\r\n@Component({\r\n selector: 'c80-profile-stats',\r\n templateUrl: './profile-stats.component.html',\r\n styleUrl: './profile-stats.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class ProfileStatsComponent {\r\n stats = input.required<StatItem[]>();\r\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>"]}
@@ -17,7 +17,7 @@ export class RatingDisplayComponent {
17
17
  }
18
18
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RatingDisplayComponent, decorators: [{
19
19
  type: Component,
20
- args: [{ selector: 'c80-rating-display', standalone: true, imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
20
+ args: [{ selector: 'c80-rating-display', imports: [IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
21
21
  '[style.--spacing.px]': 'spacing()'
22
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
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 }] }] } });
@@ -1 +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;AAYH,MAAM,OAAO,sBAAsB;IAC/B,MAAM,GAAG,KAAK,CAAS,CAAC,6EAAC,CAAC;IAC1B,IAAI,GAAG,KAAK,CAAS,GAAG,2EAAC,CAAC;IAC1B,OAAO,GAAG,KAAK,CAAS,CAAC,EAAE,8EAAC,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,4EAAC,CAAC;wGARM,sBAAsB;4FAAtB,sBAAsB,qgBCjBnC,iMAIM,wPDKQ,aAAa;;4FAQd,sBAAsB;kBAXlC,SAAS;+BACI,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';\r\nimport { IconComponent } from '../icon';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-rating-display',\r\n standalone: true,\r\n imports: [IconComponent],\r\n templateUrl: './rating-display.component.html',\r\n styleUrl: './rating-display.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n '[style.--spacing.px]': 'spacing()'\r\n }\r\n})\r\nexport class RatingDisplayComponent {\r\n rating = input<number>(0);\r\n size = input<number>(0.1);\r\n spacing = input<number>(-22);\r\n\r\n protected readonly stars = computed(() => {\r\n const rating = Math.round(this.rating());\r\n return Array.from({ length: rating });\r\n });\r\n}\r\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>"]}
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;AAWH,MAAM,OAAO,sBAAsB;IAC/B,MAAM,GAAG,KAAK,CAAS,CAAC,6EAAC,CAAC;IAC1B,IAAI,GAAG,KAAK,CAAS,GAAG,2EAAC,CAAC;IAC1B,OAAO,GAAG,KAAK,CAAS,CAAC,EAAE,8EAAC,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,4EAAC,CAAC;wGARM,sBAAsB;4FAAtB,sBAAsB,qgBChBnC,iMAIM,wPDIQ,aAAa;;4FAQd,sBAAsB;kBAVlC,SAAS;+BACI,oBAAoB,WACrB,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM,QACzC;wBACF,sBAAsB,EAAE,WAAW;qBACtC","sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-rating-display',\r\n imports: [IconComponent],\r\n templateUrl: './rating-display.component.html',\r\n styleUrl: './rating-display.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n '[style.--spacing.px]': 'spacing()'\r\n }\r\n})\r\nexport class RatingDisplayComponent {\r\n rating = input<number>(0);\r\n size = input<number>(0.1);\r\n spacing = input<number>(-22);\r\n\r\n protected readonly stars = computed(() => {\r\n const rating = Math.round(this.rating());\r\n return Array.from({ length: rating });\r\n });\r\n}\r\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>"]}
@@ -9,9 +9,8 @@ export class RatingStarsComponent {
9
9
  showLabel = input(false, ...(ngDevMode ? [{ debugName: "showLabel" }] : /* istanbul ignore next */ []));
10
10
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
11
11
  ratingChange = output();
12
- currentRating = computed(() => this.rating(), ...(ngDevMode ? [{ debugName: "currentRating" }] : /* istanbul ignore next */ []));
13
12
  stars = computed(() => {
14
- const rating = this.currentRating();
13
+ const rating = this.rating();
15
14
  return Array.from({ length: 5 }, (_, i) => i < rating);
16
15
  }, ...(ngDevMode ? [{ debugName: "stars" }] : /* istanbul ignore next */ []));
17
16
  /**
@@ -24,10 +23,10 @@ export class RatingStarsComponent {
24
23
  this.ratingChange.emit(rating);
25
24
  }
26
25
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RatingStarsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
27
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", 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 });
26
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", 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\">{{ rating() }}/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
27
  }
29
28
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: RatingStarsComponent, decorators: [{
30
29
  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"] }]
30
+ args: [{ selector: 'c80-rating-stars', 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\">{{ rating() }}/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
31
  }], 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
32
  //# sourceMappingURL=rating-stars.component.js.map
@@ -1 +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;AASH,MAAM,OAAO,oBAAoB;IAC7B,MAAM,GAAG,KAAK,CAAS,CAAC,6EAAC,CAAC;IAC1B,SAAS,GAAG,KAAK,CAAU,KAAK,gFAAC,CAAC;IAClC,QAAQ,GAAG,KAAK,CAAU,KAAK,+EAAC,CAAC;IAEjC,YAAY,GAAG,MAAM,EAAU,CAAC;IAEb,aAAa,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,oFAAC,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,4EAAC,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,mgBCdjC,8hBAQM,mkBDCQ,aAAa;;4FAKd,oBAAoB;kBARhC,SAAS;+BACI,kBAAkB,cAChB,IAAI,WACP,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-rating-stars',\r\n standalone: true,\r\n imports: [IconComponent],\r\n templateUrl: './rating-stars.component.html',\r\n styleUrl: './rating-stars.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class RatingStarsComponent {\r\n rating = input<number>(0);\r\n showLabel = input<boolean>(false);\r\n readonly = input<boolean>(false);\r\n\r\n ratingChange = output<number>();\r\n\r\n protected readonly currentRating = computed(() => this.rating());\r\n\r\n protected readonly stars = computed(() => {\r\n const rating = this.currentRating();\r\n return Array.from({ length: 5 }, (_, i) => i < rating);\r\n });\r\n\r\n /**\r\n *\r\n * @param rating\r\n */\r\n protected onStarClick(rating: number): void {\r\n if (this.readonly()) return;\r\n this.ratingChange.emit(rating);\r\n }\r\n}\r\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
+ {"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;AAQH,MAAM,OAAO,oBAAoB;IAC7B,MAAM,GAAG,KAAK,CAAS,CAAC,6EAAC,CAAC;IAC1B,SAAS,GAAG,KAAK,CAAU,KAAK,gFAAC,CAAC;IAClC,QAAQ,GAAG,KAAK,CAAU,KAAK,+EAAC,CAAC;IAEjC,YAAY,GAAG,MAAM,EAAU,CAAC;IAEb,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,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,4EAAC,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;wGAnBQ,oBAAoB;4FAApB,oBAAoB,mgBCbjC,uhBAQM,mkBDAQ,aAAa;;4FAKd,oBAAoB;kBAPhC,SAAS;+BACI,kBAAkB,WACnB,CAAC,aAAa,CAAC,mBAGP,uBAAuB,CAAC,MAAM","sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';\r\nimport { IconComponent } from '../icon';\r\n\r\n/**\r\n *\r\n */\r\n@Component({\r\n selector: 'c80-rating-stars',\r\n imports: [IconComponent],\r\n templateUrl: './rating-stars.component.html',\r\n styleUrl: './rating-stars.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class RatingStarsComponent {\r\n rating = input<number>(0);\r\n showLabel = input<boolean>(false);\r\n readonly = input<boolean>(false);\r\n\r\n ratingChange = output<number>();\r\n\r\n protected readonly stars = computed(() => {\r\n const rating = this.rating();\r\n return Array.from({ length: 5 }, (_, i) => i < rating);\r\n });\r\n\r\n /**\r\n *\r\n * @param rating\r\n */\r\n protected onStarClick(rating: number): void {\r\n if (this.readonly()) return;\r\n this.ratingChange.emit(rating);\r\n }\r\n}\r\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\">{{ rating() }}/5</span>\n }\n</div>"]}