@cqa-lib/cqa-ui 0.1.2 → 1.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 (95) hide show
  1. package/esm2020/lib/action-menu/action-menu.component.mjs +42 -0
  2. package/esm2020/lib/assets/images/image-assets.constants.mjs +28 -0
  3. package/esm2020/lib/badge/badge.component.mjs +141 -0
  4. package/esm2020/lib/button/button.component.mjs +42 -67
  5. package/esm2020/lib/column-visibility/column-visibility.component.mjs +69 -0
  6. package/esm2020/lib/dashboards/chart-card/chart-card.component.mjs +22 -0
  7. package/esm2020/lib/dashboards/coverage-module-card/coverage-module-card.component.mjs +104 -0
  8. package/esm2020/lib/dashboards/dashboard-header/dashboard-header.component.mjs +82 -0
  9. package/esm2020/lib/dashboards/failed-test-cases-card/failed-test-cases-card.component.mjs +60 -0
  10. package/esm2020/lib/dashboards/heat-error-map-cell/heat-error-map-cell.component.mjs +45 -0
  11. package/esm2020/lib/dashboards/insight-card/insight-card.component.mjs +201 -0
  12. package/esm2020/lib/dashboards/metrics-card/metrics-block.component.mjs +41 -0
  13. package/esm2020/lib/dashboards/metrics-card/metrics-card-item.interface.mjs +2 -0
  14. package/esm2020/lib/dashboards/metrics-card/metrics-card.component.mjs +62 -0
  15. package/esm2020/lib/dashboards/progress-text-card/progress-text-card.component.mjs +46 -0
  16. package/esm2020/lib/dashboards/test-distribution-card/test-distribution-card.component.mjs +35 -0
  17. package/esm2020/lib/dialog/dialog.component.mjs +4 -4
  18. package/esm2020/lib/dropdown-button/dropdown-button.component.mjs +189 -0
  19. package/esm2020/lib/dynamic-select/dynamic-select-field.component.mjs +160 -0
  20. package/esm2020/lib/empty-state/empty-state.component.mjs +37 -0
  21. package/esm2020/lib/filters/dynamic-filter/dynamic-filter.component.mjs +239 -0
  22. package/esm2020/lib/full-table-loader/full-table-loader.component.mjs +16 -0
  23. package/esm2020/lib/inline-sort/inline-sort.component.mjs +58 -0
  24. package/esm2020/lib/other-button/other-button.component.mjs +76 -0
  25. package/esm2020/lib/pagination/pagination.component.mjs +102 -0
  26. package/esm2020/lib/search-bar/search-bar.component.mjs +3 -3
  27. package/esm2020/lib/segment-control/segment-control.component.mjs +3 -3
  28. package/esm2020/lib/selected-filters/selected-filters.component.mjs +27 -0
  29. package/esm2020/lib/table/dynamic-table/dynamic-cell.directive.mjs +35 -0
  30. package/esm2020/lib/table/dynamic-table/dynamic-table.component.mjs +258 -0
  31. package/esm2020/lib/table-action-toolbar/table-action-toolbar.component.mjs +52 -0
  32. package/esm2020/lib/table-data-loader/table-data-loader.component.mjs +19 -0
  33. package/esm2020/lib/templates/table-template.component.mjs +365 -0
  34. package/esm2020/lib/ui-kit.module.mjs +196 -17
  35. package/esm2020/lib/utils/metadata-colors.util.mjs +100 -0
  36. package/esm2020/lib/utils/tw-overlay-container.mjs +22 -0
  37. package/esm2020/public-api.mjs +29 -1
  38. package/fesm2015/cqa-lib-cqa-ui.mjs +2899 -133
  39. package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
  40. package/fesm2020/cqa-lib-cqa-ui.mjs +2867 -133
  41. package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
  42. package/lib/action-menu/action-menu.component.d.ts +17 -0
  43. package/lib/assets/images/image-assets.constants.d.ts +20 -0
  44. package/lib/badge/badge.component.d.ts +25 -0
  45. package/lib/button/button.component.d.ts +6 -5
  46. package/lib/column-visibility/column-visibility.component.d.ts +33 -0
  47. package/lib/dashboards/chart-card/chart-card.component.d.ts +8 -0
  48. package/lib/dashboards/coverage-module-card/coverage-module-card.component.d.ts +44 -0
  49. package/lib/dashboards/dashboard-header/dashboard-header.component.d.ts +30 -0
  50. package/lib/dashboards/failed-test-cases-card/failed-test-cases-card.component.d.ts +28 -0
  51. package/lib/dashboards/heat-error-map-cell/heat-error-map-cell.component.d.ts +14 -0
  52. package/lib/dashboards/insight-card/insight-card.component.d.ts +73 -0
  53. package/lib/dashboards/metrics-card/metrics-block.component.d.ts +12 -0
  54. package/lib/dashboards/metrics-card/metrics-card-item.interface.d.ts +12 -0
  55. package/lib/dashboards/metrics-card/metrics-card.component.d.ts +17 -0
  56. package/lib/dashboards/progress-text-card/progress-text-card.component.d.ts +13 -0
  57. package/lib/dashboards/test-distribution-card/test-distribution-card.component.d.ts +29 -0
  58. package/lib/dropdown-button/dropdown-button.component.d.ts +32 -0
  59. package/lib/dynamic-select/dynamic-select-field.component.d.ts +43 -0
  60. package/lib/empty-state/empty-state.component.d.ts +20 -0
  61. package/lib/filters/dynamic-filter/dynamic-filter.component.d.ts +56 -0
  62. package/lib/full-table-loader/full-table-loader.component.d.ts +6 -0
  63. package/lib/inline-sort/inline-sort.component.d.ts +12 -0
  64. package/lib/other-button/other-button.component.d.ts +37 -0
  65. package/lib/pagination/pagination.component.d.ts +37 -0
  66. package/lib/selected-filters/selected-filters.component.d.ts +17 -0
  67. package/lib/table/dynamic-table/dynamic-cell.directive.d.ts +16 -0
  68. package/lib/table/dynamic-table/dynamic-table.component.d.ts +72 -0
  69. package/lib/table-action-toolbar/table-action-toolbar.component.d.ts +34 -0
  70. package/lib/table-data-loader/table-data-loader.component.d.ts +7 -0
  71. package/lib/templates/table-template.component.d.ts +90 -0
  72. package/lib/ui-kit.module.d.ts +43 -6
  73. package/lib/utils/metadata-colors.util.d.ts +50 -0
  74. package/lib/utils/tw-overlay-container.d.ts +12 -0
  75. package/package.json +1 -1
  76. package/public-api.d.ts +28 -0
  77. package/src/lib/assets/images/.gitkeep +0 -0
  78. package/src/lib/assets/images/DashboardIcon.png +0 -0
  79. package/src/lib/assets/images/FilesIcon.png +0 -0
  80. package/src/lib/assets/images/README.md +66 -0
  81. package/src/lib/assets/images/ReportsIcon.png +0 -0
  82. package/src/lib/assets/images/SearchIcon.png +0 -0
  83. package/src/lib/assets/images/StepsIcon.png +0 -0
  84. package/src/lib/assets/images/TestCaseIcon.png +0 -0
  85. package/src/lib/assets/images/analytics-chart-icon.svg +11 -0
  86. package/src/lib/assets/images/checklist-add-icon.svg +10 -0
  87. package/src/lib/assets/images/document-gear-icon.svg +9 -0
  88. package/src/lib/assets/images/empty-state-default-icon.svg +8 -0
  89. package/src/lib/assets/images/image-assets.constants.ts +38 -0
  90. package/src/lib/assets/images/search-debug-icon.svg +8 -0
  91. package/src/lib/assets/images/test-case-icon.svg +9 -0
  92. package/src/lib/assets/images/upload-folder-icon.svg +7 -0
  93. package/src/lib/utils/metadata-colors.constants.js +33 -0
  94. package/storybook-static/assets/images/README.md +66 -0
  95. package/styles.css +1 -1
@@ -1,13 +1,32 @@
1
1
  import * as i0 from '@angular/core';
2
- import { EventEmitter, Component, Input, Output, HostListener, ViewChildren, ViewChild, ChangeDetectionStrategy, NgModule, InjectionToken, Injector, Injectable } from '@angular/core';
2
+ import { EventEmitter, Component, Input, Output, HostListener, ViewChildren, ViewChild, ChangeDetectionStrategy, Directive, TemplateRef, ContentChildren, ContentChild, ElementRef, Injectable, NgModule, InjectionToken, Injector } from '@angular/core';
3
3
  import * as i2 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
- import * as i2$1 from '@angular/forms';
6
- import { FormsModule } from '@angular/forms';
5
+ import * as i1$1 from '@angular/forms';
6
+ import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
7
7
  import * as i1 from '@angular/material/icon';
8
8
  import { MatIconModule } from '@angular/material/icon';
9
- import * as i1$1 from '@angular/cdk/overlay';
10
- import { OverlayModule, OverlayConfig } from '@angular/cdk/overlay';
9
+ import * as i1$2 from '@angular/material/tooltip';
10
+ import { MatTooltipModule } from '@angular/material/tooltip';
11
+ import * as i3$1 from '@angular/material/menu';
12
+ import { MatMenuModule } from '@angular/material/menu';
13
+ import * as i1$3 from '@angular/material/button';
14
+ import { MatButtonModule } from '@angular/material/button';
15
+ import * as i3$2 from '@angular/material/form-field';
16
+ import { MatFormFieldModule } from '@angular/material/form-field';
17
+ import * as i2$1 from '@angular/material/select';
18
+ import { MatSelectModule } from '@angular/material/select';
19
+ import * as i3$3 from '@angular/material/core';
20
+ import { MatOptionModule, MatNativeDateModule } from '@angular/material/core';
21
+ import * as i3$4 from '@angular/material/checkbox';
22
+ import { MatCheckboxModule } from '@angular/material/checkbox';
23
+ import * as i4$1 from '@angular/material/radio';
24
+ import { MatRadioModule } from '@angular/material/radio';
25
+ import * as i4 from '@angular/material/datepicker';
26
+ import { MatDatepickerModule } from '@angular/material/datepicker';
27
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
28
+ import * as i1$4 from '@angular/cdk/overlay';
29
+ import { OverlayContainer, OverlayModule, OverlayConfig } from '@angular/cdk/overlay';
11
30
  import * as i3 from '@angular/cdk/portal';
12
31
  import { TemplatePortal, CdkPortalOutlet, PortalModule, ComponentPortal } from '@angular/cdk/portal';
13
32
  import { __awaiter } from 'tslib';
@@ -19,6 +38,7 @@ class ButtonComponent {
19
38
  this.variant = 'filled';
20
39
  this.disabled = false;
21
40
  this.iconPosition = 'start';
41
+ this.fullWidth = false;
22
42
  this.type = 'button';
23
43
  this.clicked = new EventEmitter();
24
44
  // Internal state tracking
@@ -31,74 +51,26 @@ class ButtonComponent {
31
51
  }
32
52
  get buttonClasses() {
33
53
  const baseClasses = [
34
- 'cqa-flex',
35
- 'cqa-flex-col',
36
- 'cqa-justify-center',
54
+ 'cqa-inline-flex',
37
55
  'cqa-items-center',
38
- 'cqa-p-0',
39
- 'cqa-gap-2',
40
- 'cqa-rounded-lg',
41
- 'cqa-cursor-pointer',
42
- 'cqa-font-inter',
43
- 'cqa-font-semibold',
44
- 'cqa-text-sm',
45
- 'cqa-leading-[14px]',
46
- 'cqa-transition-all',
47
- 'cqa-duration-200',
48
- 'cqa-outline-none'
49
- ];
50
- if (this.disabled) {
51
- baseClasses.push('cqa-cursor-not-allowed');
52
- }
53
- // Add variant and state specific classes
54
- const variantClasses = this.getVariantClasses();
55
- return [...baseClasses, ...variantClasses].join(' ');
56
- }
57
- get stateLayerClasses() {
58
- const classes = [
59
- 'cqa-flex',
60
- 'cqa-flex-row',
61
56
  'cqa-justify-center',
62
- 'cqa-items-center',
63
57
  'cqa-gap-2',
64
- 'cqa-w-full',
65
- 'cqa-h-full',
66
58
  'cqa-py-[10px]',
67
- 'cqa-px-6',
68
- ];
69
- return classes.join(' ');
70
- }
71
- get labelClasses() {
72
- const classes = [
73
- 'cqa-flex',
74
- 'cqa-items-center',
75
- 'cqa-text-center',
76
- 'cqa-font-inter',
77
- 'cqa-font-semibold',
78
- 'cqa-text-sm',
79
- 'cqa-leading-[14px]',
80
- 'cqa-flex-none',
81
- this.textClass,
59
+ 'cqa-rounded-[8px]',
60
+ 'cqa-text-[12.3px]',
61
+ 'cqa-leading-[17.5px]',
62
+ 'cqa-font-medium',
63
+ 'cqa-border',
82
64
  ];
83
65
  if (this.disabled) {
84
- classes.push('cqa-opacity-[0.38]');
66
+ baseClasses.push('cqa-cursor-not-allowed');
85
67
  }
86
- return classes.join(' ');
87
- }
88
- get iconClasses() {
89
- const classes = [
90
- 'cqa-flex',
91
- 'cqa-items-center',
92
- 'cqa-justify-center',
93
- 'cqa-w-[14px]',
94
- 'cqa-h-[14px]',
95
- 'cqa-shrink-0',
96
- 'cqa-flex-none'
97
- ];
98
- if (this.disabled) {
99
- classes.push('cqa-opacity-[0.38]');
68
+ if (this.fullWidth) {
69
+ baseClasses.push('cqa-w-full');
100
70
  }
101
- return classes.join(' ');
71
+ // Add variant and state specific classes
72
+ const variantClasses = this.getVariantClasses();
73
+ return [...baseClasses, ...variantClasses, ...(this.customClass ? [this.customClass] : [])].join(' ');
102
74
  }
103
75
  getVariantClasses() {
104
76
  const classes = [];
@@ -107,9 +79,21 @@ class ButtonComponent {
107
79
  classes.push('cqa-bg-primary-muted');
108
80
  }
109
81
  else {
110
- classes.push('cqa-bg-primary');
82
+ classes.push('cqa-bg-primary cqa-text-white');
83
+ if (this.isHovered) {
84
+ classes.push('cqa-bg-primary-hover');
85
+ }
86
+ }
87
+ }
88
+ else if (this.variant === 'grey-solid') {
89
+ // Neutral grey solid style
90
+ if (this.disabled) {
91
+ classes.push('cqa-bg-grey-400', 'cqa-border', 'cqa-border-primary-muted');
92
+ }
93
+ else {
94
+ classes.push('cqa-bg-grey-400', 'cqa-border', 'cqa-border-primary-muted');
111
95
  if (this.isHovered) {
112
- classes.push('cqa-shadow-[0px_1px_2px_rgba(0,0,0,0.3),0px_1px_3px_1px_rgba(0,0,0,0.15)]');
96
+ classes.push('cqa-bg-grey-200');
113
97
  }
114
98
  }
115
99
  }
@@ -131,10 +115,10 @@ class ButtonComponent {
131
115
  }
132
116
  else if (this.variant === 'text') {
133
117
  if (this.disabled) {
134
- classes.push('cqa-bg-transparent');
118
+ classes.push('cqa-bg-transparent', 'cqa-border-none');
135
119
  }
136
120
  else {
137
- classes.push('cqa-bg-transparent');
121
+ classes.push('cqa-bg-transparent', 'cqa-border-none');
138
122
  if (this.isHovered || this.isFocused || this.isPressed) {
139
123
  classes.push('cqa-bg-primary-surface');
140
124
  }
@@ -184,6 +168,8 @@ class ButtonComponent {
184
168
  switch (this.variant) {
185
169
  case 'filled':
186
170
  return 'cqa-text-surface-default';
171
+ case 'grey-solid':
172
+ return 'cqa-text-black-100';
187
173
  case 'outlined':
188
174
  if (this.isFocused || this.isHovered || this.isPressed) {
189
175
  return 'cqa-text-primary-hover';
@@ -231,10 +217,10 @@ class ButtonComponent {
231
217
  }
232
218
  }
233
219
  ButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
234
- ButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ButtonComponent, selector: "cqa-button", inputs: { variant: "variant", disabled: "disabled", icon: "icon", iconPosition: "iconPosition", type: "type" }, outputs: { clicked: "clicked" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "mousedown": "onMouseDown()", "mouseup": "onMouseUp()", "focus": "onFocus()", "blur": "onBlur()" } }, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"display: inline-block; width: auto;\">\n <button\n [type]=\"type\"\n [disabled]=\"disabled\"\n [attr.aria-disabled]=\"disabled\"\n [class]=\"buttonClasses\"\n (click)=\"onClick($event)\"\n >\n <span [class]=\"stateLayerClasses\">\n <span *ngIf=\"icon && iconPosition === 'start'\" [class]=\"iconClasses\" [ngClass]=\"textClass\">\n <mat-icon class=\"cqa-text-[18px] cqa-leading-[18px] cqa-w-[18px] cqa-h-[18px]\">\n {{ icon }}\n </mat-icon>\n </span>\n <span [class]=\"labelClasses\" [ngClass]=\"textClass\">\n <ng-content></ng-content>\n </span>\n <span *ngIf=\"icon && iconPosition === 'end'\" [class]=\"iconClasses\" [ngClass]=\"textClass\">\n <mat-icon class=\"cqa-text-[18px] cqa-leading-[18px] cqa-w-[18px] cqa-h-[18px]\">\n {{ icon }}\n </mat-icon>\n </span>\n </span>\n </button>\n</div>\n\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
220
+ ButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ButtonComponent, selector: "cqa-button", inputs: { variant: "variant", disabled: "disabled", icon: "icon", iconPosition: "iconPosition", fullWidth: "fullWidth", iconColor: "iconColor", type: "type", text: "text", customClass: "customClass" }, outputs: { clicked: "clicked" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()", "mousedown": "onMouseDown()", "mouseup": "onMouseUp()", "focus": "onFocus()", "blur": "onBlur()" } }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <button\n [ngClass]=\"\n text && icon && iconPosition === 'start' ? 'cqa-pr-[24px] cqa-pl-[16px]' :\n text && icon && iconPosition === 'end' ? 'cqa-pl-[24px] cqa-pr-[16px]' :\n text && !icon ? 'cqa-px-[24px]' : !text && icon ? 'cqa-px-[12px]' : 'cqa-px-[24px]'\"\n [type]=\"type\"\n [disabled]=\"disabled\"\n [attr.aria-disabled]=\"disabled\"\n [class]=\"buttonClasses\"\n (click)=\"onClick($event)\"\n >\n\n <mat-icon *ngIf=\"icon && iconPosition === 'start'\" class=\"!cqa-w-[18px] !cqa-h-[18px] !cqa-text-[18px]\" [style.color]=\"iconColor\">\n {{ icon }}\n </mat-icon>\n\n <!-- Dynamic text support -->\n <span *ngIf=\"text\">{{text}}</span>\n\n <ng-content *ngIf=\"!text\" ></ng-content>\n\n <mat-icon *ngIf=\"icon && iconPosition === 'end'\" class=\"!cqa-w-[18px] !cqa-h-[18px] !cqa-text-[18px]\" [style.color]=\"iconColor\">\n {{ icon }}\n </mat-icon>\n\n </button>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
235
221
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ButtonComponent, decorators: [{
236
222
  type: Component,
237
- args: [{ selector: 'cqa-button', template: "<div id=\"cqa-ui-root\" style=\"display: inline-block; width: auto;\">\n <button\n [type]=\"type\"\n [disabled]=\"disabled\"\n [attr.aria-disabled]=\"disabled\"\n [class]=\"buttonClasses\"\n (click)=\"onClick($event)\"\n >\n <span [class]=\"stateLayerClasses\">\n <span *ngIf=\"icon && iconPosition === 'start'\" [class]=\"iconClasses\" [ngClass]=\"textClass\">\n <mat-icon class=\"cqa-text-[18px] cqa-leading-[18px] cqa-w-[18px] cqa-h-[18px]\">\n {{ icon }}\n </mat-icon>\n </span>\n <span [class]=\"labelClasses\" [ngClass]=\"textClass\">\n <ng-content></ng-content>\n </span>\n <span *ngIf=\"icon && iconPosition === 'end'\" [class]=\"iconClasses\" [ngClass]=\"textClass\">\n <mat-icon class=\"cqa-text-[18px] cqa-leading-[18px] cqa-w-[18px] cqa-h-[18px]\">\n {{ icon }}\n </mat-icon>\n </span>\n </span>\n </button>\n</div>\n\n", styles: [] }]
223
+ args: [{ selector: 'cqa-button', template: "<div id=\"cqa-ui-root\">\n <button\n [ngClass]=\"\n text && icon && iconPosition === 'start' ? 'cqa-pr-[24px] cqa-pl-[16px]' :\n text && icon && iconPosition === 'end' ? 'cqa-pl-[24px] cqa-pr-[16px]' :\n text && !icon ? 'cqa-px-[24px]' : !text && icon ? 'cqa-px-[12px]' : 'cqa-px-[24px]'\"\n [type]=\"type\"\n [disabled]=\"disabled\"\n [attr.aria-disabled]=\"disabled\"\n [class]=\"buttonClasses\"\n (click)=\"onClick($event)\"\n >\n\n <mat-icon *ngIf=\"icon && iconPosition === 'start'\" class=\"!cqa-w-[18px] !cqa-h-[18px] !cqa-text-[18px]\" [style.color]=\"iconColor\">\n {{ icon }}\n </mat-icon>\n\n <!-- Dynamic text support -->\n <span *ngIf=\"text\">{{text}}</span>\n\n <ng-content *ngIf=\"!text\" ></ng-content>\n\n <mat-icon *ngIf=\"icon && iconPosition === 'end'\" class=\"!cqa-w-[18px] !cqa-h-[18px] !cqa-text-[18px]\" [style.color]=\"iconColor\">\n {{ icon }}\n </mat-icon>\n\n </button>\n</div>", styles: [] }]
238
224
  }], propDecorators: { variant: [{
239
225
  type: Input
240
226
  }], disabled: [{
@@ -243,8 +229,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
243
229
  type: Input
244
230
  }], iconPosition: [{
245
231
  type: Input
232
+ }], fullWidth: [{
233
+ type: Input
234
+ }], iconColor: [{
235
+ type: Input
246
236
  }], type: [{
247
237
  type: Input
238
+ }], text: [{
239
+ type: Input
240
+ }], customClass: [{
241
+ type: Input
248
242
  }], clicked: [{
249
243
  type: Output
250
244
  }], onMouseEnter: [{
@@ -331,10 +325,10 @@ class SearchBarComponent {
331
325
  }
332
326
  }
333
327
  SearchBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SearchBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
334
- SearchBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SearchBarComponent, selector: "cqa-search-bar", inputs: { placeholder: "placeholder", value: "value", disabled: "disabled", showClear: "showClear", ariaLabel: "ariaLabel", autoFocus: "autoFocus", size: "size", fullWidth: "fullWidth" }, outputs: { valueChange: "valueChange", search: "search", cleared: "cleared" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\" [style.display]=\"fullWidth ? 'block' : 'inline-block'\" [style.width]=\"fullWidth ? '100%' : 'auto'\">\n <form\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-6 cqa-py-3 cqa-text-[14px] cqa-border cqa-border-gray-200 cqa-rounded-md cqa-bg-white cqa-shadow-sm cqa-transition-colors\"\n [ngClass]=\"fullWidth ? 'cqa-w-full' : widthClasses[size]\"\n (submit)=\"onSubmit($event)\"\n >\n <span\n class=\"cqa-flex-none cqa-flex cqa-items-center cqa-justify-center cqa-text-gray-400 cqa-w-4 cqa-h-4\"\n [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\"\n >\n <mat-icon\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\"\n [style.width.px]=\"16\"\n [style.height.px]=\"16\"\n [style.fontSize.px]=\"16\"\n >\n search\n </mat-icon>\n </span>\n\n <input\n type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[180px] cqa-border-none cqa-outline-none cqa-bg-transparent placeholder:cqa-text-gray-400 disabled:cqa-text-gray-400 disabled:cqa-cursor-not-allowed cqa-font-['SF_Pro_Text'] cqa-font-normal cqa-text-[12.3px] cqa-leading-none cqa-tracking-normal cqa-align-middle cqa-text-[#99999E]\"\n style=\"font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; letter-spacing: 0;\"\n [placeholder]=\"placeholder\"\n [value]=\"inputValue\"\n (input)=\"onInput($event)\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"ariaLabel\"\n autocomplete=\"off\"\n autocapitalize=\"none\"\n spellcheck=\"false\"\n [attr.autofocus]=\"autoFocus ? '' : null\"\n />\n\n <button\n *ngIf=\"showClear && inputValue\"\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-p-0 cqa-w-4 cqa-h-4 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer cqa-text-gray-500 cqa-hover:cqa-text-gray-700 disabled:cqa-text-gray-300 cqa-transition-colors cqa-leading-none\"\n (click)=\"clear()\"\n [disabled]=\"disabled\"\n aria-label=\"Clear search\"\n >\n <mat-icon\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\"\n [style.width.px]=\"16\"\n [style.height.px]=\"16\"\n [style.fontSize.px]=\"16\"\n [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\"\n >\n close\n </mat-icon>\n </button>\n </form>\n</div>\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
328
+ SearchBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SearchBarComponent, selector: "cqa-search-bar", inputs: { placeholder: "placeholder", value: "value", disabled: "disabled", showClear: "showClear", ariaLabel: "ariaLabel", autoFocus: "autoFocus", size: "size", fullWidth: "fullWidth" }, outputs: { valueChange: "valueChange", search: "search", cleared: "cleared" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\" [style.display]=\"fullWidth ? 'block' : 'inline-block'\"\n [style.width]=\"fullWidth ? '100%' : 'auto'\">\n <form\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-6 cqa-py-3 cqa-text-[14px] cqa-border cqa-border-gray-200 cqa-rounded-md cqa-bg-white cqa-shadow-sm cqa-transition-colors\"\n [ngClass]=\"fullWidth ? 'cqa-w-full' : widthClasses[size]\" (submit)=\"onSubmit($event)\">\n <span class=\"cqa-flex-none cqa-flex cqa-items-center cqa-justify-center cqa-text-gray-400 cqa-w-4 cqa-h-4\"\n [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\">\n <mat-icon class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\" [style.width.px]=\"16\"\n [style.height.px]=\"16\" [style.fontSize.px]=\"16\">\n search\n </mat-icon>\n </span>\n\n <input\n type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[180px] cqa-border-none cqa-outline-none cqa-bg-transparent placeholder:cqa-text-gray-400 disabled:cqa-text-gray-400 disabled:cqa-cursor-not-allowed cqa-font-['SF_Pro_Text'] cqa-font-normal cqa-text-[12.3px] cqa-leading-none cqa-tracking-normal cqa-align-middle cqa-text-muted\"\n [placeholder]=\"placeholder\"\n [value]=\"inputValue\"\n (input)=\"onInput($event)\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"ariaLabel\"\n autocomplete=\"off\"\n autocapitalize=\"none\"\n spellcheck=\"false\"\n [attr.autofocus]=\"autoFocus ? '' : null\"\n />\n\n <button *ngIf=\"showClear && inputValue\" type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-p-0 cqa-w-4 cqa-h-4 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer cqa-text-gray-500 cqa-hover:cqa-text-gray-700 disabled:cqa-text-gray-300 cqa-transition-colors cqa-leading-none\"\n (click)=\"clear()\" [disabled]=\"disabled\" aria-label=\"Clear search\">\n <mat-icon class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\" [style.width.px]=\"16\"\n [style.height.px]=\"16\" [style.fontSize.px]=\"16\" [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\">\n close\n </mat-icon>\n </button>\n </form>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
335
329
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SearchBarComponent, decorators: [{
336
330
  type: Component,
337
- args: [{ selector: 'cqa-search-bar', template: "<div id=\"cqa-ui-root\" [style.display]=\"fullWidth ? 'block' : 'inline-block'\" [style.width]=\"fullWidth ? '100%' : 'auto'\">\n <form\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-6 cqa-py-3 cqa-text-[14px] cqa-border cqa-border-gray-200 cqa-rounded-md cqa-bg-white cqa-shadow-sm cqa-transition-colors\"\n [ngClass]=\"fullWidth ? 'cqa-w-full' : widthClasses[size]\"\n (submit)=\"onSubmit($event)\"\n >\n <span\n class=\"cqa-flex-none cqa-flex cqa-items-center cqa-justify-center cqa-text-gray-400 cqa-w-4 cqa-h-4\"\n [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\"\n >\n <mat-icon\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\"\n [style.width.px]=\"16\"\n [style.height.px]=\"16\"\n [style.fontSize.px]=\"16\"\n >\n search\n </mat-icon>\n </span>\n\n <input\n type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[180px] cqa-border-none cqa-outline-none cqa-bg-transparent placeholder:cqa-text-gray-400 disabled:cqa-text-gray-400 disabled:cqa-cursor-not-allowed cqa-font-['SF_Pro_Text'] cqa-font-normal cqa-text-[12.3px] cqa-leading-none cqa-tracking-normal cqa-align-middle cqa-text-[#99999E]\"\n style=\"font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; letter-spacing: 0;\"\n [placeholder]=\"placeholder\"\n [value]=\"inputValue\"\n (input)=\"onInput($event)\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"ariaLabel\"\n autocomplete=\"off\"\n autocapitalize=\"none\"\n spellcheck=\"false\"\n [attr.autofocus]=\"autoFocus ? '' : null\"\n />\n\n <button\n *ngIf=\"showClear && inputValue\"\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-p-0 cqa-w-4 cqa-h-4 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer cqa-text-gray-500 cqa-hover:cqa-text-gray-700 disabled:cqa-text-gray-300 cqa-transition-colors cqa-leading-none\"\n (click)=\"clear()\"\n [disabled]=\"disabled\"\n aria-label=\"Clear search\"\n >\n <mat-icon\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\"\n [style.width.px]=\"16\"\n [style.height.px]=\"16\"\n [style.fontSize.px]=\"16\"\n [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\"\n >\n close\n </mat-icon>\n </button>\n </form>\n</div>\n", styles: [] }]
331
+ args: [{ selector: 'cqa-search-bar', template: "<div id=\"cqa-ui-root\" [style.display]=\"fullWidth ? 'block' : 'inline-block'\"\n [style.width]=\"fullWidth ? '100%' : 'auto'\">\n <form\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-6 cqa-py-3 cqa-text-[14px] cqa-border cqa-border-gray-200 cqa-rounded-md cqa-bg-white cqa-shadow-sm cqa-transition-colors\"\n [ngClass]=\"fullWidth ? 'cqa-w-full' : widthClasses[size]\" (submit)=\"onSubmit($event)\">\n <span class=\"cqa-flex-none cqa-flex cqa-items-center cqa-justify-center cqa-text-gray-400 cqa-w-4 cqa-h-4\"\n [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\">\n <mat-icon class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\" [style.width.px]=\"16\"\n [style.height.px]=\"16\" [style.fontSize.px]=\"16\">\n search\n </mat-icon>\n </span>\n\n <input\n type=\"text\"\n class=\"cqa-flex-1 cqa-min-w-[180px] cqa-border-none cqa-outline-none cqa-bg-transparent placeholder:cqa-text-gray-400 disabled:cqa-text-gray-400 disabled:cqa-cursor-not-allowed cqa-font-['SF_Pro_Text'] cqa-font-normal cqa-text-[12.3px] cqa-leading-none cqa-tracking-normal cqa-align-middle cqa-text-muted\"\n [placeholder]=\"placeholder\"\n [value]=\"inputValue\"\n (input)=\"onInput($event)\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"ariaLabel\"\n autocomplete=\"off\"\n autocapitalize=\"none\"\n spellcheck=\"false\"\n [attr.autofocus]=\"autoFocus ? '' : null\"\n />\n\n <button *ngIf=\"showClear && inputValue\" type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-p-0 cqa-w-4 cqa-h-4 cqa-border-0 cqa-bg-transparent cqa-cursor-pointer cqa-text-gray-500 cqa-hover:cqa-text-gray-700 disabled:cqa-text-gray-300 cqa-transition-colors cqa-leading-none\"\n (click)=\"clear()\" [disabled]=\"disabled\" aria-label=\"Clear search\">\n <mat-icon class=\"cqa-flex cqa-items-center cqa-justify-center cqa-leading-none cqa-p-0\" [style.width.px]=\"16\"\n [style.height.px]=\"16\" [style.fontSize.px]=\"16\" [ngClass]=\"{ 'cqa-opacity-[0.38]': disabled }\">\n close\n </mat-icon>\n </button>\n </form>\n</div>", styles: [] }]
338
332
  }], propDecorators: { placeholder: [{
339
333
  type: Input
340
334
  }], value: [{
@@ -550,10 +544,10 @@ class SegmentControlComponent {
550
544
  }
551
545
  }
552
546
  SegmentControlComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SegmentControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
553
- SegmentControlComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SegmentControlComponent, selector: "cqa-segment-control", inputs: { segments: "segments", value: "value", disabled: "disabled" }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "segmentContainer", first: true, predicate: ["segmentContainer"], descendants: true }, { propertyName: "segmentButtons", predicate: ["segmentButton"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <div\n #segmentContainer\n class=\"cqa-relative cqa-inline-flex cqa-flex-row cqa-items-start cqa-p-[3.5px] cqa-h-[31.5px] cqa-bg-[#F5F5F5] cqa-rounded-[8px]\"\n role=\"tablist\"\n [attr.aria-disabled]=\"disabled || null\"\n >\n <div\n class=\"cqa-absolute cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-pointer-events-none\"\n [class.cqa-opacity-0]=\"!isIndicatorVisible\"\n [ngStyle]=\"indicatorStyle\"\n aria-hidden=\"true\"\n ></div>\n\n <button\n *ngFor=\"let segment of segments; index as index; trackBy: trackByValue\"\n #segmentButton\n type=\"button\"\n role=\"tab\"\n class=\"cqa-relative cqa-z-10 cqa-flex cqa-flex-col cqa-justify-center cqa-items-center cqa-px-[14px] cqa-py-[3.5px] cqa-h-[25px] cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-whitespace-nowrap cqa-text-center focus:cqa-outline-none focus-visible:cqa-outline-none focus-visible:cqa-ring-0 focus-visible:cqa-ring-offset-0 cqa-flex-none\"\n [ngClass]=\"{\n 'cqa-text-white cqa-font-medium': isSelected(segment),\n 'cqa-text-[#99999E]': !isSelected(segment) && !(disabled || segment.disabled),\n 'cqa-cursor-not-allowed': disabled || segment.disabled,\n 'cqa-text-[#C7C7C7]': (disabled || segment.disabled) && !isSelected(segment),\n 'cqa-hover:cqa-text-black': !isSelected(segment) && !disabled && !segment.disabled\n }\"\n [disabled]=\"disabled || segment.disabled\"\n [attr.aria-selected]=\"isSelected(segment)\"\n [attr.tabindex]=\"!disabled && !segment.disabled ? (isSelected(segment) ? 0 : -1) : -1\"\n (click)=\"select(segment, index)\"\n (keydown)=\"onKeyDown($event, index)\"\n >\n <span class=\"cqa-flex cqa-items-center cqa-justify-center cqa-h-[18px] cqa-font-['Inter'] cqa-font-normal cqa-text-[12px] cqa-leading-[12px] cqa-text-center cqa-align-middle\">\n {{ segment.label }}\n </span>\n </button>\n </div>\n</div>\n", directives: [{ type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
547
+ SegmentControlComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SegmentControlComponent, selector: "cqa-segment-control", inputs: { segments: "segments", value: "value", disabled: "disabled" }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "segmentContainer", first: true, predicate: ["segmentContainer"], descendants: true }, { propertyName: "segmentButtons", predicate: ["segmentButton"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <div\n #segmentContainer\n class=\"cqa-relative cqa-inline-flex cqa-flex-row cqa-items-start cqa-p-[3.5px] cqa-h-[31.5px] cqa-bg-surface-light cqa-rounded-[8px]\"\n role=\"tablist\"\n [attr.aria-disabled]=\"disabled || null\"\n >\n <div\n class=\"cqa-absolute cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-pointer-events-none\"\n [class.cqa-opacity-0]=\"!isIndicatorVisible\" [ngStyle]=\"indicatorStyle\" aria-hidden=\"true\"></div>\n\n <button *ngFor=\"let segment of segments; index as index; trackBy: trackByValue\" #segmentButton type=\"button\"\n role=\"tab\"\n class=\"cqa-relative cqa-z-10 cqa-flex cqa-flex-col cqa-justify-center cqa-items-center cqa-px-[14px] cqa-py-[3.5px] cqa-h-[25px] cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-whitespace-nowrap cqa-text-center focus:cqa-outline-none focus-visible:cqa-outline-none focus-visible:cqa-ring-0 focus-visible:cqa-ring-offset-0 cqa-flex-none\"\n [ngClass]=\"{\n 'cqa-text-white cqa-font-medium': isSelected(segment),\n 'cqa-text-muted': !isSelected(segment) && !(disabled || segment.disabled),\n 'cqa-cursor-not-allowed': disabled || segment.disabled,\n 'cqa-text-disabled': (disabled || segment.disabled) && !isSelected(segment),\n 'cqa-hover:cqa-text-black': !isSelected(segment) && !disabled && !segment.disabled\n }\" [disabled]=\"disabled || segment.disabled\" [attr.aria-selected]=\"isSelected(segment)\"\n [attr.tabindex]=\"!disabled && !segment.disabled ? (isSelected(segment) ? 0 : -1) : -1\"\n (click)=\"select(segment, index)\" (keydown)=\"onKeyDown($event, index)\">\n <span\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-h-[18px] cqa-font-['Inter'] cqa-font-normal cqa-text-[12px] cqa-leading-[12px] cqa-text-center cqa-align-middle\">\n {{ segment.label }}\n </span>\n </button>\n </div>\n</div>", directives: [{ type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
554
548
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SegmentControlComponent, decorators: [{
555
549
  type: Component,
556
- args: [{ selector: 'cqa-segment-control', template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <div\n #segmentContainer\n class=\"cqa-relative cqa-inline-flex cqa-flex-row cqa-items-start cqa-p-[3.5px] cqa-h-[31.5px] cqa-bg-[#F5F5F5] cqa-rounded-[8px]\"\n role=\"tablist\"\n [attr.aria-disabled]=\"disabled || null\"\n >\n <div\n class=\"cqa-absolute cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-pointer-events-none\"\n [class.cqa-opacity-0]=\"!isIndicatorVisible\"\n [ngStyle]=\"indicatorStyle\"\n aria-hidden=\"true\"\n ></div>\n\n <button\n *ngFor=\"let segment of segments; index as index; trackBy: trackByValue\"\n #segmentButton\n type=\"button\"\n role=\"tab\"\n class=\"cqa-relative cqa-z-10 cqa-flex cqa-flex-col cqa-justify-center cqa-items-center cqa-px-[14px] cqa-py-[3.5px] cqa-h-[25px] cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-whitespace-nowrap cqa-text-center focus:cqa-outline-none focus-visible:cqa-outline-none focus-visible:cqa-ring-0 focus-visible:cqa-ring-offset-0 cqa-flex-none\"\n [ngClass]=\"{\n 'cqa-text-white cqa-font-medium': isSelected(segment),\n 'cqa-text-[#99999E]': !isSelected(segment) && !(disabled || segment.disabled),\n 'cqa-cursor-not-allowed': disabled || segment.disabled,\n 'cqa-text-[#C7C7C7]': (disabled || segment.disabled) && !isSelected(segment),\n 'cqa-hover:cqa-text-black': !isSelected(segment) && !disabled && !segment.disabled\n }\"\n [disabled]=\"disabled || segment.disabled\"\n [attr.aria-selected]=\"isSelected(segment)\"\n [attr.tabindex]=\"!disabled && !segment.disabled ? (isSelected(segment) ? 0 : -1) : -1\"\n (click)=\"select(segment, index)\"\n (keydown)=\"onKeyDown($event, index)\"\n >\n <span class=\"cqa-flex cqa-items-center cqa-justify-center cqa-h-[18px] cqa-font-['Inter'] cqa-font-normal cqa-text-[12px] cqa-leading-[12px] cqa-text-center cqa-align-middle\">\n {{ segment.label }}\n </span>\n </button>\n </div>\n</div>\n", styles: [] }]
550
+ args: [{ selector: 'cqa-segment-control', template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <div\n #segmentContainer\n class=\"cqa-relative cqa-inline-flex cqa-flex-row cqa-items-start cqa-p-[3.5px] cqa-h-[31.5px] cqa-bg-surface-light cqa-rounded-[8px]\"\n role=\"tablist\"\n [attr.aria-disabled]=\"disabled || null\"\n >\n <div\n class=\"cqa-absolute cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-pointer-events-none\"\n [class.cqa-opacity-0]=\"!isIndicatorVisible\" [ngStyle]=\"indicatorStyle\" aria-hidden=\"true\"></div>\n\n <button *ngFor=\"let segment of segments; index as index; trackBy: trackByValue\" #segmentButton type=\"button\"\n role=\"tab\"\n class=\"cqa-relative cqa-z-10 cqa-flex cqa-flex-col cqa-justify-center cqa-items-center cqa-px-[14px] cqa-py-[3.5px] cqa-h-[25px] cqa-rounded-[8px] cqa-transition-all cqa-duration-200 cqa-ease-in-out cqa-whitespace-nowrap cqa-text-center focus:cqa-outline-none focus-visible:cqa-outline-none focus-visible:cqa-ring-0 focus-visible:cqa-ring-offset-0 cqa-flex-none\"\n [ngClass]=\"{\n 'cqa-text-white cqa-font-medium': isSelected(segment),\n 'cqa-text-muted': !isSelected(segment) && !(disabled || segment.disabled),\n 'cqa-cursor-not-allowed': disabled || segment.disabled,\n 'cqa-text-disabled': (disabled || segment.disabled) && !isSelected(segment),\n 'cqa-hover:cqa-text-black': !isSelected(segment) && !disabled && !segment.disabled\n }\" [disabled]=\"disabled || segment.disabled\" [attr.aria-selected]=\"isSelected(segment)\"\n [attr.tabindex]=\"!disabled && !segment.disabled ? (isSelected(segment) ? 0 : -1) : -1\"\n (click)=\"select(segment, index)\" (keydown)=\"onKeyDown($event, index)\">\n <span\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-h-[18px] cqa-font-['Inter'] cqa-font-normal cqa-text-[12px] cqa-leading-[12px] cqa-text-center cqa-align-middle\">\n {{ segment.label }}\n </span>\n </button>\n </div>\n</div>", styles: [] }]
557
551
  }], propDecorators: { segments: [{
558
552
  type: Input
559
553
  }], value: [{
@@ -626,7 +620,7 @@ class DialogComponent {
626
620
  'cqa-rounded-2xl',
627
621
  'cqa-shadow-md',
628
622
  'cqa-border',
629
- 'cqa-border-[#E5E7EB]',
623
+ 'cqa-border-border-default',
630
624
  'cqa-p-6',
631
625
  'cqa-text-left',
632
626
  ];
@@ -688,69 +682,2841 @@ class DialogComponent {
688
682
  }
689
683
  }
690
684
  DialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
691
- DialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DialogComponent, selector: "cqa-dialog", viewQueries: [{ propertyName: "portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, static: true }], ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"display: block;\">\n <div class=\"cqa-flex cqa-w-full cqa-justify-center cqa-px-4 sm:cqa-px-6\">\n <div [ngClass]=\"panelClassList\" [ngStyle]=\"panelStyles\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-5\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-text-lg cqa-font-semibold cqa-text-[#111827]\">\n {{ config.title }}\n </h2>\n\n <p *ngIf=\"config.description\" class=\"cqa-text-sm cqa-leading-6 cqa-text-[#4B5563]\">\n {{ config.description }}\n </p>\n\n <div\n *ngIf=\"config.warning\"\n class=\"cqa-rounded-xl cqa-border cqa-border-red-200 cqa-bg-red-50 cqa-px-4 cqa-py-3 cqa-text-sm cqa-leading-5 cqa-text-red-700\"\n >\n {{ config.warning }}\n </div>\n </div>\n\n <div class=\"cqa-text-sm cqa-text-[#111827]\" [class.hidden]=\"!contentAttached\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n\n <div class=\"cqa-mt-4 cqa-flex cqa-flex-wrap cqa-gap-3\" [ngClass]=\"buttonAlignmentClass\">\n <cqa-button\n *ngFor=\"let button of config.buttons\"\n type=\"button\"\n [variant]=\"buttonVariant(button)\"\n [ngClass]=\"buttonHostClasses(button)\"\n (clicked)=\"onButtonClick(button)\"\n >\n {{ button.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n\n", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "type"], outputs: ["clicked"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
685
+ DialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DialogComponent, selector: "cqa-dialog", viewQueries: [{ propertyName: "portalOutlet", first: true, predicate: CdkPortalOutlet, descendants: true, static: true }], ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-flex cqa-w-full cqa-justify-center cqa-px-4 sm:cqa-px-6\">\n <div [ngClass]=\"panelClassList\" [ngStyle]=\"panelStyles\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-5\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-text-lg cqa-font-semibold cqa-text-dialog\">\n {{ config.title }}\n </h2>\n\n <p *ngIf=\"config.description\" class=\"cqa-text-sm cqa-leading-6 cqa-text-dialog-secondary\">\n {{ config.description }}\n </p>\n\n <div *ngIf=\"config.warning\"\n class=\"cqa-rounded-xl cqa-border cqa-border-red-200 cqa-bg-red-50 cqa-px-4 cqa-py-3 cqa-text-sm cqa-leading-5 cqa-text-red-700\">\n {{ config.warning }}\n </div>\n </div>\n\n <div class=\"cqa-text-sm cqa-text-dialog\" [class.hidden]=\"!contentAttached\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n\n <div class=\"cqa-mt-4 cqa-flex cqa-flex-wrap cqa-gap-3\" [ngClass]=\"buttonAlignmentClass\">\n <cqa-button *ngFor=\"let button of config.buttons\" type=\"button\" [variant]=\"buttonVariant(button)\"\n [ngClass]=\"buttonHostClasses(button)\" (clicked)=\"onButtonClick(button)\">\n {{ button.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n</div>", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
692
686
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogComponent, decorators: [{
693
687
  type: Component,
694
- args: [{ selector: 'cqa-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\" style=\"display: block;\">\n <div class=\"cqa-flex cqa-w-full cqa-justify-center cqa-px-4 sm:cqa-px-6\">\n <div [ngClass]=\"panelClassList\" [ngStyle]=\"panelStyles\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-5\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-text-lg cqa-font-semibold cqa-text-[#111827]\">\n {{ config.title }}\n </h2>\n\n <p *ngIf=\"config.description\" class=\"cqa-text-sm cqa-leading-6 cqa-text-[#4B5563]\">\n {{ config.description }}\n </p>\n\n <div\n *ngIf=\"config.warning\"\n class=\"cqa-rounded-xl cqa-border cqa-border-red-200 cqa-bg-red-50 cqa-px-4 cqa-py-3 cqa-text-sm cqa-leading-5 cqa-text-red-700\"\n >\n {{ config.warning }}\n </div>\n </div>\n\n <div class=\"cqa-text-sm cqa-text-[#111827]\" [class.hidden]=\"!contentAttached\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n\n <div class=\"cqa-mt-4 cqa-flex cqa-flex-wrap cqa-gap-3\" [ngClass]=\"buttonAlignmentClass\">\n <cqa-button\n *ngFor=\"let button of config.buttons\"\n type=\"button\"\n [variant]=\"buttonVariant(button)\"\n [ngClass]=\"buttonHostClasses(button)\"\n (clicked)=\"onButtonClick(button)\"\n >\n {{ button.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n\n", styles: [] }]
688
+ args: [{ selector: 'cqa-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-flex cqa-w-full cqa-justify-center cqa-px-4 sm:cqa-px-6\">\n <div [ngClass]=\"panelClassList\" [ngStyle]=\"panelStyles\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-5\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-text-lg cqa-font-semibold cqa-text-dialog\">\n {{ config.title }}\n </h2>\n\n <p *ngIf=\"config.description\" class=\"cqa-text-sm cqa-leading-6 cqa-text-dialog-secondary\">\n {{ config.description }}\n </p>\n\n <div *ngIf=\"config.warning\"\n class=\"cqa-rounded-xl cqa-border cqa-border-red-200 cqa-bg-red-50 cqa-px-4 cqa-py-3 cqa-text-sm cqa-leading-5 cqa-text-red-700\">\n {{ config.warning }}\n </div>\n </div>\n\n <div class=\"cqa-text-sm cqa-text-dialog\" [class.hidden]=\"!contentAttached\">\n <ng-template cdkPortalOutlet></ng-template>\n </div>\n\n <div class=\"cqa-mt-4 cqa-flex cqa-flex-wrap cqa-gap-3\" [ngClass]=\"buttonAlignmentClass\">\n <cqa-button *ngFor=\"let button of config.buttons\" type=\"button\" [variant]=\"buttonVariant(button)\"\n [ngClass]=\"buttonHostClasses(button)\" (clicked)=\"onButtonClick(button)\">\n {{ button.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
695
689
  }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { portalOutlet: [{
696
690
  type: ViewChild,
697
691
  args: [CdkPortalOutlet, { static: true }]
698
692
  }] } });
699
693
 
700
- // import { RootWrapperComponent } from './root-wrapper/root-wrapper.component';
701
- // import { CardComponent } from './card/card.component';
702
- // import { InputComponent } from './input/input.component';
703
- // import { IconButtonComponent } from './icon-button/icon-button.component';
704
- class UiKitModule {
694
+ class DynamicCellTemplateDirective {
695
+ constructor(template) {
696
+ this.template = template;
697
+ }
705
698
  }
706
- UiKitModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
707
- UiKitModulemod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, declarations: [ButtonComponent,
708
- SearchBarComponent,
709
- SegmentControlComponent,
710
- DialogComponent], imports: [CommonModule,
711
- FormsModule,
712
- MatIconModule,
713
- OverlayModule,
714
- PortalModule], exports: [ButtonComponent,
715
- SearchBarComponent,
716
- SegmentControlComponent,
717
- DialogComponent] });
718
- UiKitModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, imports: [[
719
- CommonModule,
720
- FormsModule,
721
- MatIconModule,
722
- OverlayModule,
723
- PortalModule
724
- ]] });
725
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, decorators: [{
726
- type: NgModule,
699
+ DynamicCellTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicCellTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
700
+ DynamicCellTemplateDirectivedir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: DynamicCellTemplateDirective, selector: "ng-template[dynamicCell]", inputs: { name: ["dynamicCell", "name"] }, ngImport: i0 });
701
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicCellTemplateDirective, decorators: [{
702
+ type: Directive,
727
703
  args: [{
728
- declarations: [
729
- ButtonComponent,
730
- SearchBarComponent,
731
- SegmentControlComponent,
732
- DialogComponent,
733
- // RootWrapperComponent,
734
- // CardComponent,
735
- // InputComponent,
736
- // IconButtonComponent
737
- ],
738
- imports: [
739
- CommonModule,
740
- FormsModule,
741
- MatIconModule,
742
- OverlayModule,
743
- PortalModule
744
- ],
745
- exports: [
746
- ButtonComponent,
747
- SearchBarComponent,
748
- SegmentControlComponent,
749
- DialogComponent,
750
- // RootWrapperComponent,
751
- // CardComponent,
752
- // InputComponent,
753
- // IconButtonComponent
704
+ selector: "ng-template[dynamicCell]"
705
+ }]
706
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; }, propDecorators: { name: [{
707
+ type: Input,
708
+ args: ["dynamicCell"]
709
+ }] } });
710
+ class DynamicHeaderTemplateDirective {
711
+ constructor(template) {
712
+ this.template = template;
713
+ }
714
+ }
715
+ DynamicHeaderTemplateDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicHeaderTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
716
+ DynamicHeaderTemplateDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: DynamicHeaderTemplateDirective, selector: "ng-template[dynamicHeader]", inputs: { name: ["dynamicHeader", "name"] }, ngImport: i0 });
717
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicHeaderTemplateDirective, decorators: [{
718
+ type: Directive,
719
+ args: [{
720
+ selector: "ng-template[dynamicHeader]"
721
+ }]
722
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; }, propDecorators: { name: [{
723
+ type: Input,
724
+ args: ["dynamicHeader"]
725
+ }] } });
726
+
727
+ class FullTableLoaderComponent {
728
+ constructor() {
729
+ this.label = 'Loading...';
730
+ }
731
+ }
732
+ FullTableLoaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FullTableLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
733
+ FullTableLoaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: FullTableLoaderComponent, selector: "cqa-full-table-loader", inputs: { label: "label" }, ngImport: i0, template: "<div\n class=\"table-loading-overlay cqa-absolute cqa-top-0 cqa-bottom-0 cqa-left-0 cqa-right-0 cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-z-[1000]\">\n <div\n class=\"blur-backdrop cqa-absolute cqa-top-0 cqa-bottom-0 cqa-left-0 cqa-right-0 cqa-bg-white/70 cqa-backdrop-blur-[4px] cqa-z-[1]\">\n </div>\n <div\n class=\"loading-spinner cqa-flex cqa-flex-row cqa-items-center cqa-justify-center cqa-gap-3 cqa-text-center cqa-relative cqa-z-20 cqa-bg-white cqa-py-4 cqa-px-6 cqa-rounded-xl cqa-shadow-lg\">\n <svg class=\"cqa-animate-spin cqa-text-primary\" width=\"32\" height=\"32\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n <span class=\"cqa-text-primary\">{{ label }}</span>\n </div>\n</div>\n\n\n" });
734
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FullTableLoaderComponent, decorators: [{
735
+ type: Component,
736
+ args: [{ selector: 'cqa-full-table-loader', template: "<div\n class=\"table-loading-overlay cqa-absolute cqa-top-0 cqa-bottom-0 cqa-left-0 cqa-right-0 cqa-w-full cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-z-[1000]\">\n <div\n class=\"blur-backdrop cqa-absolute cqa-top-0 cqa-bottom-0 cqa-left-0 cqa-right-0 cqa-bg-white/70 cqa-backdrop-blur-[4px] cqa-z-[1]\">\n </div>\n <div\n class=\"loading-spinner cqa-flex cqa-flex-row cqa-items-center cqa-justify-center cqa-gap-3 cqa-text-center cqa-relative cqa-z-20 cqa-bg-white cqa-py-4 cqa-px-6 cqa-rounded-xl cqa-shadow-lg\">\n <svg class=\"cqa-animate-spin cqa-text-primary\" width=\"32\" height=\"32\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n <span class=\"cqa-text-primary\">{{ label }}</span>\n </div>\n</div>\n\n\n", styles: [] }]
737
+ }], propDecorators: { label: [{
738
+ type: Input
739
+ }] } });
740
+
741
+ class TableDataLoaderComponent {
742
+ constructor() {
743
+ this.label = 'Loading...';
744
+ this.size = 24;
745
+ }
746
+ }
747
+ TableDataLoaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableDataLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
748
+ TableDataLoaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TableDataLoaderComponent, selector: "cqa-table-data-loader", inputs: { label: "label", size: "size" }, ngImport: i0, template: "<div class=\"loading-spinner-simple cqa-py-2 cqa-flex cqa-flex-row cqa-items-center cqa-justify-center cqa-gap-3 cqa-text-center\">\n <svg class=\"cqa-animate-spin cqa-text-primary\" [attr.width]=\"size\" [attr.height]=\"size\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-primary\">{{ label }}</span>\n </div>\n\n\n" });
749
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableDataLoaderComponent, decorators: [{
750
+ type: Component,
751
+ args: [{ selector: 'cqa-table-data-loader', template: "<div class=\"loading-spinner-simple cqa-py-2 cqa-flex cqa-flex-row cqa-items-center cqa-justify-center cqa-gap-3 cqa-text-center\">\n <svg class=\"cqa-animate-spin cqa-text-primary\" [attr.width]=\"size\" [attr.height]=\"size\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"cqa-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"cqa-opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span class=\"cqa-text-primary\">{{ label }}</span>\n </div>\n\n\n", styles: [] }]
752
+ }], propDecorators: { label: [{
753
+ type: Input
754
+ }], size: [{
755
+ type: Input
756
+ }] } });
757
+
758
+ class DynamicTableComponent {
759
+ constructor() {
760
+ this.data = [];
761
+ this.columns = [];
762
+ // Enable built-in select-all behavior for a 'checkbox' column
763
+ this.enableSelectAll = true;
764
+ // Enable simple client-side sorting when clicking sortable headers (no custom header)
765
+ this.enableLocalSort = true;
766
+ // Emit sort changes so parent can perform server-side sort if desired
767
+ this.sortChange = new EventEmitter();
768
+ this._sortDirection = null;
769
+ }
770
+ get isXs() {
771
+ const w = this.screenWidth || window.innerWidth;
772
+ return w <= 480;
773
+ }
774
+ get isSm() {
775
+ const w = this.screenWidth || window.innerWidth;
776
+ return w <= 768;
777
+ }
778
+ get isMd() {
779
+ const w = this.screenWidth || window.innerWidth;
780
+ return w <= 992;
781
+ }
782
+ get visibleColumns() {
783
+ const responsiveFilter = (c) => {
784
+ const r = (c === null || c === void 0 ? void 0 : c.responsive) || {};
785
+ if (r.xs && this.isXs)
786
+ return false;
787
+ if (r.sm && this.isSm)
788
+ return false;
789
+ if (r.md && this.isMd)
790
+ return false;
791
+ return true;
792
+ };
793
+ return (this.columns || []).filter(c => c.isShow !== false).filter(responsiveFilter);
794
+ }
795
+ getHeaderTemplate(colId) {
796
+ var _a;
797
+ const tpl = (_a = this.headerTemplates) === null || _a === void 0 ? void 0 : _a.find(t => t.name === colId);
798
+ return tpl ? tpl.template : null;
799
+ }
800
+ getCellTemplate(colId) {
801
+ var _a;
802
+ const tpl = (_a = this.cellTemplates) === null || _a === void 0 ? void 0 : _a.find(t => t.name === colId);
803
+ return tpl ? tpl.template : null;
804
+ }
805
+ getCellValue(row, path) {
806
+ if (!row || !path)
807
+ return "";
808
+ const parts = path.split(".");
809
+ let current = row;
810
+ for (const part of parts) {
811
+ if (current == null)
812
+ return "";
813
+ current = current[part];
814
+ }
815
+ return current !== null && current !== void 0 ? current : "";
816
+ }
817
+ trackByIndex(index) {
818
+ return index;
819
+ }
820
+ // Compute grid-template-columns string from column config
821
+ get computedGridTemplate() {
822
+ if (this.gridTemplateColumns) {
823
+ return this.gridTemplateColumns;
824
+ }
825
+ const cols = this.visibleColumns;
826
+ if (!(cols === null || cols === void 0 ? void 0 : cols.length))
827
+ return '';
828
+ const fixedPx = cols.reduce((sum, c) => sum + (c.fixedPx || 0), 0);
829
+ const dynamicCols = cols.filter(c => !c.fixedPx);
830
+ const totalWeight = dynamicCols.reduce((sum, c) => sum + (c.weight || 1), 0) || 1;
831
+ const parts = cols.map(c => {
832
+ if (c.fixedPx && c.fixedPx > 0) {
833
+ return `${c.fixedPx}px`;
834
+ }
835
+ const share = (c.weight || 1) / totalWeight;
836
+ return `calc((100% - ${fixedPx}px) * ${share.toFixed(4)})`;
837
+ });
838
+ return parts.join(' ');
839
+ }
840
+ // Compute per-column widths for use with <colgroup>
841
+ get computedColumnWidths() {
842
+ const cols = this.visibleColumns;
843
+ if (!(cols === null || cols === void 0 ? void 0 : cols.length))
844
+ return [];
845
+ const fixedPx = cols.reduce((sum, c) => sum + (c.fixedPx || 0), 0);
846
+ const dynamicCols = cols.filter(c => !c.fixedPx);
847
+ const totalWeight = dynamicCols.reduce((sum, c) => sum + (c.weight || 1), 0) || 1;
848
+ return cols.map(c => {
849
+ if (c.fixedPx && c.fixedPx > 0) {
850
+ return `${c.fixedPx}px`;
851
+ }
852
+ const share = (c.weight || 1) / totalWeight;
853
+ return `calc((100% - ${fixedPx}px) * ${share.toFixed(4)})`;
854
+ });
855
+ }
856
+ // Selection helpers
857
+ get allSelected() {
858
+ const rows = this.data || [];
859
+ if (!rows.length)
860
+ return false;
861
+ return rows.every(r => !!(r === null || r === void 0 ? void 0 : r.isSelected));
862
+ }
863
+ get someSelected() {
864
+ const rows = this.data || [];
865
+ if (!rows.length)
866
+ return false;
867
+ const anySelected = rows.some(r => !!(r === null || r === void 0 ? void 0 : r.isSelected));
868
+ return anySelected && !this.allSelected;
869
+ }
870
+ onSelectAllChange(event) {
871
+ const target = event.target;
872
+ this.toggleSelectAll(target.checked);
873
+ }
874
+ onRowSelectChange(event, row) {
875
+ const target = event.target;
876
+ row.isSelected = target.checked;
877
+ }
878
+ toggleSelectAll(checked) {
879
+ const rows = this.data || [];
880
+ for (const row of rows) {
881
+ if (row) {
882
+ row.isSelected = checked;
883
+ }
884
+ }
885
+ }
886
+ get computedData() {
887
+ const source = this.data || [];
888
+ if (!this.enableLocalSort || !this._sortActive || !this._sortDirection) {
889
+ return source;
890
+ }
891
+ const col = this.visibleColumns.find(c => c.fieldId === this._sortActive);
892
+ if (!col || !col.fieldValue) {
893
+ return source;
894
+ }
895
+ const dir = this._sortDirection === 'asc' ? 1 : -1;
896
+ const fieldPath = col.fieldValue;
897
+ const out = [...source];
898
+ out.sort((a, b) => dir * this.compareValues(this.getCellValue(a, fieldPath), this.getCellValue(b, fieldPath)));
899
+ return out;
900
+ }
901
+ // Computed loading flags to support backward compatibility
902
+ get showTableLoading() {
903
+ var _a;
904
+ return (_a = this.isTableLoading) !== null && _a !== void 0 ? _a : false;
905
+ }
906
+ get showTableDataLoading() {
907
+ var _a;
908
+ return (_a = this.isTableDataLoading) !== null && _a !== void 0 ? _a : false;
909
+ }
910
+ // True when table has no data and is not currently loading — used to show an empty state
911
+ get isEmpty() {
912
+ const anyLoading = this.showTableLoading || this.showTableDataLoading;
913
+ return !anyLoading && (!(this.data && this.data.length) || this.data.length === 0);
914
+ }
915
+ isSortedAsc(colId) {
916
+ return this._sortActive === colId && this._sortDirection === 'asc';
917
+ }
918
+ isSortedDesc(colId) {
919
+ return this._sortActive === colId && this._sortDirection === 'desc';
920
+ }
921
+ toggleSort(col) {
922
+ if (!(col === null || col === void 0 ? void 0 : col.sortable))
923
+ return;
924
+ const colId = col.fieldId;
925
+ if (this._sortActive !== colId) {
926
+ this._sortActive = colId;
927
+ this._sortDirection = 'asc';
928
+ }
929
+ else {
930
+ // cycle asc -> desc -> null -> asc
931
+ if (this._sortDirection === 'asc')
932
+ this._sortDirection = 'desc';
933
+ else if (this._sortDirection === 'desc')
934
+ this._sortDirection = null;
935
+ else
936
+ this._sortDirection = 'asc';
937
+ }
938
+ this.sortChange.emit({ fieldId: this._sortActive, fieldValue: col.fieldValue, direction: this._sortDirection });
939
+ }
940
+ compareValues(a, b) {
941
+ if (a == null && b == null)
942
+ return 0;
943
+ if (a == null)
944
+ return 1; // nulls last in asc (handled by dir multiplier)
945
+ if (b == null)
946
+ return -1;
947
+ const numA = typeof a === 'number' ? a : Number(a);
948
+ const numB = typeof b === 'number' ? b : Number(b);
949
+ const aIsNum = !isNaN(numA) && a !== '' && a !== null && a !== false;
950
+ const bIsNum = !isNaN(numB) && b !== '' && b !== null && b !== false;
951
+ if (aIsNum && bIsNum) {
952
+ if (numA < numB)
953
+ return -1;
954
+ if (numA > numB)
955
+ return 1;
956
+ return 0;
957
+ }
958
+ // Date detection: attempt parse when both values are strings and parseable
959
+ if (typeof a === 'string' && typeof b === 'string') {
960
+ const tsA = Date.parse(a);
961
+ const tsB = Date.parse(b);
962
+ if (!isNaN(tsA) && !isNaN(tsB)) {
963
+ if (tsA < tsB)
964
+ return -1;
965
+ if (tsA > tsB)
966
+ return 1;
967
+ return 0;
968
+ }
969
+ // localeCompare, case-insensitive
970
+ return a.localeCompare(b, undefined, { sensitivity: 'base', numeric: true });
971
+ }
972
+ // Fallback to string comparison
973
+ const sa = String(a);
974
+ const sb = String(b);
975
+ return sa.localeCompare(sb, undefined, { sensitivity: 'base', numeric: true });
976
+ }
977
+ }
978
+ DynamicTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
979
+ DynamicTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicTableComponent, selector: "app-dynamic-table", inputs: { data: "data", columns: "columns", emptyState: "emptyState", gridTemplateColumns: "gridTemplateColumns", screenWidth: "screenWidth", enableSelectAll: "enableSelectAll", enableLocalSort: "enableLocalSort", isTableLoading: "isTableLoading", isTableDataLoading: "isTableDataLoading" }, outputs: { sortChange: "sortChange" }, queries: [{ propertyName: "emptyTableTpl", first: true, predicate: ["emptyTableTpl"], descendants: true, read: TemplateRef }, { propertyName: "cellTemplates", predicate: DynamicCellTemplateDirective }, { propertyName: "headerTemplates", predicate: DynamicHeaderTemplateDirective }], ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-relative\">\n <cqa-full-table-loader *ngIf=\"showTableLoading\"></cqa-full-table-loader>\n <cqa-table-data-loader *ngIf=\"showTableDataLoading\"></cqa-table-data-loader>\n <table class=\"table-inner cqa-w-full\" [class.is-loading]=\"true\">\n <colgroup>\n <ng-container *ngFor=\"let width of computedColumnWidths; trackBy: trackByIndex\">\n <col [style.width]=\"width\" />\n </ng-container>\n </colgroup>\n\n <thead *ngIf=\"data?.length\">\n <tr class=\"table-header cqa-items-center\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <th\n class=\"header-cell cqa-py-[13.25px] cqa-px-[10.5px] cqa-text-xs cqa-font-semibold cqa-text-left cqa-text-[#374151] cqa-bg-[#eff0f7]\"\n [ngClass]=\"col.fieldId + '-cell'\">\n <!-- Built-in select-all for checkbox column when enabled and no custom header template -->\n <ng-container\n *ngIf=\"col.fieldId === 'checkbox' && enableSelectAll && !getHeaderTemplate(col.fieldId); else headerTplOrDefault\">\n <div class=\"custom-checkbox\">\n <input type=\"checkbox\" id=\"checkbox\" aria-label=\"Select all rows\" [checked]=\"allSelected\"\n [indeterminate]=\"someSelected\" (change)=\"onSelectAllChange($event)\" class=\"hidden-checkbox\" />\n <label for=\"checkbox\" class=\"custom-checkbox-label\"></label>\n </div>\n </ng-container>\n <ng-template #headerTplOrDefault>\n <ng-container *ngIf=\"getHeaderTemplate(col.fieldId) as headerTpl; else defaultHeader\">\n <ng-container *ngTemplateOutlet=\"headerTpl\"></ng-container>\n </ng-container>\n <ng-template #defaultHeader>\n <ng-container *ngIf=\"col.sortable; else plainHeader\">\n <button type=\"button\" class=\"header-text cqa-inline-flex cqa-items-center cqa-gap-1\"\n (click)=\"toggleSort(col)\" [attr.aria-label]=\"'Sort by ' + (col.fieldName || col.fieldId)\">\n <span class=\"cqa-text-[12.3px] cqa-leading-[17.5px] cqa-text-[#0A0A0A] cqa-font-medium\">{{\n col.fieldName }}</span>\n <span *ngIf=\"isSortedAsc(col.fieldId)\">\u25B2</span>\n <span *ngIf=\"isSortedDesc(col.fieldId)\">\u25BC</span>\n </button>\n </ng-container>\n <ng-template #plainHeader>\n <span class=\"header-text\">{{ col.fieldName }}</span>\n </ng-template>\n </ng-template>\n </ng-template>\n </th>\n </ng-container>\n </tr>\n </thead>\n\n <tbody class=\"table-body cqa-w-full\">\n <tr class=\"table-row cqa-bg-surface-default hover:cqa-bg-surface-hover\" *ngFor=\"let row of computedData; let rowIndex = index; trackBy: trackByIndex\"\n [class.selected]=\"row?.isSelected\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <td class=\"cell cqa-px-[10.5px] cqa-py-[11px]\" [ngClass]=\"col.fieldId + '-cell'\">\n <!-- Built-in checkbox cell when no custom template is provided -->\n <ng-container *ngIf=\"col.fieldId === 'checkbox' && !getCellTemplate(col.fieldId); else regularCell\">\n <div class=\"custom-checkbox\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + rowIndex\"\n aria-label=\"Select row\"\n [checked]=\"row?.isSelected\"\n (change)=\"onRowSelectChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [attr.for]=\"'row-checkbox-' + rowIndex\">\n </label>\n </div>\n </ng-container>\n <ng-template #regularCell>\n <ng-container *ngIf=\"getCellTemplate(col.fieldId) as cellTpl; else defaultCell\">\n <ng-container\n *ngTemplateOutlet=\"cellTpl; context: {$implicit: row, row: row, value: getCellValue(row, col.fieldValue)}\"></ng-container>\n </ng-container>\n <ng-template #defaultCell>\n <span class=\"cqa-text-xs cqa-text-[#374151]\">{{ getCellValue(row, col.fieldValue) }}</span>\n </ng-template>\n </ng-template>\n </td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n</div>", components: [{ type: FullTableLoaderComponent, selector: "cqa-full-table-loader", inputs: ["label"] }, { type: TableDataLoaderComponent, selector: "cqa-table-data-loader", inputs: ["label", "size"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] });
980
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicTableComponent, decorators: [{
981
+ type: Component,
982
+ args: [{ selector: "app-dynamic-table", template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-relative\">\n <cqa-full-table-loader *ngIf=\"showTableLoading\"></cqa-full-table-loader>\n <cqa-table-data-loader *ngIf=\"showTableDataLoading\"></cqa-table-data-loader>\n <table class=\"table-inner cqa-w-full\" [class.is-loading]=\"true\">\n <colgroup>\n <ng-container *ngFor=\"let width of computedColumnWidths; trackBy: trackByIndex\">\n <col [style.width]=\"width\" />\n </ng-container>\n </colgroup>\n\n <thead *ngIf=\"data?.length\">\n <tr class=\"table-header cqa-items-center\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <th\n class=\"header-cell cqa-py-[13.25px] cqa-px-[10.5px] cqa-text-xs cqa-font-semibold cqa-text-left cqa-text-[#374151] cqa-bg-[#eff0f7]\"\n [ngClass]=\"col.fieldId + '-cell'\">\n <!-- Built-in select-all for checkbox column when enabled and no custom header template -->\n <ng-container\n *ngIf=\"col.fieldId === 'checkbox' && enableSelectAll && !getHeaderTemplate(col.fieldId); else headerTplOrDefault\">\n <div class=\"custom-checkbox\">\n <input type=\"checkbox\" id=\"checkbox\" aria-label=\"Select all rows\" [checked]=\"allSelected\"\n [indeterminate]=\"someSelected\" (change)=\"onSelectAllChange($event)\" class=\"hidden-checkbox\" />\n <label for=\"checkbox\" class=\"custom-checkbox-label\"></label>\n </div>\n </ng-container>\n <ng-template #headerTplOrDefault>\n <ng-container *ngIf=\"getHeaderTemplate(col.fieldId) as headerTpl; else defaultHeader\">\n <ng-container *ngTemplateOutlet=\"headerTpl\"></ng-container>\n </ng-container>\n <ng-template #defaultHeader>\n <ng-container *ngIf=\"col.sortable; else plainHeader\">\n <button type=\"button\" class=\"header-text cqa-inline-flex cqa-items-center cqa-gap-1\"\n (click)=\"toggleSort(col)\" [attr.aria-label]=\"'Sort by ' + (col.fieldName || col.fieldId)\">\n <span class=\"cqa-text-[12.3px] cqa-leading-[17.5px] cqa-text-[#0A0A0A] cqa-font-medium\">{{\n col.fieldName }}</span>\n <span *ngIf=\"isSortedAsc(col.fieldId)\">\u25B2</span>\n <span *ngIf=\"isSortedDesc(col.fieldId)\">\u25BC</span>\n </button>\n </ng-container>\n <ng-template #plainHeader>\n <span class=\"header-text\">{{ col.fieldName }}</span>\n </ng-template>\n </ng-template>\n </ng-template>\n </th>\n </ng-container>\n </tr>\n </thead>\n\n <tbody class=\"table-body cqa-w-full\">\n <tr class=\"table-row cqa-bg-surface-default hover:cqa-bg-surface-hover\" *ngFor=\"let row of computedData; let rowIndex = index; trackBy: trackByIndex\"\n [class.selected]=\"row?.isSelected\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <td class=\"cell cqa-px-[10.5px] cqa-py-[11px]\" [ngClass]=\"col.fieldId + '-cell'\">\n <!-- Built-in checkbox cell when no custom template is provided -->\n <ng-container *ngIf=\"col.fieldId === 'checkbox' && !getCellTemplate(col.fieldId); else regularCell\">\n <div class=\"custom-checkbox\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + rowIndex\"\n aria-label=\"Select row\"\n [checked]=\"row?.isSelected\"\n (change)=\"onRowSelectChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [attr.for]=\"'row-checkbox-' + rowIndex\">\n </label>\n </div>\n </ng-container>\n <ng-template #regularCell>\n <ng-container *ngIf=\"getCellTemplate(col.fieldId) as cellTpl; else defaultCell\">\n <ng-container\n *ngTemplateOutlet=\"cellTpl; context: {$implicit: row, row: row, value: getCellValue(row, col.fieldValue)}\"></ng-container>\n </ng-container>\n <ng-template #defaultCell>\n <span class=\"cqa-text-xs cqa-text-[#374151]\">{{ getCellValue(row, col.fieldValue) }}</span>\n </ng-template>\n </ng-template>\n </td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n</div>", styles: [] }]
983
+ }], propDecorators: { data: [{
984
+ type: Input
985
+ }], columns: [{
986
+ type: Input
987
+ }], emptyState: [{
988
+ type: Input
989
+ }], gridTemplateColumns: [{
990
+ type: Input
991
+ }], screenWidth: [{
992
+ type: Input
993
+ }], enableSelectAll: [{
994
+ type: Input
995
+ }], enableLocalSort: [{
996
+ type: Input
997
+ }], isTableLoading: [{
998
+ type: Input
999
+ }], isTableDataLoading: [{
1000
+ type: Input
1001
+ }], sortChange: [{
1002
+ type: Output
1003
+ }], cellTemplates: [{
1004
+ type: ContentChildren,
1005
+ args: [DynamicCellTemplateDirective]
1006
+ }], headerTemplates: [{
1007
+ type: ContentChildren,
1008
+ args: [DynamicHeaderTemplateDirective]
1009
+ }], emptyTableTpl: [{
1010
+ type: ContentChild,
1011
+ args: ['emptyTableTpl', { read: TemplateRef }]
1012
+ }] } });
1013
+
1014
+ class InlineSortComponent {
1015
+ get getToolTip() {
1016
+ var _a, _b;
1017
+ if (this.ascending == true)
1018
+ return ((_a = this.heading) === null || _a === void 0 ? void 0 : _a.includes('created_at')) ? 'message.common.sort_by.old' : 'message.common.sort_by.ascending';
1019
+ else if (this.ascending == false)
1020
+ return ((_b = this.heading) === null || _b === void 0 ? void 0 : _b.includes('created_at')) ? 'message.common.sort_by.new' : 'message.common.sort_by.descending';
1021
+ else
1022
+ return 'message.common.sort';
1023
+ }
1024
+ ngOnChanges() {
1025
+ var _a, _b;
1026
+ if (this.ascending != undefined) {
1027
+ (_a = this.tooltipDiv) === null || _a === void 0 ? void 0 : _a.hide();
1028
+ (_b = this.tooltipDiv) === null || _b === void 0 ? void 0 : _b.show(200);
1029
+ }
1030
+ }
1031
+ }
1032
+ InlineSortComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: InlineSortComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1033
+ InlineSortComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: InlineSortComponent, selector: "app-inline-sort, cqa-inline-sort", inputs: { ascending: "ascending", heading: "heading" }, viewQueries: [{ propertyName: "tooltipDiv", first: true, predicate: ["tooltipDiv"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
1034
+ <div #tooltipDiv="matTooltip"
1035
+ class="w-fit-content sort-header"
1036
+ [matTooltip]="getToolTip"
1037
+ [matTooltipPosition]="'after'">
1038
+ <span>{{ heading }}</span>
1039
+ <span *ngIf="ascending" class='fa-down-sort'></span>
1040
+ <span *ngIf="ascending==false" class='fa-up-sort'></span>
1041
+ <span *ngIf="ascending==undefined" class='fa-down-sort opaque-50'></span>
1042
+ </div>
1043
+ `, isInline: true, directives: [{ type: i1$2.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
1044
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: InlineSortComponent, decorators: [{
1045
+ type: Component,
1046
+ args: [{
1047
+ selector: 'app-inline-sort, cqa-inline-sort',
1048
+ template: `
1049
+ <div #tooltipDiv="matTooltip"
1050
+ class="w-fit-content sort-header"
1051
+ [matTooltip]="getToolTip"
1052
+ [matTooltipPosition]="'after'">
1053
+ <span>{{ heading }}</span>
1054
+ <span *ngIf="ascending" class='fa-down-sort'></span>
1055
+ <span *ngIf="ascending==false" class='fa-up-sort'></span>
1056
+ <span *ngIf="ascending==undefined" class='fa-down-sort opaque-50'></span>
1057
+ </div>
1058
+ `,
1059
+ styles: []
1060
+ }]
1061
+ }], propDecorators: { ascending: [{
1062
+ type: Input
1063
+ }], heading: [{
1064
+ type: Input
1065
+ }], tooltipDiv: [{
1066
+ type: ViewChild,
1067
+ args: ['tooltipDiv']
1068
+ }] } });
1069
+
1070
+ class PaginationComponent {
1071
+ constructor() {
1072
+ this.totalElements = 0;
1073
+ this.pageIndex = 0; // 0-based
1074
+ this.pageSize = 10;
1075
+ this.pageItemCount = 0; // number of items currently rendered on this page
1076
+ this.pageSizeOptions = [10, 20, 40, 60, 80];
1077
+ this.pageIndexChange = new EventEmitter();
1078
+ this.pageSizeChange = new EventEmitter();
1079
+ this.paginate = new EventEmitter();
1080
+ // Local UI state for custom page-size dropdown
1081
+ this.pageSizeOpen = false;
1082
+ this.pagesOption = {
1083
+ placeholder: 'Choose page',
1084
+ disabled: false,
1085
+ multiple: false,
1086
+ searchable: false,
1087
+ options: [
1088
+ { id: 1, name: '10' },
1089
+ { id: 2, name: '20' },
1090
+ { id: 3, name: '30' },
1091
+ { id: 4, name: '40' },
1092
+ ],
1093
+ };
1094
+ }
1095
+ get computedTotalPages() {
1096
+ if (this.totalPages != null && this.totalPages > 0) {
1097
+ return this.totalPages;
1098
+ }
1099
+ if (this.pageSize > 0 && this.totalElements >= 0) {
1100
+ return Math.max(1, Math.ceil(this.totalElements / this.pageSize));
1101
+ }
1102
+ return 0;
1103
+ }
1104
+ getStartItem() {
1105
+ if (!this.totalElements) {
1106
+ return 0;
1107
+ }
1108
+ return this.pageIndex * this.pageSize + 1;
1109
+ }
1110
+ getEndItem() {
1111
+ const end = this.getStartItem() + this.pageItemCount - 1;
1112
+ if (end < 0) {
1113
+ return 0;
1114
+ }
1115
+ return Math.min(end, this.totalElements);
1116
+ }
1117
+ togglePageSizeMenu() {
1118
+ this.pageSizeOpen = !this.pageSizeOpen;
1119
+ }
1120
+ selectPageSize(size) {
1121
+ if (this.pageSize !== size) {
1122
+ this.pageSize = size;
1123
+ this.onPageSizeChange();
1124
+ }
1125
+ this.pageSizeOpen = false;
1126
+ }
1127
+ onPageSizeChange() {
1128
+ this.pageIndex = 0;
1129
+ this.pageSizeChange.emit(this.pageSize);
1130
+ this.pageIndexChange.emit(this.pageIndex);
1131
+ this.paginate.emit({ pageIndex: this.pageIndex, pageSize: this.pageSize });
1132
+ }
1133
+ goToPage(index) {
1134
+ const lastIndex = Math.max(0, this.computedTotalPages - 1);
1135
+ const next = Math.max(0, Math.min(index, lastIndex));
1136
+ if (next === this.pageIndex) {
1137
+ return;
1138
+ }
1139
+ this.pageIndex = next;
1140
+ this.pageIndexChange.emit(this.pageIndex);
1141
+ this.paginate.emit({ pageIndex: this.pageIndex, pageSize: this.pageSize });
1142
+ }
1143
+ }
1144
+ PaginationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1145
+ PaginationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: PaginationComponent, selector: "cqa-pagination", inputs: { totalElements: "totalElements", totalPages: "totalPages", pageIndex: "pageIndex", pageSize: "pageSize", pageItemCount: "pageItemCount", pageSizeOptions: "pageSizeOptions" }, outputs: { pageIndexChange: "pageIndexChange", pageSizeChange: "pageSizeChange", paginate: "paginate" }, ngImport: i0, template: "<!-- Bottom Pagination -->\n<div id=\"cqa-ui-root\" >\n <div class=\"table-footer-pagination cqa-text-grey-300 cqa-text-[12.3px] cqa-leading-[17.5px] cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-flex-wrap cqa-bg-surface-default cqa-px-[21px] cqa-py-[15px]\" *ngIf=\"pageItemCount && totalElements\">\n <div class=\"pagination-info cqa-flex cqa-items-center cqa-gap-[7px] cqa-relative\">\n <span class=\"rows-label\">Rows per page</span>\n <div class=\"cqa-relative\">\n <!-- Custom Select Trigger -->\n <button\n type=\"button\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-[19px] cqa-bg-white cqa-text-black-100 cqa-rounded-[5px] cqa-px-[11.5px] cqa-py-[6.75px]\"\n (click)=\"togglePageSizeMenu()\"\n [attr.aria-expanded]=\"pageSizeOpen\"\n aria-haspopup=\"listbox\"\n >\n {{ pageSize }}\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><g opacity=\"0.5\"><path d=\"M3.5 5.25L7 8.75L10.5 5.25\" stroke=\"#717182\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></g></svg>\n </button>\n <!-- Dropdown Menu -->\n <div\n *ngIf=\"pageSizeOpen\"\n class=\"cqa-absolute cqa-z-[100] cqa-bottom-[calc(100%+8px)] cqa-left-0 cqa-w-[75px] cqa-max-h-[170px] cqa-overflow-auto cqa-rounded-lg cqa-border cqa-border-[#E5E7EB] cqa-bg-white cqa-shadow-[0px_4px_6px_-1px_rgba(0,0,0,0.1)] cqa-p-[5px]\"\n role=\"listbox\"\n [attr.aria-activedescendant]=\"'pagesize-' + pageSize\"\n >\n <button\n *ngFor=\"let size of pageSizeOptions\"\n type=\"button\"\n class=\"cqa-w-full cqa-px-2 cqa-py-[6px] hover:cqa-bg-[#F7F8FA] cqa-text-left cqa-rounded-md cqa-text-black-100\"\n [attr.id]=\"'pagesize-' + size\"\n role=\"option\"\n [attr.aria-selected]=\"pageSize === size\"\n (click)=\"selectPageSize(size)\"\n >\n {{ size }}\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"pagination-right cqa-flex cqa-items-center cqa-gap-[21px]\">\n <div class=\"pagination-range\">\n {{ getStartItem() }}&ndash;{{ getEndItem() }} of {{ totalElements }}\n </div>\n <div class=\"pagination-controls cqa-flex cqa-items-stretch cqa-gap-[3.5px]\">\n <button class=\"pagination-btn cqa-w-[28px] cqa-h-[28px] cqa-min-w-[28px] cqa-rounded-[5px] cqa-border cqa-border-[#E5E7EB] cqa-bg-[#F7F8FA] cqa-flex cqa-items-center cqa-justify-center\" [disabled]=\"pageIndex === 0\" (click)=\"goToPage(pageIndex - 1)\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.75 10.5L5.25 7L8.75 3.5\" stroke=\"#838384\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button class=\"pagination-btn cqa-w-[28px] cqa-h-[28px] cqa-min-w-[28px] cqa-rounded-[5px] cqa-border cqa-border-[#E5E7EB] cqa-bg-[#F7F8FA] cqa-flex cqa-items-center cqa-justify-center\" [disabled]=\"pageIndex >= computedTotalPages - 1\" (click)=\"goToPage(pageIndex + 1)\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.25 10.5L8.75 7L5.25 3.5\" stroke=\"#838384\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n </div>\n </div>\n </div>\n</div>", directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
1146
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: PaginationComponent, decorators: [{
1147
+ type: Component,
1148
+ args: [{ selector: 'cqa-pagination', template: "<!-- Bottom Pagination -->\n<div id=\"cqa-ui-root\" >\n <div class=\"table-footer-pagination cqa-text-grey-300 cqa-text-[12.3px] cqa-leading-[17.5px] cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-flex-wrap cqa-bg-surface-default cqa-px-[21px] cqa-py-[15px]\" *ngIf=\"pageItemCount && totalElements\">\n <div class=\"pagination-info cqa-flex cqa-items-center cqa-gap-[7px] cqa-relative\">\n <span class=\"rows-label\">Rows per page</span>\n <div class=\"cqa-relative\">\n <!-- Custom Select Trigger -->\n <button\n type=\"button\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-[19px] cqa-bg-white cqa-text-black-100 cqa-rounded-[5px] cqa-px-[11.5px] cqa-py-[6.75px]\"\n (click)=\"togglePageSizeMenu()\"\n [attr.aria-expanded]=\"pageSizeOpen\"\n aria-haspopup=\"listbox\"\n >\n {{ pageSize }}\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><g opacity=\"0.5\"><path d=\"M3.5 5.25L7 8.75L10.5 5.25\" stroke=\"#717182\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></g></svg>\n </button>\n <!-- Dropdown Menu -->\n <div\n *ngIf=\"pageSizeOpen\"\n class=\"cqa-absolute cqa-z-[100] cqa-bottom-[calc(100%+8px)] cqa-left-0 cqa-w-[75px] cqa-max-h-[170px] cqa-overflow-auto cqa-rounded-lg cqa-border cqa-border-[#E5E7EB] cqa-bg-white cqa-shadow-[0px_4px_6px_-1px_rgba(0,0,0,0.1)] cqa-p-[5px]\"\n role=\"listbox\"\n [attr.aria-activedescendant]=\"'pagesize-' + pageSize\"\n >\n <button\n *ngFor=\"let size of pageSizeOptions\"\n type=\"button\"\n class=\"cqa-w-full cqa-px-2 cqa-py-[6px] hover:cqa-bg-[#F7F8FA] cqa-text-left cqa-rounded-md cqa-text-black-100\"\n [attr.id]=\"'pagesize-' + size\"\n role=\"option\"\n [attr.aria-selected]=\"pageSize === size\"\n (click)=\"selectPageSize(size)\"\n >\n {{ size }}\n </button>\n </div>\n </div>\n </div>\n\n <div class=\"pagination-right cqa-flex cqa-items-center cqa-gap-[21px]\">\n <div class=\"pagination-range\">\n {{ getStartItem() }}&ndash;{{ getEndItem() }} of {{ totalElements }}\n </div>\n <div class=\"pagination-controls cqa-flex cqa-items-stretch cqa-gap-[3.5px]\">\n <button class=\"pagination-btn cqa-w-[28px] cqa-h-[28px] cqa-min-w-[28px] cqa-rounded-[5px] cqa-border cqa-border-[#E5E7EB] cqa-bg-[#F7F8FA] cqa-flex cqa-items-center cqa-justify-center\" [disabled]=\"pageIndex === 0\" (click)=\"goToPage(pageIndex - 1)\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8.75 10.5L5.25 7L8.75 3.5\" stroke=\"#838384\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n <button class=\"pagination-btn cqa-w-[28px] cqa-h-[28px] cqa-min-w-[28px] cqa-rounded-[5px] cqa-border cqa-border-[#E5E7EB] cqa-bg-[#F7F8FA] cqa-flex cqa-items-center cqa-justify-center\" [disabled]=\"pageIndex >= computedTotalPages - 1\" (click)=\"goToPage(pageIndex + 1)\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5.25 10.5L8.75 7L5.25 3.5\" stroke=\"#838384\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
1149
+ }], propDecorators: { totalElements: [{
1150
+ type: Input
1151
+ }], totalPages: [{
1152
+ type: Input
1153
+ }], pageIndex: [{
1154
+ type: Input
1155
+ }], pageSize: [{
1156
+ type: Input
1157
+ }], pageItemCount: [{
1158
+ type: Input
1159
+ }], pageSizeOptions: [{
1160
+ type: Input
1161
+ }], pageIndexChange: [{
1162
+ type: Output
1163
+ }], pageSizeChange: [{
1164
+ type: Output
1165
+ }], paginate: [{
1166
+ type: Output
1167
+ }] } });
1168
+
1169
+ class ActionMenuButtonComponent {
1170
+ constructor() {
1171
+ this.view = new EventEmitter();
1172
+ this.edit = new EventEmitter();
1173
+ this.delete = new EventEmitter();
1174
+ }
1175
+ navigateToTestCase(id) {
1176
+ if (id === undefined || id === null)
1177
+ return;
1178
+ this.view.emit(id);
1179
+ }
1180
+ editTestCase(row) {
1181
+ if (!row)
1182
+ return;
1183
+ this.edit.emit(row);
1184
+ }
1185
+ deleteTestCase(row) {
1186
+ if (!row)
1187
+ return;
1188
+ this.delete.emit(row);
1189
+ }
1190
+ }
1191
+ ActionMenuButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ActionMenuButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1192
+ ActionMenuButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ActionMenuButtonComponent, selector: "cqa-action-menu-button", inputs: { row: "row" }, outputs: { view: "view", edit: "edit", delete: "delete" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <button class=\"action-menu-btn\" [matMenuTriggerFor]=\"actionMenu\" (click)=\"$event.stopPropagation()\" mat-icon-button\n type=\"button\" aria-label=\"More actions\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n\n <mat-menu #actionMenu=\"matMenu\" class=\"action-menu\" xPosition=\"after\" yPosition=\"below\" hasBackdrop=\"true\">\n <button mat-menu-item (click)=\"navigateToTestCase(row?.id)\">\n <mat-icon>visibility</mat-icon>\n <span>View</span>\n </button>\n <button mat-menu-item (click)=\"editTestCase(row)\">\n <mat-icon>edit_square</mat-icon>\n <span>Edit</span>\n </button>\n <button mat-menu-item (click)=\"deleteTestCase(row)\" class=\"delete-menu-item\">\n <mat-icon>delete</mat-icon>\n <span>Delete</span>\n </button>\n </mat-menu>\n</div>", components: [{ type: i1$3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: i3$1.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i3$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }], directives: [{ type: i3$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }] });
1193
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ActionMenuButtonComponent, decorators: [{
1194
+ type: Component,
1195
+ args: [{ selector: 'cqa-action-menu-button', template: "<div id=\"cqa-ui-root\">\n <button class=\"action-menu-btn\" [matMenuTriggerFor]=\"actionMenu\" (click)=\"$event.stopPropagation()\" mat-icon-button\n type=\"button\" aria-label=\"More actions\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n\n <mat-menu #actionMenu=\"matMenu\" class=\"action-menu\" xPosition=\"after\" yPosition=\"below\" hasBackdrop=\"true\">\n <button mat-menu-item (click)=\"navigateToTestCase(row?.id)\">\n <mat-icon>visibility</mat-icon>\n <span>View</span>\n </button>\n <button mat-menu-item (click)=\"editTestCase(row)\">\n <mat-icon>edit_square</mat-icon>\n <span>Edit</span>\n </button>\n <button mat-menu-item (click)=\"deleteTestCase(row)\" class=\"delete-menu-item\">\n <mat-icon>delete</mat-icon>\n <span>Delete</span>\n </button>\n </mat-menu>\n</div>", styles: [] }]
1196
+ }], propDecorators: { row: [{
1197
+ type: Input
1198
+ }], view: [{
1199
+ type: Output
1200
+ }], edit: [{
1201
+ type: Output
1202
+ }], delete: [{
1203
+ type: Output
1204
+ }] } });
1205
+
1206
+ class OtherButtonComponent {
1207
+ constructor() {
1208
+ // Single button API (backwards compatible)
1209
+ this.icon = '';
1210
+ this.label = '';
1211
+ this.classes = '';
1212
+ this.colorClass = '';
1213
+ this.buttonClass = '';
1214
+ this.disabled = false;
1215
+ this.type = 'button';
1216
+ // Group buttons API (new)
1217
+ this.buttons = null;
1218
+ /** Extra classes for the button group container */
1219
+ this.groupClass = '';
1220
+ /** Gap utility class; defaults to Tailwind spacing applied in template */
1221
+ this.gapClass = 'cqa-gap-2';
1222
+ /** When true, allows wrapping to next line on smaller screens */
1223
+ this.wrap = true;
1224
+ this.clicked = new EventEmitter();
1225
+ /** Emits the config of the clicked button in a group, along with the event */
1226
+ this.buttonClick = new EventEmitter();
1227
+ }
1228
+ onClick(event) {
1229
+ if (this.disabled) {
1230
+ event.preventDefault();
1231
+ event.stopPropagation();
1232
+ return;
1233
+ }
1234
+ this.clicked.emit(event);
1235
+ }
1236
+ onItemClick(event, item) {
1237
+ if (item === null || item === void 0 ? void 0 : item.disabled) {
1238
+ event.preventDefault();
1239
+ event.stopPropagation();
1240
+ return;
1241
+ }
1242
+ this.buttonClick.emit({ event, item });
1243
+ }
1244
+ }
1245
+ OtherButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: OtherButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1246
+ OtherButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: OtherButtonComponent, selector: "cqa-other-button", inputs: { icon: "icon", label: "label", classes: "classes", colorClass: "colorClass", buttonClass: "buttonClass", disabled: "disabled", type: "type", buttons: "buttons", groupClass: "groupClass", gapClass: "gapClass", wrap: "wrap" }, outputs: { clicked: "clicked", buttonClick: "buttonClick" }, ngImport: i0, template: "<div id=\"cqa-ui-root\" >\n <!-- Group rendering if buttons are provided -->\n <ng-container *ngIf=\"buttons?.length; else singleButton\">\n <div class=\"cqa-inline-flex cqa-items-center\" [ngClass]=\"[wrap ? 'cqa-flex-wrap' : '', gapClass, groupClass]\">\n <button *ngFor=\"let b of buttons\"\n [type]=\"b.type || 'button'\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-py-[5.75px] cqa-px-[11.5px] cqa-rounded-[5px] cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium cqa-border\"\n [ngClass]=\"[b.classes || classes, buttonClass, b.colorClass || colorClass]\"\n [disabled]=\"b.disabled\"\n (click)=\"onItemClick($event, b)\">\n <mat-icon *ngIf=\"b.icon || icon\" class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ b.icon || icon }}</mat-icon>\n <span>{{ b.label }}</span>\n </button>\n </div>\n </ng-container>\n\n <!-- Single button (backwards compatible) -->\n <ng-template #singleButton>\n <button [type]=\"type\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-py-[5.75px] cqa-px-[11.5px] cqa-rounded-[5px] cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium cqa-border\"\n [ngClass]=\"[classes, buttonClass, colorClass]\" [disabled]=\"disabled\" (click)=\"onClick($event)\">\n <mat-icon *ngIf=\"icon\" class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ icon }}</mat-icon>\n <span>{{ label }}</span>\n </button>\n </ng-template>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1247
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: OtherButtonComponent, decorators: [{
1248
+ type: Component,
1249
+ args: [{ selector: 'cqa-other-button', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\" >\n <!-- Group rendering if buttons are provided -->\n <ng-container *ngIf=\"buttons?.length; else singleButton\">\n <div class=\"cqa-inline-flex cqa-items-center\" [ngClass]=\"[wrap ? 'cqa-flex-wrap' : '', gapClass, groupClass]\">\n <button *ngFor=\"let b of buttons\"\n [type]=\"b.type || 'button'\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-py-[5.75px] cqa-px-[11.5px] cqa-rounded-[5px] cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium cqa-border\"\n [ngClass]=\"[b.classes || classes, buttonClass, b.colorClass || colorClass]\"\n [disabled]=\"b.disabled\"\n (click)=\"onItemClick($event, b)\">\n <mat-icon *ngIf=\"b.icon || icon\" class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ b.icon || icon }}</mat-icon>\n <span>{{ b.label }}</span>\n </button>\n </div>\n </ng-container>\n\n <!-- Single button (backwards compatible) -->\n <ng-template #singleButton>\n <button [type]=\"type\"\n class=\"cqa-inline-flex cqa-items-center cqa-gap-1 cqa-py-[5.75px] cqa-px-[11.5px] cqa-rounded-[5px] cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium cqa-border\"\n [ngClass]=\"[classes, buttonClass, colorClass]\" [disabled]=\"disabled\" (click)=\"onClick($event)\">\n <mat-icon *ngIf=\"icon\" class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ icon }}</mat-icon>\n <span>{{ label }}</span>\n </button>\n </ng-template>\n</div>", styles: [] }]
1250
+ }], propDecorators: { icon: [{
1251
+ type: Input
1252
+ }], label: [{
1253
+ type: Input
1254
+ }], classes: [{
1255
+ type: Input
1256
+ }], colorClass: [{
1257
+ type: Input
1258
+ }], buttonClass: [{
1259
+ type: Input
1260
+ }], disabled: [{
1261
+ type: Input
1262
+ }], type: [{
1263
+ type: Input
1264
+ }], buttons: [{
1265
+ type: Input
1266
+ }], groupClass: [{
1267
+ type: Input
1268
+ }], gapClass: [{
1269
+ type: Input
1270
+ }], wrap: [{
1271
+ type: Input
1272
+ }], clicked: [{
1273
+ type: Output
1274
+ }], buttonClick: [{
1275
+ type: Output
1276
+ }] } });
1277
+
1278
+ class DynamicSelectFieldComponent {
1279
+ constructor() {
1280
+ // Must be public for template access in Angular's strict template checking mode
1281
+ this.searchTextByKey = {};
1282
+ }
1283
+ ngOnInit() {
1284
+ if (!this.config || !this.config.key) {
1285
+ throw new Error('cqa-dynamic-select: input "config.key" is required.');
1286
+ }
1287
+ }
1288
+ ngOnChanges(changes) {
1289
+ if ('config' in changes) {
1290
+ // When config changes (including toggling multiple), ensure control value shape matches
1291
+ this.syncControlValueForMultipleMode();
1292
+ }
1293
+ }
1294
+ get panelClass() {
1295
+ return `ctc-select-panel ${this.isMultiple ? 'multiple' : ''}`.trim();
1296
+ }
1297
+ get isMultiple() {
1298
+ var _a;
1299
+ return this.toBoolean((_a = this.config) === null || _a === void 0 ? void 0 : _a.multiple);
1300
+ }
1301
+ get isDisabled() {
1302
+ var _a;
1303
+ return this.toBoolean((_a = this.config) === null || _a === void 0 ? void 0 : _a.disabled);
1304
+ }
1305
+ toBoolean(value) {
1306
+ if (typeof value === 'string') {
1307
+ const v = value.trim().toLowerCase();
1308
+ if (v === 'true' || v === '1')
1309
+ return true;
1310
+ if (v === 'false' || v === '0' || v === '')
1311
+ return false;
1312
+ return true; // any other non-empty string treated as truthy
1313
+ }
1314
+ if (typeof value === 'number') {
1315
+ return value !== 0;
1316
+ }
1317
+ return !!value;
1318
+ }
1319
+ syncControlValueForMultipleMode() {
1320
+ var _a;
1321
+ const key = (_a = this.config) === null || _a === void 0 ? void 0 : _a.key;
1322
+ if (!key || !this.form)
1323
+ return;
1324
+ const control = this.form.get(key);
1325
+ if (!control)
1326
+ return;
1327
+ const currentValue = control.value;
1328
+ if (this.isMultiple) {
1329
+ if (currentValue == null)
1330
+ return;
1331
+ if (Array.isArray(currentValue))
1332
+ return;
1333
+ control.setValue([currentValue], { emitEvent: false });
1334
+ }
1335
+ else {
1336
+ if (!Array.isArray(currentValue))
1337
+ return;
1338
+ control.setValue(currentValue.length ? currentValue[0] : null, { emitEvent: false });
1339
+ }
1340
+ }
1341
+ onSelectOpenedChange(opened, _select) {
1342
+ var _a, _b;
1343
+ if (!opened) {
1344
+ // Reset search text on close so the next open shows full list
1345
+ if ((_a = this.config) === null || _a === void 0 ? void 0 : _a.key) {
1346
+ this.searchTextByKey[this.config.key] = '';
1347
+ }
1348
+ // Ensure any previous custom listeners are cleared (legacy compatibility)
1349
+ if (this.outsideCleanup) {
1350
+ this.outsideCleanup();
1351
+ this.outsideCleanup = undefined;
1352
+ }
1353
+ return;
1354
+ }
1355
+ // Focus the search box if enabled
1356
+ if ((_b = this.config) === null || _b === void 0 ? void 0 : _b.searchable) {
1357
+ setTimeout(() => {
1358
+ const input = document.querySelector('.ts-select-search-input');
1359
+ input === null || input === void 0 ? void 0 : input.focus();
1360
+ }, 0);
1361
+ }
1362
+ }
1363
+ onSearch(key, value) {
1364
+ this.searchTextByKey[key] = value !== null && value !== void 0 ? value : '';
1365
+ }
1366
+ filteredOptions(c) {
1367
+ const t = (this.searchTextByKey[c.key] || '').toLowerCase().trim();
1368
+ if (!t)
1369
+ return c.options || [];
1370
+ return (c.options || []).filter((opt) => {
1371
+ var _a, _b, _c;
1372
+ const text = String((_c = (_b = (_a = opt.name) !== null && _a !== void 0 ? _a : opt.label) !== null && _b !== void 0 ? _b : opt.value) !== null && _c !== void 0 ? _c : '').toLowerCase();
1373
+ return text.includes(t);
1374
+ });
1375
+ }
1376
+ // Close when an option is selected if requested. Always close for single-select.
1377
+ onOptionSelected(select) {
1378
+ var _a, _b, _c;
1379
+ // Let Angular Material auto-close for single-select.
1380
+ // For multi-select, close only if explicitly requested.
1381
+ const shouldClose = this.isMultiple ? !!((_a = this.config) === null || _a === void 0 ? void 0 : _a.closeOnSelect) : false;
1382
+ if (shouldClose) {
1383
+ try {
1384
+ select.close();
1385
+ }
1386
+ catch (_d) { }
1387
+ }
1388
+ // If searchable, clear the search after selection so reopening works predictably
1389
+ if (((_b = this.config) === null || _b === void 0 ? void 0 : _b.searchable) && ((_c = this.config) === null || _c === void 0 ? void 0 : _c.key)) {
1390
+ this.searchTextByKey[this.config.key] = '';
1391
+ }
1392
+ }
1393
+ handleDocumentClick(event) {
1394
+ var _a, _b;
1395
+ // Close when clicking outside of the trigger and outside of the open panel
1396
+ if (!((_a = this.selectRef) === null || _a === void 0 ? void 0 : _a.panelOpen)) {
1397
+ return;
1398
+ }
1399
+ const target = event.target;
1400
+ if (!target)
1401
+ return;
1402
+ // If click is inside the component host, ignore
1403
+ if (((_b = this.hostEl) === null || _b === void 0 ? void 0 : _b.nativeElement) && this.hostEl.nativeElement.contains(target)) {
1404
+ return;
1405
+ }
1406
+ // If click is inside any open mat-select panel, ignore
1407
+ const panelEls = Array.from(document.querySelectorAll('.mat-select-panel'));
1408
+ const clickInsidePanel = panelEls.some((el) => el.contains(target));
1409
+ if (clickInsidePanel) {
1410
+ return;
1411
+ }
1412
+ try {
1413
+ this.selectRef.close();
1414
+ }
1415
+ catch (_c) { }
1416
+ }
1417
+ }
1418
+ DynamicSelectFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1419
+ DynamicSelectFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: { form: "form", config: "config" }, host: { listeners: { "document:click": "handleDocumentClick($event)" } }, viewQueries: [{ propertyName: "selectRef", first: true, predicate: ["selectRef"], descendants: true }, { propertyName: "hostEl", first: true, predicate: ["host"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <ng-container [formGroup]=\"form\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n <mat-form-field #host class=\"mat-select-custom cqa-w-full\" appearance=\"fill\">\n <mat-select #selectRef=\"matSelect\" [placeholder]=\"config.placeholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onOptionSelected(selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input\" type=\"text\" [value]=\"searchTextByKey[config.key] || ''\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" (input)=\"onSearch(config.key, $any($event.target).value)\"\n placeholder=\"Search...\" />\n </mat-option>\n\n <mat-option *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\"\n [textContent]=\"opt.name ?? opt.label ?? opt.value\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </mat-option>\n </mat-select>\n\n <div>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n </ng-container>\n</div>", components: [{ type: i3$2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$1.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$3.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1420
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, decorators: [{
1421
+ type: Component,
1422
+ args: [{ selector: 'cqa-dynamic-select', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <ng-container [formGroup]=\"form\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n <mat-form-field #host class=\"mat-select-custom cqa-w-full\" appearance=\"fill\">\n <mat-select #selectRef=\"matSelect\" [placeholder]=\"config.placeholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onOptionSelected(selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input\" type=\"text\" [value]=\"searchTextByKey[config.key] || ''\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" (input)=\"onSearch(config.key, $any($event.target).value)\"\n placeholder=\"Search...\" />\n </mat-option>\n\n <mat-option *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\"\n [textContent]=\"opt.name ?? opt.label ?? opt.value\">\n {{ opt.name ?? opt.label ?? opt.value }}\n </mat-option>\n </mat-select>\n\n <div>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n </ng-container>\n</div>", styles: [] }]
1423
+ }], propDecorators: { form: [{
1424
+ type: Input
1425
+ }], config: [{
1426
+ type: Input
1427
+ }], selectRef: [{
1428
+ type: ViewChild,
1429
+ args: ['selectRef', { static: false }]
1430
+ }], hostEl: [{
1431
+ type: ViewChild,
1432
+ args: ['host', { static: false, read: ElementRef }]
1433
+ }], handleDocumentClick: [{
1434
+ type: HostListener,
1435
+ args: ['document:click', ['$event']]
1436
+ }] } });
1437
+
1438
+ class DynamicFilterComponent {
1439
+ constructor(fb) {
1440
+ this.fb = fb;
1441
+ this.config = [];
1442
+ this.model = {};
1443
+ this.showFilterPanel = true;
1444
+ this.filtersApplied = new EventEmitter();
1445
+ this.filtersChanged = new EventEmitter();
1446
+ this.resetAction = new EventEmitter();
1447
+ this.form = this.fb.group({});
1448
+ this.maxDate = new Date();
1449
+ this.searchTextByKey = {};
1450
+ this.selectOutsideCleanup = new Map();
1451
+ }
1452
+ ngOnChanges(changes) {
1453
+ if (changes['config'] || changes['model']) {
1454
+ this.buildForm();
1455
+ }
1456
+ }
1457
+ onDateChange(event, key) {
1458
+ var _a, _b;
1459
+ const formGroup = this.getDateGroup(key);
1460
+ const start = (_a = formGroup.get('start')) === null || _a === void 0 ? void 0 : _a.value;
1461
+ const end = (_b = formGroup.get('end')) === null || _b === void 0 ? void 0 : _b.value;
1462
+ // When both dates are selected, auto-apply
1463
+ // if (start && end) {
1464
+ // this.applyDateRange(key, { start, end });
1465
+ // }
1466
+ }
1467
+ buildForm() {
1468
+ const ctrls = {};
1469
+ (this.config || []).forEach(c => {
1470
+ var _a;
1471
+ if (c.hidden)
1472
+ return;
1473
+ if (c.type === 'date-range') {
1474
+ ctrls[c.key] = this.fb.group({ start: new FormControl(), end: new FormControl() });
1475
+ }
1476
+ else {
1477
+ const initial = (_a = this.model) === null || _a === void 0 ? void 0 : _a[c.key];
1478
+ if (c.multiple) {
1479
+ const value = Array.isArray(initial) ? initial : (initial != null ? [initial] : []);
1480
+ ctrls[c.key] = new FormControl(value);
1481
+ }
1482
+ else {
1483
+ ctrls[c.key] = new FormControl(Array.isArray(initial) ? (initial.length ? initial[0] : undefined) : initial);
1484
+ }
1485
+ }
1486
+ });
1487
+ this.form = this.fb.group(ctrls);
1488
+ this.form.valueChanges.subscribe(() => this.filtersChanged.emit(this.serialize()));
1489
+ }
1490
+ onSelectOpenedChange(opened, select) {
1491
+ if (opened) {
1492
+ setTimeout(() => {
1493
+ const onDocDown = (e) => {
1494
+ var _a;
1495
+ const panel = document.querySelector('.cdk-overlay-pane .mat-select-panel');
1496
+ const target = e.target;
1497
+ const originEl = ((_a = select === null || select === void 0 ? void 0 : select._elementRef) === null || _a === void 0 ? void 0 : _a.nativeElement) || null;
1498
+ const insidePanel = !!(panel && target && panel.contains(target));
1499
+ const insideOrigin = !!(originEl && target && originEl.contains(target));
1500
+ if (!insidePanel && !insideOrigin) {
1501
+ select.close();
1502
+ }
1503
+ };
1504
+ document.addEventListener('mousedown', onDocDown, true);
1505
+ this.selectOutsideCleanup.set(select, () => document.removeEventListener('mousedown', onDocDown, true));
1506
+ }, 0);
1507
+ }
1508
+ else {
1509
+ const cleanup = this.selectOutsideCleanup.get(select);
1510
+ if (cleanup)
1511
+ cleanup();
1512
+ this.selectOutsideCleanup.delete(select);
1513
+ }
1514
+ }
1515
+ onSearch(key, text) {
1516
+ this.searchTextByKey[key] = (text || '').toLowerCase();
1517
+ }
1518
+ filteredOptions(item) {
1519
+ const options = (item === null || item === void 0 ? void 0 : item.options) || [];
1520
+ const q = (this.searchTextByKey[item.key] || '').trim();
1521
+ if (!q)
1522
+ return options;
1523
+ return options.filter(opt => {
1524
+ var _a, _b, _c;
1525
+ const name = ((_b = (_a = opt.name) !== null && _a !== void 0 ? _a : opt.label) !== null && _b !== void 0 ? _b : String((_c = opt.value) !== null && _c !== void 0 ? _c : '')).toLowerCase();
1526
+ return name.includes(q);
1527
+ });
1528
+ }
1529
+ getDateGroup(key) {
1530
+ return this.form.get(key);
1531
+ }
1532
+ getSelectConfig(item) {
1533
+ return {
1534
+ key: item.key,
1535
+ label: item.label,
1536
+ placeholder: item.placeholder,
1537
+ disabled: item.disabled,
1538
+ multiple: item.multiple,
1539
+ searchable: item.searchable,
1540
+ options: item.options || []
1541
+ };
1542
+ }
1543
+ apply() {
1544
+ this.filtersApplied.emit(this.serialize());
1545
+ }
1546
+ reset() {
1547
+ Object.keys(this.form.controls).forEach(key => {
1548
+ var _a, _b;
1549
+ const ctrl = this.form.get(key);
1550
+ if (ctrl instanceof FormGroup) {
1551
+ (_a = ctrl.get('start')) === null || _a === void 0 ? void 0 : _a.setValue(undefined);
1552
+ (_b = ctrl.get('end')) === null || _b === void 0 ? void 0 : _b.setValue(undefined);
1553
+ }
1554
+ else {
1555
+ ctrl === null || ctrl === void 0 ? void 0 : ctrl.setValue(undefined);
1556
+ }
1557
+ });
1558
+ this.resetAction.emit();
1559
+ this.filtersChanged.emit(this.serialize());
1560
+ }
1561
+ serialize() {
1562
+ const result = {};
1563
+ (this.config || []).forEach(c => {
1564
+ const ctrl = this.form.get(c.key);
1565
+ if (!ctrl)
1566
+ return;
1567
+ let val = ctrl instanceof FormGroup ? ctrl.getRawValue() : ctrl.value;
1568
+ if (c.type === 'date-range') {
1569
+ const start = val === null || val === void 0 ? void 0 : val.start;
1570
+ const end = val === null || val === void 0 ? void 0 : val.end;
1571
+ if (start || end)
1572
+ result[c.key] = { start, end };
1573
+ }
1574
+ else {
1575
+ if (val !== undefined && val !== null && (Array.isArray(val) ? val.length > 0 : val !== '')) {
1576
+ result[c.key] = val;
1577
+ }
1578
+ }
1579
+ });
1580
+ return result;
1581
+ }
1582
+ // Mat date range picker overlay preset helpers
1583
+ applyPresetToGroup(key, presetKey) {
1584
+ const dateGroup = this.getDateGroup(key);
1585
+ if (!dateGroup)
1586
+ return;
1587
+ const { start, end } = this.getPresetDates(presetKey);
1588
+ dateGroup.patchValue({ start, end });
1589
+ this.filtersChanged.emit(this.serialize());
1590
+ }
1591
+ getPresetDates(presetKey) {
1592
+ const today = new Date();
1593
+ const clampToEndOfToday = (d) => { const nd = new Date(d); nd.setHours(23, 59, 59, 999); return nd; };
1594
+ switch (presetKey) {
1595
+ case 'today':
1596
+ return { start: today, end: today };
1597
+ case 'last7days': {
1598
+ const start = new Date();
1599
+ start.setDate(start.getDate() - 6);
1600
+ return { start, end: today };
1601
+ }
1602
+ case 'last30days': {
1603
+ const start = new Date();
1604
+ start.setDate(start.getDate() - 29);
1605
+ return { start, end: today };
1606
+ }
1607
+ case 'last90days': {
1608
+ const start = new Date();
1609
+ start.setDate(start.getDate() - 89);
1610
+ return { start, end: today };
1611
+ }
1612
+ case 'thismonth': {
1613
+ const start = new Date(today.getFullYear(), today.getMonth(), 1);
1614
+ return { start, end: today };
1615
+ }
1616
+ case 'lastmonth': {
1617
+ const start = new Date(today.getFullYear(), today.getMonth() - 1, 1);
1618
+ const end = new Date(today.getFullYear(), today.getMonth(), 0);
1619
+ return { start, end: clampToEndOfToday(end) };
1620
+ }
1621
+ }
1622
+ }
1623
+ getDateValidationError(key) {
1624
+ var _a, _b, _c, _d, _e;
1625
+ const dateGroup = this.getDateGroup(key);
1626
+ if (!dateGroup)
1627
+ return null;
1628
+ const startCtrl = dateGroup.controls['start'];
1629
+ const endCtrl = dateGroup.controls['end'];
1630
+ const startVal = startCtrl === null || startCtrl === void 0 ? void 0 : startCtrl.value;
1631
+ const endVal = endCtrl === null || endCtrl === void 0 ? void 0 : endCtrl.value;
1632
+ const startParseErr = (_b = (_a = startCtrl === null || startCtrl === void 0 ? void 0 : startCtrl.errors) === null || _a === void 0 ? void 0 : _a['matDatepickerParse']) === null || _b === void 0 ? void 0 : _b.text;
1633
+ const endParseErr = (_d = (_c = endCtrl === null || endCtrl === void 0 ? void 0 : endCtrl.errors) === null || _c === void 0 ? void 0 : _c['matDatepickerParse']) === null || _d === void 0 ? void 0 : _d.text;
1634
+ if (!startVal && !endVal && !startParseErr && !endParseErr)
1635
+ return null;
1636
+ if (startParseErr)
1637
+ return `Invalid start date format`;
1638
+ if (endParseErr)
1639
+ return `Invalid end date format`;
1640
+ if (startVal && !endVal)
1641
+ return `Please select an end date`;
1642
+ if (!startVal && endVal)
1643
+ return `Please select a start date`;
1644
+ if (dateGroup.hasError('matStartDateInvalid'))
1645
+ return `Start date must be before end date`;
1646
+ if (dateGroup.hasError('matEndDateInvalid'))
1647
+ return `End date must be after start date`;
1648
+ if (dateGroup.invalid) {
1649
+ const config = (_e = this.config) === null || _e === void 0 ? void 0 : _e.find(c => c.key === key);
1650
+ return config ? `${config.label} is invalid` : 'Date range is invalid';
1651
+ }
1652
+ return null;
1653
+ }
1654
+ }
1655
+ DynamicFilterComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicFilterComponent, deps: [{ token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
1656
+ DynamicFilterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicFilterComponent, selector: "cqa-dynamic-filter", inputs: { config: "config", model: "model", showFilterPanel: "showFilterPanel" }, outputs: { filtersApplied: "filtersApplied", filtersChanged: "filtersChanged", resetAction: "resetAction" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-filter cqa-mb-[28px]\" *ngIf=\"showFilterPanel\">\n <form class=\"ts-form cqa-grid lg:cqa-grid-cols-4 md:cqa-grid-cols-2 cqa-gap-4\" [formGroup]=\"form\"\n (keydown.enter)=\"(false)\" novalidate=\"novalidate\">\n <ng-container *ngFor=\"let c of config\">\n <ng-container *ngIf=\"!c.hidden\">\n <div class=\"form-group cqa-flex cqa-flex-col cqa-gap-2\">\n <!-- Select -->\n <ng-container *ngIf=\"c.type === 'select'\">\n <cqa-dynamic-select [form]=\"form\" [config]=\"getSelectConfig(c)\"></cqa-dynamic-select>\n </ng-container>\n\n <!-- Date Range --> \n <ng-container *ngIf=\"c.type === 'date-range'\">\n <label\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4]\">{{\n c.label }}</label>\n <mat-form-field class=\"mat-date-custom\" appearance=\"fill\">\n <mat-date-range-input [rangePicker]=\"picker\" [formGroup]=\"getDateGroup(c.key)\" [max]=\"maxDate\">\n <input matStartDate formControlName=\"start\" placeholder=\"Start date\" [max]=\"maxDate\" required\n [readonly]=\"true\" (focus)=\"picker.open()\" (click)=\"picker.open()\" />\n <input matEndDate formControlName=\"end\" placeholder=\"End date\" [max]=\"maxDate\" required\n [readonly]=\"true\" (focus)=\"picker.open()\" (click)=\"picker.open()\" />\n </mat-date-range-input>\n <mat-date-range-picker #picker (dateChange)=\"onDateChange($event, c.key)\"\n [panelClass]=\"'ctc-date-range-panel'\">\n <mat-datepicker-actions>\n <div class=\"ctc-date-presets\">\n <div class=\"cqa-mb-2 cqa-font-medium\">Quick Presets</div>\n <div class=\"btn-group\">\n <button type=\"button\" class=\"preset-btn today\"\n (click)=\"applyPresetToGroup(c.key, 'today'); picker.close()\">Today</button>\n <button type=\"button\" class=\"preset-btn last7days\"\n (click)=\"applyPresetToGroup(c.key, 'last7days'); picker.close()\">Last 7 days</button>\n <button type=\"button\" class=\"preset-btn last30days\"\n (click)=\"applyPresetToGroup(c.key, 'last30days'); picker.close()\">Last 30 days</button>\n <button type=\"button\" class=\"preset-btn last90days\"\n (click)=\"applyPresetToGroup(c.key, 'last90days'); picker.close()\">Last 90 days</button>\n <button type=\"button\" class=\"preset-btn thismonth\"\n (click)=\"applyPresetToGroup(c.key, 'thismonth'); picker.close()\">This month</button>\n <button type=\"button\" class=\"preset-btn lastmonth\"\n (click)=\"applyPresetToGroup(c.key, 'lastmonth'); picker.close()\">Last month</button>\n </div>\n </div>\n <div class=\"cqa-font-medium cqa-mb-2 cqa-mt-[10px] cqa-w-full\">Custom Range</div>\n <button\n class=\"cqa-font-medium !cqa-mb-2 !cqa-mt-[10px] cqa-w-[calc(100%-32px)] !cqa-absolute cqa-bottom-[2px]\"\n mat-flat-button color=\"primary\" matDatepickerApply>Apply</button>\n </mat-datepicker-actions>\n </mat-date-range-picker>\n <div (click)=\"picker.open()\" class=\"cqa-cursor-pointer\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.33398 1.33203V3.9987\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M10.666 1.33203V3.9987\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M12.6667 2.66797H3.33333C2.59695 2.66797 2 3.26492 2 4.0013V13.3346C2 14.071 2.59695 14.668 3.33333 14.668H12.6667C13.403 14.668 14 14.071 14 13.3346V4.0013C14 3.26492 13.403 2.66797 12.6667 2.66797Z\"\n stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 6.66797H14\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n <!-- Specific validation messages -->\n <mat-error *ngIf=\"getDateValidationError(c.key) && !picker.opened\">\n {{ getDateValidationError(c.key) }}\n </mat-error>\n\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </form>\n\n <div class=\"cqa-flex cqa-justify-end cqa-items-stretch cqa-gap-2 cqa-mt-4\">\n <button type=\"button\"\n class=\"cqa-text-[13.33px] cqa-leading-[1] cqa-flex cqa-flex-row cqa-justify-center cqa-items-center cqa-px-[11px] cqa-py-[1px] cqa-gap-[14px] cqa-h-8 cqa-border cqa-border-[#0B0B0C] cqa-shadow-[0_1px_2px_rgba(0,0,0,0.05)] cqa-rounded-lg cqa-text-[#0B0B0C]\"\n (click)=\"reset()\">Reset</button>\n <button type=\"button\"\n class=\"cqa-text-[13.33px] cqa-leading-[1] cqa-flex cqa-flex-row cqa-justify-center cqa-items-center cqa-px-[11px] cqa-py-[1px] cqa-gap-[14px] cqa-h-8 cqa-bg-[#0B0B0C] cqa-border cqa-border-[#E5E5E5] cqa-shadow-[0_1px_2px_rgba(0,0,0,0.05)] cqa-rounded-lg cqa-text-white\"\n (click)=\"apply()\">Apply Filter</button>\n </div>\n </div>\n</div>", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"] }, { type: i3$2.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i4.MatDateRangeInput, selector: "mat-date-range-input", inputs: ["rangePicker", "required", "dateFilter", "min", "max", "disabled", "separator", "comparisonStart", "comparisonEnd"], exportAs: ["matDateRangeInput"] }, { type: i4.MatDateRangePicker, selector: "mat-date-range-picker", exportAs: ["matDateRangePicker"] }, { type: i4.MatDatepickerActions, selector: "mat-datepicker-actions, mat-date-range-picker-actions" }, { type: i1$3.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.MatStartDate, selector: "input[matStartDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4.MatEndDate, selector: "input[matEndDate]", inputs: ["errorStateMatcher"], outputs: ["dateChange", "dateInput"] }, { type: i4.MatDatepickerApply, selector: "[matDatepickerApply], [matDateRangePickerApply]" }, { type: i3$2.MatError, selector: "mat-error", inputs: ["id"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1657
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicFilterComponent, decorators: [{
1658
+ type: Component,
1659
+ args: [{ selector: 'cqa-dynamic-filter', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-filter cqa-mb-[28px]\" *ngIf=\"showFilterPanel\">\n <form class=\"ts-form cqa-grid lg:cqa-grid-cols-4 md:cqa-grid-cols-2 cqa-gap-4\" [formGroup]=\"form\"\n (keydown.enter)=\"(false)\" novalidate=\"novalidate\">\n <ng-container *ngFor=\"let c of config\">\n <ng-container *ngIf=\"!c.hidden\">\n <div class=\"form-group cqa-flex cqa-flex-col cqa-gap-2\">\n <!-- Select -->\n <ng-container *ngIf=\"c.type === 'select'\">\n <cqa-dynamic-select [form]=\"form\" [config]=\"getSelectConfig(c)\"></cqa-dynamic-select>\n </ng-container>\n\n <!-- Date Range --> \n <ng-container *ngIf=\"c.type === 'date-range'\">\n <label\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4]\">{{\n c.label }}</label>\n <mat-form-field class=\"mat-date-custom\" appearance=\"fill\">\n <mat-date-range-input [rangePicker]=\"picker\" [formGroup]=\"getDateGroup(c.key)\" [max]=\"maxDate\">\n <input matStartDate formControlName=\"start\" placeholder=\"Start date\" [max]=\"maxDate\" required\n [readonly]=\"true\" (focus)=\"picker.open()\" (click)=\"picker.open()\" />\n <input matEndDate formControlName=\"end\" placeholder=\"End date\" [max]=\"maxDate\" required\n [readonly]=\"true\" (focus)=\"picker.open()\" (click)=\"picker.open()\" />\n </mat-date-range-input>\n <mat-date-range-picker #picker (dateChange)=\"onDateChange($event, c.key)\"\n [panelClass]=\"'ctc-date-range-panel'\">\n <mat-datepicker-actions>\n <div class=\"ctc-date-presets\">\n <div class=\"cqa-mb-2 cqa-font-medium\">Quick Presets</div>\n <div class=\"btn-group\">\n <button type=\"button\" class=\"preset-btn today\"\n (click)=\"applyPresetToGroup(c.key, 'today'); picker.close()\">Today</button>\n <button type=\"button\" class=\"preset-btn last7days\"\n (click)=\"applyPresetToGroup(c.key, 'last7days'); picker.close()\">Last 7 days</button>\n <button type=\"button\" class=\"preset-btn last30days\"\n (click)=\"applyPresetToGroup(c.key, 'last30days'); picker.close()\">Last 30 days</button>\n <button type=\"button\" class=\"preset-btn last90days\"\n (click)=\"applyPresetToGroup(c.key, 'last90days'); picker.close()\">Last 90 days</button>\n <button type=\"button\" class=\"preset-btn thismonth\"\n (click)=\"applyPresetToGroup(c.key, 'thismonth'); picker.close()\">This month</button>\n <button type=\"button\" class=\"preset-btn lastmonth\"\n (click)=\"applyPresetToGroup(c.key, 'lastmonth'); picker.close()\">Last month</button>\n </div>\n </div>\n <div class=\"cqa-font-medium cqa-mb-2 cqa-mt-[10px] cqa-w-full\">Custom Range</div>\n <button\n class=\"cqa-font-medium !cqa-mb-2 !cqa-mt-[10px] cqa-w-[calc(100%-32px)] !cqa-absolute cqa-bottom-[2px]\"\n mat-flat-button color=\"primary\" matDatepickerApply>Apply</button>\n </mat-datepicker-actions>\n </mat-date-range-picker>\n <div (click)=\"picker.open()\" class=\"cqa-cursor-pointer\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.33398 1.33203V3.9987\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M10.666 1.33203V3.9987\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path\n d=\"M12.6667 2.66797H3.33333C2.59695 2.66797 2 3.26492 2 4.0013V13.3346C2 14.071 2.59695 14.668 3.33333 14.668H12.6667C13.403 14.668 14 14.071 14 13.3346V4.0013C14 3.26492 13.403 2.66797 12.6667 2.66797Z\"\n stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path d=\"M2 6.66797H14\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n <!-- Specific validation messages -->\n <mat-error *ngIf=\"getDateValidationError(c.key) && !picker.opened\">\n {{ getDateValidationError(c.key) }}\n </mat-error>\n\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </form>\n\n <div class=\"cqa-flex cqa-justify-end cqa-items-stretch cqa-gap-2 cqa-mt-4\">\n <button type=\"button\"\n class=\"cqa-text-[13.33px] cqa-leading-[1] cqa-flex cqa-flex-row cqa-justify-center cqa-items-center cqa-px-[11px] cqa-py-[1px] cqa-gap-[14px] cqa-h-8 cqa-border cqa-border-[#0B0B0C] cqa-shadow-[0_1px_2px_rgba(0,0,0,0.05)] cqa-rounded-lg cqa-text-[#0B0B0C]\"\n (click)=\"reset()\">Reset</button>\n <button type=\"button\"\n class=\"cqa-text-[13.33px] cqa-leading-[1] cqa-flex cqa-flex-row cqa-justify-center cqa-items-center cqa-px-[11px] cqa-py-[1px] cqa-gap-[14px] cqa-h-8 cqa-bg-[#0B0B0C] cqa-border cqa-border-[#E5E5E5] cqa-shadow-[0_1px_2px_rgba(0,0,0,0.05)] cqa-rounded-lg cqa-text-white\"\n (click)=\"apply()\">Apply Filter</button>\n </div>\n </div>\n</div>", styles: [] }]
1660
+ }], ctorParameters: function () { return [{ type: i1$1.FormBuilder }]; }, propDecorators: { config: [{
1661
+ type: Input
1662
+ }], model: [{
1663
+ type: Input
1664
+ }], showFilterPanel: [{
1665
+ type: Input
1666
+ }], filtersApplied: [{
1667
+ type: Output
1668
+ }], filtersChanged: [{
1669
+ type: Output
1670
+ }], resetAction: [{
1671
+ type: Output
1672
+ }] } });
1673
+
1674
+ class ColumnVisibilityComponent {
1675
+ constructor() {
1676
+ this.isStepGroup = false;
1677
+ // Dynamic columns (preferred). Each item defines the id used as key and the label to render.
1678
+ this.columns = [];
1679
+ // Start with an empty visibility map; keys will be added from 'columns'
1680
+ this.columnVisibility = {};
1681
+ this.selectedAutoRefreshInterval = 0; // 0 = Off
1682
+ this.columnVisibilityChange = new EventEmitter();
1683
+ this.autoRefreshChange = new EventEmitter();
1684
+ }
1685
+ ngOnChanges(changes) {
1686
+ // When dynamic columns change, ensure we have keys in the visibility map
1687
+ if (changes['columns'] && Array.isArray(this.columns) && this.columns.length) {
1688
+ for (const col of this.columns) {
1689
+ if (this.columnVisibility[col.id] === undefined) {
1690
+ this.columnVisibility[col.id] = true;
1691
+ }
1692
+ }
1693
+ }
1694
+ }
1695
+ get areAllColumnsSelected() {
1696
+ const keys = this.getTogglableKeys();
1697
+ return keys.every(k => !!this.columnVisibility[k]);
1698
+ }
1699
+ toggleAllColumns(checked) {
1700
+ const keys = this.getTogglableKeys();
1701
+ for (const k of keys) {
1702
+ this.columnVisibility[k] = checked;
1703
+ }
1704
+ this.saveColumnPreferences();
1705
+ }
1706
+ saveColumnPreferences() {
1707
+ this.columnVisibilityChange.emit(Object.assign({}, this.columnVisibility));
1708
+ }
1709
+ onAutoRefreshChange() {
1710
+ this.autoRefreshChange.emit(this.selectedAutoRefreshInterval);
1711
+ }
1712
+ getTogglableKeys() {
1713
+ return Array.isArray(this.columns) ? this.columns.map(c => c.id) : [];
1714
+ }
1715
+ }
1716
+ ColumnVisibilityComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ColumnVisibilityComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1717
+ ColumnVisibilityComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ColumnVisibilityComponent, selector: "cqa-column-visibility", inputs: { isStepGroup: "isStepGroup", columns: "columns", columnVisibility: "columnVisibility", selectedAutoRefreshInterval: "selectedAutoRefreshInterval" }, outputs: { columnVisibilityChange: "columnVisibilityChange", autoRefreshChange: "autoRefreshChange" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <cqa-button variant=\"grey-solid\" icon=\"settings\" [matMenuTriggerFor]=\"settingsMenu\" aria-label=\"Settings\">\n </cqa-button>\n\n <mat-menu #settingsMenu=\"matMenu\" class=\"table-settings-menu\">\n <div class=\"settings-menu-content cqa-p-[17px]\" (click)=\"$event.stopPropagation()\">\n <div class=\"settings-section cqa-mb-3\">\n <h4 class=\"settings-title cqa-font-bold cqa-text-[14px] cqa-leading-[20px] cqa-mb-2\">Show Columns</h4>\n <div class=\"settings-options cqa-flex cqa-flex-col cqa-gap-2 cqa-text-[14px] cqa-leading-[20px]\">\n <mat-checkbox [checked]=\"areAllColumnsSelected\" (change)=\"toggleAllColumns($event.checked)\"\n class=\"select-all-checkbox\">\n {{ areAllColumnsSelected ? 'Unselect All' : 'Select All' }}\n </mat-checkbox>\n <!-- Dynamic column list -->\n <ng-container *ngIf=\"columns?.length\">\n <mat-checkbox *ngFor=\"let col of columns\" [(ngModel)]=\"columnVisibility[col.id]\"\n (change)=\"saveColumnPreferences()\">\n {{ col.label }}\n </mat-checkbox>\n </ng-container>\n </div>\n </div>\n\n <div class=\"settings-section\">\n <h4 class=\"settings-title cqa-font-bold cqa-text-[14px] cqa-leading-[20px] cqa-mb-2\">Auto refresh every</h4>\n <div class=\"refresh-options\">\n <mat-radio-group [(ngModel)]=\"selectedAutoRefreshInterval\" (change)=\"onAutoRefreshChange()\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-text-[14px] cqa-leading-[20px]\">\n <label><mat-radio-button [value]=\"10000\">10 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"20000\">20 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"30000\">30 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"0\">Off</mat-radio-button></label>\n </mat-radio-group>\n </div>\n </div>\n </div>\n </mat-menu>", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }, { type: i3$1.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { type: i3$4.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i4$1.MatRadioButton, selector: "mat-radio-button", inputs: ["disableRipple", "tabIndex"], exportAs: ["matRadioButton"] }], directives: [{ type: i3$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i4$1.MatRadioGroup, selector: "mat-radio-group", exportAs: ["matRadioGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1718
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ColumnVisibilityComponent, decorators: [{
1719
+ type: Component,
1720
+ args: [{ selector: 'cqa-column-visibility', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <cqa-button variant=\"grey-solid\" icon=\"settings\" [matMenuTriggerFor]=\"settingsMenu\" aria-label=\"Settings\">\n </cqa-button>\n\n <mat-menu #settingsMenu=\"matMenu\" class=\"table-settings-menu\">\n <div class=\"settings-menu-content cqa-p-[17px]\" (click)=\"$event.stopPropagation()\">\n <div class=\"settings-section cqa-mb-3\">\n <h4 class=\"settings-title cqa-font-bold cqa-text-[14px] cqa-leading-[20px] cqa-mb-2\">Show Columns</h4>\n <div class=\"settings-options cqa-flex cqa-flex-col cqa-gap-2 cqa-text-[14px] cqa-leading-[20px]\">\n <mat-checkbox [checked]=\"areAllColumnsSelected\" (change)=\"toggleAllColumns($event.checked)\"\n class=\"select-all-checkbox\">\n {{ areAllColumnsSelected ? 'Unselect All' : 'Select All' }}\n </mat-checkbox>\n <!-- Dynamic column list -->\n <ng-container *ngIf=\"columns?.length\">\n <mat-checkbox *ngFor=\"let col of columns\" [(ngModel)]=\"columnVisibility[col.id]\"\n (change)=\"saveColumnPreferences()\">\n {{ col.label }}\n </mat-checkbox>\n </ng-container>\n </div>\n </div>\n\n <div class=\"settings-section\">\n <h4 class=\"settings-title cqa-font-bold cqa-text-[14px] cqa-leading-[20px] cqa-mb-2\">Auto refresh every</h4>\n <div class=\"refresh-options\">\n <mat-radio-group [(ngModel)]=\"selectedAutoRefreshInterval\" (change)=\"onAutoRefreshChange()\"\n class=\"cqa-flex cqa-flex-col cqa-gap-2 cqa-text-[14px] cqa-leading-[20px]\">\n <label><mat-radio-button [value]=\"10000\">10 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"20000\">20 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"30000\">30 Seconds</mat-radio-button></label>\n <label><mat-radio-button [value]=\"0\">Off</mat-radio-button></label>\n </mat-radio-group>\n </div>\n </div>\n </div>\n </mat-menu>", styles: [] }]
1721
+ }], propDecorators: { isStepGroup: [{
1722
+ type: Input
1723
+ }], columns: [{
1724
+ type: Input
1725
+ }], columnVisibility: [{
1726
+ type: Input
1727
+ }], selectedAutoRefreshInterval: [{
1728
+ type: Input
1729
+ }], columnVisibilityChange: [{
1730
+ type: Output
1731
+ }], autoRefreshChange: [{
1732
+ type: Output
1733
+ }] } });
1734
+
1735
+ class TableActionToolbarComponent {
1736
+ constructor() {
1737
+ this.selectedItems = [];
1738
+ this.actions = [];
1739
+ this.actionClick = new EventEmitter();
1740
+ }
1741
+ get hasSelection() {
1742
+ var _a;
1743
+ return (((_a = this.selectedItems) === null || _a === void 0 ? void 0 : _a.length) || 0) > 0;
1744
+ }
1745
+ get isSingleSelection() {
1746
+ var _a;
1747
+ return ((_a = this.selectedItems) === null || _a === void 0 ? void 0 : _a.length) === 1;
1748
+ }
1749
+ get selectionLabel() {
1750
+ var _a;
1751
+ const n = ((_a = this.selectedItems) === null || _a === void 0 ? void 0 : _a.length) || 0;
1752
+ return n === 1 ? '1 selected' : `${n} selected`;
1753
+ }
1754
+ visibleActions() {
1755
+ const ctx = { selected: this.selectedItems || [] };
1756
+ return (this.actions || []).filter(a => (a.show ? a.show(ctx) : true));
1757
+ }
1758
+ isDisabled(action) {
1759
+ const ctx = { selected: this.selectedItems || [] };
1760
+ return action.disabled ? !!action.disabled(ctx) : false;
1761
+ }
1762
+ onAction(action) {
1763
+ if (this.isDisabled(action)) {
1764
+ return;
1765
+ }
1766
+ const context = { id: action.id, selected: this.selectedItems || [] };
1767
+ if (action.onClick) {
1768
+ action.onClick(context);
1769
+ }
1770
+ this.actionClick.emit(context);
1771
+ }
1772
+ }
1773
+ TableActionToolbarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableActionToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1774
+ TableActionToolbarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TableActionToolbarComponent, selector: "cqa-table-action-toolbar", inputs: { selectedItems: "selectedItems", actions: "actions" }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"action-toolbar cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-flex-wrap cqa-py-[15.5px] sm:cqa-px-[34px] cqa-px-[20px] cqa-bg-primary cqa-text-white cqa-rounded-[7px]\"\n *ngIf=\"hasSelection\">\n <div class=\"action-toolbar-left cqa-text-[14px] cqa-leading-[21px] cqa-font-medium\">\n {{ selectionLabel }}\n </div>\n <div class=\"action-toolbar-right cqa-flex cqa-items-center cqa-gap-[7px]\">\n <ng-container *ngFor=\"let action of visibleActions()\">\n <div [attr.aria-disabled]=\"isDisabled(action)\" [class.cqa-opacity-50]=\"isDisabled(action)\" [class.cqa-cursor-not-allowed]=\"isDisabled(action)\" (click)=\"!isDisabled(action) && onAction(action)\"\n class=\"cqa-flex cqa-items-center cqa-gap-[8.75px] cqa-py-[5px] cqa-px-[8.75px] cqa-cursor-pointer cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium\">\n <mat-icon class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ action.icon }}</mat-icon>\n <span class=\"md:cqa-flex cqa-hidden\">{{ action.label }}</span>\n </div>\n </ng-container>\n </div>\n <!-- Forwards clicks inside toolbar without affecting outer selections -->\n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1775
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableActionToolbarComponent, decorators: [{
1776
+ type: Component,
1777
+ args: [{ selector: 'cqa-table-action-toolbar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"action-toolbar cqa-flex cqa-items-center cqa-justify-between cqa-gap-2 cqa-flex-wrap cqa-py-[15.5px] sm:cqa-px-[34px] cqa-px-[20px] cqa-bg-primary cqa-text-white cqa-rounded-[7px]\"\n *ngIf=\"hasSelection\">\n <div class=\"action-toolbar-left cqa-text-[14px] cqa-leading-[21px] cqa-font-medium\">\n {{ selectionLabel }}\n </div>\n <div class=\"action-toolbar-right cqa-flex cqa-items-center cqa-gap-[7px]\">\n <ng-container *ngFor=\"let action of visibleActions()\">\n <div [attr.aria-disabled]=\"isDisabled(action)\" [class.cqa-opacity-50]=\"isDisabled(action)\" [class.cqa-cursor-not-allowed]=\"isDisabled(action)\" (click)=\"!isDisabled(action) && onAction(action)\"\n class=\"cqa-flex cqa-items-center cqa-gap-[8.75px] cqa-py-[5px] cqa-px-[8.75px] cqa-cursor-pointer cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium\">\n <mat-icon class=\"!cqa-w-[16px] !cqa-h-[16px] !cqa-text-[16px]\">{{ action.icon }}</mat-icon>\n <span class=\"md:cqa-flex cqa-hidden\">{{ action.label }}</span>\n </div>\n </ng-container>\n </div>\n <!-- Forwards clicks inside toolbar without affecting outer selections -->\n </div>\n</div>", styles: [] }]
1778
+ }], propDecorators: { selectedItems: [{
1779
+ type: Input
1780
+ }], actions: [{
1781
+ type: Input
1782
+ }], actionClick: [{
1783
+ type: Output
1784
+ }] } });
1785
+
1786
+ class MetricsBlockComponent {
1787
+ constructor() {
1788
+ this.progress = '0%';
1789
+ this.layout = '1';
1790
+ this.itemslength = '0';
1791
+ }
1792
+ formatPercent(value) {
1793
+ if (value === undefined || value === null || Number.isNaN(value))
1794
+ return '';
1795
+ const sign = value > 0 ? '+' : value < 0 ? '' : '';
1796
+ return `${sign}${value}%`;
1797
+ }
1798
+ percentClass(value) {
1799
+ if (value === undefined || value === null || Number.isNaN(value))
1800
+ return 'cqa-text-[#6B7280]';
1801
+ if (value > 0)
1802
+ return 'cqa-text-[#10B981]';
1803
+ if (value < 0)
1804
+ return 'cqa-text-[#EF4444]';
1805
+ return 'cqa-text-[#6B7280]';
1806
+ }
1807
+ }
1808
+ MetricsBlockComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MetricsBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1809
+ MetricsBlockComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: MetricsBlockComponent, selector: "cqa-metrics-block", inputs: { item: "item", progress: "progress", layout: "layout", itemslength: "itemslength" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n [ngClass]=\"[layout === '1'\n ? 'cqa-flex cqa-justify-center cqa-items-center cqa-py-3 md:cqa-pt-1 md:cqa-pb-0.5 cqa-px-5 cqa-gap-3 cqa-w-full md:cqa-h-[62px] cqa-border-b-0 cqa-border-[#E5E7EB]'\n : 'cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-py-3 md:cqa-py-1 lg:cqa-px-5 cqa-px-2 cqa-w-full md:cqa-h-[53px]', itemslength == item.id ? 'cqa-border-l md:cqa-border-l-0 md:cqa-border-l' : '' , item.id == '1' && layout === '1' ? 'cqa-border-l md:cqa-border-r' : '']\">\n <ng-container *ngIf=\"layout === '1'; else layout2\">\n <!-- [ngClass]=\"{ 'border-l md:border-l-0': itemslength == item.id }\" -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-min-w-[40px] cqa-rounded-[10px]\"\n [ngClass]=\"item.accentBgClass || 'cqa-bg-[#EEF2FF]'\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\" [ngClass]=\"item.iconColorClass || 'cqa-text-[#3F43EE]'\"\n *ngIf=\"item.icon\">{{ item.icon }}</mat-icon>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start cqa-gap-0.5 cqa-w-full cqa-h-auto cqa-flex-1 cqa-truncate\">\n <div class=\"cqa-w-full cqa-h-4 cqa-text-[12px] cqa-leading-4 cqa-font-medium cqa-text-[#6A7282]\">{{ item.label\n }}</div>\n <div class=\"cqa-w-full cqa-h-7 cqa-gap-2 cqa-flex\"\n [ngClass]=\"item.subtext ? 'cqa-justify-between cqa-items-center' : 'cqa-justify-start cqa-items-center'\">\n <div\n class=\"cqa-text-[20px] cqa-leading-[28px] cqa-font-semibold cqa-tracking-[-0.449219px] cqa-text-[#101828]\">\n {{ item.value | number }}</div>\n <div *ngIf=\"item.subtext\"\n class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6A7282] cqa-truncate cqa-hidden sm:cqa-block\">{{\n item.subtext }}</div>\n </div>\n <div class=\"cqa-w-full cqa-h-1 cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [ngClass]=\"item.colorClass || 'cqa-bg-[#3F43EE]'\"\n [style.width]=\"progress\"></div>\n </div>\n </div>\n </ng-container>\n <ng-template #layout2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[16px]\" [ngClass]=\"item.iconColorClass || 'cqa-text-[#3F43EE]'\"\n *ngIf=\"item.icon\">{{ item.icon }}</mat-icon>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6B7280]\">{{ item.label }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-w-full cqa-justify-between\">\n <h6 class=\"cqa-text-[16px] cqa-leading-7 cqa-tracking-[-0.45px] cqa-text-[#111827]\">{{ item.value | number }}\n </h6>\n <span *ngIf=\"item.percent !== undefined\" class=\"cqa-text-[10px] cqa-leading-4\"\n [ngClass]=\"percentClass(item.percent)\">{{ formatPercent(item.percent) }}</span>\n </div>\n </ng-template>\n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "number": i2.DecimalPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1810
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MetricsBlockComponent, decorators: [{
1811
+ type: Component,
1812
+ args: [{ selector: 'cqa-metrics-block', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n [ngClass]=\"[layout === '1'\n ? 'cqa-flex cqa-justify-center cqa-items-center cqa-py-3 md:cqa-pt-1 md:cqa-pb-0.5 cqa-px-5 cqa-gap-3 cqa-w-full md:cqa-h-[62px] cqa-border-b-0 cqa-border-[#E5E7EB]'\n : 'cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-py-3 md:cqa-py-1 lg:cqa-px-5 cqa-px-2 cqa-w-full md:cqa-h-[53px]', itemslength == item.id ? 'cqa-border-l md:cqa-border-l-0 md:cqa-border-l' : '' , item.id == '1' && layout === '1' ? 'cqa-border-l md:cqa-border-r' : '']\">\n <ng-container *ngIf=\"layout === '1'; else layout2\">\n <!-- [ngClass]=\"{ 'border-l md:border-l-0': itemslength == item.id }\" -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-min-w-[40px] cqa-rounded-[10px]\"\n [ngClass]=\"item.accentBgClass || 'cqa-bg-[#EEF2FF]'\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[20px]\" [ngClass]=\"item.iconColorClass || 'cqa-text-[#3F43EE]'\"\n *ngIf=\"item.icon\">{{ item.icon }}</mat-icon>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start cqa-gap-0.5 cqa-w-full cqa-h-auto cqa-flex-1 cqa-truncate\">\n <div class=\"cqa-w-full cqa-h-4 cqa-text-[12px] cqa-leading-4 cqa-font-medium cqa-text-[#6A7282]\">{{ item.label\n }}</div>\n <div class=\"cqa-w-full cqa-h-7 cqa-gap-2 cqa-flex\"\n [ngClass]=\"item.subtext ? 'cqa-justify-between cqa-items-center' : 'cqa-justify-start cqa-items-center'\">\n <div\n class=\"cqa-text-[20px] cqa-leading-[28px] cqa-font-semibold cqa-tracking-[-0.449219px] cqa-text-[#101828]\">\n {{ item.value | number }}</div>\n <div *ngIf=\"item.subtext\"\n class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6A7282] cqa-truncate cqa-hidden sm:cqa-block\">{{\n item.subtext }}</div>\n </div>\n <div class=\"cqa-w-full cqa-h-1 cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [ngClass]=\"item.colorClass || 'cqa-bg-[#3F43EE]'\"\n [style.width]=\"progress\"></div>\n </div>\n </div>\n </ng-container>\n <ng-template #layout2>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <mat-icon class=\"!cqa-w-5 !cqa-h-5 !cqa-text-[16px]\" [ngClass]=\"item.iconColorClass || 'cqa-text-[#3F43EE]'\"\n *ngIf=\"item.icon\">{{ item.icon }}</mat-icon>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6B7280]\">{{ item.label }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5 cqa-w-full cqa-justify-between\">\n <h6 class=\"cqa-text-[16px] cqa-leading-7 cqa-tracking-[-0.45px] cqa-text-[#111827]\">{{ item.value | number }}\n </h6>\n <span *ngIf=\"item.percent !== undefined\" class=\"cqa-text-[10px] cqa-leading-4\"\n [ngClass]=\"percentClass(item.percent)\">{{ formatPercent(item.percent) }}</span>\n </div>\n </ng-template>\n </div>\n</div>", styles: [] }]
1813
+ }], propDecorators: { item: [{
1814
+ type: Input
1815
+ }], progress: [{
1816
+ type: Input
1817
+ }], layout: [{
1818
+ type: Input
1819
+ }], itemslength: [{
1820
+ type: Input
1821
+ }] } });
1822
+
1823
+ class MetricsCardComponent {
1824
+ constructor() {
1825
+ this.icon = 'text_snippet';
1826
+ this.title = 'Total Test Cases';
1827
+ this.total = 0;
1828
+ this.items = [];
1829
+ this.cardClass = '';
1830
+ this.layout = '1';
1831
+ }
1832
+ progressWidth(item) {
1833
+ var _a;
1834
+ const max = (_a = item.max) !== null && _a !== void 0 ? _a : this.inferMax();
1835
+ if (!max || max <= 0)
1836
+ return '0%';
1837
+ const pct = Math.max(0, Math.min(100, (item.value / max) * 100));
1838
+ return pct.toFixed(1) + '%';
1839
+ }
1840
+ inferMax() {
1841
+ const maxFromItems = this.items.reduce((m, it) => Math.max(m, it.value), 0);
1842
+ return maxFromItems || 1;
1843
+ }
1844
+ formatPercent(value) {
1845
+ if (value === undefined || value === null || Number.isNaN(value))
1846
+ return '';
1847
+ const sign = value > 0 ? '+' : value < 0 ? '' : '';
1848
+ return `${sign}${value}%`;
1849
+ }
1850
+ percentClass(value) {
1851
+ if (value === undefined || value === null || Number.isNaN(value))
1852
+ return 'cqa-text-[#6B7280]';
1853
+ if (value > 0)
1854
+ return 'cqa-text-[#10B981]'; // green
1855
+ if (value < 0)
1856
+ return 'cqa-text-[#EF4444]'; // red
1857
+ return 'cqa-text-[#6B7280]'; // neutral
1858
+ }
1859
+ }
1860
+ MetricsCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MetricsCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1861
+ MetricsCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: MetricsCardComponent, selector: "cqa-metrics-card", inputs: { icon: "icon", title: "title", total: "total", items: "items", cardClass: "cardClass", layout: "layout", totalPercent: "totalPercent" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div *ngIf=\"layout === '1'\"\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-items-start cqa-px-px cqa-pb-px md:cqa-h-[63px] cqa-bg-white cqa-border-t-2 cqa-border-r cqa-border-b-0 cqa-border-l cqa-border-solid cqa-border-[#3F43EE] cqa-rounded-[10px] cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0\"\n [ngClass]=\"cardClass\">\n <!-- Metric blocks -->\n <div\n class=\"cqa-flex-1 cqa-w-full cqa-grid cqa-grid-cols-2 md:cqa-gap-0 cqa-gap-y-2 cqa-py-1 md:cqa-p-0 sm:cqa-grid-cols-2 md:cqa-grid-cols-4 sm:cqa-border-r cqa-border-[#E5E7EB]\">\n <!-- Left total block -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-justify-center cqa-items-start cqa-py-3 md:cqa-pt-1 md:cqa-pb-0.5 cqa-px-6 cqa-gap-1 cqa-w-full sm:cqa-w-[100%] md:cqa-w-[180px] lg:cqa-w-[290px] md:cqa-h-[61px] cqa-border-b-1 sm:cqa-border-b-0 md:cqa-border-b-0 cqa-border-[#E5E7EB]\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-text-[#6A7282]\"> {{ title }} </span>\n <h3 class=\"cqa-text-[30px] cqa-leading-[36px] cqa-font-bold cqa-tracking-[0.395508px] cqa-text-[#101828]\"> {{\n total | number }} </h3>\n </div>\n <cqa-metrics-block *ngFor=\"let it of items;\" [item]=\"it\" [itemslength]=\"items.length.toString()\"\n [progress]=\"progressWidth(it)\">\n </cqa-metrics-block>\n </div>\n </div>\n\n <div *ngIf=\"layout === '2'\"\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-items-start cqa-px-px cqa-pb-px md:cqa-h-[63px] cqa-bg-white cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0\"\n [ngClass]=\"cardClass\">\n <div\n class=\"cqa-flex cqa-flex-col md:cqa-flex-row cqa-flex-wrap cqa-items-stretch cqa-w-full cqa-min-h-[53px] cqa-rounded-none cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0 cqa-gap-4\">\n <!-- Left total block -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-justify-center cqa-items-start cqa-py-3 md:cqa-py-1 cqa-px-4 sm:cqa-px-6 cqa-gap-1 cqa-w-full sm:cqa-w-[100%] md:cqa-w-[240px] lg:cqa-w-[290px] md:cqa-h-[61px] cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-relative cqa-overflow-hidden before:cqa-content-[''] before:cqa-bg-[#4C4C51] before:cqa-h-[2px] before:cqa-w-full before:cqa-absolute before:cqa-top-0 before:cqa-left-0\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-justify-between cqa-w-full\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px] cqa-text-[#6B7280]\">{{ icon }}</mat-icon>\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-4\">{{ title }}</span>\n <div class=\"cqa-flex cqa-items-end cqa-gap-2 cqa-ml-auto\">\n <h4 class=\"cqa-text-[28px] cqa-leading-7 cqa-tracking-[-0.45px] cqa-text-[#111827]\">{{ total | number }}\n </h4>\n <span *ngIf=\"totalPercent !== undefined\" class=\"cqa-text-[10px] cqa-leading-4\"\n [ngClass]=\"percentClass(totalPercent)\">{{ formatPercent(totalPercent) }}</span>\n </div>\n </div>\n\n </div>\n <!-- Metric blocks -->\n <div\n class=\"cqa-flex-1 cqa-w-full cqa-grid cqa-grid-cols-2 md:cqa-grid-cols-3 cqa-items-center cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-relative cqa-overflow-hidden\">\n <span class=\"cqa-h-[2px] cqa-w-full cqa-absolute cqa-top-0 cqa-left-0\"\n [style.background]=\"'linear-gradient(90deg, #3B82F6 0%, rgba(0, 0, 0, 0) 100%)'\"></span>\n <cqa-metrics-block *ngFor=\"let it of items; let i = index\" [item]=\"it\" [layout]=\"layout\">\n </cqa-metrics-block>\n </div>\n </div>\n </div>\n</div>", components: [{ type: MetricsBlockComponent, selector: "cqa-metrics-block", inputs: ["item", "progress", "layout", "itemslength"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "number": i2.DecimalPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
1862
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: MetricsCardComponent, decorators: [{
1863
+ type: Component,
1864
+ args: [{ selector: 'cqa-metrics-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div *ngIf=\"layout === '1'\"\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-items-start cqa-px-px cqa-pb-px md:cqa-h-[63px] cqa-bg-white cqa-border-t-2 cqa-border-r cqa-border-b-0 cqa-border-l cqa-border-solid cqa-border-[#3F43EE] cqa-rounded-[10px] cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0\"\n [ngClass]=\"cardClass\">\n <!-- Metric blocks -->\n <div\n class=\"cqa-flex-1 cqa-w-full cqa-grid cqa-grid-cols-2 md:cqa-gap-0 cqa-gap-y-2 cqa-py-1 md:cqa-p-0 sm:cqa-grid-cols-2 md:cqa-grid-cols-4 sm:cqa-border-r cqa-border-[#E5E7EB]\">\n <!-- Left total block -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-justify-center cqa-items-start cqa-py-3 md:cqa-pt-1 md:cqa-pb-0.5 cqa-px-6 cqa-gap-1 cqa-w-full sm:cqa-w-[100%] md:cqa-w-[180px] lg:cqa-w-[290px] md:cqa-h-[61px] cqa-border-b-1 sm:cqa-border-b-0 md:cqa-border-b-0 cqa-border-[#E5E7EB]\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-text-[#6A7282]\"> {{ title }} </span>\n <h3 class=\"cqa-text-[30px] cqa-leading-[36px] cqa-font-bold cqa-tracking-[0.395508px] cqa-text-[#101828]\"> {{\n total | number }} </h3>\n </div>\n <cqa-metrics-block *ngFor=\"let it of items;\" [item]=\"it\" [itemslength]=\"items.length.toString()\"\n [progress]=\"progressWidth(it)\">\n </cqa-metrics-block>\n </div>\n </div>\n\n <div *ngIf=\"layout === '2'\"\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-items-start cqa-px-px cqa-pb-px md:cqa-h-[63px] cqa-bg-white cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0\"\n [ngClass]=\"cardClass\">\n <div\n class=\"cqa-flex cqa-flex-col md:cqa-flex-row cqa-flex-wrap cqa-items-stretch cqa-w-full cqa-min-h-[53px] cqa-rounded-none cqa-flex-none cqa-order-0 cqa-self-stretch cqa-grow-0 cqa-gap-4\">\n <!-- Left total block -->\n <div\n class=\"cqa-flex cqa-flex-col cqa-justify-center cqa-items-start cqa-py-3 md:cqa-py-1 cqa-px-4 sm:cqa-px-6 cqa-gap-1 cqa-w-full sm:cqa-w-[100%] md:cqa-w-[240px] lg:cqa-w-[290px] md:cqa-h-[61px] cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-relative cqa-overflow-hidden before:cqa-content-[''] before:cqa-bg-[#4C4C51] before:cqa-h-[2px] before:cqa-w-full before:cqa-absolute before:cqa-top-0 before:cqa-left-0\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-justify-between cqa-w-full\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px] cqa-text-[#6B7280]\">{{ icon }}</mat-icon>\n <span class=\"cqa-text-[#6B7280] cqa-text-[14px] cqa-leading-4\">{{ title }}</span>\n <div class=\"cqa-flex cqa-items-end cqa-gap-2 cqa-ml-auto\">\n <h4 class=\"cqa-text-[28px] cqa-leading-7 cqa-tracking-[-0.45px] cqa-text-[#111827]\">{{ total | number }}\n </h4>\n <span *ngIf=\"totalPercent !== undefined\" class=\"cqa-text-[10px] cqa-leading-4\"\n [ngClass]=\"percentClass(totalPercent)\">{{ formatPercent(totalPercent) }}</span>\n </div>\n </div>\n\n </div>\n <!-- Metric blocks -->\n <div\n class=\"cqa-flex-1 cqa-w-full cqa-grid cqa-grid-cols-2 md:cqa-grid-cols-3 cqa-items-center cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-relative cqa-overflow-hidden\">\n <span class=\"cqa-h-[2px] cqa-w-full cqa-absolute cqa-top-0 cqa-left-0\"\n [style.background]=\"'linear-gradient(90deg, #3B82F6 0%, rgba(0, 0, 0, 0) 100%)'\"></span>\n <cqa-metrics-block *ngFor=\"let it of items; let i = index\" [item]=\"it\" [layout]=\"layout\">\n </cqa-metrics-block>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
1865
+ }], propDecorators: { icon: [{
1866
+ type: Input
1867
+ }], title: [{
1868
+ type: Input
1869
+ }], total: [{
1870
+ type: Input
1871
+ }], items: [{
1872
+ type: Input
1873
+ }], cardClass: [{
1874
+ type: Input
1875
+ }], layout: [{
1876
+ type: Input
1877
+ }], totalPercent: [{
1878
+ type: Input
1879
+ }] } });
1880
+
1881
+ class ChartCardComponent {
1882
+ constructor() {
1883
+ this.title = 'Chart';
1884
+ this.cardClass = '';
1885
+ }
1886
+ }
1887
+ ChartCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ChartCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1888
+ ChartCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ChartCardComponent, selector: "cqa-chart-card", inputs: { title: "title", subtitle: "subtitle", cardClass: "cardClass" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-rounded-[10px]\"\n [ngClass]=\"cardClass\">\n <!-- Header -->\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-px-4 sm:cqa-px-6 cqa-py-3 cqa-border-b cqa-border-[#E5E7EB]\">\n <div class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-text-[14px] cqa-leading-5 cqa-font-semibold cqa-text-[#101828]\">{{ title }}</div>\n <div *ngIf=\"subtitle\" class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6A7282] cqa-mt-0.5\">{{ subtitle }}</div>\n </div>\n <!-- Right-side actions slot -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <ng-content select=\"[chart-actions]\"></ng-content>\n </div>\n </div>\n\n <!-- Chart/content area -->\n <div class=\"cqa-p-3 sm:cqa-p-4\">\n <div class=\"cqa-w-full cqa-min-h-[220px]\">\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n</div>", directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1889
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ChartCardComponent, decorators: [{
1890
+ type: Component,
1891
+ args: [{ selector: 'cqa-chart-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-rounded-[10px]\"\n [ngClass]=\"cardClass\">\n <!-- Header -->\n <div\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-px-4 sm:cqa-px-6 cqa-py-3 cqa-border-b cqa-border-[#E5E7EB]\">\n <div class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-text-[14px] cqa-leading-5 cqa-font-semibold cqa-text-[#101828]\">{{ title }}</div>\n <div *ngIf=\"subtitle\" class=\"cqa-text-[12px] cqa-leading-4 cqa-text-[#6A7282] cqa-mt-0.5\">{{ subtitle }}</div>\n </div>\n <!-- Right-side actions slot -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <ng-content select=\"[chart-actions]\"></ng-content>\n </div>\n </div>\n\n <!-- Chart/content area -->\n <div class=\"cqa-p-3 sm:cqa-p-4\">\n <div class=\"cqa-w-full cqa-min-h-[220px]\">\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
1892
+ }], propDecorators: { title: [{
1893
+ type: Input
1894
+ }], subtitle: [{
1895
+ type: Input
1896
+ }], cardClass: [{
1897
+ type: Input
1898
+ }] } });
1899
+
1900
+ class ProgressTextCardComponent {
1901
+ constructor() {
1902
+ this.value = 0; // 0 - 100
1903
+ this.label = 'Test Success Rate';
1904
+ this.deltaSuffix = 'since last run';
1905
+ this.cardClass = '';
1906
+ }
1907
+ get percentText() {
1908
+ const v = Math.max(0, Math.min(100, Number(this.value) || 0));
1909
+ return `${v}%`;
1910
+ }
1911
+ get fillWidth() {
1912
+ const v = Math.max(0, Math.min(100, Number(this.value) || 0));
1913
+ return v + '%';
1914
+ }
1915
+ deltaClass() {
1916
+ if (this.deltaPercent === undefined || this.deltaPercent === null || Number.isNaN(this.deltaPercent)) {
1917
+ return 'text-[#6B7280]';
1918
+ }
1919
+ if (this.deltaPercent > 0)
1920
+ return 'text-[#10B981]';
1921
+ if (this.deltaPercent < 0)
1922
+ return 'text-[#EF4444]';
1923
+ return 'text-[#6B7280]';
1924
+ }
1925
+ }
1926
+ ProgressTextCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ProgressTextCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1927
+ ProgressTextCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ProgressTextCardComponent, selector: "cqa-progress-text-card", inputs: { value: "value", label: "label", deltaPercent: "deltaPercent", deltaSuffix: "deltaSuffix", cardClass: "cardClass" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-rounded-[10px] cqa-p-4 sm:cqa-p-5\"\n [ngClass]=\"cardClass\">\n <div class=\"cqa-flex cqa-items-baseline cqa-gap-2\">\n <div\n class=\"cqa-text-[28px] sm:cqa-text-[32px] cqa-leading-[36px] cqa-font-bold cqa-tracking-[-0.3px] cqa-text-[#111827]\">\n {{ percentText }}</div>\n <div class=\"cqa-text-[18px] sm:cqa-text-[20px] cqa-leading-[28px] cqa-text-[#111827]\">{{ label }}</div>\n </div>\n <div class=\"cqa-mt-4 cqa-w-full cqa-h-[14px] cqa-bg-[#E5E7EB] cqa-rounded-full cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [style.width]=\"fillWidth\"\n [style.background]=\"'linear-gradient(90deg, #DD5A38 0%, #F59E0B 40%, #10B981 100%)'\">\n </div>\n </div>\n <div class=\"cqa-mt-2 cqa-text-[14px] cqa-leading-5\" [ngClass]=\"deltaClass()\" *ngIf=\"deltaPercent !== undefined\">\n {{ deltaPercent > 0 ? '+' : ''}}{{ deltaPercent }}% {{ deltaSuffix }}\n </div>\n </div>\n</div>", directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1928
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ProgressTextCardComponent, decorators: [{
1929
+ type: Component,
1930
+ args: [{ selector: 'cqa-progress-text-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-box-border cqa-flex cqa-flex-col cqa-bg-white cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-rounded-[10px] cqa-p-4 sm:cqa-p-5\"\n [ngClass]=\"cardClass\">\n <div class=\"cqa-flex cqa-items-baseline cqa-gap-2\">\n <div\n class=\"cqa-text-[28px] sm:cqa-text-[32px] cqa-leading-[36px] cqa-font-bold cqa-tracking-[-0.3px] cqa-text-[#111827]\">\n {{ percentText }}</div>\n <div class=\"cqa-text-[18px] sm:cqa-text-[20px] cqa-leading-[28px] cqa-text-[#111827]\">{{ label }}</div>\n </div>\n <div class=\"cqa-mt-4 cqa-w-full cqa-h-[14px] cqa-bg-[#E5E7EB] cqa-rounded-full cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [style.width]=\"fillWidth\"\n [style.background]=\"'linear-gradient(90deg, #DD5A38 0%, #F59E0B 40%, #10B981 100%)'\">\n </div>\n </div>\n <div class=\"cqa-mt-2 cqa-text-[14px] cqa-leading-5\" [ngClass]=\"deltaClass()\" *ngIf=\"deltaPercent !== undefined\">\n {{ deltaPercent > 0 ? '+' : ''}}{{ deltaPercent }}% {{ deltaSuffix }}\n </div>\n </div>\n</div>", styles: [] }]
1931
+ }], propDecorators: { value: [{
1932
+ type: Input
1933
+ }], label: [{
1934
+ type: Input
1935
+ }], deltaPercent: [{
1936
+ type: Input
1937
+ }], deltaSuffix: [{
1938
+ type: Input
1939
+ }], cardClass: [{
1940
+ type: Input
1941
+ }] } });
1942
+
1943
+ class DashboardHeaderComponent {
1944
+ constructor() {
1945
+ this.title = '';
1946
+ this.badgeClass = 'bg-[#D1FAE5] text-[#065F46]';
1947
+ this.headerClass = '';
1948
+ // Optional workspace select on the right
1949
+ this.workspaceOptions = [];
1950
+ this.workspacePlaceholder = 'Workspace';
1951
+ this.workspaceDisabled = false;
1952
+ this.workspaceMultiple = true;
1953
+ this.workspaceSearchable = false;
1954
+ this.workspaceValueChange = new EventEmitter();
1955
+ this.workspaceForm = new FormGroup({
1956
+ workspace: new FormControl(),
1957
+ });
1958
+ }
1959
+ ngOnInit() {
1960
+ var _a;
1961
+ this.syncFormFromInput();
1962
+ (_a = this.workspaceForm.get('workspace')) === null || _a === void 0 ? void 0 : _a.valueChanges.subscribe((v) => {
1963
+ this.workspaceValue = v;
1964
+ this.workspaceValueChange.emit(v);
1965
+ });
1966
+ }
1967
+ ngOnChanges(_changes) {
1968
+ this.syncFormFromInput();
1969
+ }
1970
+ get workspaceConfig() {
1971
+ return {
1972
+ key: 'workspace',
1973
+ placeholder: this.workspacePlaceholder,
1974
+ disabled: this.workspaceDisabled,
1975
+ multiple: this.workspaceMultiple,
1976
+ searchable: this.workspaceSearchable,
1977
+ options: this.workspaceOptions,
1978
+ };
1979
+ }
1980
+ syncFormFromInput() {
1981
+ const ctrl = this.workspaceForm.get('workspace');
1982
+ if (!ctrl)
1983
+ return;
1984
+ const val = this.workspaceValue;
1985
+ const normalized = this.workspaceMultiple
1986
+ ? Array.isArray(val) ? val : (val != null ? [val] : [])
1987
+ : (Array.isArray(val) ? (val.length ? val[0] : undefined) : val);
1988
+ ctrl.setValue(normalized, { emitEvent: false });
1989
+ }
1990
+ }
1991
+ DashboardHeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DashboardHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1992
+ DashboardHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DashboardHeaderComponent, selector: "cqa-dashboard-header", inputs: { title: "title", badgeText: "badgeText", badgeClass: "badgeClass", headerClass: "headerClass", workspaceOptions: "workspaceOptions", workspacePlaceholder: "workspacePlaceholder", workspaceDisabled: "workspaceDisabled", workspaceValue: "workspaceValue", workspaceMultiple: "workspaceMultiple", workspaceSearchable: "workspaceSearchable" }, outputs: { workspaceValueChange: "workspaceValueChange" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-flex cqa-items-end cqa-justify-between cqa-bg-white cqa-pr-6 cqa-pl-2 lg:cqa-px-6 lg:cqa-py-[6px] cqa-py-2 cqa-border-b cqa-border-default cqa-shadow-header\"\n [ngClass]=\"headerClass\">\n <!-- Left branding block -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-min-w-0\">\n <div class=\"cqa-pr-4 lg:cqa-hidden cqa-gap-2 md:cqa-flex\">\n <cqa-button variant=\"filled\" icon=\"\" [customClass]=\"'!cqa-rounded-[10px] !cqa-p-[7px] !cqa-min-w-[47px]'\">\n <svg width=\"31\" height=\"22\" viewBox=\"0 0 31 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.16675 11H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M5.16675 16.5H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M5.16675 5.5H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </cqa-button>\n <span class=\"cqa-border-l cqa-border-primary-surface cqa-hidden md:cqa-flex\"></span>\n <cqa-button variant=\"filled\" icon=\"\" class=\"cqa-hidden md:cqa-flex\" [customClass]=\"'!cqa-rounded-[10px] !cqa-p-[7px] !cqa-min-w-[47px]'\">\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 22 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4.58337 11H17.4167\" stroke=\"white\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M11 4.58301V17.4163\" stroke=\"white\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </cqa-button>\n </div>\n <!-- Optional projected logo -->\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"15.5\" fill=\"url(#pattern0_6303_22035)\" />\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"15.5\" stroke=\"#D8D9FC\" />\n <defs>\n <pattern id=\"pattern0_6303_22035\" patternContentUnits=\"objectBoundingBox\" width=\"1\" height=\"1\">\n <use xlink:href=\"#image0_6303_22035\" transform=\"scale(0.005)\" />\n </pattern>\n <image id=\"image0_6303_22035\" width=\"200\" height=\"200\" preserveAspectRatio=\"none\"\n xlink:href=\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8SEBMQEBASEBAQEBYRFRUXFRARERASGRkWGxYXGBUYHigsGBomGxUYITEhJSkrLjouGSAzODMsNygtLjcBCgoKDg0OGxAQGy4dICUrNy0rKysrMDctLisvLS0tKy0tLTcuLS0tMDctNi0tLSstLS0rLS0rLTEtLS0tLS0tLf/AABEIAMgAyAMBIgACEQEDEQH/xAAcAAEAAgIDAQAAAAAAAAAAAAAABQYCBwEDBAj/xABBEAABAwICAwsKBQUAAwEAAAABAAIDBBEFIQYSQQciMVFSYXGBkaHRExQWIzJUkqKxwRdCYnKyU4LC4fAkNPEV/8QAGwEBAAIDAQEAAAAAAAAAAAAAAAIDAQQFBgf/xAAuEQACAQIEAwYGAwAAAAAAAAAAAQIDEQQSIVETMUEFUmGBkbEUIjJCccEVodH/2gAMAwEAAhEDEQA/AN4oiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiA81XK5jdcDWDc3DaW8Y5xwrkyFzNeIg3F2n8ruZd6r/AJbzSo1DlTzm7eKN+3qz71KKuRbsS1JViVhLbtIJa4H2mOHCCF1UNfrPdC+zZo7awzs5p4HtvsPdwKMxwuppRVxi7HEMmbyh+V3SuNI4TJEytpT66Aa7CPzxn2mnjy2KagvJ+5jMyS8/1JxBLl5S5hdsfbNzDxOHeOtcYjiBgc18n/rvIa539F/5Sf0k5X2G3Go9zosSorsOo/hBz1oZm8Gf/ZFdOjOLCshkpapvr4wY5mG2/GY1gmTq+nMZiD08bidNeopqqV1OTvm70mHrtm1Uf00xP3uT5PBbI0br3QzvwmrOvqj1DnWPlYiCdU9X3CoWnui5optaME08pJZw7w7WH7LcoON8kkvB7lM780eT00xP3uT5PBPTTE/e5Pk8FAItvhQ2RVne5P8AppifvcnyeCemmJ+9yfJ4KAROFDZDO9yz0GnmIxyNe6YytBzY4N1XDaLgZHnW4cAxqGrhE0JyOTm/mY7aCvndTeiekMlFOJG3MbspGctvHzEcK16+GUleK1J06jT1PoBVTTKmrmtM9JO8Bou6MWOXG247lY6KqZLG2WN2sx7Q5p4wu9cqUbqx0KFXhTU7J+DNLeleIe8v+XwT0rxD3l/y+Cm9P9GvJONTC31TzvwOBjuPoJVKXOm5wdmz2uFjhcRTU4wXoia9K8Q95f8AL4J6V4h7y/5fBQqKGeW5sfCUO4vRE16V4h7y/wCXwWUel1eCD5w42PAQ0g9OSg0Wc8tw8HQ7i9Ebo0X0hjq49Yb2Vvts4uccYU4tD4ViMlPK2aI2c09ThtBW6MExSOphbLHwEZja120FbtGrnVnzPJ9qdnPDSzR+l/14EiiIrzknCjseofLQOaPaG+b0j/rKSXCynZ3MNXViuYBVNqad1PLmWt1ect2HpC8OiVa6KV9FKeBx1P3bR0EZrpmd5rXEjJhdf+x3D3/RYabQmKojqGZF4vf9bbfay21FN5ej18ym7tfY80U3/wCbiTozlTTkHmAPAf7XXHQsdNo30VbFiEIykNnjYSALg/ub/FerTyJs9HDVtHs2vzNdYEdTgEa7z7B3tOcsDevWZmO1uXWVJdJv8MxuvNGG6DTCelhxGnO+hs4OHDqEjva77qUopIsWw4tfYOcNV3HHK3gcO49ahNzesE1PNQy5t1SWj9Drhw6jn/covc7rXUte+kkOUrjGeLyjL2PWLjrCw4NRcesdV+DKlqnuUSupHwyPikFnxuLXDnH1C6FsTdewgNljq2jKUaj/AN7RvT1t/itdrepTzwUiicbOwREVhEIiIDYu5PpCWyGikO9ku6L9L8y5vQRn1c62svmmmndG9sjDZ7HBwPEQvoXB8WingjnDmjyjA61xkdo7brmYulaWZdTZoyurM9dXTMkY6N4u14LSOMLSWPYW6mqHwuz1Tdp5TTwFbv8AOGctvaFSd0uhZJC2oYWl0R1XWIuWOsO427VzMRTco32O92Ni+FXyN6S9+hrVERc89mEREAVn0Exw09QGPNoZiGu4mu/K77KsLlShJxd0U4ihGtTcJdT6DuigtDcUNRSMc43e0ajukbesWPWuV1Iu6uj5/VpunNwlzROoiLJWVDTeHfRv4wW9lrfVYY563DY5dsZF+0sPfZe7TZvqmHik+oK8EG+wuYckn6tK24P5YvZlEvqaOnBfXYbUwHPUDiP5N+YKO3Mqq00sJ4JI9a3O3/Tu5SGgJuZ2bHMb3aw+6rmgj9XEIhx67fkd4K5rSovMhfWLOjRmTzXFWsvZomfCecG4HfZYadtNPirpWZG8c7emwv3tKx0kPk8VkI/LUNd/Er37rbLVcR44P8nKa1nF7oj9r8GXLTumbUYZK5udmNnb1WP8b9q0Wt+YR6zCmA569Jq/JZaDWMJpmjsyVbowiItwpCIiAIiIAso3WIPEViijKKasydObjJSXRkui4jOQ6AuV42Ss2j6pTlmgnugiIokwiIgL5uV1lpJoScnNDx0jI/UdiKK3OpCK9g5THjuv9lyujh3eB4vtuChim91f9G3URFcckrWmz/VRjjeT2A+K8EO9wuY8o/5NCz02mvJGzktJ7f8A4sdIfU4fFDteRcdrj3kLbgvlit2US+ps6NAsjO88DWD/ACP2Vc0DYXYhEeIPcfgd9yrJhfqMLqJjkZAQP4DvJUfuZ03rJp3ZNjYG36bk9zVc5aVH5EEtYor2kI8pisgGetUtZ3tH2Xv3W5L1cbeTAO9zl59EojU4o2QjLyj53cwFyPmIXVpmTVYs6Jme/ZA3sAPzXVi0mlsjH2vxZsjC/VYUwnLUo9b5LrQa3lugVbafDZGtyL2tgYOmwPygrRqjhNVKW7M1uiCIi3CkIiIAiKUotHa2Zgkip5JI3Xs4DI2JH1Cw5Jcxa/Ii0U36I4j7pL8Kwn0Zro2l8lNIyNvtOIsAFCVWCTdyynTlKSilzZjGMh0LlEXjpO8mz6pTjlilsgiIsEgiIgLRucx3r2nksee633RS+5XR76acjIARt7y77IujhlaB4vtqanin4K37NjLhFFaSV3koTb25N437nsV8Vd2OQ3ZXK9GzzuuJ4WB1zxajbfX7rq0vkdPVsp2Zllm/3OzPdZTeG07aOldLJ7ZGs7/Fv/ca8eiVAbvrZvafctvsGes5bSkk822iKbPluR26DO2Gnho2bcz+1vB2k9yyrGeYYOWnKacWPHrP4R1M+i68IpjiFe+reP8Ax4XAMB4HW9kD+R6QurSVrsRxBlHGfU0+cjhwAm2t15BvSpq2kH01Zjd+SMtAKVtLRzV8o9ppLf2Nv9T9FF7meHOnq5K2QXEZJB45X3+gJ7QpjdBqCWwYXSt38pbdo2MbbVHRcX/tUnWTw4RhwaLOeBZo2yzHhPRfPoCw5tptc5exlJabIpu61jIknZSsO9p8388jgPo36lUFdlRM57nPeS5z3FxO0krrW9ShkiolEnd3CIisIhERAeigpHzSshjF3yODQOc/ZfROF0LYIY4WezGwNHPbb2qgblOjZaPPpW5uBbCOJvA5/Xwdq2SuXi6uaWVdDaoxsrhUPdPxWzGUrTm867+Zo9kdv0VxxSvZBE6aQ2awX5zxAc91pHFa99RM+Z/tPde3ENg7FzMRUyxtueg7Fwbq1eI+Ufc8iIi0D2AREQBcgXyGZ4FwrjueYCZZfOJB6qI73ifJ/r6qUIuTsa+KxEaFJ1JF70UwvzaljjPt21nfuOZ7ODqRTCLqJWVkeAqTdSbm+bOHEAXPAFC0lOZ5vOXj1bMoWnb+sqVqIdcap9n8w5XN0LKVhLbNOrsvxdCmnbkVtXITEITVzCLgp4XXkP8AUfyR0LHSIvl1aGn3rpB6xw4IYfE8AHSpuGFrGajAAAMhn3rGkpGsueF7zrPceF5+w2WUlO3lyI5SJr3CjpmwUzLzP9XC3K7n7XG+wcJK68LoYcOpHySHWf7cr/zSSHIAceZsOlTEVIPKGV2+kI1QdjGclv1J/wBLiajD5GPfm2M3Y3Zr8o8ZGxM/T1M5SuYPRCnE2J15DZ5RrG+fkGcDWDjNrDuWrtLdIpK2cyOu2Nu9jZyG7TzklbA0y0cxOuksHxMp2HeM1nZnlONsz9FW/wAL6/lw/E7wW5QlTXzSevsUTUnoloUdFePwvr+XD8TvBPwvr+XD8TvBbPxFPvFfDlsUdFePwvr+XD8TvBPwvr+XD8TvBPiKfeHDlsUdWvQTRN1ZLryAimjO+P8AUPIB+qlsO3LqkyN8vJG2K++1CS4jiFx3raNBRxwxtiiaGRsFgBsVFfFJK0GWQpO92d0cYaA1oAaBYAZAAJLIGgucQABck8ACzKqul2F11V6qFzGQbbuOtIeew4OZcuTaV1qb1CnGc1GTyrdlL000kNVJqRm0EZ3v6zyj9lWVb/w9reVF8TvBPw9reVF8TvBaEqdSTu0exoYzBUKahCasioIrf+Htbyovid4J+Htbyovid4KPBnsXfyeF76Kgit/4e1vKi+J3gsotzyrJGs+MNvmQXEgdFlngz2MPtPC99EJo5gclXKGNyYM3u2Nb4rctBRxwxtijbqsYLALpwbCoqaIRRCwHCdrjxkr3rcpUsi8Ty3aOPlip6aRXL/TlERXHNCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiA/9k=\" />\n </defs>\n </svg>\n\n <!-- Title + optional badge -->\n <div class=\"cqa-items-end cqa-gap-3 cqa-min-w-0 cqa-hidden md:cqa-flex\">\n <div\n class=\"cqa-truncate cqa-text-[#22223B] cqa-font-extrabold cqa-text-[32px] cqa-font-nunito-sans cqa-leading-[1]\">\n {{ title }}</div>\n <span *ngIf=\"badgeText\"\n class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-lg cqa-text-[12px] cqa-font-medium cqa-leading-4 cqa-whitespace-nowrap cqa-text-[#007A55] cqa-bg-[#D0FAE5] cqa-border cqa-border-[#A4F4CF]\"\n [ngClass]=\"badgeClass\">{{ badgeText }}</span>\n </div>\n </div>\n\n <!-- Right controls/actions -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-1\">\n <!-- Optional workspace select -->\n <div *ngIf=\"workspaceOptions?.length\" class=\"cqa-w-full cqa-max-w-[199px] cqa-ml-auto header-dropdown\">\n <cqa-dynamic-select [form]=\"workspaceForm\" [config]=\"workspaceConfig\">\n </cqa-dynamic-select>\n </div>\n\n <ng-content></ng-content>\n </div>\n </div>\n</div>", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }, { type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1993
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DashboardHeaderComponent, decorators: [{
1994
+ type: Component,
1995
+ args: [{ selector: 'cqa-dashboard-header', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div\n class=\"cqa-w-full cqa-flex cqa-items-end cqa-justify-between cqa-bg-white cqa-pr-6 cqa-pl-2 lg:cqa-px-6 lg:cqa-py-[6px] cqa-py-2 cqa-border-b cqa-border-default cqa-shadow-header\"\n [ngClass]=\"headerClass\">\n <!-- Left branding block -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-min-w-0\">\n <div class=\"cqa-pr-4 lg:cqa-hidden cqa-gap-2 md:cqa-flex\">\n <cqa-button variant=\"filled\" icon=\"\" [customClass]=\"'!cqa-rounded-[10px] !cqa-p-[7px] !cqa-min-w-[47px]'\">\n <svg width=\"31\" height=\"22\" viewBox=\"0 0 31 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5.16675 11H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M5.16675 16.5H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M5.16675 5.5H25.8334\" stroke=\"white\" stroke-width=\"1.83333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </cqa-button>\n <span class=\"cqa-border-l cqa-border-primary-surface cqa-hidden md:cqa-flex\"></span>\n <cqa-button variant=\"filled\" icon=\"\" class=\"cqa-hidden md:cqa-flex\" [customClass]=\"'!cqa-rounded-[10px] !cqa-p-[7px] !cqa-min-w-[47px]'\">\n <svg width=\"22\" height=\"22\" viewBox=\"0 0 22 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4.58337 11H17.4167\" stroke=\"white\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M11 4.58301V17.4163\" stroke=\"white\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </cqa-button>\n </div>\n <!-- Optional projected logo -->\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 32 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"15.5\" fill=\"url(#pattern0_6303_22035)\" />\n <rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"15.5\" stroke=\"#D8D9FC\" />\n <defs>\n <pattern id=\"pattern0_6303_22035\" patternContentUnits=\"objectBoundingBox\" width=\"1\" height=\"1\">\n <use xlink:href=\"#image0_6303_22035\" transform=\"scale(0.005)\" />\n </pattern>\n <image id=\"image0_6303_22035\" width=\"200\" height=\"200\" preserveAspectRatio=\"none\"\n xlink:href=\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBw8SEBMQEBASEBAQEBYRFRUXFRARERASGRkWGxYXGBUYHigsGBomGxUYITEhJSkrLjouGSAzODMsNygtLjcBCgoKDg0OGxAQGy4dICUrNy0rKysrMDctLisvLS0tKy0tLTcuLS0tMDctNi0tLSstLS0rLS0rLTEtLS0tLS0tLf/AABEIAMgAyAMBIgACEQEDEQH/xAAcAAEAAgIDAQAAAAAAAAAAAAAABQYCBwEDBAj/xABBEAABAwICAwsKBQUAAwEAAAABAAIDBBEFIQYSQQciMVFSYXGBkaHRExQWIzJUkqKxwRdCYnKyU4LC4fAkNPEV/8QAGwEBAAIDAQEAAAAAAAAAAAAAAAIDAQQFBgf/xAAuEQACAQIEAwYGAwAAAAAAAAAAAQIDEQQSIVETMUEFUmGBkbEUIjJCccEVodH/2gAMAwEAAhEDEQA/AN4oiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiA81XK5jdcDWDc3DaW8Y5xwrkyFzNeIg3F2n8ruZd6r/AJbzSo1DlTzm7eKN+3qz71KKuRbsS1JViVhLbtIJa4H2mOHCCF1UNfrPdC+zZo7awzs5p4HtvsPdwKMxwuppRVxi7HEMmbyh+V3SuNI4TJEytpT66Aa7CPzxn2mnjy2KagvJ+5jMyS8/1JxBLl5S5hdsfbNzDxOHeOtcYjiBgc18n/rvIa539F/5Sf0k5X2G3Go9zosSorsOo/hBz1oZm8Gf/ZFdOjOLCshkpapvr4wY5mG2/GY1gmTq+nMZiD08bidNeopqqV1OTvm70mHrtm1Uf00xP3uT5PBbI0br3QzvwmrOvqj1DnWPlYiCdU9X3CoWnui5optaME08pJZw7w7WH7LcoON8kkvB7lM780eT00xP3uT5PBPTTE/e5Pk8FAItvhQ2RVne5P8AppifvcnyeCemmJ+9yfJ4KAROFDZDO9yz0GnmIxyNe6YytBzY4N1XDaLgZHnW4cAxqGrhE0JyOTm/mY7aCvndTeiekMlFOJG3MbspGctvHzEcK16+GUleK1J06jT1PoBVTTKmrmtM9JO8Bou6MWOXG247lY6KqZLG2WN2sx7Q5p4wu9cqUbqx0KFXhTU7J+DNLeleIe8v+XwT0rxD3l/y+Cm9P9GvJONTC31TzvwOBjuPoJVKXOm5wdmz2uFjhcRTU4wXoia9K8Q95f8AL4J6V4h7y/5fBQqKGeW5sfCUO4vRE16V4h7y/wCXwWUel1eCD5w42PAQ0g9OSg0Wc8tw8HQ7i9Ebo0X0hjq49Yb2Vvts4uccYU4tD4ViMlPK2aI2c09ThtBW6MExSOphbLHwEZja120FbtGrnVnzPJ9qdnPDSzR+l/14EiiIrzknCjseofLQOaPaG+b0j/rKSXCynZ3MNXViuYBVNqad1PLmWt1ect2HpC8OiVa6KV9FKeBx1P3bR0EZrpmd5rXEjJhdf+x3D3/RYabQmKojqGZF4vf9bbfay21FN5ej18ym7tfY80U3/wCbiTozlTTkHmAPAf7XXHQsdNo30VbFiEIykNnjYSALg/ub/FerTyJs9HDVtHs2vzNdYEdTgEa7z7B3tOcsDevWZmO1uXWVJdJv8MxuvNGG6DTCelhxGnO+hs4OHDqEjva77qUopIsWw4tfYOcNV3HHK3gcO49ahNzesE1PNQy5t1SWj9Drhw6jn/covc7rXUte+kkOUrjGeLyjL2PWLjrCw4NRcesdV+DKlqnuUSupHwyPikFnxuLXDnH1C6FsTdewgNljq2jKUaj/AN7RvT1t/itdrepTzwUiicbOwREVhEIiIDYu5PpCWyGikO9ku6L9L8y5vQRn1c62svmmmndG9sjDZ7HBwPEQvoXB8WingjnDmjyjA61xkdo7brmYulaWZdTZoyurM9dXTMkY6N4u14LSOMLSWPYW6mqHwuz1Tdp5TTwFbv8AOGctvaFSd0uhZJC2oYWl0R1XWIuWOsO427VzMRTco32O92Ni+FXyN6S9+hrVERc89mEREAVn0Exw09QGPNoZiGu4mu/K77KsLlShJxd0U4ihGtTcJdT6DuigtDcUNRSMc43e0ajukbesWPWuV1Iu6uj5/VpunNwlzROoiLJWVDTeHfRv4wW9lrfVYY563DY5dsZF+0sPfZe7TZvqmHik+oK8EG+wuYckn6tK24P5YvZlEvqaOnBfXYbUwHPUDiP5N+YKO3Mqq00sJ4JI9a3O3/Tu5SGgJuZ2bHMb3aw+6rmgj9XEIhx67fkd4K5rSovMhfWLOjRmTzXFWsvZomfCecG4HfZYadtNPirpWZG8c7emwv3tKx0kPk8VkI/LUNd/Er37rbLVcR44P8nKa1nF7oj9r8GXLTumbUYZK5udmNnb1WP8b9q0Wt+YR6zCmA569Jq/JZaDWMJpmjsyVbowiItwpCIiAIiIAso3WIPEViijKKasydObjJSXRkui4jOQ6AuV42Ss2j6pTlmgnugiIokwiIgL5uV1lpJoScnNDx0jI/UdiKK3OpCK9g5THjuv9lyujh3eB4vtuChim91f9G3URFcckrWmz/VRjjeT2A+K8EO9wuY8o/5NCz02mvJGzktJ7f8A4sdIfU4fFDteRcdrj3kLbgvlit2US+ps6NAsjO88DWD/ACP2Vc0DYXYhEeIPcfgd9yrJhfqMLqJjkZAQP4DvJUfuZ03rJp3ZNjYG36bk9zVc5aVH5EEtYor2kI8pisgGetUtZ3tH2Xv3W5L1cbeTAO9zl59EojU4o2QjLyj53cwFyPmIXVpmTVYs6Jme/ZA3sAPzXVi0mlsjH2vxZsjC/VYUwnLUo9b5LrQa3lugVbafDZGtyL2tgYOmwPygrRqjhNVKW7M1uiCIi3CkIiIAiKUotHa2Zgkip5JI3Xs4DI2JH1Cw5Jcxa/Ii0U36I4j7pL8Kwn0Zro2l8lNIyNvtOIsAFCVWCTdyynTlKSilzZjGMh0LlEXjpO8mz6pTjlilsgiIsEgiIgLRucx3r2nksee633RS+5XR76acjIARt7y77IujhlaB4vtqanin4K37NjLhFFaSV3koTb25N437nsV8Vd2OQ3ZXK9GzzuuJ4WB1zxajbfX7rq0vkdPVsp2Zllm/3OzPdZTeG07aOldLJ7ZGs7/Fv/ca8eiVAbvrZvafctvsGes5bSkk822iKbPluR26DO2Gnho2bcz+1vB2k9yyrGeYYOWnKacWPHrP4R1M+i68IpjiFe+reP8Ax4XAMB4HW9kD+R6QurSVrsRxBlHGfU0+cjhwAm2t15BvSpq2kH01Zjd+SMtAKVtLRzV8o9ppLf2Nv9T9FF7meHOnq5K2QXEZJB45X3+gJ7QpjdBqCWwYXSt38pbdo2MbbVHRcX/tUnWTw4RhwaLOeBZo2yzHhPRfPoCw5tptc5exlJabIpu61jIknZSsO9p8388jgPo36lUFdlRM57nPeS5z3FxO0krrW9ShkiolEnd3CIisIhERAeigpHzSshjF3yODQOc/ZfROF0LYIY4WezGwNHPbb2qgblOjZaPPpW5uBbCOJvA5/Xwdq2SuXi6uaWVdDaoxsrhUPdPxWzGUrTm867+Zo9kdv0VxxSvZBE6aQ2awX5zxAc91pHFa99RM+Z/tPde3ENg7FzMRUyxtueg7Fwbq1eI+Ufc8iIi0D2AREQBcgXyGZ4FwrjueYCZZfOJB6qI73ifJ/r6qUIuTsa+KxEaFJ1JF70UwvzaljjPt21nfuOZ7ODqRTCLqJWVkeAqTdSbm+bOHEAXPAFC0lOZ5vOXj1bMoWnb+sqVqIdcap9n8w5XN0LKVhLbNOrsvxdCmnbkVtXITEITVzCLgp4XXkP8AUfyR0LHSIvl1aGn3rpB6xw4IYfE8AHSpuGFrGajAAAMhn3rGkpGsueF7zrPceF5+w2WUlO3lyI5SJr3CjpmwUzLzP9XC3K7n7XG+wcJK68LoYcOpHySHWf7cr/zSSHIAceZsOlTEVIPKGV2+kI1QdjGclv1J/wBLiajD5GPfm2M3Y3Zr8o8ZGxM/T1M5SuYPRCnE2J15DZ5RrG+fkGcDWDjNrDuWrtLdIpK2cyOu2Nu9jZyG7TzklbA0y0cxOuksHxMp2HeM1nZnlONsz9FW/wAL6/lw/E7wW5QlTXzSevsUTUnoloUdFePwvr+XD8TvBPwvr+XD8TvBbPxFPvFfDlsUdFePwvr+XD8TvBPwvr+XD8TvBPiKfeHDlsUdWvQTRN1ZLryAimjO+P8AUPIB+qlsO3LqkyN8vJG2K++1CS4jiFx3raNBRxwxtiiaGRsFgBsVFfFJK0GWQpO92d0cYaA1oAaBYAZAAJLIGgucQABck8ACzKqul2F11V6qFzGQbbuOtIeew4OZcuTaV1qb1CnGc1GTyrdlL000kNVJqRm0EZ3v6zyj9lWVb/w9reVF8TvBPw9reVF8TvBaEqdSTu0exoYzBUKahCasioIrf+Htbyovid4J+Htbyovid4KPBnsXfyeF76Kgit/4e1vKi+J3gsotzyrJGs+MNvmQXEgdFlngz2MPtPC99EJo5gclXKGNyYM3u2Nb4rctBRxwxtijbqsYLALpwbCoqaIRRCwHCdrjxkr3rcpUsi8Ty3aOPlip6aRXL/TlERXHNCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCIiA/9k=\" />\n </defs>\n </svg>\n\n <!-- Title + optional badge -->\n <div class=\"cqa-items-end cqa-gap-3 cqa-min-w-0 cqa-hidden md:cqa-flex\">\n <div\n class=\"cqa-truncate cqa-text-[#22223B] cqa-font-extrabold cqa-text-[32px] cqa-font-nunito-sans cqa-leading-[1]\">\n {{ title }}</div>\n <span *ngIf=\"badgeText\"\n class=\"cqa-px-2 cqa-py-[2px] cqa-rounded-lg cqa-text-[12px] cqa-font-medium cqa-leading-4 cqa-whitespace-nowrap cqa-text-[#007A55] cqa-bg-[#D0FAE5] cqa-border cqa-border-[#A4F4CF]\"\n [ngClass]=\"badgeClass\">{{ badgeText }}</span>\n </div>\n </div>\n\n <!-- Right controls/actions -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-flex-1\">\n <!-- Optional workspace select -->\n <div *ngIf=\"workspaceOptions?.length\" class=\"cqa-w-full cqa-max-w-[199px] cqa-ml-auto header-dropdown\">\n <cqa-dynamic-select [form]=\"workspaceForm\" [config]=\"workspaceConfig\">\n </cqa-dynamic-select>\n </div>\n\n <ng-content></ng-content>\n </div>\n </div>\n</div>", styles: [] }]
1996
+ }], propDecorators: { title: [{
1997
+ type: Input
1998
+ }], badgeText: [{
1999
+ type: Input
2000
+ }], badgeClass: [{
2001
+ type: Input
2002
+ }], headerClass: [{
2003
+ type: Input
2004
+ }], workspaceOptions: [{
2005
+ type: Input
2006
+ }], workspacePlaceholder: [{
2007
+ type: Input
2008
+ }], workspaceDisabled: [{
2009
+ type: Input
2010
+ }], workspaceValue: [{
2011
+ type: Input
2012
+ }], workspaceMultiple: [{
2013
+ type: Input
2014
+ }], workspaceSearchable: [{
2015
+ type: Input
2016
+ }], workspaceValueChange: [{
2017
+ type: Output
2018
+ }] } });
2019
+
2020
+ class CoverageModuleCardComponent {
2021
+ constructor() {
2022
+ /** Card title, e.g. "AI Ask" */
2023
+ this.title = 'Coverage';
2024
+ /** Number of issues to display next to title */
2025
+ this.issues = 0;
2026
+ /** Optional "View" action visibility */
2027
+ this.showViewAction = true;
2028
+ /** Middle metrics: left group */
2029
+ this.positiveCount = 0;
2030
+ this.negativeCount = 0;
2031
+ this.edgeCaseCount = 0;
2032
+ this.positiveLabel = 'Positive';
2033
+ this.negativeLabel = 'Negative';
2034
+ this.edgeCaseLabel = 'Edge Case';
2035
+ /** Middle metrics: right group */
2036
+ this.aiCount = 0;
2037
+ this.humanCount = 0;
2038
+ this.aiLabel = 'AI';
2039
+ this.humanLabel = 'Human';
2040
+ /** Rows of coverage with percentage bars */
2041
+ this.items = [];
2042
+ /** CTA button label */
2043
+ this.ctaText = 'AI Coverage';
2044
+ /** Disable CTA */
2045
+ this.ctaDisabled = false;
2046
+ this.view = new EventEmitter();
2047
+ this.ctaClicked = new EventEmitter();
2048
+ }
2049
+ statusColorClass(item) {
2050
+ var _a;
2051
+ const status = (_a = item.status) !== null && _a !== void 0 ? _a : 'neutral';
2052
+ switch (status) {
2053
+ case 'success':
2054
+ return 'cqa-bg-[#10B981]'; // green
2055
+ case 'error':
2056
+ return 'cqa-bg-[#EF4444]'; // red
2057
+ default:
2058
+ return 'cqa-bg-[#3B82F6]'; // blue
2059
+ }
2060
+ }
2061
+ textColorClass(item) {
2062
+ var _a;
2063
+ const status = (_a = item.status) !== null && _a !== void 0 ? _a : 'neutral';
2064
+ switch (status) {
2065
+ case 'success':
2066
+ return 'cqa-text-[#10B981]';
2067
+ case 'error':
2068
+ return 'cqa-text-[#EF4444]';
2069
+ default:
2070
+ return 'cqa-text-[#374151]';
2071
+ }
2072
+ }
2073
+ formatPercent(pct) {
2074
+ if (pct === undefined || pct === null || Number.isNaN(pct))
2075
+ return '0%';
2076
+ const clamped = Math.max(0, Math.min(100, pct));
2077
+ return `${clamped}%`;
2078
+ }
2079
+ }
2080
+ CoverageModuleCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CoverageModuleCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2081
+ CoverageModuleCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: CoverageModuleCardComponent, selector: "cqa-coverage-module-card", inputs: { title: "title", issues: "issues", showViewAction: "showViewAction", positiveCount: "positiveCount", negativeCount: "negativeCount", edgeCaseCount: "edgeCaseCount", positiveLabel: "positiveLabel", negativeLabel: "negativeLabel", edgeCaseLabel: "edgeCaseLabel", aiCount: "aiCount", humanCount: "humanCount", aiLabel: "aiLabel", humanLabel: "humanLabel", items: "items", ctaText: "ctaText", ctaDisabled: "ctaDisabled" }, outputs: { view: "view", ctaClicked: "ctaClicked" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-white cqa-rounded-[8px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-py-[10px] cqa-px-[17px] cqa-shadow-card\">\n <!-- Header -->\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-3\">\n <h3 class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-dialog\">{{ title }}</h3>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span\n class=\"cqa-px-[10px] cqa-py-[4px] cqa-text-[12px] cqa-leading-[16px] cqa-flex cqa-items-center cqa-gap-1 cqa-rounded-full cqa-bg-warning-light cqa-text-danger\">\n {{ issues }} {{ issues === 1 ? 'issue' : 'issues' }}\n </span>\n <button type=\"button\"\n class=\"cqa-text-[14px] cqa-leading-[20px] cqa-text-primary cqa-flex cqa-items-center cqa-gap-1\"\n *ngIf=\"showViewAction\" (click)=\"view.emit()\">\n View\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6 12L10 8L6 4\" stroke=\"#4F46E5\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n </div>\n </div>\n\n <!-- Middle metrics row -->\n <div class=\"cqa-flex cqa-items-stretch cqa-justify-between cqa-gap-6 cqa-mb-4\">\n <!-- Left: Positive / Negative / Edge Case -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-6\">\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-[#10B981]\">{{ positiveCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ positiveLabel }}</span>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-[#EF4444]\">{{ negativeCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ negativeLabel }}</span>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-[#F59E0B]\">{{ edgeCaseCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ edgeCaseLabel }}</span>\n </div>\n </div>\n\n <!-- Divider -->\n <div class=\"cqa-w-px cqa-bg-[#E5E7EB]\"></div>\n\n <!-- Right: AI / Human -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-6\">\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-dialog\">{{ aiCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ aiLabel }}</span>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-dialog\">{{ humanCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ humanLabel }}</span>\n </div>\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div *ngFor=\"let it of items\" class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <span class=\"cqa-min-w-[120px] cqa-text-[12px] cqa-leading-4 cqa-text-[#374151]\">{{ it.label }}</span>\n <div class=\"cqa-flex-1 cqa-h-[8px] cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [ngClass]=\"statusColorClass(it)\"\n [style.width]=\"formatPercent(it.percent)\"></div>\n </div>\n <span class=\"cqa-w-[40px] cqa-text-right cqa-text-[12px] cqa-leading-4\" [ngClass]=\"textColorClass(it)\">{{\n formatPercent(it.percent) }}</span>\n </div>\n </div>\n\n <!-- Footer -->\n <div class=\"cqa-mt-4\">\n <button type=\"button\"\n class=\"cqa-w-full cqa-h-[40px] cqa-rounded-[8px] cqa-bg-[#4338CA] cqa-text-white cqa-text-[14px] cqa-leading-[20px] hover:cqa-bg-[#3730A3] disabled:cqa-opacity-50 disabled:cqa-cursor-not-allowed\"\n [disabled]=\"ctaDisabled\" (click)=\"ctaClicked.emit()\">\n \u2728 {{ ctaText }}\n </button>\n </div>\n </div>\n</div>", directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2082
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CoverageModuleCardComponent, decorators: [{
2083
+ type: Component,
2084
+ args: [{ selector: 'cqa-coverage-module-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-white cqa-rounded-[8px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-py-[10px] cqa-px-[17px] cqa-shadow-card\">\n <!-- Header -->\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-3\">\n <h3 class=\"cqa-text-[18px] cqa-leading-[28px] cqa-font-bold cqa-text-dialog\">{{ title }}</h3>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span\n class=\"cqa-px-[10px] cqa-py-[4px] cqa-text-[12px] cqa-leading-[16px] cqa-flex cqa-items-center cqa-gap-1 cqa-rounded-full cqa-bg-warning-light cqa-text-danger\">\n {{ issues }} {{ issues === 1 ? 'issue' : 'issues' }}\n </span>\n <button type=\"button\"\n class=\"cqa-text-[14px] cqa-leading-[20px] cqa-text-primary cqa-flex cqa-items-center cqa-gap-1\"\n *ngIf=\"showViewAction\" (click)=\"view.emit()\">\n View\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6 12L10 8L6 4\" stroke=\"#4F46E5\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </button>\n </div>\n </div>\n\n <!-- Middle metrics row -->\n <div class=\"cqa-flex cqa-items-stretch cqa-justify-between cqa-gap-6 cqa-mb-4\">\n <!-- Left: Positive / Negative / Edge Case -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-6\">\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-[#10B981]\">{{ positiveCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ positiveLabel }}</span>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-[#EF4444]\">{{ negativeCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ negativeLabel }}</span>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-[#F59E0B]\">{{ edgeCaseCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ edgeCaseLabel }}</span>\n </div>\n </div>\n\n <!-- Divider -->\n <div class=\"cqa-w-px cqa-bg-[#E5E7EB]\"></div>\n\n <!-- Right: AI / Human -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-6\">\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-dialog\">{{ aiCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ aiLabel }}</span>\n </div>\n <div class=\"cqa-flex cqa-flex-col cqa-items-start\">\n <span class=\"cqa-text-[18px] cqa-leading-6 cqa-font-semibold cqa-text-dialog\">{{ humanCount }}</span>\n <span class=\"cqa-text-[12px] cqa-leading-4 cqa-text-danger\">{{ humanLabel }}</span>\n </div>\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div *ngFor=\"let it of items\" class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <span class=\"cqa-min-w-[120px] cqa-text-[12px] cqa-leading-4 cqa-text-[#374151]\">{{ it.label }}</span>\n <div class=\"cqa-flex-1 cqa-h-[8px] cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden\">\n <div class=\"cqa-h-full cqa-rounded-full\" [ngClass]=\"statusColorClass(it)\"\n [style.width]=\"formatPercent(it.percent)\"></div>\n </div>\n <span class=\"cqa-w-[40px] cqa-text-right cqa-text-[12px] cqa-leading-4\" [ngClass]=\"textColorClass(it)\">{{\n formatPercent(it.percent) }}</span>\n </div>\n </div>\n\n <!-- Footer -->\n <div class=\"cqa-mt-4\">\n <button type=\"button\"\n class=\"cqa-w-full cqa-h-[40px] cqa-rounded-[8px] cqa-bg-[#4338CA] cqa-text-white cqa-text-[14px] cqa-leading-[20px] hover:cqa-bg-[#3730A3] disabled:cqa-opacity-50 disabled:cqa-cursor-not-allowed\"\n [disabled]=\"ctaDisabled\" (click)=\"ctaClicked.emit()\">\n \u2728 {{ ctaText }}\n </button>\n </div>\n </div>\n</div>", styles: [] }]
2085
+ }], propDecorators: { title: [{
2086
+ type: Input
2087
+ }], issues: [{
2088
+ type: Input
2089
+ }], showViewAction: [{
2090
+ type: Input
2091
+ }], positiveCount: [{
2092
+ type: Input
2093
+ }], negativeCount: [{
2094
+ type: Input
2095
+ }], edgeCaseCount: [{
2096
+ type: Input
2097
+ }], positiveLabel: [{
2098
+ type: Input
2099
+ }], negativeLabel: [{
2100
+ type: Input
2101
+ }], edgeCaseLabel: [{
2102
+ type: Input
2103
+ }], aiCount: [{
2104
+ type: Input
2105
+ }], humanCount: [{
2106
+ type: Input
2107
+ }], aiLabel: [{
2108
+ type: Input
2109
+ }], humanLabel: [{
2110
+ type: Input
2111
+ }], items: [{
2112
+ type: Input
2113
+ }], ctaText: [{
2114
+ type: Input
2115
+ }], ctaDisabled: [{
2116
+ type: Input
2117
+ }], view: [{
2118
+ type: Output
2119
+ }], ctaClicked: [{
2120
+ type: Output
2121
+ }] } });
2122
+
2123
+ class TestDistributionCardComponent {
2124
+ constructor() {
2125
+ this.title = 'Test Distribution';
2126
+ this.segments = [];
2127
+ this.items = [];
2128
+ }
2129
+ totalSegments() {
2130
+ return this.segments.reduce((sum, s) => sum + (s.value || 0), 0) || 1;
2131
+ }
2132
+ segmentWidth(segment) {
2133
+ const total = this.totalSegments();
2134
+ const pct = Math.max(0, Math.min(100, (segment.value / total) * 100));
2135
+ return pct + '%';
2136
+ }
2137
+ segmentColor(segment, fallback) {
2138
+ return segment.colorClass || fallback;
2139
+ }
2140
+ }
2141
+ TestDistributionCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestDistributionCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2142
+ TestDistributionCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TestDistributionCardComponent, selector: "cqa-test-distribution-card", inputs: { title: "title", segments: "segments", items: "items" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-white cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-p-4\">\n <!-- Title -->\n <h3 class=\"cqa-text-[16px] cqa-leading-6 cqa-font-medium cqa-text-[#111827] cqa-mb-3\">{{ title }}</h3>\n\n <!-- Stacked segments pill -->\n <div class=\"cqa-w-full cqa-h-[28px] cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden cqa-flex cqa-mb-3\">\n <ng-container *ngFor=\"let s of segments; let i = index; let last = last\">\n <div\n class=\"cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-text-white cqa-text-[12px] cqa-leading-[12px]\"\n [ngClass]=\"[\n segmentColor(s, i === 0 ? 'cqa-bg-[#4F46E5]' : i === segments.length - 1 ? 'cqa-bg-[#10B981]' : 'cqa-bg-[#8B5CF6]'),\n i === 0 ? 'cqa-rounded-l-full' : '',\n last ? 'cqa-rounded-r-full' : ''\n ]\" [style.width]=\"segmentWidth(s)\">\n {{ s.label }}\n </div>\n </ng-container>\n </div>\n\n <!-- Items list -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <div *ngFor=\"let it of items\" class=\"cqa-flex cqa-flex-col\">\n <!-- Parent row -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-py-1\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <mat-icon class=\"cqa-text-[#6B7280]\" [style.width.px]=\"16\" [style.height.px]=\"16\" [style.fontSize.px]=\"16\"\n *ngIf=\"it.icon\">{{ it.icon }}</mat-icon>\n <span class=\"cqa-text-[14px] cqa-leading-5 cqa-text-[#111827]\">{{ it.label }}</span>\n </div>\n <div class=\"cqa-text-[14px] cqa-leading-5 cqa-font-semibold cqa-text-[#111827]\">{{ it.value | number }}</div>\n </div>\n\n <!-- Children rows -->\n <div *ngIf=\"it.children?.length\" class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <div *ngFor=\"let ch of it.children\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-px-2 cqa-py-1 cqa-rounded-md cqa-bg-[#F9FAFB] cqa-text-[#6B7280]\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span class=\"cqa-w-[6px] cqa-h-[14px] cqa-rounded-full\"\n [ngClass]=\"ch.colorClass || 'cqa-bg-[#8B5CF6]'\"></span>\n <span class=\"cqa-text-[12px] cqa-leading-5\">\n {{ ch.label }}\n <span class=\"cqa-font-semibold cqa-text-[#111827]\">{{ ch.value }}</span>\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "number": i2.DecimalPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
2143
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TestDistributionCardComponent, decorators: [{
2144
+ type: Component,
2145
+ args: [{ selector: 'cqa-test-distribution-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-white cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-p-4\">\n <!-- Title -->\n <h3 class=\"cqa-text-[16px] cqa-leading-6 cqa-font-medium cqa-text-[#111827] cqa-mb-3\">{{ title }}</h3>\n\n <!-- Stacked segments pill -->\n <div class=\"cqa-w-full cqa-h-[28px] cqa-rounded-full cqa-bg-[#F3F4F6] cqa-overflow-hidden cqa-flex cqa-mb-3\">\n <ng-container *ngFor=\"let s of segments; let i = index; let last = last\">\n <div\n class=\"cqa-h-full cqa-flex cqa-items-center cqa-justify-center cqa-text-white cqa-text-[12px] cqa-leading-[12px]\"\n [ngClass]=\"[\n segmentColor(s, i === 0 ? 'cqa-bg-[#4F46E5]' : i === segments.length - 1 ? 'cqa-bg-[#10B981]' : 'cqa-bg-[#8B5CF6]'),\n i === 0 ? 'cqa-rounded-l-full' : '',\n last ? 'cqa-rounded-r-full' : ''\n ]\" [style.width]=\"segmentWidth(s)\">\n {{ s.label }}\n </div>\n </ng-container>\n </div>\n\n <!-- Items list -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <div *ngFor=\"let it of items\" class=\"cqa-flex cqa-flex-col\">\n <!-- Parent row -->\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-py-1\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <mat-icon class=\"cqa-text-[#6B7280]\" [style.width.px]=\"16\" [style.height.px]=\"16\" [style.fontSize.px]=\"16\"\n *ngIf=\"it.icon\">{{ it.icon }}</mat-icon>\n <span class=\"cqa-text-[14px] cqa-leading-5 cqa-text-[#111827]\">{{ it.label }}</span>\n </div>\n <div class=\"cqa-text-[14px] cqa-leading-5 cqa-font-semibold cqa-text-[#111827]\">{{ it.value | number }}</div>\n </div>\n\n <!-- Children rows -->\n <div *ngIf=\"it.children?.length\" class=\"cqa-flex cqa-flex-col cqa-gap-2\">\n <div *ngFor=\"let ch of it.children\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-px-2 cqa-py-1 cqa-rounded-md cqa-bg-[#F9FAFB] cqa-text-[#6B7280]\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <span class=\"cqa-w-[6px] cqa-h-[14px] cqa-rounded-full\"\n [ngClass]=\"ch.colorClass || 'cqa-bg-[#8B5CF6]'\"></span>\n <span class=\"cqa-text-[12px] cqa-leading-5\">\n {{ ch.label }}\n <span class=\"cqa-font-semibold cqa-text-[#111827]\">{{ ch.value }}</span>\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>", styles: [] }]
2146
+ }], propDecorators: { title: [{
2147
+ type: Input
2148
+ }], segments: [{
2149
+ type: Input
2150
+ }], items: [{
2151
+ type: Input
2152
+ }] } });
2153
+
2154
+ class FailedTestCasesCardComponent {
2155
+ constructor() {
2156
+ /** E.g., "C-62: Upload Content" */
2157
+ this.title = 'Failed Test Case';
2158
+ /** Number of failures to display in the pill */
2159
+ this.failures = 0;
2160
+ /** Pill label (e.g., "failures") */
2161
+ this.failuresLabel = 'failures';
2162
+ /** Optional custom class for the pill background */
2163
+ this.pillClass = 'bg-[#EF4444] text-white';
2164
+ /** Root cause label (left part, emphasized) */
2165
+ this.rootCauseLabel = 'Root cause';
2166
+ /** If false, hide the root cause row */
2167
+ this.showRootCause = true;
2168
+ /** Label for timestamp */
2169
+ this.lastFailedLabel = 'Last failed';
2170
+ /** Optional extra class for the outer card */
2171
+ this.cardClass = '';
2172
+ /** Left border accent class */
2173
+ this.leftAccentClass = 'border-l-[4px] border-[#EF4444]';
2174
+ }
2175
+ get rootCauseDisplay() {
2176
+ return this.rootCause && this.rootCause.trim().length
2177
+ ? this.rootCause
2178
+ : 'No root cause available';
2179
+ }
2180
+ }
2181
+ FailedTestCasesCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FailedTestCasesCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2182
+ FailedTestCasesCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: FailedTestCasesCardComponent, selector: "cqa-failed-test-cases-card", inputs: { title: "title", failures: "failures", failuresLabel: "failuresLabel", pillClass: "pillClass", rootCause: "rootCause", rootCauseLabel: "rootCauseLabel", showRootCause: "showRootCause", lastFailed: "lastFailed", lastFailedLabel: "lastFailedLabel", cardClass: "cardClass", leftAccentClass: "leftAccentClass" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-white cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-p-4\"\n [ngClass]=\"[leftAccentClass, cardClass]\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-gap-2\">\n <!-- Title -->\n <h3 class=\"cqa-text-[16px] cqa-leading-6 cqa-font-semibold cqa-text-[#111827]\">{{ title }}</h3>\n\n <!-- Failures pill -->\n <span class=\"cqa-px-2.5 cqa-py-1 cqa-rounded-full cqa-text-[12px] cqa-leading-4 cqa-font-medium\"\n [ngClass]=\"pillClass\">\n {{ failures | number }} {{ failuresLabel }}\n </span>\n </div>\n\n <!-- Root cause -->\n <div *ngIf=\"showRootCause\" class=\"cqa-mt-2 cqa-text-[14px] cqa-leading-5\">\n <span class=\"cqa-font-semibold cqa-text-[#EF4444]\">{{ rootCauseLabel }}:</span>\n <span class=\"cqa-text-[#EF4444]\">{{ rootCauseDisplay }}</span>\n </div>\n\n <!-- Timestamp -->\n <div *ngIf=\"lastFailed\"\n class=\"cqa-mt-1 cqa-flex cqa-items-center cqa-gap-2 cqa-text-[12px] cqa-leading-5 cqa-text-[#6B7280]\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">schedule</mat-icon>\n <span>{{ lastFailedLabel }}: {{ lastFailed }}</span>\n </div>\n </div>\n</div>", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "number": i2.DecimalPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
2183
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FailedTestCasesCardComponent, decorators: [{
2184
+ type: Component,
2185
+ args: [{ selector: 'cqa-failed-test-cases-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-bg-white cqa-rounded-[10px] cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-p-4\"\n [ngClass]=\"[leftAccentClass, cardClass]\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-gap-2\">\n <!-- Title -->\n <h3 class=\"cqa-text-[16px] cqa-leading-6 cqa-font-semibold cqa-text-[#111827]\">{{ title }}</h3>\n\n <!-- Failures pill -->\n <span class=\"cqa-px-2.5 cqa-py-1 cqa-rounded-full cqa-text-[12px] cqa-leading-4 cqa-font-medium\"\n [ngClass]=\"pillClass\">\n {{ failures | number }} {{ failuresLabel }}\n </span>\n </div>\n\n <!-- Root cause -->\n <div *ngIf=\"showRootCause\" class=\"cqa-mt-2 cqa-text-[14px] cqa-leading-5\">\n <span class=\"cqa-font-semibold cqa-text-[#EF4444]\">{{ rootCauseLabel }}:</span>\n <span class=\"cqa-text-[#EF4444]\">{{ rootCauseDisplay }}</span>\n </div>\n\n <!-- Timestamp -->\n <div *ngIf=\"lastFailed\"\n class=\"cqa-mt-1 cqa-flex cqa-items-center cqa-gap-2 cqa-text-[12px] cqa-leading-5 cqa-text-[#6B7280]\">\n <mat-icon class=\"!cqa-w-4 !cqa-h-4 !cqa-text-[16px]\">schedule</mat-icon>\n <span>{{ lastFailedLabel }}: {{ lastFailed }}</span>\n </div>\n </div>\n</div>", styles: [] }]
2186
+ }], propDecorators: { title: [{
2187
+ type: Input
2188
+ }], failures: [{
2189
+ type: Input
2190
+ }], failuresLabel: [{
2191
+ type: Input
2192
+ }], pillClass: [{
2193
+ type: Input
2194
+ }], rootCause: [{
2195
+ type: Input
2196
+ }], rootCauseLabel: [{
2197
+ type: Input
2198
+ }], showRootCause: [{
2199
+ type: Input
2200
+ }], lastFailed: [{
2201
+ type: Input
2202
+ }], lastFailedLabel: [{
2203
+ type: Input
2204
+ }], cardClass: [{
2205
+ type: Input
2206
+ }], leftAccentClass: [{
2207
+ type: Input
2208
+ }] } });
2209
+
2210
+ class SelectedFiltersComponent {
2211
+ constructor() {
2212
+ this.filterApplied = false;
2213
+ this.chips = [];
2214
+ this.removeChip = new EventEmitter();
2215
+ this.clearAll = new EventEmitter();
2216
+ }
2217
+ }
2218
+ SelectedFiltersComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SelectedFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2219
+ SelectedFiltersComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: SelectedFiltersComponent, selector: "cqa-selected-filters", inputs: { filterApplied: "filterApplied", chips: "chips" }, outputs: { removeChip: "removeChip", clearAll: "clearAll" }, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-flex cqa-flex-wrap cqa-justify-end cqa-gap-2 cqa-mb-3\"\n *ngIf=\"filterApplied && (chips?.length || 0)\">\n <div\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-2 cqa-py-1 cqa-rounded-full cqa-border cqa-border-success-100 cqa-bg-primary-surface\"\n *ngFor=\"let chip of chips\" [matTooltip]=\"chip.hasMore ? chip.fullText : ''\" [matTooltipDisabled]=\"!chip.hasMore\"\n matTooltipPosition=\"above\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-text-primary\">{{ chip.label || chip.key\n }}:</span>\n <span class=\"cqa-text-[12px] cqa-leading-[16px]\">{{ chip.text }}</span>\n <button type=\"button\"\n class=\"cqa-ml-1 cqa-inline-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-border cqa-border-transparent hover:cqa-bg-[#EEF2FF]\"\n (click)=\"removeChip.emit(chip)\" aria-label=\"Remove filter\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 12 11\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M8.625 2.875L3.375 8.125\" stroke=\"#3F43EE\" stroke-width=\"0.875\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M3.375 2.875L8.625 8.125\" stroke=\"#3F43EE\" stroke-width=\"0.875\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n\n <button type=\"button\" class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-grey-300 hover:cqa-underline\"\n (click)=\"clearAll.emit()\">\n Clear All\n </button>\n </div>\n</div>", directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$2.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2220
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: SelectedFiltersComponent, decorators: [{
2221
+ type: Component,
2222
+ args: [{ selector: 'cqa-selected-filters', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-flex cqa-flex-wrap cqa-justify-end cqa-gap-2 cqa-mb-3\"\n *ngIf=\"filterApplied && (chips?.length || 0)\">\n <div\n class=\"cqa-inline-flex cqa-items-center cqa-gap-2 cqa-px-2 cqa-py-1 cqa-rounded-full cqa-border cqa-border-success-100 cqa-bg-primary-surface\"\n *ngFor=\"let chip of chips\" [matTooltip]=\"chip.hasMore ? chip.fullText : ''\" [matTooltipDisabled]=\"!chip.hasMore\"\n matTooltipPosition=\"above\">\n <span class=\"cqa-text-[12px] cqa-leading-[16px] cqa-font-medium cqa-text-primary\">{{ chip.label || chip.key\n }}:</span>\n <span class=\"cqa-text-[12px] cqa-leading-[16px]\">{{ chip.text }}</span>\n <button type=\"button\"\n class=\"cqa-ml-1 cqa-inline-flex cqa-items-center cqa-justify-center cqa-rounded-full cqa-border cqa-border-transparent hover:cqa-bg-[#EEF2FF]\"\n (click)=\"removeChip.emit(chip)\" aria-label=\"Remove filter\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 12 11\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M8.625 2.875L3.375 8.125\" stroke=\"#3F43EE\" stroke-width=\"0.875\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n <path d=\"M3.375 2.875L8.625 8.125\" stroke=\"#3F43EE\" stroke-width=\"0.875\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </button>\n </div>\n\n <button type=\"button\" class=\"cqa-text-[12px] cqa-leading-[16px] cqa-text-grey-300 hover:cqa-underline\"\n (click)=\"clearAll.emit()\">\n Clear All\n </button>\n </div>\n</div>", styles: [] }]
2223
+ }], propDecorators: { filterApplied: [{
2224
+ type: Input
2225
+ }], chips: [{
2226
+ type: Input
2227
+ }], removeChip: [{
2228
+ type: Output
2229
+ }], clearAll: [{
2230
+ type: Output
2231
+ }] } });
2232
+
2233
+ /**
2234
+ * Utility for getting consistent colors for metadata values
2235
+ * Used across Status, Priority, and Result fields
2236
+ *
2237
+ * Colors are defined here and also exported in metadata-colors.constants.js for tailwind.config.js
2238
+ */
2239
+ // Color constants (also exported in metadata-colors.constants.js for Tailwind)
2240
+ const PRIORITY_COLOR_VALUES = {
2241
+ critical: '#DC2626',
2242
+ major: '#C10007',
2243
+ medium: '#CA8A04',
2244
+ minor: '#2563EB',
2245
+ 'not-set': '#101828', // Default dark
2246
+ };
2247
+ const RESULT_COLOR_VALUES = {
2248
+ passed: '#16A34A',
2249
+ failed: '#DC2626',
2250
+ aborted: '#EA580C',
2251
+ 'in-review': '#2563EB',
2252
+ 'not-executed': '#101828', // Default dark
2253
+ };
2254
+ const STATUS_COLOR_VALUES = {
2255
+ active: '#16A34A',
2256
+ inactive: '#6B7280',
2257
+ pending: '#CA8A04',
2258
+ completed: '#16A34A', // Green-600
2259
+ };
2260
+ const DEFAULT_METADATA_COLOR_VALUE = '#101828';
2261
+ /**
2262
+ * Color mappings for Priority values
2263
+ */
2264
+ const PRIORITY_COLORS = {
2265
+ 'critical': PRIORITY_COLOR_VALUES.critical,
2266
+ 'major': PRIORITY_COLOR_VALUES.major,
2267
+ 'medium': PRIORITY_COLOR_VALUES.medium,
2268
+ 'minor': PRIORITY_COLOR_VALUES.minor,
2269
+ 'not set': PRIORITY_COLOR_VALUES['not-set'],
2270
+ };
2271
+ /**
2272
+ * Color mappings for Result values
2273
+ */
2274
+ const RESULT_COLORS = {
2275
+ 'passed': RESULT_COLOR_VALUES.passed,
2276
+ 'failed': RESULT_COLOR_VALUES.failed,
2277
+ 'aborted': RESULT_COLOR_VALUES.aborted,
2278
+ 'in review': RESULT_COLOR_VALUES['in-review'],
2279
+ 'not executed': RESULT_COLOR_VALUES['not-executed'],
2280
+ };
2281
+ /**
2282
+ * Color mappings for Status values
2283
+ */
2284
+ const STATUS_COLORS = {
2285
+ 'active': STATUS_COLOR_VALUES.active,
2286
+ 'inactive': STATUS_COLOR_VALUES.inactive,
2287
+ 'pending': STATUS_COLOR_VALUES.pending,
2288
+ 'completed': STATUS_COLOR_VALUES.completed,
2289
+ };
2290
+ /**
2291
+ * Default color for metadata values
2292
+ */
2293
+ const DEFAULT_METADATA_COLOR = DEFAULT_METADATA_COLOR_VALUE;
2294
+ /**
2295
+ * Gets the color for a metadata value based on its key and value
2296
+ * @param key - The metadata key (priority, result, or status)
2297
+ * @param value - The metadata value (string or object with value property)
2298
+ * @returns Color hex code as a string
2299
+ */
2300
+ function getMetadataColor(key, value) {
2301
+ // Extract the actual value
2302
+ const actualValue = typeof value === 'string' ? value : value.value;
2303
+ const normalizedValue = actualValue.toLowerCase().trim();
2304
+ const normalizedKey = key.toLowerCase().trim();
2305
+ // Get color based on key
2306
+ let colorMap;
2307
+ switch (normalizedKey) {
2308
+ case 'priority':
2309
+ colorMap = PRIORITY_COLORS;
2310
+ break;
2311
+ case 'result':
2312
+ colorMap = RESULT_COLORS;
2313
+ break;
2314
+ case 'status':
2315
+ colorMap = STATUS_COLORS;
2316
+ break;
2317
+ default:
2318
+ return DEFAULT_METADATA_COLOR;
2319
+ }
2320
+ // Return color for the value, or default if not found
2321
+ return colorMap[normalizedValue] || DEFAULT_METADATA_COLOR;
2322
+ }
2323
+ /**
2324
+ * Gets inline style object for metadata value color
2325
+ * @param key - The metadata key
2326
+ * @param value - The metadata value
2327
+ * @returns Style object with color property
2328
+ */
2329
+ function getMetadataValueStyle(key, value) {
2330
+ return { color: getMetadataColor(key, value) };
2331
+ }
2332
+
2333
+ class BadgeComponent {
2334
+ constructor() {
2335
+ this.label = '';
2336
+ this.variant = 'default';
2337
+ }
2338
+ get badgeClasses() {
2339
+ const baseClasses = [
2340
+ 'cqa-inline-flex',
2341
+ 'cqa-items-center',
2342
+ 'cqa-justify-center',
2343
+ 'cqa-rounded-[6px]',
2344
+ 'cqa-font-normal',
2345
+ 'cqa-leading-[17px]'
2346
+ ];
2347
+ // Only apply variant-specific Tailwind classes if custom colors are not provided
2348
+ if (!this.backgroundColor && !this.textColor) {
2349
+ switch (this.variant) {
2350
+ case 'error':
2351
+ return [...baseClasses, 'cqa-bg-red-100', 'cqa-text-red-800'].join(' ');
2352
+ case 'warning':
2353
+ return [...baseClasses, 'cqa-bg-yellow-100', 'cqa-text-yellow-800'].join(' ');
2354
+ case 'info':
2355
+ return [...baseClasses, 'cqa-bg-blue-100', 'cqa-text-blue-800'].join(' ');
2356
+ case 'success':
2357
+ return [...baseClasses, 'cqa-bg-green-100', 'cqa-text-green-800'].join(' ');
2358
+ case 'outline':
2359
+ return [...baseClasses, 'cqa-bg-transparent', 'cqa-text-gray-800'].join(' ');
2360
+ default:
2361
+ return [...baseClasses, 'cqa-bg-gray-100', 'cqa-text-gray-800'].join(' ');
2362
+ }
2363
+ }
2364
+ // If custom colors are provided, only return base classes
2365
+ return baseClasses.join(' ');
2366
+ }
2367
+ get badgeStyles() {
2368
+ const styles = {};
2369
+ if (this.backgroundColor) {
2370
+ styles['background-color'] = this.backgroundColor;
2371
+ }
2372
+ else if (this.variant === 'outline') {
2373
+ styles['background-color'] = 'transparent';
2374
+ }
2375
+ if (this.textColor) {
2376
+ styles['color'] = this.textColor;
2377
+ }
2378
+ return styles;
2379
+ }
2380
+ get iconContainerClasses() {
2381
+ const baseClasses = [
2382
+ 'cqa-inline-flex',
2383
+ 'cqa-items-center',
2384
+ 'cqa-justify-center',
2385
+ 'cqa-flex-shrink-0',
2386
+ 'cqa-mr-1.5'
2387
+ ];
2388
+ // No circular background for any variant - just return base classes
2389
+ return baseClasses.join(' ');
2390
+ }
2391
+ get iconContainerStyles() {
2392
+ const styles = {
2393
+ 'display': 'inline-flex',
2394
+ 'align-items': 'center',
2395
+ 'justify-content': 'center'
2396
+ };
2397
+ // No circular background - only apply custom icon background color if explicitly provided
2398
+ if (this.iconBackgroundColor) {
2399
+ styles['background-color'] = this.iconBackgroundColor;
2400
+ // If custom background is provided, add circle dimensions
2401
+ styles['width'] = '16px';
2402
+ styles['height'] = '16px';
2403
+ styles['min-width'] = '16px';
2404
+ styles['min-height'] = '16px';
2405
+ styles['border-radius'] = '50%';
2406
+ }
2407
+ return styles;
2408
+ }
2409
+ get iconClasses() {
2410
+ const baseClasses = [];
2411
+ // Only apply white text class if custom icon color is not provided
2412
+ if (!this.iconColor) {
2413
+ return [...baseClasses, 'cqa-text-white'].join(' ');
2414
+ }
2415
+ return baseClasses.join(' ');
2416
+ }
2417
+ get iconStyles() {
2418
+ const styles = {
2419
+ 'font-size': '14px',
2420
+ 'width': '14px',
2421
+ 'height': '14px',
2422
+ 'line-height': '14px'
2423
+ };
2424
+ if (this.iconColor) {
2425
+ styles['color'] = this.iconColor;
2426
+ }
2427
+ else {
2428
+ // Use variant-specific text color for icon (no white background anymore)
2429
+ switch (this.variant) {
2430
+ case 'error':
2431
+ styles['color'] = '#991B1B'; // red-800
2432
+ break;
2433
+ case 'warning':
2434
+ styles['color'] = '#854D0E'; // yellow-800
2435
+ break;
2436
+ case 'info':
2437
+ styles['color'] = '#1E40AF'; // blue-800
2438
+ break;
2439
+ case 'success':
2440
+ styles['color'] = '#166534'; // green-800
2441
+ break;
2442
+ default:
2443
+ styles['color'] = this.textColor || '#374151'; // gray-700 default
2444
+ }
2445
+ }
2446
+ return styles;
2447
+ }
2448
+ }
2449
+ BadgeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: BadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2450
+ BadgeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: BadgeComponent, selector: "cqa-badge", inputs: { label: "label", icon: "icon", variant: "variant", backgroundColor: "backgroundColor", textColor: "textColor", iconBackgroundColor: "iconBackgroundColor", iconColor: "iconColor" }, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <span \n [ngClass]=\"badgeClasses\" \n [ngStyle]=\"badgeStyles\"\n class=\"cqa-font-inter cqa-font-normal cqa-text-sm cqa-leading-[17px] cqa-py-[4px] cqa-px-3\">\n <span \n *ngIf=\"icon\" \n [ngClass]=\"iconContainerClasses\"\n [ngStyle]=\"iconContainerStyles\">\n <mat-icon \n [ngClass]=\"iconClasses\"\n [ngStyle]=\"iconStyles\">{{ icon }}</mat-icon>\n </span>\n {{ label }}\n </span>\n</div>\n\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
2451
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: BadgeComponent, decorators: [{
2452
+ type: Component,
2453
+ args: [{ selector: 'cqa-badge', template: "<div id=\"cqa-ui-root\" style=\"display: inline-block;\">\n <span \n [ngClass]=\"badgeClasses\" \n [ngStyle]=\"badgeStyles\"\n class=\"cqa-font-inter cqa-font-normal cqa-text-sm cqa-leading-[17px] cqa-py-[4px] cqa-px-3\">\n <span \n *ngIf=\"icon\" \n [ngClass]=\"iconContainerClasses\"\n [ngStyle]=\"iconContainerStyles\">\n <mat-icon \n [ngClass]=\"iconClasses\"\n [ngStyle]=\"iconStyles\">{{ icon }}</mat-icon>\n </span>\n {{ label }}\n </span>\n</div>\n\n", styles: [] }]
2454
+ }], propDecorators: { label: [{
2455
+ type: Input
2456
+ }], icon: [{
2457
+ type: Input
2458
+ }], variant: [{
2459
+ type: Input
2460
+ }], backgroundColor: [{
2461
+ type: Input
2462
+ }], textColor: [{
2463
+ type: Input
2464
+ }], iconBackgroundColor: [{
2465
+ type: Input
2466
+ }], iconColor: [{
2467
+ type: Input
2468
+ }] } });
2469
+
2470
+ class InsightCardComponent {
2471
+ constructor() {
2472
+ this.title = '';
2473
+ this.description = '';
2474
+ this._badges = [];
2475
+ this.metadataExpanded = true;
2476
+ this.isPrerequisiteMissing = false;
2477
+ this.isTestDataMissing = false;
2478
+ // Track expanded state for sections
2479
+ this.sectionExpandedState = new Map();
2480
+ // Loading state for main action
2481
+ this.isApplying = false;
2482
+ this.metadataToggle = new EventEmitter();
2483
+ this.sectionToggle = new EventEmitter();
2484
+ this.sectionActionClick = new EventEmitter();
2485
+ this.onApplySuggestionClick = new EventEmitter();
2486
+ this.onAttachPrerequisitesClick = new EventEmitter();
2487
+ this.onImportTestDataClick = new EventEmitter();
2488
+ }
2489
+ set badges(value) {
2490
+ this._badges = value;
2491
+ }
2492
+ get badges() {
2493
+ return this._badges;
2494
+ }
2495
+ toggleMetadata() {
2496
+ this.metadataExpanded = !this.metadataExpanded;
2497
+ this.metadataToggle.emit(this.metadataExpanded);
2498
+ }
2499
+ toggleSection(section) {
2500
+ var _a, _b;
2501
+ const currentState = (_a = this.sectionExpandedState.get(section.id)) !== null && _a !== void 0 ? _a : ((_b = section.expanded) !== null && _b !== void 0 ? _b : true);
2502
+ const newState = !currentState;
2503
+ this.sectionExpandedState.set(section.id, newState);
2504
+ this.sectionToggle.emit({ id: section.id, expanded: newState });
2505
+ }
2506
+ onSectionAction(sectionId) {
2507
+ this.sectionActionClick.emit(sectionId);
2508
+ // Emit specific events for known actions
2509
+ if (sectionId === 'prerequisite') {
2510
+ this.onAttachPrerequisitesClick.emit();
2511
+ }
2512
+ else if (sectionId === 'test-data') {
2513
+ this.onImportTestDataClick.emit();
2514
+ }
2515
+ }
2516
+ get visibleBadges() {
2517
+ const visible = [];
2518
+ if (this.isPrerequisiteMissing) {
2519
+ visible.push({ label: 'Prerequisite Missing', variant: 'warning' });
2520
+ }
2521
+ if (this.isTestDataMissing) {
2522
+ visible.push({ label: 'Test Data Missing', variant: 'error' });
2523
+ }
2524
+ // Also include any custom badges
2525
+ if (this.badges) {
2526
+ visible.push(...this.badges);
2527
+ }
2528
+ return visible;
2529
+ }
2530
+ get visibleSections() {
2531
+ const visible = [];
2532
+ if (this.isPrerequisiteMissing && this.prerequisiteSection) {
2533
+ // Use stored state if available, otherwise default to true
2534
+ const expanded = this.sectionExpandedState.has('prerequisite')
2535
+ ? this.sectionExpandedState.get('prerequisite')
2536
+ : true;
2537
+ visible.push({
2538
+ id: 'prerequisite',
2539
+ title: 'Prerequisite Missing',
2540
+ variant: 'warning',
2541
+ reason: this.prerequisiteSection,
2542
+ actionButtonLabel: 'Attach Prerequisites',
2543
+ expanded: expanded,
2544
+ });
2545
+ }
2546
+ if (this.isTestDataMissing && this.testDataSection) {
2547
+ // Use stored state if available, otherwise default to true
2548
+ const expanded = this.sectionExpandedState.has('test-data')
2549
+ ? this.sectionExpandedState.get('test-data')
2550
+ : true;
2551
+ visible.push({
2552
+ id: 'test-data',
2553
+ title: 'Test Data Missing',
2554
+ variant: 'error',
2555
+ reason: this.testDataSection,
2556
+ actionButtonLabel: 'Import Test Data',
2557
+ expanded: expanded,
2558
+ });
2559
+ }
2560
+ return visible;
2561
+ }
2562
+ onMainAction() {
2563
+ return __awaiter(this, void 0, void 0, function* () {
2564
+ if (this.isApplying) {
2565
+ return; // Prevent multiple clicks
2566
+ }
2567
+ this.isApplying = true;
2568
+ try {
2569
+ this.onApplySuggestionClick.emit();
2570
+ }
2571
+ finally {
2572
+ // Reset loading state after action completes
2573
+ // If you need to keep the loading state longer, call resetApplyingState() manually
2574
+ // after your async operation completes
2575
+ this.isApplying = false;
2576
+ }
2577
+ });
2578
+ }
2579
+ // Method to reset loading state (can be called externally if needed)
2580
+ resetApplyingState() {
2581
+ this.isApplying = false;
2582
+ }
2583
+ // Removed getBadgeClasses - now using BadgeComponent
2584
+ getSectionBorderClass(section) {
2585
+ switch (section.variant) {
2586
+ case 'warning':
2587
+ return 'cqa-border-l-4 cqa-border-l-yellow-500';
2588
+ case 'error':
2589
+ return 'cqa-border-l-4 cqa-border-l-red-500';
2590
+ default:
2591
+ return 'cqa-border-l-4 cqa-border-l-gray-500';
2592
+ }
2593
+ }
2594
+ getMetadataValueClasses(key, value) {
2595
+ // Base classes for all values (font-size: 14px, line-height: 18px, font-weight: 400)
2596
+ return 'cqa-font-normal cqa-leading-[18px] cqa-tracking-normal';
2597
+ }
2598
+ getMetadataValue(value) {
2599
+ if (typeof value === 'string') {
2600
+ return value;
2601
+ }
2602
+ return value.value;
2603
+ }
2604
+ getMetadataValueStyle(key, value) {
2605
+ // Use the shared utility function for consistent colors
2606
+ return getMetadataValueStyle(key, value);
2607
+ }
2608
+ getSectionTitleClasses(section) {
2609
+ const baseClasses = ['cqa-text-sm', 'cqa-font-bold'];
2610
+ switch (section.variant) {
2611
+ case 'warning':
2612
+ return [...baseClasses, 'cqa-text-yellow-800'].join(' ');
2613
+ case 'error':
2614
+ return [...baseClasses, 'cqa-text-red-600'].join(' ');
2615
+ default:
2616
+ return [...baseClasses, 'cqa-text-ink'].join(' ');
2617
+ }
2618
+ }
2619
+ getSectionIconColor(section) {
2620
+ switch (section.variant) {
2621
+ case 'warning':
2622
+ return 'cqa-text-yellow-800';
2623
+ case 'error':
2624
+ return 'cqa-text-red-600';
2625
+ default:
2626
+ return 'cqa-text-gray-400';
2627
+ }
2628
+ }
2629
+ }
2630
+ InsightCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: InsightCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2631
+ InsightCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: InsightCardComponent, selector: "cqa-insight-card", inputs: { title: "title", description: "description", badges: "badges", metadata: "metadata", prerequisiteSection: "prerequisiteSection", testDataSection: "testDataSection", metadataExpanded: "metadataExpanded", isPrerequisiteMissing: "isPrerequisiteMissing", isTestDataMissing: "isTestDataMissing" }, outputs: { metadataToggle: "metadataToggle", sectionToggle: "sectionToggle", sectionActionClick: "sectionActionClick", onApplySuggestionClick: "onApplySuggestionClick", onAttachPrerequisitesClick: "onAttachPrerequisitesClick", onImportTestDataClick: "onImportTestDataClick" }, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"background-color: white; border-radius: 0.5rem; border: 1px solid #E5E7EB; box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-[21px] cqa-py-3 cqa-border cqa-border-gray-200 cqa-rounded-2xl\">\n <!-- Section 1: Badges -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" *ngIf=\"visibleBadges.length > 0\">\n <mat-icon *ngIf=\"isPrerequisiteMissing || isTestDataMissing\"\n class=\"cqa-text-yellow-500 cqa-w-6 cqa-h-6\">warning</mat-icon>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge \n *ngFor=\"let badge of visibleBadges\" \n [label]=\"badge.label\"\n [icon]=\"badge.icon\"\n [variant]=\"badge.variant || 'default'\"\n ></cqa-badge>\n </div>\n </div>\n\n <!-- Section 2: Title & Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-font-medium cqa-text-lg cqa-text-title\">\n {{ title }}\n </h2>\n <p class=\"cqa-text-base cqa-font-normal cqa-text-description\">\n {{ description }}\n </p>\n </div>\n\n <!-- Section 3: Metadata Section (always visible) -->\n <div *ngIf=\"metadata\" class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <div class=\"cqa-bg-surface-default cqa-rounded-xl cqa-border cqa-border-border-light cqa-px-4 cqa-py-3 cqa-border-t-2 cqa-border-t-primary-surface\">\n <div class=\"cqa-flex cqa-flex-wrap cqa-items-center cqa-gap-3\">\n <ng-container *ngFor=\"let item of metadata | keyvalue; let last = last\">\n <div class=\"cqa-flex cqa-items-baseline cqa-gap-2\">\n <span class=\"cqa-text-xs cqa-font-normal cqa-tracking-normal cqa-font-inter cqa-text-metadata-key\">\n {{ item.key }}:\n </span>\n <span \n [ngClass]=\"getMetadataValueClasses(item.key, item.value)\" \n [ngStyle]=\"getMetadataValueStyle(item.key, item.value)\"\n class=\"cqa-font-normal cqa-leading-[18px] cqa-tracking-normal cqa-font-inter cqa-text-sm\">\n {{ getMetadataValue(item.value) }}\n </span>\n </div>\n <div *ngIf=\"!last\" class=\"cqa-h-4 cqa-w-px cqa-bg-gray-200\"></div>\n </ng-container>\n </div>\n </div>\n\n <!-- Section 4: Metadata toggle -->\n <button *ngIf=\"metadata && (isPrerequisiteMissing || isTestDataMissing)\" type=\"button\"\n class=\"cqa-text-sm cqa-text-primary-hover cqa-font-medium cqa-inline-flex cqa-items-center cqa-gap-1 cqa-cursor-pointer cqa-bg-transparent cqa-border-0 cqa-p-0 cqa-hover:cqa-text-primary cqa-transition-colors\"\n (click)=\"toggleMetadata()\">\n <span>{{ metadataExpanded ? 'Hide details' : 'Show details' }}</span>\n <mat-icon class=\"cqa-w-4 cqa-h-4 cqa-text-[16px] cqa-leading-[16px]\">\n {{ metadataExpanded ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </button>\n\n <!-- Section 5: Sections (toggle visibility) -->\n <div *ngIf=\"metadataExpanded && visibleSections?.length\" class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <div\n *ngFor=\"let section of visibleSections\"\n class=\"cqa-border cqa-border-gray-200 cqa-rounded-md cqa-bg-white cqa-overflow-hidden\"\n [ngClass]=\"getSectionBorderClass(section)\"\n >\n <div class=\"cqa-p-4 cqa-flex cqa-flex-col cqa-gap-3\">\n <!-- Section Title with Inline Collapse Button -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <h3 [ngClass]=\"getSectionTitleClasses(section)\" class=\"cqa-m-0\">\n {{ section.title }}\n </h3>\n <button\n type=\"button\"\n class=\"cqa-ml-auto cqa-inline-flex cqa-items-center cqa-justify-center cqa-cursor-pointer cqa-bg-transparent cqa-border-0 cqa-p-1 cqa-rounded-full cqa-hover:cqa-bg-gray-100 cqa-transition-colors\"\n (click)=\"toggleSection(section)\"\n [attr.aria-label]=\"section.expanded !== false ? 'Collapse section' : 'Expand section'\"\n >\n <mat-icon [ngClass]=\"getSectionIconColor(section)\" class=\"cqa-w-4 cqa-h-4 cqa-text-[16px] cqa-leading-[16px]\">\n {{ section.expanded !== false ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </button>\n </div>\n\n <!-- Collapsible Content: Reason and Action Button -->\n <div *ngIf=\"section.expanded !== false\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <!-- Reason -->\n <p class=\"cqa-text-sm cqa-font-normal cqa-leading-4 cqa-text-neutral-600\">\n <strong>Reason:</strong> {{ section.reason }}\n </p>\n \n <!-- Action Button -->\n <div>\n <cqa-button\n variant=\"outlined\"\n (clicked)=\"onSectionAction(section.id)\"\n >\n {{ section.actionButtonLabel }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <cqa-button\n variant=\"filled\"\n [icon]=\"isApplying ? 'hourglass_empty' : 'auto_awesome'\"\n iconPosition=\"start\"\n (clicked)=\"onMainAction()\"\n [fullWidth]=\"true\"\n [disabled]=\"isApplying\"\n [iconColor]=\"isApplying ? '#EAB308' : undefined\"\n >\n {{ isApplying ? 'Applying suggestion' : 'Apply suggestion' }}\n </cqa-button>\n </div>\n</div>\n \n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: BadgeComponent, selector: "cqa-badge", inputs: ["label", "icon", "variant", "backgroundColor", "textColor", "iconBackgroundColor", "iconColor"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], pipes: { "keyvalue": i2.KeyValuePipe } });
2632
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: InsightCardComponent, decorators: [{
2633
+ type: Component,
2634
+ args: [{ selector: 'cqa-insight-card', template: "<div id=\"cqa-ui-root\" style=\"background-color: white; border-radius: 0.5rem; border: 1px solid #E5E7EB; box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-4 cqa-px-[21px] cqa-py-3 cqa-border cqa-border-gray-200 cqa-rounded-2xl\">\n <!-- Section 1: Badges -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" *ngIf=\"visibleBadges.length > 0\">\n <mat-icon *ngIf=\"isPrerequisiteMissing || isTestDataMissing\"\n class=\"cqa-text-yellow-500 cqa-w-6 cqa-h-6\">warning</mat-icon>\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-2\">\n <cqa-badge \n *ngFor=\"let badge of visibleBadges\" \n [label]=\"badge.label\"\n [icon]=\"badge.icon\"\n [variant]=\"badge.variant || 'default'\"\n ></cqa-badge>\n </div>\n </div>\n\n <!-- Section 2: Title & Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <h2 class=\"cqa-font-medium cqa-text-lg cqa-text-title\">\n {{ title }}\n </h2>\n <p class=\"cqa-text-base cqa-font-normal cqa-text-description\">\n {{ description }}\n </p>\n </div>\n\n <!-- Section 3: Metadata Section (always visible) -->\n <div *ngIf=\"metadata\" class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <div class=\"cqa-bg-surface-default cqa-rounded-xl cqa-border cqa-border-border-light cqa-px-4 cqa-py-3 cqa-border-t-2 cqa-border-t-primary-surface\">\n <div class=\"cqa-flex cqa-flex-wrap cqa-items-center cqa-gap-3\">\n <ng-container *ngFor=\"let item of metadata | keyvalue; let last = last\">\n <div class=\"cqa-flex cqa-items-baseline cqa-gap-2\">\n <span class=\"cqa-text-xs cqa-font-normal cqa-tracking-normal cqa-font-inter cqa-text-metadata-key\">\n {{ item.key }}:\n </span>\n <span \n [ngClass]=\"getMetadataValueClasses(item.key, item.value)\" \n [ngStyle]=\"getMetadataValueStyle(item.key, item.value)\"\n class=\"cqa-font-normal cqa-leading-[18px] cqa-tracking-normal cqa-font-inter cqa-text-sm\">\n {{ getMetadataValue(item.value) }}\n </span>\n </div>\n <div *ngIf=\"!last\" class=\"cqa-h-4 cqa-w-px cqa-bg-gray-200\"></div>\n </ng-container>\n </div>\n </div>\n\n <!-- Section 4: Metadata toggle -->\n <button *ngIf=\"metadata && (isPrerequisiteMissing || isTestDataMissing)\" type=\"button\"\n class=\"cqa-text-sm cqa-text-primary-hover cqa-font-medium cqa-inline-flex cqa-items-center cqa-gap-1 cqa-cursor-pointer cqa-bg-transparent cqa-border-0 cqa-p-0 cqa-hover:cqa-text-primary cqa-transition-colors\"\n (click)=\"toggleMetadata()\">\n <span>{{ metadataExpanded ? 'Hide details' : 'Show details' }}</span>\n <mat-icon class=\"cqa-w-4 cqa-h-4 cqa-text-[16px] cqa-leading-[16px]\">\n {{ metadataExpanded ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </button>\n\n <!-- Section 5: Sections (toggle visibility) -->\n <div *ngIf=\"metadataExpanded && visibleSections?.length\" class=\"cqa-flex cqa-flex-col cqa-gap-4\">\n <div\n *ngFor=\"let section of visibleSections\"\n class=\"cqa-border cqa-border-gray-200 cqa-rounded-md cqa-bg-white cqa-overflow-hidden\"\n [ngClass]=\"getSectionBorderClass(section)\"\n >\n <div class=\"cqa-p-4 cqa-flex cqa-flex-col cqa-gap-3\">\n <!-- Section Title with Inline Collapse Button -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <h3 [ngClass]=\"getSectionTitleClasses(section)\" class=\"cqa-m-0\">\n {{ section.title }}\n </h3>\n <button\n type=\"button\"\n class=\"cqa-ml-auto cqa-inline-flex cqa-items-center cqa-justify-center cqa-cursor-pointer cqa-bg-transparent cqa-border-0 cqa-p-1 cqa-rounded-full cqa-hover:cqa-bg-gray-100 cqa-transition-colors\"\n (click)=\"toggleSection(section)\"\n [attr.aria-label]=\"section.expanded !== false ? 'Collapse section' : 'Expand section'\"\n >\n <mat-icon [ngClass]=\"getSectionIconColor(section)\" class=\"cqa-w-4 cqa-h-4 cqa-text-[16px] cqa-leading-[16px]\">\n {{ section.expanded !== false ? 'expand_less' : 'expand_more' }}\n </mat-icon>\n </button>\n </div>\n\n <!-- Collapsible Content: Reason and Action Button -->\n <div *ngIf=\"section.expanded !== false\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <!-- Reason -->\n <p class=\"cqa-text-sm cqa-font-normal cqa-leading-4 cqa-text-neutral-600\">\n <strong>Reason:</strong> {{ section.reason }}\n </p>\n \n <!-- Action Button -->\n <div>\n <cqa-button\n variant=\"outlined\"\n (clicked)=\"onSectionAction(section.id)\"\n >\n {{ section.actionButtonLabel }}\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n </div>\n \n <cqa-button\n variant=\"filled\"\n [icon]=\"isApplying ? 'hourglass_empty' : 'auto_awesome'\"\n iconPosition=\"start\"\n (clicked)=\"onMainAction()\"\n [fullWidth]=\"true\"\n [disabled]=\"isApplying\"\n [iconColor]=\"isApplying ? '#EAB308' : undefined\"\n >\n {{ isApplying ? 'Applying suggestion' : 'Apply suggestion' }}\n </cqa-button>\n </div>\n</div>\n \n", styles: [] }]
2635
+ }], propDecorators: { title: [{
2636
+ type: Input
2637
+ }], description: [{
2638
+ type: Input
2639
+ }], badges: [{
2640
+ type: Input
2641
+ }], metadata: [{
2642
+ type: Input
2643
+ }], prerequisiteSection: [{
2644
+ type: Input
2645
+ }], testDataSection: [{
2646
+ type: Input
2647
+ }], metadataExpanded: [{
2648
+ type: Input
2649
+ }], isPrerequisiteMissing: [{
2650
+ type: Input
2651
+ }], isTestDataMissing: [{
2652
+ type: Input
2653
+ }], metadataToggle: [{
2654
+ type: Output
2655
+ }], sectionToggle: [{
2656
+ type: Output
2657
+ }], sectionActionClick: [{
2658
+ type: Output
2659
+ }], onApplySuggestionClick: [{
2660
+ type: Output
2661
+ }], onAttachPrerequisitesClick: [{
2662
+ type: Output
2663
+ }], onImportTestDataClick: [{
2664
+ type: Output
2665
+ }] } });
2666
+
2667
+ class DropdownButtonComponent {
2668
+ constructor() {
2669
+ this.label = 'Select an option';
2670
+ this.options = [];
2671
+ this.disabled = false;
2672
+ this.selectionChange = new EventEmitter();
2673
+ this.opened = new EventEmitter();
2674
+ this.closed = new EventEmitter();
2675
+ this.isOpen = false;
2676
+ this.clickInside = false;
2677
+ }
2678
+ get displayLabel() {
2679
+ if (this.selectedValue !== undefined && this.selectedValue !== null) {
2680
+ const selectedOption = this.options.find(opt => opt.value === this.selectedValue);
2681
+ return selectedOption ? selectedOption.label : this.label;
2682
+ }
2683
+ return this.placeholder || this.label;
2684
+ }
2685
+ get buttonClasses() {
2686
+ const baseClasses = [
2687
+ 'cqa-h-9',
2688
+ 'cqa-px-3',
2689
+ 'cqa-py-2',
2690
+ 'cqa-bg-gray-100',
2691
+ 'cqa-rounded-[5px]',
2692
+ 'cqa-outline',
2693
+ 'cqa-outline-1',
2694
+ 'cqa-outline-offset-[-1px]',
2695
+ 'cqa-outline-gray-200',
2696
+ 'cqa-inline-flex',
2697
+ 'cqa-justify-center',
2698
+ 'cqa-items-center',
2699
+ 'cqa-gap-1',
2700
+ 'cqa-cursor-pointer',
2701
+ 'cqa-transition-colors'
2702
+ ];
2703
+ if (this.disabled) {
2704
+ baseClasses.push('cqa-opacity-50', 'cqa-cursor-not-allowed');
2705
+ }
2706
+ else {
2707
+ baseClasses.push('cqa-hover:cqa-bg-gray-200');
2708
+ }
2709
+ if (this.isOpen) {
2710
+ baseClasses.push('cqa-bg-gray-200');
2711
+ }
2712
+ return baseClasses.join(' ');
2713
+ }
2714
+ get labelClasses() {
2715
+ return [
2716
+ 'cqa-text-center',
2717
+ 'cqa-justify-center',
2718
+ 'cqa-text-gray-950',
2719
+ 'cqa-text-xs',
2720
+ 'cqa-font-medium',
2721
+ 'cqa-leading-4'
2722
+ ].join(' ');
2723
+ }
2724
+ get arrowClasses() {
2725
+ const baseClasses = [
2726
+ 'cqa-w-4',
2727
+ 'cqa-h-4',
2728
+ 'cqa-relative',
2729
+ 'cqa-transition-transform'
2730
+ ];
2731
+ if (this.isOpen) {
2732
+ baseClasses.push('cqa-rotate-180');
2733
+ }
2734
+ return baseClasses.join(' ');
2735
+ }
2736
+ toggleDropdown(event) {
2737
+ if (this.disabled)
2738
+ return;
2739
+ if (event) {
2740
+ event.stopPropagation();
2741
+ event.preventDefault();
2742
+ this.clickInside = true;
2743
+ }
2744
+ this.isOpen = !this.isOpen;
2745
+ // Reset clickInside flag after a short delay
2746
+ setTimeout(() => {
2747
+ this.clickInside = false;
2748
+ if (this.isOpen) {
2749
+ this.opened.emit();
2750
+ }
2751
+ else {
2752
+ this.closed.emit();
2753
+ }
2754
+ }, 100);
2755
+ }
2756
+ selectOption(option, event) {
2757
+ if (option.disabled)
2758
+ return;
2759
+ if (event) {
2760
+ event.stopPropagation();
2761
+ this.clickInside = true;
2762
+ }
2763
+ this.selectedValue = option.value;
2764
+ this.isOpen = false;
2765
+ this.selectionChange.emit(option.value);
2766
+ this.closed.emit();
2767
+ // Reset flag after selection
2768
+ setTimeout(() => {
2769
+ this.clickInside = false;
2770
+ }, 100);
2771
+ }
2772
+ getButtonWidth() {
2773
+ var _a;
2774
+ if ((_a = this.buttonElement) === null || _a === void 0 ? void 0 : _a.nativeElement) {
2775
+ const width = this.buttonElement.nativeElement.offsetWidth;
2776
+ return width > 0 ? width : 150; // Fallback to 150px if width is 0
2777
+ }
2778
+ return 150; // Default fallback width
2779
+ }
2780
+ getOptionClasses(option) {
2781
+ const baseClasses = [
2782
+ 'cqa-p-1.5',
2783
+ 'cqa-rounded-md',
2784
+ 'cqa-inline-flex',
2785
+ 'cqa-justify-start',
2786
+ 'cqa-items-center',
2787
+ 'cqa-cursor-pointer',
2788
+ 'cqa-transition-colors'
2789
+ ];
2790
+ if (option.disabled) {
2791
+ baseClasses.push('cqa-opacity-50', 'cqa-cursor-not-allowed');
2792
+ }
2793
+ else {
2794
+ baseClasses.push('cqa-hover:cqa-bg-gray-50');
2795
+ }
2796
+ if (this.selectedValue === option.value) {
2797
+ baseClasses.push('cqa-bg-primary-surface');
2798
+ }
2799
+ return baseClasses.join(' ');
2800
+ }
2801
+ onDocumentClick(event) {
2802
+ // Ignore if click was inside the component (button click)
2803
+ if (this.clickInside) {
2804
+ return;
2805
+ }
2806
+ // Use a longer delay to ensure dropdown has time to render
2807
+ setTimeout(() => {
2808
+ var _a, _b;
2809
+ if (!this.isOpen)
2810
+ return;
2811
+ const target = event.target;
2812
+ // Check if click is inside the component container
2813
+ if ((_b = (_a = this.dropdownContainer) === null || _a === void 0 ? void 0 : _a.nativeElement) === null || _b === void 0 ? void 0 : _b.contains(target)) {
2814
+ return;
2815
+ }
2816
+ // Close dropdown if click is outside
2817
+ this.isOpen = false;
2818
+ this.closed.emit();
2819
+ }, 200);
2820
+ }
2821
+ }
2822
+ DropdownButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DropdownButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2823
+ DropdownButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DropdownButtonComponent, selector: "cqa-dropdown-button", inputs: { label: "label", options: "options", selectedValue: "selectedValue", disabled: "disabled", placeholder: "placeholder" }, outputs: { selectionChange: "selectionChange", opened: "opened", closed: "closed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "dropdownContainer", first: true, predicate: ["dropdownContainer"], descendants: true }, { propertyName: "buttonElement", first: true, predicate: ["buttonElement"], descendants: true }], ngImport: i0, template: "<div id=\"cqa-ui-root\" #dropdownContainer style=\"position: relative; display: inline-block; width: auto;\">\n <button\n #buttonElement\n type=\"button\"\n [class]=\"buttonClasses\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown($event)\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-haspopup]=\"true\"\n >\n <div [class]=\"labelClasses\">\n {{ displayLabel }}\n </div>\n <div [class]=\"arrowClasses\">\n <svg\n class=\"cqa-w-2 cqa-h-1 cqa-absolute cqa-left-[4px] cqa-top-[6px]\"\n viewBox=\"0 0 8 4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M0 0L4 4L8 0\"\n stroke=\"#0B0B0C\"\n stroke-width=\"1.33\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </button>\n\n <!-- Dropdown Menu -->\n <div\n *ngIf=\"isOpen && options && options.length > 0\"\n class=\"cqa-absolute cqa-top-full cqa-left-0 cqa-mt-1 cqa-p-1.5 cqa-bg-white cqa-rounded-lg cqa-shadow-[0px_2px_4px_-2px_rgba(0,0,0,0.10)] cqa-shadow-md cqa-outline cqa-outline-1 cqa-outline-offset-[-1px] cqa-outline-gray-200 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-z-[9999] cqa-w-auto cqa-max-w-[350px]\"\n >\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5 cqa-w-full\">\n <div\n *ngFor=\"let option of options\"\n (click)=\"selectOption(option, $event)\"\n [class]=\"getOptionClasses(option)\"\n class=\"cqa-w-full cqa-whitespace-nowrap\"\n >\n <div class=\"cqa-w-6 cqa-h-4 cqa-pr-2 cqa-inline-flex cqa-flex-col cqa-justify-center cqa-items-center\">\n <mat-icon\n *ngIf=\"selectedValue === option.value\"\n class=\"cqa-w-4 cqa-h-4 cqa-text-primary cqa-text-base cqa-leading-4\"\n >check</mat-icon>\n </div>\n <div class=\"cqa-flex-1 cqa-inline-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-justify-center cqa-text-gray-950 cqa-text-sm cqa-font-normal cqa-leading-5 cqa-font-geist\">\n {{ option.label }}\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n", components: [{ type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
2824
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DropdownButtonComponent, decorators: [{
2825
+ type: Component,
2826
+ args: [{ selector: 'cqa-dropdown-button', template: "<div id=\"cqa-ui-root\" #dropdownContainer style=\"position: relative; display: inline-block; width: auto;\">\n <button\n #buttonElement\n type=\"button\"\n [class]=\"buttonClasses\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown($event)\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-haspopup]=\"true\"\n >\n <div [class]=\"labelClasses\">\n {{ displayLabel }}\n </div>\n <div [class]=\"arrowClasses\">\n <svg\n class=\"cqa-w-2 cqa-h-1 cqa-absolute cqa-left-[4px] cqa-top-[6px]\"\n viewBox=\"0 0 8 4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M0 0L4 4L8 0\"\n stroke=\"#0B0B0C\"\n stroke-width=\"1.33\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </button>\n\n <!-- Dropdown Menu -->\n <div\n *ngIf=\"isOpen && options && options.length > 0\"\n class=\"cqa-absolute cqa-top-full cqa-left-0 cqa-mt-1 cqa-p-1.5 cqa-bg-white cqa-rounded-lg cqa-shadow-[0px_2px_4px_-2px_rgba(0,0,0,0.10)] cqa-shadow-md cqa-outline cqa-outline-1 cqa-outline-offset-[-1px] cqa-outline-gray-200 cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-z-[9999] cqa-w-auto cqa-max-w-[350px]\"\n >\n <div class=\"cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-0.5 cqa-w-full\">\n <div\n *ngFor=\"let option of options\"\n (click)=\"selectOption(option, $event)\"\n [class]=\"getOptionClasses(option)\"\n class=\"cqa-w-full cqa-whitespace-nowrap\"\n >\n <div class=\"cqa-w-6 cqa-h-4 cqa-pr-2 cqa-inline-flex cqa-flex-col cqa-justify-center cqa-items-center\">\n <mat-icon\n *ngIf=\"selectedValue === option.value\"\n class=\"cqa-w-4 cqa-h-4 cqa-text-primary cqa-text-base cqa-leading-4\"\n >check</mat-icon>\n </div>\n <div class=\"cqa-flex-1 cqa-inline-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-justify-center cqa-text-gray-950 cqa-text-sm cqa-font-normal cqa-leading-5 cqa-font-geist\">\n {{ option.label }}\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n", styles: [] }]
2827
+ }], propDecorators: { label: [{
2828
+ type: Input
2829
+ }], options: [{
2830
+ type: Input
2831
+ }], selectedValue: [{
2832
+ type: Input
2833
+ }], disabled: [{
2834
+ type: Input
2835
+ }], placeholder: [{
2836
+ type: Input
2837
+ }], selectionChange: [{
2838
+ type: Output
2839
+ }], opened: [{
2840
+ type: Output
2841
+ }], closed: [{
2842
+ type: Output
2843
+ }], dropdownContainer: [{
2844
+ type: ViewChild,
2845
+ args: ['dropdownContainer', { static: false }]
2846
+ }], buttonElement: [{
2847
+ type: ViewChild,
2848
+ args: ['buttonElement', { static: false }]
2849
+ }], onDocumentClick: [{
2850
+ type: HostListener,
2851
+ args: ['document:click', ['$event']]
2852
+ }] } });
2853
+
2854
+ class HeatErrorMapCellComponent {
2855
+ constructor() {
2856
+ this.type = 'smoke';
2857
+ this.cases = 0;
2858
+ this.defects = 0;
2859
+ this.progress = 0; // Progress value from 0 to 100
2860
+ }
2861
+ get backgroundColorStyle() {
2862
+ switch (this.type) {
2863
+ case 'smoke':
2864
+ return { 'background-color': '#FDBA74' }; // orange-300
2865
+ case 'sanity':
2866
+ return { 'background-color': '#FCD34D' }; // amber-300
2867
+ case 'regression':
2868
+ return { 'background-color': '#A7F3D0' }; // emerald-200
2869
+ case 'revisit':
2870
+ return { 'background-color': '#F4F4F5' }; // zinc-100
2871
+ default:
2872
+ return { 'background-color': '#FDBA74' }; // orange-300
2873
+ }
2874
+ }
2875
+ get progressWidth() {
2876
+ // Clamp progress between 0 and 100
2877
+ const clampedProgress = Math.max(0, Math.min(100, this.progress));
2878
+ return `${clampedProgress}%`;
2879
+ }
2880
+ }
2881
+ HeatErrorMapCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: HeatErrorMapCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2882
+ HeatErrorMapCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: HeatErrorMapCellComponent, selector: "cqa-heat-error-map-cell", inputs: { type: "type", cases: "cases", defects: "defects", progress: "progress" }, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"width: 14rem; height: 6rem; display: inline-flex; justify-content: space-between; align-items: flex-start;\">\n <div class=\"min-w-56 min-h-24 cqa-self-stretch cqa-flex cqa-flex-col cqa-rounded-2xl cqa-justify-start cqa-items-start cqa-gap-4 cqa-p-4\" [ngStyle]=\"backgroundColorStyle\">\n <!-- section 1 -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-px\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-self-stretch cqa-justify-center cqa-text-gray-900 cqa-text-base cqa-font-bold cqa-leading-5 cqa-font-geist\">\n {{ cases }} cases\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-self-stretch cqa-justify-center cqa-text-gray-900 cqa-text-xs cqa-font-normal cqa-leading-4 cqa-font-geist\">\n {{ defects }} defects\n </div>\n </div>\n </div>\n <!-- section 2 -->\n <div class=\"cqa-self-stretch cqa-h-1 cqa-relative cqa-rounded-full cqa-overflow-hidden cqa-bg-white/70\">\n <div \n class=\"cqa-h-1 cqa-left-0 cqa-top-0 cqa-absolute cqa-bg-red-500 cqa-rounded-full\"\n [style.width]=\"progressWidth\"\n ></div>\n </div>\n </div>\n</div>\n\n\n", directives: [{ type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
2883
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: HeatErrorMapCellComponent, decorators: [{
2884
+ type: Component,
2885
+ args: [{ selector: 'cqa-heat-error-map-cell', template: "<div id=\"cqa-ui-root\" style=\"width: 14rem; height: 6rem; display: inline-flex; justify-content: space-between; align-items: flex-start;\">\n <div class=\"min-w-56 min-h-24 cqa-self-stretch cqa-flex cqa-flex-col cqa-rounded-2xl cqa-justify-start cqa-items-start cqa-gap-4 cqa-p-4\" [ngStyle]=\"backgroundColorStyle\">\n <!-- section 1 -->\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start cqa-gap-px\">\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-self-stretch cqa-justify-center cqa-text-gray-900 cqa-text-base cqa-font-bold cqa-leading-5 cqa-font-geist\">\n {{ cases }} cases\n </div>\n </div>\n <div class=\"cqa-self-stretch cqa-flex cqa-flex-col cqa-justify-start cqa-items-start\">\n <div class=\"cqa-self-stretch cqa-justify-center cqa-text-gray-900 cqa-text-xs cqa-font-normal cqa-leading-4 cqa-font-geist\">\n {{ defects }} defects\n </div>\n </div>\n </div>\n <!-- section 2 -->\n <div class=\"cqa-self-stretch cqa-h-1 cqa-relative cqa-rounded-full cqa-overflow-hidden cqa-bg-white/70\">\n <div \n class=\"cqa-h-1 cqa-left-0 cqa-top-0 cqa-absolute cqa-bg-red-500 cqa-rounded-full\"\n [style.width]=\"progressWidth\"\n ></div>\n </div>\n </div>\n</div>\n\n\n", styles: [] }]
2886
+ }], propDecorators: { type: [{
2887
+ type: Input
2888
+ }], cases: [{
2889
+ type: Input
2890
+ }], defects: [{
2891
+ type: Input
2892
+ }], progress: [{
2893
+ type: Input
2894
+ }] } });
2895
+
2896
+ class EmptyStateComponent {
2897
+ constructor() {
2898
+ this.title = '';
2899
+ this.description = '';
2900
+ this.actions = [];
2901
+ this.actionClick = new EventEmitter();
2902
+ }
2903
+ onActionClick(action, event) {
2904
+ if (!action.disabled) {
2905
+ if (action.onClick) {
2906
+ action.onClick();
2907
+ }
2908
+ this.actionClick.emit(action);
2909
+ }
2910
+ }
2911
+ }
2912
+ EmptyStateComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: EmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2913
+ EmptyStateComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: EmptyStateComponent, selector: "cqa-empty-state", inputs: { imageUrl: "imageUrl", title: "title", description: "description", actions: "actions" }, outputs: { actionClick: "actionClick" }, ngImport: i0, template: "<div id=\"cqa-ui-root\" style=\"background-color: white; border-radius: 14px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 84.63px 33px 84.62px 33px;\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-[62px] cqa-items-center\">\n <!-- Icon Container -->\n <div *ngIf=\"imageUrl\" class=\"cqa-relative cqa-shrink-0 cqa-w-32 cqa-h-32\">\n <!-- Main Icon Container with Gradient Background and Shadow -->\n <div class=\"cqa-relative cqa-rounded-3xl cqa-w-32 cqa-h-32 cqa-shadow-sm\">\n <div class=\"cqa-absolute cqa-inset-0 cqa-bg-gradient-to-br cqa-from-indigo-500 cqa-to-violet-950 cqa-rounded-3xl cqa-opacity-10\"></div>\n <!-- Icon/Image centered inside on top layer - fully opaque -->\n <div class=\"cqa-absolute cqa-inset-0 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-3xl\">\n <div class=\"cqa-w-20 cqa-h-20 cqa-flex cqa-items-center cqa-justify-center cqa-relative\">\n <img [src]=\"imageUrl\" alt=\"\" width=\"80px\" height=\"80px\" class=\"cqa-block cqa-max-w-none cqa-w-20 cqa-h-20 cqa-object-contain\" />\n </div>\n </div>\n </div>\n <!-- Decorative Dots -->\n <div class=\"cqa-absolute cqa-rounded-full cqa-bg-primary-300 cqa-opacity-[0.815]\" style=\"left: 120.79px; top: -9.21px; width: 18.416px; height: 18.416px; z-index: 20;\"></div>\n <div class=\"cqa-absolute cqa-rounded-full cqa-bg-primary-300 cqa-opacity-[0.695]\" style=\"left: -9.02px; top: 124.98px; width: 14.044px; height: 14.044px; z-index: 20;\"></div>\n </div>\n\n <!-- Content Container -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-9 cqa-items-center\">\n <!-- Title and Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-items-center cqa-w-full\">\n <!-- Title -->\n <div *ngIf=\"title\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-w-full\">\n <h3 class=\"cqa-font-inter cqa-text-lg cqa-font-medium cqa-leading-[18px] cqa-text-center cqa-text-neutral-900\">\n {{ title }}\n </h3>\n </div>\n <!-- Description -->\n <div *ngIf=\"description\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-w-full\">\n <p class=\"cqa-font-inter cqa-font-medium cqa-text-sm cqa-leading-[14px] cqa-text-center cqa-text-neutral-500\">\n {{ description }}\n </p>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div\n *ngIf=\"actions && actions.length > 0\"\n class=\"cqa-flex cqa-items-center cqa-justify-center\"\n [ngClass]=\"actions.length > 1 ? 'cqa-flex-row cqa-flex-wrap cqa-gap-4' : 'cqa-flex-col cqa-gap-2'\"\n >\n <cqa-button\n *ngFor=\"let action of actions\"\n [variant]=\"action.variant || 'filled'\"\n [icon]=\"action.icon\"\n [iconPosition]=\"action.iconPosition || 'start'\"\n [disabled]=\"action.disabled\"\n (clicked)=\"onActionClick(action, $event)\"\n >\n {{ action.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n</div>\n\n", components: [{ type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
2914
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: EmptyStateComponent, decorators: [{
2915
+ type: Component,
2916
+ args: [{ selector: 'cqa-empty-state', template: "<div id=\"cqa-ui-root\" style=\"background-color: white; border-radius: 14px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 84.63px 33px 84.62px 33px;\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-[62px] cqa-items-center\">\n <!-- Icon Container -->\n <div *ngIf=\"imageUrl\" class=\"cqa-relative cqa-shrink-0 cqa-w-32 cqa-h-32\">\n <!-- Main Icon Container with Gradient Background and Shadow -->\n <div class=\"cqa-relative cqa-rounded-3xl cqa-w-32 cqa-h-32 cqa-shadow-sm\">\n <div class=\"cqa-absolute cqa-inset-0 cqa-bg-gradient-to-br cqa-from-indigo-500 cqa-to-violet-950 cqa-rounded-3xl cqa-opacity-10\"></div>\n <!-- Icon/Image centered inside on top layer - fully opaque -->\n <div class=\"cqa-absolute cqa-inset-0 cqa-flex cqa-items-center cqa-justify-center cqa-rounded-3xl\">\n <div class=\"cqa-w-20 cqa-h-20 cqa-flex cqa-items-center cqa-justify-center cqa-relative\">\n <img [src]=\"imageUrl\" alt=\"\" width=\"80px\" height=\"80px\" class=\"cqa-block cqa-max-w-none cqa-w-20 cqa-h-20 cqa-object-contain\" />\n </div>\n </div>\n </div>\n <!-- Decorative Dots -->\n <div class=\"cqa-absolute cqa-rounded-full cqa-bg-primary-300 cqa-opacity-[0.815]\" style=\"left: 120.79px; top: -9.21px; width: 18.416px; height: 18.416px; z-index: 20;\"></div>\n <div class=\"cqa-absolute cqa-rounded-full cqa-bg-primary-300 cqa-opacity-[0.695]\" style=\"left: -9.02px; top: 124.98px; width: 14.044px; height: 14.044px; z-index: 20;\"></div>\n </div>\n\n <!-- Content Container -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-9 cqa-items-center\">\n <!-- Title and Description -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 cqa-items-center cqa-w-full\">\n <!-- Title -->\n <div *ngIf=\"title\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-w-full\">\n <h3 class=\"cqa-font-inter cqa-text-lg cqa-font-medium cqa-leading-[18px] cqa-text-center cqa-text-neutral-900\">\n {{ title }}\n </h3>\n </div>\n <!-- Description -->\n <div *ngIf=\"description\" class=\"cqa-flex cqa-flex-col cqa-items-center cqa-w-full\">\n <p class=\"cqa-font-inter cqa-font-medium cqa-text-sm cqa-leading-[14px] cqa-text-center cqa-text-neutral-500\">\n {{ description }}\n </p>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div\n *ngIf=\"actions && actions.length > 0\"\n class=\"cqa-flex cqa-items-center cqa-justify-center\"\n [ngClass]=\"actions.length > 1 ? 'cqa-flex-row cqa-flex-wrap cqa-gap-4' : 'cqa-flex-col cqa-gap-2'\"\n >\n <cqa-button\n *ngFor=\"let action of actions\"\n [variant]=\"action.variant || 'filled'\"\n [icon]=\"action.icon\"\n [iconPosition]=\"action.iconPosition || 'start'\"\n [disabled]=\"action.disabled\"\n (clicked)=\"onActionClick(action, $event)\"\n >\n {{ action.label }}\n </cqa-button>\n </div>\n </div>\n </div>\n</div>\n\n", styles: [] }]
2917
+ }], propDecorators: { imageUrl: [{
2918
+ type: Input
2919
+ }], title: [{
2920
+ type: Input
2921
+ }], description: [{
2922
+ type: Input
2923
+ }], actions: [{
2924
+ type: Input
2925
+ }], actionClick: [{
2926
+ type: Output
2927
+ }] } });
2928
+
2929
+ /**
2930
+ * Image assets constants for the UI library
2931
+ *
2932
+ * Place your image files in src/lib/assets/images/ and reference them here
2933
+ *
2934
+ * Usage in components:
2935
+ * import { EMPTY_STATE_IMAGES } from '../assets/images/image-assets.constants';
2936
+ * imageUrl: EMPTY_STATE_IMAGES.TEST_CASE
2937
+ */
2938
+ const EMPTY_STATE_IMAGES = {
2939
+ // Test Case icon (document with gear)
2940
+ TEST_CASE: 'assets/images/TestCaseIcon.png',
2941
+ // Search/Debug icon (magnifying glass with question mark)
2942
+ SEARCH_DEBUG: 'assets/images/SearchIcon.png',
2943
+ // Upload/Folder icon (folder with upload arrow and plus)
2944
+ UPLOAD_FOLDER: 'assets/images/FilesIcon.png',
2945
+ // Dashboard overview
2946
+ DASHBOARD: 'assets/images/DashboardIcon.png',
2947
+ // Checklist/Add icon (clipboard with plus)
2948
+ CHECKLIST_ADD: 'assets/images/StepsIcon.png',
2949
+ // Document/Gear icon (document with gear overlay)
2950
+ DOCUMENT_GEAR: 'assets/images/document-gear-icon.svg',
2951
+ // Analytics/Chart icon (bar chart)
2952
+ ANALYTICS_CHART: 'assets/images/ReportsIcon.png',
2953
+ // Default empty state icon
2954
+ DEFAULT: 'assets/images/SearchIcon.png',
2955
+ };
2956
+
2957
+ class TableTemplateComponent {
2958
+ constructor() {
2959
+ // Search bar inputs
2960
+ this.searchPlaceholder = 'Search components';
2961
+ this.searchValue = '';
2962
+ this.showClear = true;
2963
+ this.showSearchBar = true;
2964
+ // Filter inputs
2965
+ this.filterConfig = [];
2966
+ this.showFilterPanel = false;
2967
+ this.showFilterButton = true;
2968
+ // Other button input
2969
+ this.otherButtonLabel = 'Other Button';
2970
+ this.otherButtonVariant = 'filled';
2971
+ this.showOtherButton = true;
2972
+ // Action menu button (three-dot menu in table rows)
2973
+ this.showActionButton = true;
2974
+ // Settings and refresh buttons
2975
+ this.showSettingsButton = true;
2976
+ this.showAutoRefreshButton = true;
2977
+ // Data input
2978
+ this.data = [];
2979
+ // Empty state inputs
2980
+ this.isEmptyState = false;
2981
+ this.emptyStateConfig = {
2982
+ title: 'No Data Available Yet',
2983
+ description: 'Run or upload your first test to see your analytics and trends here. Watch your quality metrics come to life with real-time insights.',
2984
+ imageUrl: EMPTY_STATE_IMAGES.DASHBOARD,
2985
+ actions: [{ label: 'Run Test Suite', variant: 'filled' }],
2986
+ };
2987
+ // Action bar inputs
2988
+ this.actions = [
2989
+ {
2990
+ id: 'delete',
2991
+ label: 'Delete',
2992
+ icon: 'delete',
2993
+ tooltip: 'Delete selected',
2994
+ onClick: (context) => {
2995
+ console.log('Delete action clicked:', context);
2996
+ }
2997
+ },
2998
+ {
2999
+ id: 'edit',
3000
+ label: 'Edit',
3001
+ icon: 'edit',
3002
+ tooltip: 'Edit selected',
3003
+ onClick: (context) => {
3004
+ console.log('Edit action clicked:', context);
3005
+ }
3006
+ },
3007
+ {
3008
+ id: 'add-tag',
3009
+ label: 'Add Tag',
3010
+ icon: 'local_offer',
3011
+ tooltip: 'Add tags',
3012
+ onClick: (context) => {
3013
+ console.log('Add tag action clicked:', context);
3014
+ }
3015
+ },
3016
+ {
3017
+ id: 'remove-tag',
3018
+ label: 'Remove Tag',
3019
+ icon: 'label_off',
3020
+ tooltip: 'Remove tags',
3021
+ onClick: (context) => {
3022
+ console.log('Remove tag action clicked:', context);
3023
+ }
3024
+ },
3025
+ ];
3026
+ // Chips inputs
3027
+ this.chips = [];
3028
+ this.filterApplied = false;
3029
+ // Table inputs
3030
+ this.columns = [];
3031
+ this.selectedAutoRefreshInterval = 0;
3032
+ this.pageIndex = 0;
3033
+ this.pageSize = 10;
3034
+ // Backward-compatibility flag; if provided, dynamic table will use it when specific flags are undefined
3035
+ // Internal state for column visibility
3036
+ this._columnVisibility = {};
3037
+ this._cachedVisibilityColumns = [];
3038
+ this.filteredRows = [];
3039
+ this.pagedRows = [];
3040
+ }
3041
+ // Derived columns with visibility applied. Avoid mutating @Input() columns so parent bindings aren't overridden.
3042
+ get computedColumns() {
3043
+ const visibility = this._columnVisibility || {};
3044
+ const source = this.columns || [];
3045
+ return source.map(col => {
3046
+ if (['checkbox', 'actions'].includes(col.fieldId)) {
3047
+ return col;
3048
+ }
3049
+ const show = visibility[col.fieldId];
3050
+ return Object.assign(Object.assign({}, col), { isShow: show !== false });
3051
+ });
3052
+ }
3053
+ // Auto-generated visibility columns from columns input (excludes default columns and checkbox/actions)
3054
+ // Cached to avoid creating new arrays on every change detection cycle
3055
+ get visibilityColumns() {
3056
+ return this._cachedVisibilityColumns;
3057
+ }
3058
+ // Internal column visibility state
3059
+ get columnVisibility() {
3060
+ return this._columnVisibility;
3061
+ }
3062
+ ngOnInit() {
3063
+ this.initializeComponent();
3064
+ }
3065
+ ngOnChanges(changes) {
3066
+ if (changes['data'] || changes['isEmptyState']) {
3067
+ this.initializeComponent();
3068
+ }
3069
+ if (changes['columns']) {
3070
+ this.initializeColumnVisibility();
3071
+ }
3072
+ }
3073
+ initializeComponent() {
3074
+ if (this.isEmptyState) {
3075
+ this.filteredRows = [];
3076
+ this.pagedRows = [];
3077
+ return;
3078
+ }
3079
+ this.filteredRows = [...this.data];
3080
+ this.applyPagination();
3081
+ this.initializeColumnVisibility();
3082
+ }
3083
+ initializeColumnVisibility() {
3084
+ // Cache visibility columns to avoid creating new arrays on every change detection
3085
+ this._cachedVisibilityColumns = this.mapVisibilityColumns();
3086
+ // Initialize visibility state for all visibility columns (default to true)
3087
+ for (const col of this._cachedVisibilityColumns) {
3088
+ if (this._columnVisibility[col.id] === undefined) {
3089
+ this._columnVisibility[col.id] = true;
3090
+ }
3091
+ }
3092
+ }
3093
+ get anyRowSelected() {
3094
+ return !!(this.pagedRows && this.pagedRows.some(r => !!r.isSelected));
3095
+ }
3096
+ get currentSelectedItems() {
3097
+ return (this.pagedRows || []).filter(r => !!r.isSelected);
3098
+ }
3099
+ actionClick(data) {
3100
+ console.log('action toolbar', data);
3101
+ }
3102
+ view(id) {
3103
+ console.log('View', id);
3104
+ }
3105
+ edit(row) {
3106
+ console.log('Edit', row);
3107
+ }
3108
+ delete(row) {
3109
+ console.log('Delete', row);
3110
+ }
3111
+ onRowCheckboxChange(event, row) {
3112
+ const input = event.target;
3113
+ const checked = !!(input === null || input === void 0 ? void 0 : input.checked);
3114
+ row.isSelected = checked;
3115
+ }
3116
+ toggleFilter() {
3117
+ this.showFilterPanel = !this.showFilterPanel;
3118
+ }
3119
+ onColumnVisibilityChange(cfg) {
3120
+ this._columnVisibility = Object.assign({}, cfg);
3121
+ // Do not mutate this.columns; computedColumns getter will reflect changes
3122
+ }
3123
+ onAutoRefreshChange(intervalMs) {
3124
+ this.selectedAutoRefreshInterval = intervalMs;
3125
+ console.log('Auto refresh interval', intervalMs);
3126
+ }
3127
+ valueChange(value) {
3128
+ console.log('Value changed', value);
3129
+ }
3130
+ search(value) {
3131
+ console.log('Search', value);
3132
+ }
3133
+ cleared() {
3134
+ console.log('Cleared');
3135
+ }
3136
+ resultBadgeClass(result) {
3137
+ const value = (result || '').toUpperCase();
3138
+ if (value === 'SUCCESS')
3139
+ return 'cqa-bg-green-100 cqa-text-green-700';
3140
+ if (value === 'FAILURE' || value === 'ABORTED')
3141
+ return 'cqa-bg-red-100 cqa-text-red-700';
3142
+ if (value === 'QUEUED' || value === 'NOT_EXECUTED' || value === 'STOPPED')
3143
+ return 'cqa-bg-gray-100 cqa-text-gray-700';
3144
+ return 'cqa-bg-gray-100 cqa-text-gray-700';
3145
+ }
3146
+ onEmptyAction(action) {
3147
+ if ((action === null || action === void 0 ? void 0 : action.label) === 'Show filters') {
3148
+ this.toggleFilter();
3149
+ }
3150
+ }
3151
+ onFiltersChanged(current) {
3152
+ var _a, _b, _c;
3153
+ this.filteredRows = this.data.filter(r => this.passFilters(current, r));
3154
+ this.pageIndex = 0;
3155
+ this.applyPagination();
3156
+ const chips = [];
3157
+ if (current) {
3158
+ for (const key of Object.keys(current)) {
3159
+ const value = current[key];
3160
+ if (value == null || value === '' || (Array.isArray(value) && value.length === 0))
3161
+ continue;
3162
+ let text = '';
3163
+ if (Array.isArray(value)) {
3164
+ text = value.map((v) => { var _a, _b, _c; return ((_c = (_b = (_a = v === null || v === void 0 ? void 0 : v.name) !== null && _a !== void 0 ? _a : v === null || v === void 0 ? void 0 : v.label) !== null && _b !== void 0 ? _b : v === null || v === void 0 ? void 0 : v.value) !== null && _c !== void 0 ? _c : v); }).join(', ');
3165
+ }
3166
+ else if (typeof value === 'object') {
3167
+ if ('start' in value || 'end' in value) {
3168
+ const s = value.start ? new Date(value.start).toLocaleDateString() : '';
3169
+ const e = value.end ? new Date(value.end).toLocaleDateString() : '';
3170
+ text = [s, e].filter(Boolean).join(' - ');
3171
+ }
3172
+ else {
3173
+ text = ((_c = (_b = (_a = value === null || value === void 0 ? void 0 : value.name) !== null && _a !== void 0 ? _a : value === null || value === void 0 ? void 0 : value.label) !== null && _b !== void 0 ? _b : value === null || value === void 0 ? void 0 : value.value) !== null && _c !== void 0 ? _c : JSON.stringify(value));
3174
+ }
3175
+ }
3176
+ else {
3177
+ text = String(value);
3178
+ }
3179
+ chips.push({ key, text, fullText: text, hasMore: text.length > 30 });
3180
+ }
3181
+ }
3182
+ this.chips = chips;
3183
+ this.filterApplied = this.chips.length > 0;
3184
+ }
3185
+ onFiltersApplied(_) {
3186
+ // handled in onFiltersChanged for this demo
3187
+ }
3188
+ onPaginate(e) {
3189
+ this.pageIndex = e.pageIndex;
3190
+ this.pageSize = e.pageSize;
3191
+ this.applyPagination();
3192
+ }
3193
+ onPageSizeChange(size) {
3194
+ this.pageSize = size;
3195
+ this.pageIndex = 0;
3196
+ this.applyPagination();
3197
+ }
3198
+ onRemoveChip(chip) {
3199
+ this.chips = this.chips.filter(c => c !== chip);
3200
+ this.filterApplied = this.chips.length > 0;
3201
+ }
3202
+ onClearAllChips() {
3203
+ this.chips = [];
3204
+ this.filterApplied = false;
3205
+ }
3206
+ applyPagination() {
3207
+ const start = this.pageIndex * this.pageSize;
3208
+ const end = start + this.pageSize;
3209
+ this.pagedRows = this.filteredRows.slice(start, end);
3210
+ }
3211
+ mapVisibilityColumns() {
3212
+ return (this.columns || [])
3213
+ .filter(c => c.isDefault === false)
3214
+ .map(c => ({ id: c.fieldId, label: c.fieldName || c.fieldId }));
3215
+ }
3216
+ normalizeDate(d) {
3217
+ if (!d)
3218
+ return null;
3219
+ const ts = Date.parse(d);
3220
+ return isNaN(ts) ? null : ts;
3221
+ }
3222
+ passFilters(filters, row) {
3223
+ if (!filters)
3224
+ return true;
3225
+ if (filters.status && Array.isArray(filters.status) && filters.status.length) {
3226
+ if (!filters.status.includes(row.status))
3227
+ return false;
3228
+ }
3229
+ if (filters.priority && Array.isArray(filters.priority) && filters.priority.length) {
3230
+ if (!filters.priority.includes(row.priorityName))
3231
+ return false;
3232
+ }
3233
+ if (filters.testType && Array.isArray(filters.testType) && filters.testType.length) {
3234
+ if (!filters.testType.includes(row.testType))
3235
+ return false;
3236
+ }
3237
+ if (filters.created_date && (filters.created_date.start || filters.created_date.end)) {
3238
+ const startTs = this.normalizeDate(filters.created_date.start);
3239
+ const endTs = this.normalizeDate(filters.created_date.end);
3240
+ const rowTs = this.normalizeDate(row.createdAt);
3241
+ if (rowTs != null) {
3242
+ if (startTs != null && rowTs < startTs)
3243
+ return false;
3244
+ if (endTs != null && rowTs > endTs)
3245
+ return false;
3246
+ }
3247
+ }
3248
+ return true;
3249
+ }
3250
+ }
3251
+ TableTemplateComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableTemplateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3252
+ TableTemplateComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: TableTemplateComponent, selector: "cqa-table-template", inputs: { searchPlaceholder: "searchPlaceholder", searchValue: "searchValue", showClear: "showClear", showSearchBar: "showSearchBar", filterConfig: "filterConfig", showFilterPanel: "showFilterPanel", showFilterButton: "showFilterButton", otherButtonLabel: "otherButtonLabel", otherButtonVariant: "otherButtonVariant", showOtherButton: "showOtherButton", showActionButton: "showActionButton", showSettingsButton: "showSettingsButton", showAutoRefreshButton: "showAutoRefreshButton", data: "data", isEmptyState: "isEmptyState", emptyStateConfig: "emptyStateConfig", actions: "actions", chips: "chips", filterApplied: "filterApplied", columns: "columns", selectedAutoRefreshInterval: "selectedAutoRefreshInterval", pageIndex: "pageIndex", pageSize: "pageSize", isTableLoading: "isTableLoading", isTableDataLoading: "isTableDataLoading" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-flex cqa-flex-col cqa-relative\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-gap-3 cqa-flex-wrap cqa-mb-3\">\n <cqa-search-bar\n *ngIf=\"showSearchBar\"\n [placeholder]=\"searchPlaceholder\"\n [value]=\"searchValue\"\n [showClear]=\"showClear\"\n (valueChange)=\"valueChange($event)\"\n (search)=\"search($event)\"\n (cleared)=\"cleared()\"\n ></cqa-search-bar>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-flex-wrap\">\n <cqa-button\n *ngIf=\"showFilterButton\"\n variant=\"grey-solid\"\n icon=\"add\"\n [text]=\"'Filter'\"\n (clicked)=\"toggleFilter()\"\n >\n <span>Filter</span>\n </cqa-button>\n <cqa-column-visibility\n *ngIf=\"showSettingsButton\"\n [columns]=\"visibilityColumns\"\n [columnVisibility]=\"columnVisibility\"\n [selectedAutoRefreshInterval]=\"selectedAutoRefreshInterval\"\n (columnVisibilityChange)=\"onColumnVisibilityChange($event)\"\n (autoRefreshChange)=\"onAutoRefreshChange($event)\"\n ></cqa-column-visibility>\n <cqa-button *ngIf=\"showAutoRefreshButton\" variant=\"grey-solid\" icon=\"refresh\"></cqa-button>\n <cqa-button *ngIf=\"showOtherButton\" [variant]=\"otherButtonVariant\" [text]=\"otherButtonLabel\"></cqa-button>\n </div>\n </div>\n\n <cqa-selected-filters \n *ngIf=\"showFilterPanel\"\n [filterApplied]=\"filterApplied\"\n [chips]=\"chips\"\n (removeChip)=\"onRemoveChip($event)\"\n (clearAll)=\"onClearAllChips()\"\n >\n </cqa-selected-filters>\n\n <cqa-dynamic-filter\n *ngIf=\"showFilterPanel\"\n [config]=\"filterConfig\"\n [showFilterPanel]=\"showFilterPanel\"\n (filtersChanged)=\"onFiltersChanged($event)\"\n (filtersApplied)=\"onFiltersApplied($event)\"\n >\n </cqa-dynamic-filter>\n\n <div class=\"cqa-rounded-[7px] cqa-overflow-hidden cqa-border-t cqa-border-l cqa-border-r cqa-border-grey-200 cqa-relative\">\n <ng-container *ngIf=\"!isEmptyState && pagedRows && pagedRows.length > 0; else storyEmptyTpl\">\n <app-dynamic-table\n [columns]=\"computedColumns\"\n [data]=\"pagedRows\"\n [isTableLoading]=\"isTableLoading\"\n [isTableDataLoading]=\"isTableDataLoading\">\n <ng-template dynamicCell=\"checkbox\" let-row=\"row\">\n <div class=\"custom-checkbox\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + row.id\"\n [checked]=\"row.isSelected\"\n aria-label=\"Select row\"\n (change)=\"onRowCheckboxChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [attr.for]=\"'row-checkbox-' + row.id\">\n </label>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"testCases\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium\">\n <div class=\"cqa-text-[#3F43EE] cqa-truncate\">\n #{{ row.id }}\n </div>\n <div class=\"cqa-text-[#0A0A0A]\">{{ value }}</div>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"type\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-text-xs cqa-text-[#111827] cqa-truncate\">{{ value }}</div>\n </ng-template>\n\n <ng-template dynamicCell=\"priority\" let-row=\"row\" let-value=\"value\">\n <span\n class=\"cqa-inline-flex cqa-items-center cqa-px-2 cqa-py-0.5 cqa-rounded cqa-text-xs\"\n [ngClass]=\"{\n 'cqa-bg-red-100 cqa-text-red-700': value === 'Critical' || value === 'Major',\n 'cqa-bg-yellow-100 cqa-text-yellow-700': value === 'Medium',\n 'cqa-bg-blue-100 cqa-text-blue-700': value === 'Minor',\n 'cqa-bg-gray-100 cqa-text-gray-700': !value || value === 'Not Set'\n }\"\n >{{ value || 'Not Set' }}</span\n >\n </ng-template>\n\n <ng-template dynamicCell=\"result\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-inline-flex cqa-items-center cqa-px-2 cqa-py-0.5 cqa-rounded cqa-text-xs\" [ngClass]=\"resultBadgeClass(value)\">\n {{ value || 'NOT_EXECUTED' }}\n </span>\n </ng-template>\n\n <ng-template dynamicCell=\"status\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs\">{{ value }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"labels\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-1\">\n <span *ngFor=\"let tag of (row.tags || []) | slice: 0:3\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded cqa-bg-gray-100 cqa-text-gray-700 cqa-text-xs\">\n {{ tag }}\n </span>\n <span *ngIf=\"(row.tags?.length || 0) > 3\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded cqa-bg-gray-100 cqa-text-gray-700 cqa-text-xs\">\n +{{ (row.tags?.length || 0) - 3 }} more\n </span>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"createdBy\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs\">{{ value }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"createdAt\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs cqa-text-gray-700\">{{ value | date: 'medium' }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"updatedAt\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs cqa-text-gray-700\">{{ value | date: 'medium' }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"lastRun\" let-row=\"row\">\n <div class=\"cqa-flex cqa-flex-col\">\n <span class=\"cqa-text-xs cqa-text-[#111827]\">{{ row.lastRun?.startTime | date: 'medium' }}</span>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"actions\" let-row=\"row\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" *ngIf=\"showActionButton\">\n <cqa-action-menu-button\n [row]=\"row\"\n (view)=\"view($event)\"\n (edit)=\"edit($event)\"\n (delete)=\"delete($event)\"\n ></cqa-action-menu-button>\n </div>\n </ng-template>\n\n <ng-template #emptyTableTpl>\n <div class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-py-8\">\n <img src=\"/assets/illustrations/empty-state.svg\" alt=\"No data\" class=\"cqa-w-32 cqa-h-32 cqa-mb-4\" />\n <h3 class=\"cqa-text-lg cqa-font-semibold cqa-mb-2\">No test cases</h3>\n <p class=\"cqa-text-sm cqa-text-neutral-500 cqa-mb-4\">Try adjusting filters or create a new test case.</p>\n <cqa-button variant=\"filled\" (clicked)=\"toggleFilter()\">Show Filters</cqa-button>\n </div>\n </ng-template>\n </app-dynamic-table>\n </ng-container>\n\n <ng-template #storyEmptyTpl>\n <div class=\"cqa-p-6 cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <cqa-empty-state\n *ngIf=\"isEmptyState\"\n [title]=\"emptyStateConfig.title\"\n [description]=\"emptyStateConfig.description\"\n [imageUrl]=\"emptyStateConfig.imageUrl\"\n [actions]=\"emptyStateConfig.actions\"\n (actionClick)=\"onEmptyAction($event)\"\n >\n </cqa-empty-state>\n </div>\n </ng-template>\n\n </div>\n\n <cqa-pagination\n [totalElements]=\"filteredRows.length\"\n [pageIndex]=\"pageIndex\"\n [pageSize]=\"pageSize\"\n [pageItemCount]=\"pagedRows.length\"\n (paginate)=\"onPaginate($event)\"\n (pageSizeChange)=\"onPageSizeChange($event)\"\n >\n </cqa-pagination>\n\n <div *ngIf=\"anyRowSelected\" class=\"cqa-absolute cqa-bottom-[18.75px] cqa-left-[50%] cqa-translate-x-[-50%] cqa-w-full lg:cqa-max-w-[68%] cqa-sm:max-w-[75%] cqa-max-w-[90%] cqa-z-[1]\" >\n <cqa-table-action-toolbar\n [selectedItems]=\"currentSelectedItems\"\n [actions]=\"actions\"\n (actionClick)=\"actionClick($event)\"\n ></cqa-table-action-toolbar>\n </div>\n \n </div>\n</div>\n\n", components: [{ type: SearchBarComponent, selector: "cqa-search-bar", inputs: ["placeholder", "value", "disabled", "showClear", "ariaLabel", "autoFocus", "size", "fullWidth"], outputs: ["valueChange", "search", "cleared"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass"], outputs: ["clicked"] }, { type: ColumnVisibilityComponent, selector: "cqa-column-visibility", inputs: ["isStepGroup", "columns", "columnVisibility", "selectedAutoRefreshInterval"], outputs: ["columnVisibilityChange", "autoRefreshChange"] }, { type: SelectedFiltersComponent, selector: "cqa-selected-filters", inputs: ["filterApplied", "chips"], outputs: ["removeChip", "clearAll"] }, { type: DynamicFilterComponent, selector: "cqa-dynamic-filter", inputs: ["config", "model", "showFilterPanel"], outputs: ["filtersApplied", "filtersChanged", "resetAction"] }, { type: DynamicTableComponent, selector: "app-dynamic-table", inputs: ["data", "columns", "emptyState", "gridTemplateColumns", "screenWidth", "enableSelectAll", "enableLocalSort", "isTableLoading", "isTableDataLoading"], outputs: ["sortChange"] }, { type: ActionMenuButtonComponent, selector: "cqa-action-menu-button", inputs: ["row"], outputs: ["view", "edit", "delete"] }, { type: EmptyStateComponent, selector: "cqa-empty-state", inputs: ["imageUrl", "title", "description", "actions"], outputs: ["actionClick"] }, { type: PaginationComponent, selector: "cqa-pagination", inputs: ["totalElements", "totalPages", "pageIndex", "pageSize", "pageItemCount", "pageSizeOptions"], outputs: ["pageIndexChange", "pageSizeChange", "paginate"] }, { type: TableActionToolbarComponent, selector: "cqa-table-action-toolbar", inputs: ["selectedItems", "actions"], outputs: ["actionClick"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: DynamicCellTemplateDirective, selector: "ng-template[dynamicCell]", inputs: ["dynamicCell"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "slice": i2.SlicePipe, "date": i2.DatePipe } });
3253
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TableTemplateComponent, decorators: [{
3254
+ type: Component,
3255
+ args: [{ selector: 'cqa-table-template', template: "<div id=\"cqa-ui-root\">\n <div class=\"cqa-w-full cqa-flex cqa-flex-col cqa-relative\">\n <div class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-gap-3 cqa-flex-wrap cqa-mb-3\">\n <cqa-search-bar\n *ngIf=\"showSearchBar\"\n [placeholder]=\"searchPlaceholder\"\n [value]=\"searchValue\"\n [showClear]=\"showClear\"\n (valueChange)=\"valueChange($event)\"\n (search)=\"search($event)\"\n (cleared)=\"cleared()\"\n ></cqa-search-bar>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-flex-wrap\">\n <cqa-button\n *ngIf=\"showFilterButton\"\n variant=\"grey-solid\"\n icon=\"add\"\n [text]=\"'Filter'\"\n (clicked)=\"toggleFilter()\"\n >\n <span>Filter</span>\n </cqa-button>\n <cqa-column-visibility\n *ngIf=\"showSettingsButton\"\n [columns]=\"visibilityColumns\"\n [columnVisibility]=\"columnVisibility\"\n [selectedAutoRefreshInterval]=\"selectedAutoRefreshInterval\"\n (columnVisibilityChange)=\"onColumnVisibilityChange($event)\"\n (autoRefreshChange)=\"onAutoRefreshChange($event)\"\n ></cqa-column-visibility>\n <cqa-button *ngIf=\"showAutoRefreshButton\" variant=\"grey-solid\" icon=\"refresh\"></cqa-button>\n <cqa-button *ngIf=\"showOtherButton\" [variant]=\"otherButtonVariant\" [text]=\"otherButtonLabel\"></cqa-button>\n </div>\n </div>\n\n <cqa-selected-filters \n *ngIf=\"showFilterPanel\"\n [filterApplied]=\"filterApplied\"\n [chips]=\"chips\"\n (removeChip)=\"onRemoveChip($event)\"\n (clearAll)=\"onClearAllChips()\"\n >\n </cqa-selected-filters>\n\n <cqa-dynamic-filter\n *ngIf=\"showFilterPanel\"\n [config]=\"filterConfig\"\n [showFilterPanel]=\"showFilterPanel\"\n (filtersChanged)=\"onFiltersChanged($event)\"\n (filtersApplied)=\"onFiltersApplied($event)\"\n >\n </cqa-dynamic-filter>\n\n <div class=\"cqa-rounded-[7px] cqa-overflow-hidden cqa-border-t cqa-border-l cqa-border-r cqa-border-grey-200 cqa-relative\">\n <ng-container *ngIf=\"!isEmptyState && pagedRows && pagedRows.length > 0; else storyEmptyTpl\">\n <app-dynamic-table\n [columns]=\"computedColumns\"\n [data]=\"pagedRows\"\n [isTableLoading]=\"isTableLoading\"\n [isTableDataLoading]=\"isTableDataLoading\">\n <ng-template dynamicCell=\"checkbox\" let-row=\"row\">\n <div class=\"custom-checkbox\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + row.id\"\n [checked]=\"row.isSelected\"\n aria-label=\"Select row\"\n (change)=\"onRowCheckboxChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [attr.for]=\"'row-checkbox-' + row.id\">\n </label>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"testCases\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1 cqa-text-[12.3px] cqa-leading-[17.5px] cqa-font-medium\">\n <div class=\"cqa-text-[#3F43EE] cqa-truncate\">\n #{{ row.id }}\n </div>\n <div class=\"cqa-text-[#0A0A0A]\">{{ value }}</div>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"type\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-text-xs cqa-text-[#111827] cqa-truncate\">{{ value }}</div>\n </ng-template>\n\n <ng-template dynamicCell=\"priority\" let-row=\"row\" let-value=\"value\">\n <span\n class=\"cqa-inline-flex cqa-items-center cqa-px-2 cqa-py-0.5 cqa-rounded cqa-text-xs\"\n [ngClass]=\"{\n 'cqa-bg-red-100 cqa-text-red-700': value === 'Critical' || value === 'Major',\n 'cqa-bg-yellow-100 cqa-text-yellow-700': value === 'Medium',\n 'cqa-bg-blue-100 cqa-text-blue-700': value === 'Minor',\n 'cqa-bg-gray-100 cqa-text-gray-700': !value || value === 'Not Set'\n }\"\n >{{ value || 'Not Set' }}</span\n >\n </ng-template>\n\n <ng-template dynamicCell=\"result\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-inline-flex cqa-items-center cqa-px-2 cqa-py-0.5 cqa-rounded cqa-text-xs\" [ngClass]=\"resultBadgeClass(value)\">\n {{ value || 'NOT_EXECUTED' }}\n </span>\n </ng-template>\n\n <ng-template dynamicCell=\"status\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs\">{{ value }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"labels\" let-row=\"row\" let-value=\"value\">\n <div class=\"cqa-flex cqa-flex-wrap cqa-gap-1\">\n <span *ngFor=\"let tag of (row.tags || []) | slice: 0:3\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded cqa-bg-gray-100 cqa-text-gray-700 cqa-text-xs\">\n {{ tag }}\n </span>\n <span *ngIf=\"(row.tags?.length || 0) > 3\" class=\"cqa-px-2 cqa-py-0.5 cqa-rounded cqa-bg-gray-100 cqa-text-gray-700 cqa-text-xs\">\n +{{ (row.tags?.length || 0) - 3 }} more\n </span>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"createdBy\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs\">{{ value }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"createdAt\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs cqa-text-gray-700\">{{ value | date: 'medium' }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"updatedAt\" let-row=\"row\" let-value=\"value\">\n <span class=\"cqa-text-xs cqa-text-gray-700\">{{ value | date: 'medium' }}</span>\n </ng-template>\n\n <ng-template dynamicCell=\"lastRun\" let-row=\"row\">\n <div class=\"cqa-flex cqa-flex-col\">\n <span class=\"cqa-text-xs cqa-text-[#111827]\">{{ row.lastRun?.startTime | date: 'medium' }}</span>\n </div>\n </ng-template>\n\n <ng-template dynamicCell=\"actions\" let-row=\"row\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" *ngIf=\"showActionButton\">\n <cqa-action-menu-button\n [row]=\"row\"\n (view)=\"view($event)\"\n (edit)=\"edit($event)\"\n (delete)=\"delete($event)\"\n ></cqa-action-menu-button>\n </div>\n </ng-template>\n\n <ng-template #emptyTableTpl>\n <div class=\"cqa-flex cqa-flex-col cqa-items-center cqa-justify-center cqa-py-8\">\n <img src=\"/assets/illustrations/empty-state.svg\" alt=\"No data\" class=\"cqa-w-32 cqa-h-32 cqa-mb-4\" />\n <h3 class=\"cqa-text-lg cqa-font-semibold cqa-mb-2\">No test cases</h3>\n <p class=\"cqa-text-sm cqa-text-neutral-500 cqa-mb-4\">Try adjusting filters or create a new test case.</p>\n <cqa-button variant=\"filled\" (clicked)=\"toggleFilter()\">Show Filters</cqa-button>\n </div>\n </ng-template>\n </app-dynamic-table>\n </ng-container>\n\n <ng-template #storyEmptyTpl>\n <div class=\"cqa-p-6 cqa-flex cqa-flex-col cqa-items-center cqa-justify-center\">\n <cqa-empty-state\n *ngIf=\"isEmptyState\"\n [title]=\"emptyStateConfig.title\"\n [description]=\"emptyStateConfig.description\"\n [imageUrl]=\"emptyStateConfig.imageUrl\"\n [actions]=\"emptyStateConfig.actions\"\n (actionClick)=\"onEmptyAction($event)\"\n >\n </cqa-empty-state>\n </div>\n </ng-template>\n\n </div>\n\n <cqa-pagination\n [totalElements]=\"filteredRows.length\"\n [pageIndex]=\"pageIndex\"\n [pageSize]=\"pageSize\"\n [pageItemCount]=\"pagedRows.length\"\n (paginate)=\"onPaginate($event)\"\n (pageSizeChange)=\"onPageSizeChange($event)\"\n >\n </cqa-pagination>\n\n <div *ngIf=\"anyRowSelected\" class=\"cqa-absolute cqa-bottom-[18.75px] cqa-left-[50%] cqa-translate-x-[-50%] cqa-w-full lg:cqa-max-w-[68%] cqa-sm:max-w-[75%] cqa-max-w-[90%] cqa-z-[1]\" >\n <cqa-table-action-toolbar\n [selectedItems]=\"currentSelectedItems\"\n [actions]=\"actions\"\n (actionClick)=\"actionClick($event)\"\n ></cqa-table-action-toolbar>\n </div>\n \n </div>\n</div>\n\n", styles: [] }]
3256
+ }], propDecorators: { searchPlaceholder: [{
3257
+ type: Input
3258
+ }], searchValue: [{
3259
+ type: Input
3260
+ }], showClear: [{
3261
+ type: Input
3262
+ }], showSearchBar: [{
3263
+ type: Input
3264
+ }], filterConfig: [{
3265
+ type: Input
3266
+ }], showFilterPanel: [{
3267
+ type: Input
3268
+ }], showFilterButton: [{
3269
+ type: Input
3270
+ }], otherButtonLabel: [{
3271
+ type: Input
3272
+ }], otherButtonVariant: [{
3273
+ type: Input
3274
+ }], showOtherButton: [{
3275
+ type: Input
3276
+ }], showActionButton: [{
3277
+ type: Input
3278
+ }], showSettingsButton: [{
3279
+ type: Input
3280
+ }], showAutoRefreshButton: [{
3281
+ type: Input
3282
+ }], data: [{
3283
+ type: Input
3284
+ }], isEmptyState: [{
3285
+ type: Input
3286
+ }], emptyStateConfig: [{
3287
+ type: Input
3288
+ }], actions: [{
3289
+ type: Input
3290
+ }], chips: [{
3291
+ type: Input
3292
+ }], filterApplied: [{
3293
+ type: Input
3294
+ }], columns: [{
3295
+ type: Input
3296
+ }], selectedAutoRefreshInterval: [{
3297
+ type: Input
3298
+ }], pageIndex: [{
3299
+ type: Input
3300
+ }], pageSize: [{
3301
+ type: Input
3302
+ }], isTableLoading: [{
3303
+ type: Input
3304
+ }], isTableDataLoading: [{
3305
+ type: Input
3306
+ }] } });
3307
+
3308
+ /**
3309
+ * Ensures Angular CDK overlay content (e.g., MatSelect, Datepicker panels)
3310
+ * is nested under an element with id="cqa-ui-root" so Tailwind utilities
3311
+ * configured with important: '#cqa-ui-root' are applied inside overlays.
3312
+ */
3313
+ class TailwindOverlayContainer extends OverlayContainer {
3314
+ _createContainer() {
3315
+ super._createContainer();
3316
+ if (this._containerElement) {
3317
+ this._containerElement.id = 'cqa-ui-root';
3318
+ }
3319
+ }
3320
+ }
3321
+ TailwindOverlayContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TailwindOverlayContainer, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
3322
+ TailwindOverlayContainer.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TailwindOverlayContainer });
3323
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: TailwindOverlayContainer, decorators: [{
3324
+ type: Injectable
3325
+ }] });
3326
+
3327
+ class UiKitModule {
3328
+ }
3329
+ UiKitModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3330
+ UiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, declarations: [ButtonComponent,
3331
+ SearchBarComponent,
3332
+ SegmentControlComponent,
3333
+ DialogComponent,
3334
+ DynamicTableComponent,
3335
+ DynamicCellTemplateDirective,
3336
+ DynamicHeaderTemplateDirective,
3337
+ InlineSortComponent,
3338
+ PaginationComponent,
3339
+ ActionMenuButtonComponent,
3340
+ OtherButtonComponent,
3341
+ DynamicFilterComponent,
3342
+ ColumnVisibilityComponent,
3343
+ TableActionToolbarComponent,
3344
+ MetricsCardComponent,
3345
+ MetricsBlockComponent,
3346
+ ChartCardComponent,
3347
+ ProgressTextCardComponent,
3348
+ DashboardHeaderComponent,
3349
+ CoverageModuleCardComponent,
3350
+ TestDistributionCardComponent,
3351
+ FailedTestCasesCardComponent,
3352
+ DynamicSelectFieldComponent,
3353
+ SelectedFiltersComponent,
3354
+ InsightCardComponent,
3355
+ BadgeComponent,
3356
+ DropdownButtonComponent,
3357
+ HeatErrorMapCellComponent,
3358
+ EmptyStateComponent,
3359
+ TableTemplateComponent,
3360
+ FullTableLoaderComponent,
3361
+ TableDataLoaderComponent], imports: [CommonModule,
3362
+ FormsModule,
3363
+ ReactiveFormsModule,
3364
+ MatIconModule,
3365
+ MatTooltipModule,
3366
+ MatMenuModule,
3367
+ MatButtonModule,
3368
+ MatFormFieldModule,
3369
+ MatSelectModule,
3370
+ MatOptionModule,
3371
+ MatCheckboxModule,
3372
+ MatRadioModule,
3373
+ MatDatepickerModule,
3374
+ MatNativeDateModule,
3375
+ MatProgressSpinnerModule,
3376
+ OverlayModule,
3377
+ PortalModule], exports: [ButtonComponent,
3378
+ SearchBarComponent,
3379
+ SegmentControlComponent,
3380
+ DialogComponent,
3381
+ DynamicTableComponent,
3382
+ DynamicCellTemplateDirective,
3383
+ DynamicHeaderTemplateDirective,
3384
+ InlineSortComponent,
3385
+ PaginationComponent,
3386
+ ActionMenuButtonComponent,
3387
+ OtherButtonComponent,
3388
+ DynamicFilterComponent,
3389
+ ColumnVisibilityComponent,
3390
+ TableActionToolbarComponent,
3391
+ MetricsCardComponent,
3392
+ ChartCardComponent,
3393
+ ProgressTextCardComponent,
3394
+ DashboardHeaderComponent,
3395
+ CoverageModuleCardComponent,
3396
+ TestDistributionCardComponent,
3397
+ FailedTestCasesCardComponent,
3398
+ DynamicSelectFieldComponent,
3399
+ SelectedFiltersComponent,
3400
+ InsightCardComponent,
3401
+ BadgeComponent,
3402
+ DropdownButtonComponent,
3403
+ HeatErrorMapCellComponent,
3404
+ EmptyStateComponent,
3405
+ TableTemplateComponent,
3406
+ FullTableLoaderComponent,
3407
+ TableDataLoaderComponent] });
3408
+ UiKitModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, providers: [
3409
+ { provide: OverlayContainer, useClass: TailwindOverlayContainer }
3410
+ ], imports: [[
3411
+ CommonModule,
3412
+ FormsModule,
3413
+ ReactiveFormsModule,
3414
+ MatIconModule,
3415
+ MatTooltipModule,
3416
+ MatMenuModule,
3417
+ MatButtonModule,
3418
+ MatFormFieldModule,
3419
+ MatSelectModule,
3420
+ MatOptionModule,
3421
+ MatCheckboxModule,
3422
+ MatRadioModule,
3423
+ MatDatepickerModule,
3424
+ MatNativeDateModule,
3425
+ MatProgressSpinnerModule,
3426
+ OverlayModule,
3427
+ PortalModule
3428
+ ]] });
3429
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: UiKitModule, decorators: [{
3430
+ type: NgModule,
3431
+ args: [{
3432
+ declarations: [
3433
+ ButtonComponent,
3434
+ SearchBarComponent,
3435
+ SegmentControlComponent,
3436
+ DialogComponent,
3437
+ DynamicTableComponent,
3438
+ DynamicCellTemplateDirective,
3439
+ DynamicHeaderTemplateDirective,
3440
+ InlineSortComponent,
3441
+ PaginationComponent,
3442
+ ActionMenuButtonComponent,
3443
+ OtherButtonComponent,
3444
+ DynamicFilterComponent,
3445
+ ColumnVisibilityComponent,
3446
+ TableActionToolbarComponent,
3447
+ MetricsCardComponent,
3448
+ MetricsBlockComponent,
3449
+ ChartCardComponent,
3450
+ ProgressTextCardComponent,
3451
+ DashboardHeaderComponent,
3452
+ CoverageModuleCardComponent,
3453
+ TestDistributionCardComponent,
3454
+ FailedTestCasesCardComponent,
3455
+ DynamicSelectFieldComponent,
3456
+ SelectedFiltersComponent,
3457
+ InsightCardComponent,
3458
+ BadgeComponent,
3459
+ DropdownButtonComponent,
3460
+ HeatErrorMapCellComponent,
3461
+ EmptyStateComponent,
3462
+ TableTemplateComponent,
3463
+ FullTableLoaderComponent,
3464
+ TableDataLoaderComponent
3465
+ ],
3466
+ imports: [
3467
+ CommonModule,
3468
+ FormsModule,
3469
+ ReactiveFormsModule,
3470
+ MatIconModule,
3471
+ MatTooltipModule,
3472
+ MatMenuModule,
3473
+ MatButtonModule,
3474
+ MatFormFieldModule,
3475
+ MatSelectModule,
3476
+ MatOptionModule,
3477
+ MatCheckboxModule,
3478
+ MatRadioModule,
3479
+ MatDatepickerModule,
3480
+ MatNativeDateModule,
3481
+ MatProgressSpinnerModule,
3482
+ OverlayModule,
3483
+ PortalModule
3484
+ ],
3485
+ exports: [
3486
+ ButtonComponent,
3487
+ SearchBarComponent,
3488
+ SegmentControlComponent,
3489
+ DialogComponent,
3490
+ DynamicTableComponent,
3491
+ DynamicCellTemplateDirective,
3492
+ DynamicHeaderTemplateDirective,
3493
+ InlineSortComponent,
3494
+ PaginationComponent,
3495
+ ActionMenuButtonComponent,
3496
+ OtherButtonComponent,
3497
+ DynamicFilterComponent,
3498
+ ColumnVisibilityComponent,
3499
+ TableActionToolbarComponent,
3500
+ MetricsCardComponent,
3501
+ ChartCardComponent,
3502
+ ProgressTextCardComponent,
3503
+ DashboardHeaderComponent,
3504
+ CoverageModuleCardComponent,
3505
+ TestDistributionCardComponent,
3506
+ FailedTestCasesCardComponent,
3507
+ DynamicSelectFieldComponent,
3508
+ SelectedFiltersComponent,
3509
+ InsightCardComponent,
3510
+ BadgeComponent,
3511
+ DropdownButtonComponent,
3512
+ HeatErrorMapCellComponent,
3513
+ EmptyStateComponent,
3514
+ TableTemplateComponent,
3515
+ FullTableLoaderComponent,
3516
+ TableDataLoaderComponent
3517
+ ],
3518
+ providers: [
3519
+ { provide: OverlayContainer, useClass: TailwindOverlayContainer }
754
3520
  ]
755
3521
  }]
756
3522
  }] });
@@ -878,18 +3644,18 @@ class DialogService {
878
3644
  });
879
3645
  }
880
3646
  }
881
- DialogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogService, deps: [{ token: i1$1.Overlay }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
3647
+ DialogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogService, deps: [{ token: i1$4.Overlay }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
882
3648
  DialogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogService, providedIn: 'root' });
883
3649
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DialogService, decorators: [{
884
3650
  type: Injectable,
885
3651
  args: [{
886
3652
  providedIn: 'root',
887
3653
  }]
888
- }], ctorParameters: function () { return [{ type: i1$1.Overlay }, { type: i0.Injector }]; } });
3654
+ }], ctorParameters: function () { return [{ type: i1$4.Overlay }, { type: i0.Injector }]; } });
889
3655
 
890
3656
  /**
891
3657
  * Generated bundle index. Do not edit.
892
3658
  */
893
3659
 
894
- export { ButtonComponent, DIALOG_DATA, DIALOG_REF, DialogComponent, DialogRef, DialogService, SearchBarComponent, SegmentControlComponent, UiKitModule };
3660
+ export { ActionMenuButtonComponent, BadgeComponent, ButtonComponent, ChartCardComponent, ColumnVisibilityComponent, CoverageModuleCardComponent, DEFAULT_METADATA_COLOR, DIALOG_DATA, DIALOG_REF, DashboardHeaderComponent, DialogComponent, DialogRef, DialogService, DropdownButtonComponent, DynamicCellTemplateDirective, DynamicFilterComponent, DynamicHeaderTemplateDirective, DynamicSelectFieldComponent, DynamicTableComponent, EMPTY_STATE_IMAGES, EmptyStateComponent, FailedTestCasesCardComponent, FullTableLoaderComponent, HeatErrorMapCellComponent, InlineSortComponent, InsightCardComponent, MetricsCardComponent, OtherButtonComponent, PRIORITY_COLORS, PaginationComponent, ProgressTextCardComponent, RESULT_COLORS, STATUS_COLORS, SearchBarComponent, SegmentControlComponent, SelectedFiltersComponent, TableActionToolbarComponent, TableDataLoaderComponent, TableTemplateComponent, TestDistributionCardComponent, UiKitModule, getMetadataColor, getMetadataValueStyle };
895
3661
  //# sourceMappingURL=cqa-lib-cqa-ui.mjs.map