commons-shared-web-ui 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2051 @@
1
+ import * as i0 from '@angular/core';
2
+ import { NgModule, EventEmitter, Output, Input, Component, HostListener, forwardRef, HostBinding } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import { MatCardModule } from '@angular/material/card';
6
+ import * as i2$1 from '@angular/material/snack-bar';
7
+ import { MatSnackBarModule } from '@angular/material/snack-bar';
8
+ import * as i4 from '@angular/material/checkbox';
9
+ import { MatCheckboxModule } from '@angular/material/checkbox';
10
+ import { MatDividerModule } from '@angular/material/divider';
11
+ import * as i6 from '@angular/material/radio';
12
+ import { MatRadioModule } from '@angular/material/radio';
13
+ import { MatDialogModule } from '@angular/material/dialog';
14
+ import { MatFormFieldModule } from '@angular/material/form-field';
15
+ import * as i2 from '@angular/material/icon';
16
+ import { MatIconModule } from '@angular/material/icon';
17
+ import * as i7 from '@angular/material/button';
18
+ import { MatButtonModule } from '@angular/material/button';
19
+ import { MatMenuModule } from '@angular/material/menu';
20
+ import * as i7$1 from '@angular/material/datepicker';
21
+ import { MatDatepickerModule } from '@angular/material/datepicker';
22
+ import { MatTabsModule } from '@angular/material/tabs';
23
+ import { MatNativeDateModule } from '@angular/material/core';
24
+ import * as i8$1 from '@angular/material/input';
25
+ import { MatInputModule } from '@angular/material/input';
26
+ import { MatProgressBarModule } from '@angular/material/progress-bar';
27
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
28
+ import * as i5 from '@angular/material/select';
29
+ import { MatSelectModule } from '@angular/material/select';
30
+ import { MatTooltipModule } from '@angular/material/tooltip';
31
+ import { MatSliderModule } from '@angular/material/slider';
32
+ import { MatListModule } from '@angular/material/list';
33
+ import { MatChipsModule } from '@angular/material/chips';
34
+ import { MatPaginatorModule } from '@angular/material/paginator';
35
+ import { MatTableModule } from '@angular/material/table';
36
+ import * as i8 from '@angular/material/expansion';
37
+ import { MatExpansionModule } from '@angular/material/expansion';
38
+ import { CdkAccordionModule } from '@angular/cdk/accordion';
39
+ import { MatSortModule } from '@angular/material/sort';
40
+ import { MatAutocompleteModule } from '@angular/material/autocomplete';
41
+ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
42
+ import { MatButtonToggleModule } from '@angular/material/button-toggle';
43
+ import * as i1$2 from '@angular/forms';
44
+ import { FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule, Validators } from '@angular/forms';
45
+ import * as i1$1 from '@angular/router';
46
+ import * as i3 from '@angular/common/http';
47
+ import { HttpClientModule } from '@angular/common/http';
48
+
49
+ class MaterialModule {
50
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
51
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: MaterialModule, imports: [MatCardModule,
52
+ MatSnackBarModule,
53
+ MatCheckboxModule,
54
+ MatDividerModule,
55
+ MatSelectModule,
56
+ MatRadioModule,
57
+ MatDialogModule,
58
+ MatFormFieldModule,
59
+ MatDatepickerModule,
60
+ MatNativeDateModule,
61
+ MatInputModule,
62
+ MatIconModule,
63
+ MatProgressSpinnerModule,
64
+ MatTabsModule,
65
+ MatButtonModule,
66
+ MatMenuModule,
67
+ MatTabsModule,
68
+ MatProgressBarModule,
69
+ MatTooltipModule,
70
+ MatSliderModule,
71
+ MatListModule,
72
+ MatChipsModule,
73
+ MatSortModule,
74
+ MatAutocompleteModule,
75
+ MatSlideToggleModule,
76
+ MatButtonToggleModule], exports: [MatCardModule,
77
+ MatSnackBarModule,
78
+ MatCheckboxModule,
79
+ MatDividerModule,
80
+ MatSelectModule,
81
+ MatRadioModule,
82
+ MatDialogModule,
83
+ MatFormFieldModule,
84
+ MatDatepickerModule,
85
+ MatNativeDateModule,
86
+ MatInputModule,
87
+ MatIconModule,
88
+ MatProgressSpinnerModule,
89
+ MatTabsModule,
90
+ MatButtonModule,
91
+ MatMenuModule,
92
+ MatTabsModule,
93
+ MatProgressBarModule,
94
+ MatTooltipModule,
95
+ MatSliderModule,
96
+ MatListModule,
97
+ MatChipsModule,
98
+ MatPaginatorModule,
99
+ MatTableModule,
100
+ MatExpansionModule,
101
+ CdkAccordionModule,
102
+ MatSortModule,
103
+ MatAutocompleteModule,
104
+ MatSlideToggleModule,
105
+ MatButtonToggleModule] });
106
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MaterialModule, imports: [MatCardModule,
107
+ MatSnackBarModule,
108
+ MatCheckboxModule,
109
+ MatDividerModule,
110
+ MatSelectModule,
111
+ MatRadioModule,
112
+ MatDialogModule,
113
+ MatFormFieldModule,
114
+ MatDatepickerModule,
115
+ MatNativeDateModule,
116
+ MatInputModule,
117
+ MatIconModule,
118
+ MatProgressSpinnerModule,
119
+ MatTabsModule,
120
+ MatButtonModule,
121
+ MatMenuModule,
122
+ MatTabsModule,
123
+ MatProgressBarModule,
124
+ MatTooltipModule,
125
+ MatSliderModule,
126
+ MatListModule,
127
+ MatChipsModule,
128
+ MatSortModule,
129
+ MatAutocompleteModule,
130
+ MatSlideToggleModule,
131
+ MatButtonToggleModule, MatCardModule,
132
+ MatSnackBarModule,
133
+ MatCheckboxModule,
134
+ MatDividerModule,
135
+ MatSelectModule,
136
+ MatRadioModule,
137
+ MatDialogModule,
138
+ MatFormFieldModule,
139
+ MatDatepickerModule,
140
+ MatNativeDateModule,
141
+ MatInputModule,
142
+ MatIconModule,
143
+ MatProgressSpinnerModule,
144
+ MatTabsModule,
145
+ MatButtonModule,
146
+ MatMenuModule,
147
+ MatTabsModule,
148
+ MatProgressBarModule,
149
+ MatTooltipModule,
150
+ MatSliderModule,
151
+ MatListModule,
152
+ MatChipsModule,
153
+ MatPaginatorModule,
154
+ MatTableModule,
155
+ MatExpansionModule,
156
+ CdkAccordionModule,
157
+ MatSortModule,
158
+ MatAutocompleteModule,
159
+ MatSlideToggleModule,
160
+ MatButtonToggleModule] });
161
+ }
162
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MaterialModule, decorators: [{
163
+ type: NgModule,
164
+ args: [{
165
+ imports: [
166
+ MatCardModule,
167
+ MatSnackBarModule,
168
+ MatCheckboxModule,
169
+ MatDividerModule,
170
+ MatSelectModule,
171
+ MatRadioModule,
172
+ MatDialogModule,
173
+ MatFormFieldModule,
174
+ MatDatepickerModule,
175
+ MatNativeDateModule,
176
+ MatInputModule,
177
+ MatIconModule,
178
+ MatProgressSpinnerModule,
179
+ MatTabsModule,
180
+ MatButtonModule,
181
+ MatMenuModule,
182
+ MatTabsModule,
183
+ MatProgressBarModule,
184
+ MatTooltipModule,
185
+ MatSliderModule,
186
+ MatListModule,
187
+ MatChipsModule,
188
+ MatSortModule,
189
+ MatAutocompleteModule,
190
+ MatSlideToggleModule,
191
+ MatButtonToggleModule
192
+ ],
193
+ exports: [
194
+ MatCardModule,
195
+ MatSnackBarModule,
196
+ MatCheckboxModule,
197
+ MatDividerModule,
198
+ MatSelectModule,
199
+ MatRadioModule,
200
+ MatDialogModule,
201
+ MatFormFieldModule,
202
+ MatDatepickerModule,
203
+ MatNativeDateModule,
204
+ MatInputModule,
205
+ MatIconModule,
206
+ MatProgressSpinnerModule,
207
+ MatTabsModule,
208
+ MatButtonModule,
209
+ MatMenuModule,
210
+ MatTabsModule,
211
+ MatProgressBarModule,
212
+ MatTooltipModule,
213
+ MatSliderModule,
214
+ MatListModule,
215
+ MatChipsModule,
216
+ MatPaginatorModule,
217
+ MatTableModule,
218
+ MatExpansionModule,
219
+ CdkAccordionModule,
220
+ MatSortModule,
221
+ MatAutocompleteModule,
222
+ MatSlideToggleModule,
223
+ MatButtonToggleModule
224
+ ]
225
+ }]
226
+ }] });
227
+
228
+ class CardType1Component {
229
+ config;
230
+ theme = 'theme-1';
231
+ cardClick = new EventEmitter();
232
+ get valueStyle() {
233
+ return this.config.valueColor ? { color: this.config.valueColor } : {};
234
+ }
235
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CardType1Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
236
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: CardType1Component, isStandalone: false, selector: "lib-card-type-1", inputs: { config: "config", theme: "theme" }, outputs: { cardClick: "cardClick" }, ngImport: i0, template: "<div [class]=\"'cc-card ' + theme\" [style.width]=\"config.width || '100%'\" [style.height]=\"config.height || '100%'\" (click)=\"cardClick.emit()\">\n <div class=\"card-content\">\n <div class=\"card-label\">{{ config.label }}</div>\n <div class=\"card-value\" [ngStyle]=\"valueStyle\">{{ config.value }}</div>\n <div\n *ngIf=\"config.subtext\"\n class=\"card-subtext\"\n [ngClass]=\"config.subtextClass\"\n >\n {{ config.subtext }}\n </div>\n </div>\n</div>\n", styles: [".cc-card{display:flex;flex-direction:column;justify-content:center;max-width:100%;box-sizing:border-box;overflow:hidden}.card-label{font-family:var(--cc-font-family);font-size:var(--cc-text-size-label);color:var(--cc-text-color-secondary);text-transform:uppercase;font-weight:var(--cc-text-weight-medium);margin-bottom:8px}.card-value{font-family:var(--cc-font-family);font-size:var(--cc-text-size-value);color:var(--cc-text-color-primary);font-weight:var(--cc-text-weight-bold);margin-bottom:4px}.card-subtext{font-family:var(--cc-font-family);font-size:12px;color:var(--cc-text-color-secondary)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
237
+ }
238
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CardType1Component, decorators: [{
239
+ type: Component,
240
+ args: [{ selector: 'lib-card-type-1', standalone: false, template: "<div [class]=\"'cc-card ' + theme\" [style.width]=\"config.width || '100%'\" [style.height]=\"config.height || '100%'\" (click)=\"cardClick.emit()\">\n <div class=\"card-content\">\n <div class=\"card-label\">{{ config.label }}</div>\n <div class=\"card-value\" [ngStyle]=\"valueStyle\">{{ config.value }}</div>\n <div\n *ngIf=\"config.subtext\"\n class=\"card-subtext\"\n [ngClass]=\"config.subtextClass\"\n >\n {{ config.subtext }}\n </div>\n </div>\n</div>\n", styles: [".cc-card{display:flex;flex-direction:column;justify-content:center;max-width:100%;box-sizing:border-box;overflow:hidden}.card-label{font-family:var(--cc-font-family);font-size:var(--cc-text-size-label);color:var(--cc-text-color-secondary);text-transform:uppercase;font-weight:var(--cc-text-weight-medium);margin-bottom:8px}.card-value{font-family:var(--cc-font-family);font-size:var(--cc-text-size-value);color:var(--cc-text-color-primary);font-weight:var(--cc-text-weight-bold);margin-bottom:4px}.card-subtext{font-family:var(--cc-font-family);font-size:12px;color:var(--cc-text-color-secondary)}\n"] }]
241
+ }], propDecorators: { config: [{
242
+ type: Input
243
+ }], theme: [{
244
+ type: Input
245
+ }], cardClick: [{
246
+ type: Output
247
+ }] } });
248
+
249
+ class CardType2Component {
250
+ config;
251
+ theme = 'theme-1';
252
+ cardClick = new EventEmitter();
253
+ get iconBoxStyle() {
254
+ if (this.config.iconUrl) {
255
+ return { backgroundColor: 'transparent' };
256
+ }
257
+ return this.config.iconBackgroundColor ? { backgroundColor: this.config.iconBackgroundColor } : {};
258
+ }
259
+ get iconStyle() {
260
+ return this.config.iconColor ? { color: this.config.iconColor } : {};
261
+ }
262
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CardType2Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
263
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: CardType2Component, isStandalone: false, selector: "lib-card-type-2", inputs: { config: "config", theme: "theme" }, outputs: { cardClick: "cardClick" }, ngImport: i0, template: "<div [class]=\"'cc-card ' + theme\" [style.width]=\"config.width || '100%'\" [style.height]=\"config.height || '100%'\" (click)=\"cardClick.emit()\">\n <div class=\"card-content-wrapper\">\n <div class=\"icon-box\" [ngStyle]=\"iconBoxStyle\">\n <img *ngIf=\"config.iconUrl; else matIconTpl\" [src]=\"config.iconUrl\" class=\"icon-image\" alt=\"icon\">\n <ng-template #matIconTpl>\n <mat-icon [ngStyle]=\"iconStyle\">{{ config.iconName }}</mat-icon>\n </ng-template>\n </div>\n <div class=\"text-content\">\n <div class=\"card-label\">{{ config.label }}</div>\n <div class=\"value-wrapper\">\n <span class=\"card-value\">{{ config.value }}</span>\n <span *ngIf=\"config.targetText\" class=\"card-target\">{{ config.targetText }}</span>\n </div>\n </div>\n </div>\n</div>\n", styles: [".cc-card{display:flex;flex-direction:column;justify-content:center;max-width:100%;box-sizing:border-box;overflow:hidden}.card-content-wrapper{display:flex;align-items:center;gap:16px}.icon-box{width:48px;height:48px;border-radius:8px;display:flex;align-items:center;justify-content:center;background-color:#fce8e6;color:#d32f2f}.icon-box mat-icon{font-size:24px;width:24px;height:24px}.icon-box .icon-image{object-fit:contain;border-radius:.5rem}.text-content{display:flex;flex-direction:column}.card-label{font-family:var(--cc-font-family);font-size:var(--cc-text-size-label);color:var(--cc-text-color-secondary);text-transform:uppercase;font-weight:var(--cc-text-weight-medium);margin-bottom:4px}.value-wrapper{display:flex;align-items:baseline;gap:8px}.card-value{font-family:var(--cc-font-family);font-size:var(--cc-text-size-value);color:var(--cc-text-color-primary);font-weight:var(--cc-text-weight-bold)}.card-target{font-family:var(--cc-font-family);font-size:12px;color:var(--cc-text-color-secondary)}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
264
+ }
265
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CardType2Component, decorators: [{
266
+ type: Component,
267
+ args: [{ selector: 'lib-card-type-2', standalone: false, template: "<div [class]=\"'cc-card ' + theme\" [style.width]=\"config.width || '100%'\" [style.height]=\"config.height || '100%'\" (click)=\"cardClick.emit()\">\n <div class=\"card-content-wrapper\">\n <div class=\"icon-box\" [ngStyle]=\"iconBoxStyle\">\n <img *ngIf=\"config.iconUrl; else matIconTpl\" [src]=\"config.iconUrl\" class=\"icon-image\" alt=\"icon\">\n <ng-template #matIconTpl>\n <mat-icon [ngStyle]=\"iconStyle\">{{ config.iconName }}</mat-icon>\n </ng-template>\n </div>\n <div class=\"text-content\">\n <div class=\"card-label\">{{ config.label }}</div>\n <div class=\"value-wrapper\">\n <span class=\"card-value\">{{ config.value }}</span>\n <span *ngIf=\"config.targetText\" class=\"card-target\">{{ config.targetText }}</span>\n </div>\n </div>\n </div>\n</div>\n", styles: [".cc-card{display:flex;flex-direction:column;justify-content:center;max-width:100%;box-sizing:border-box;overflow:hidden}.card-content-wrapper{display:flex;align-items:center;gap:16px}.icon-box{width:48px;height:48px;border-radius:8px;display:flex;align-items:center;justify-content:center;background-color:#fce8e6;color:#d32f2f}.icon-box mat-icon{font-size:24px;width:24px;height:24px}.icon-box .icon-image{object-fit:contain;border-radius:.5rem}.text-content{display:flex;flex-direction:column}.card-label{font-family:var(--cc-font-family);font-size:var(--cc-text-size-label);color:var(--cc-text-color-secondary);text-transform:uppercase;font-weight:var(--cc-text-weight-medium);margin-bottom:4px}.value-wrapper{display:flex;align-items:baseline;gap:8px}.card-value{font-family:var(--cc-font-family);font-size:var(--cc-text-size-value);color:var(--cc-text-color-primary);font-weight:var(--cc-text-weight-bold)}.card-target{font-family:var(--cc-font-family);font-size:12px;color:var(--cc-text-color-secondary)}\n"] }]
268
+ }], propDecorators: { config: [{
269
+ type: Input
270
+ }], theme: [{
271
+ type: Input
272
+ }], cardClick: [{
273
+ type: Output
274
+ }] } });
275
+
276
+ class CardsModule {
277
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CardsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
278
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: CardsModule, declarations: [CardType1Component,
279
+ CardType2Component], imports: [CommonModule,
280
+ MaterialModule], exports: [CardType1Component,
281
+ CardType2Component] });
282
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CardsModule, imports: [CommonModule,
283
+ MaterialModule] });
284
+ }
285
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CardsModule, decorators: [{
286
+ type: NgModule,
287
+ args: [{
288
+ declarations: [
289
+ CardType1Component,
290
+ CardType2Component
291
+ ],
292
+ imports: [
293
+ CommonModule,
294
+ MaterialModule
295
+ ],
296
+ exports: [
297
+ CardType1Component,
298
+ CardType2Component
299
+ ]
300
+ }]
301
+ }] });
302
+
303
+ class AlertComponent {
304
+ variant = 'info';
305
+ title = '';
306
+ message = '';
307
+ icon = true;
308
+ customIcon = ''; // New input for custom class
309
+ // Customization Inputs
310
+ width;
311
+ height;
312
+ borderRadius;
313
+ padding;
314
+ gap;
315
+ backgroundColor;
316
+ color; // New input for custom text color
317
+ borderColor;
318
+ fontSize;
319
+ fontWeight;
320
+ boxShadow;
321
+ // Granular Border Radius Customization
322
+ borderTopLeftRadius;
323
+ borderTopRightRadius;
324
+ borderBottomLeftRadius;
325
+ borderBottomRightRadius;
326
+ constructor() { }
327
+ ngOnInit() {
328
+ }
329
+ get isDefaultIcon() {
330
+ return this.icon === true;
331
+ }
332
+ get isStringIcon() {
333
+ return typeof this.icon === 'string';
334
+ }
335
+ get isObjectIcon() {
336
+ return typeof this.icon === 'object' && this.icon !== null;
337
+ }
338
+ get iconString() {
339
+ return typeof this.icon === 'string' ? this.icon : '';
340
+ }
341
+ get isImgIcon() {
342
+ const icon = this.icon;
343
+ if (typeof icon === 'string') {
344
+ return icon.includes('/') || icon.includes('.') || icon.startsWith('http');
345
+ }
346
+ return typeof icon === 'object' && icon !== null && icon.type === 'img';
347
+ }
348
+ get iconObject() {
349
+ return typeof this.icon === 'object' ? this.icon : { type: '', value: '' };
350
+ }
351
+ get defaultIconClass() {
352
+ switch (this.variant) {
353
+ case 'success': return 'fa-solid fa-circle-check';
354
+ case 'warning':
355
+ case 'warning-shadow': return 'fa-solid fa-triangle-exclamation';
356
+ case 'error': return 'fa-solid fa-triangle-exclamation';
357
+ case 'info':
358
+ default: return 'fa-solid fa-circle-info';
359
+ }
360
+ }
361
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
362
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: AlertComponent, isStandalone: false, selector: "lib-alert", inputs: { variant: "variant", title: "title", message: "message", icon: "icon", customIcon: "customIcon", width: "width", height: "height", borderRadius: "borderRadius", padding: "padding", gap: "gap", backgroundColor: "backgroundColor", color: "color", borderColor: "borderColor", fontSize: "fontSize", fontWeight: "fontWeight", boxShadow: "boxShadow", borderTopLeftRadius: "borderTopLeftRadius", borderTopRightRadius: "borderTopRightRadius", borderBottomLeftRadius: "borderBottomLeftRadius", borderBottomRightRadius: "borderBottomRightRadius" }, ngImport: i0, template: "<div class=\"cc-alert\" [ngClass]=\"'cc-alert-' + variant\" [style.width]=\"width\" [style.height]=\"height\"\r\n [style.border-radius]=\"borderRadius\" [style.border-top-left-radius]=\"borderTopLeftRadius\"\r\n [style.border-top-right-radius]=\"borderTopRightRadius\" [style.border-bottom-left-radius]=\"borderBottomLeftRadius\"\r\n [style.border-bottom-right-radius]=\"borderBottomRightRadius\" [style.padding]=\"padding\" [style.gap]=\"gap\"\r\n [style.background-color]=\"backgroundColor\" [style.color]=\"color\" [style.border-color]=\"borderColor\"\r\n [style.font-size]=\"fontSize\" [style.font-weight]=\"fontWeight\" [style.box-shadow]=\"boxShadow\">\r\n\r\n <div class=\"cc-alert-icon\" *ngIf=\"icon\">\r\n <i *ngIf=\"customIcon\" [ngClass]=\"customIcon\"></i>\r\n <i *ngIf=\"!customIcon && isDefaultIcon\" [ngClass]=\"defaultIconClass\"></i>\r\n <i *ngIf=\"!customIcon && isStringIcon && !isImgIcon\" [ngClass]=\"iconString\"></i>\r\n <img *ngIf=\"!customIcon && isStringIcon && isImgIcon\" [src]=\"iconString\" alt=\"alert icon\" />\r\n <ng-container *ngIf=\"isObjectIcon\">\r\n <i *ngIf=\"iconObject.type === 'fontawesome'\" [ngClass]=\"iconObject.value\"></i>\r\n <span *ngIf=\"iconObject.type === 'material'\" class=\"material-icons\">{{ iconObject.value }}</span>\r\n <img *ngIf=\"iconObject.type === 'img'\" [src]=\"iconObject.value\" alt=\"alert icon\" />\r\n </ng-container>\r\n </div>\r\n\r\n <div class=\"cc-alert-content\">\r\n <div class=\"cc-alert-title\" *ngIf=\"title\">{{ title }}</div>\r\n <div class=\"cc-alert-message\" *ngIf=\"message\">{{ message }}</div>\r\n <ng-content></ng-content>\r\n </div>\r\n</div>", styles: [".cc-alert{display:flex;align-items:flex-start;width:100%;padding:var(--cc-alert-padding, 1rem 2rem);border-radius:var(--cc-alert-radius, .75rem);gap:var(--cc-alert-gap, 1rem);box-sizing:border-box;font-family:var(--cc-alert-font-family, inherit)}.cc-alert .cc-alert-icon{font-size:var(--cc-alert-icon-size, 1.25rem);flex-shrink:0;margin-top:var(--cc-alert-icon-margin-top, .125rem)}.cc-alert .cc-alert-icon img{width:var(--cc-alert-icon-size, 1.25rem);height:var(--cc-alert-icon-size, 1.25rem);object-fit:contain}.cc-alert .cc-alert-content{display:flex;flex-direction:column;gap:.25rem;flex-grow:1}.cc-alert .cc-alert-content .cc-alert-title{font-weight:700;font-size:var(--cc-alert-title-size, 1rem);line-height:var(--cc-alert-title-line-height, 1.5rem)}.cc-alert .cc-alert-content .cc-alert-message{font-size:var(--cc-alert-message-size, .875rem);line-height:200%;opacity:.9}.cc-alert.cc-alert-info{background-color:var(--cc-alert-info-bg);color:var(--cc-alert-info-color)}.cc-alert.cc-alert-info .cc-alert-icon{color:#5f6368}.cc-alert.cc-alert-warning{background-color:var(--cc-alert-warning-bg);color:var(--cc-alert-warning-color)}.cc-alert.cc-alert-warning .cc-alert-title,.cc-alert.cc-alert-warning .cc-alert-icon{color:var(--cc-alert-warning-title-color)}.cc-alert.cc-alert-warning-shadow{background-color:var(--cc-alert-warning-bg);color:var(--cc-alert-warning-color);box-shadow:var(--cc-alert-warning-shadow)}.cc-alert.cc-alert-warning-shadow .cc-alert-title,.cc-alert.cc-alert-warning-shadow .cc-alert-icon{color:var(--cc-alert-warning-title-color)}.cc-alert.cc-alert-success{background-color:var(--cc-alert-success-bg);color:var(--cc-alert-success-color)}.cc-alert.cc-alert-error{background-color:var(--cc-alert-error-bg);color:var(--cc-alert-error-color)}.cc-alert.cc-alert-error .cc-alert-icon{color:var(--cc-alert-error-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
363
+ }
364
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AlertComponent, decorators: [{
365
+ type: Component,
366
+ args: [{ selector: 'lib-alert', standalone: false, template: "<div class=\"cc-alert\" [ngClass]=\"'cc-alert-' + variant\" [style.width]=\"width\" [style.height]=\"height\"\r\n [style.border-radius]=\"borderRadius\" [style.border-top-left-radius]=\"borderTopLeftRadius\"\r\n [style.border-top-right-radius]=\"borderTopRightRadius\" [style.border-bottom-left-radius]=\"borderBottomLeftRadius\"\r\n [style.border-bottom-right-radius]=\"borderBottomRightRadius\" [style.padding]=\"padding\" [style.gap]=\"gap\"\r\n [style.background-color]=\"backgroundColor\" [style.color]=\"color\" [style.border-color]=\"borderColor\"\r\n [style.font-size]=\"fontSize\" [style.font-weight]=\"fontWeight\" [style.box-shadow]=\"boxShadow\">\r\n\r\n <div class=\"cc-alert-icon\" *ngIf=\"icon\">\r\n <i *ngIf=\"customIcon\" [ngClass]=\"customIcon\"></i>\r\n <i *ngIf=\"!customIcon && isDefaultIcon\" [ngClass]=\"defaultIconClass\"></i>\r\n <i *ngIf=\"!customIcon && isStringIcon && !isImgIcon\" [ngClass]=\"iconString\"></i>\r\n <img *ngIf=\"!customIcon && isStringIcon && isImgIcon\" [src]=\"iconString\" alt=\"alert icon\" />\r\n <ng-container *ngIf=\"isObjectIcon\">\r\n <i *ngIf=\"iconObject.type === 'fontawesome'\" [ngClass]=\"iconObject.value\"></i>\r\n <span *ngIf=\"iconObject.type === 'material'\" class=\"material-icons\">{{ iconObject.value }}</span>\r\n <img *ngIf=\"iconObject.type === 'img'\" [src]=\"iconObject.value\" alt=\"alert icon\" />\r\n </ng-container>\r\n </div>\r\n\r\n <div class=\"cc-alert-content\">\r\n <div class=\"cc-alert-title\" *ngIf=\"title\">{{ title }}</div>\r\n <div class=\"cc-alert-message\" *ngIf=\"message\">{{ message }}</div>\r\n <ng-content></ng-content>\r\n </div>\r\n</div>", styles: [".cc-alert{display:flex;align-items:flex-start;width:100%;padding:var(--cc-alert-padding, 1rem 2rem);border-radius:var(--cc-alert-radius, .75rem);gap:var(--cc-alert-gap, 1rem);box-sizing:border-box;font-family:var(--cc-alert-font-family, inherit)}.cc-alert .cc-alert-icon{font-size:var(--cc-alert-icon-size, 1.25rem);flex-shrink:0;margin-top:var(--cc-alert-icon-margin-top, .125rem)}.cc-alert .cc-alert-icon img{width:var(--cc-alert-icon-size, 1.25rem);height:var(--cc-alert-icon-size, 1.25rem);object-fit:contain}.cc-alert .cc-alert-content{display:flex;flex-direction:column;gap:.25rem;flex-grow:1}.cc-alert .cc-alert-content .cc-alert-title{font-weight:700;font-size:var(--cc-alert-title-size, 1rem);line-height:var(--cc-alert-title-line-height, 1.5rem)}.cc-alert .cc-alert-content .cc-alert-message{font-size:var(--cc-alert-message-size, .875rem);line-height:200%;opacity:.9}.cc-alert.cc-alert-info{background-color:var(--cc-alert-info-bg);color:var(--cc-alert-info-color)}.cc-alert.cc-alert-info .cc-alert-icon{color:#5f6368}.cc-alert.cc-alert-warning{background-color:var(--cc-alert-warning-bg);color:var(--cc-alert-warning-color)}.cc-alert.cc-alert-warning .cc-alert-title,.cc-alert.cc-alert-warning .cc-alert-icon{color:var(--cc-alert-warning-title-color)}.cc-alert.cc-alert-warning-shadow{background-color:var(--cc-alert-warning-bg);color:var(--cc-alert-warning-color);box-shadow:var(--cc-alert-warning-shadow)}.cc-alert.cc-alert-warning-shadow .cc-alert-title,.cc-alert.cc-alert-warning-shadow .cc-alert-icon{color:var(--cc-alert-warning-title-color)}.cc-alert.cc-alert-success{background-color:var(--cc-alert-success-bg);color:var(--cc-alert-success-color)}.cc-alert.cc-alert-error{background-color:var(--cc-alert-error-bg);color:var(--cc-alert-error-color)}.cc-alert.cc-alert-error .cc-alert-icon{color:var(--cc-alert-error-color)}\n"] }]
367
+ }], ctorParameters: () => [], propDecorators: { variant: [{
368
+ type: Input
369
+ }], title: [{
370
+ type: Input
371
+ }], message: [{
372
+ type: Input
373
+ }], icon: [{
374
+ type: Input
375
+ }], customIcon: [{
376
+ type: Input
377
+ }], width: [{
378
+ type: Input
379
+ }], height: [{
380
+ type: Input
381
+ }], borderRadius: [{
382
+ type: Input
383
+ }], padding: [{
384
+ type: Input
385
+ }], gap: [{
386
+ type: Input
387
+ }], backgroundColor: [{
388
+ type: Input
389
+ }], color: [{
390
+ type: Input
391
+ }], borderColor: [{
392
+ type: Input
393
+ }], fontSize: [{
394
+ type: Input
395
+ }], fontWeight: [{
396
+ type: Input
397
+ }], boxShadow: [{
398
+ type: Input
399
+ }], borderTopLeftRadius: [{
400
+ type: Input
401
+ }], borderTopRightRadius: [{
402
+ type: Input
403
+ }], borderBottomLeftRadius: [{
404
+ type: Input
405
+ }], borderBottomRightRadius: [{
406
+ type: Input
407
+ }] } });
408
+
409
+ class AlertModule {
410
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AlertModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
411
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: AlertModule, declarations: [AlertComponent], imports: [CommonModule], exports: [AlertComponent] });
412
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AlertModule, imports: [CommonModule] });
413
+ }
414
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AlertModule, decorators: [{
415
+ type: NgModule,
416
+ args: [{
417
+ declarations: [
418
+ AlertComponent
419
+ ],
420
+ imports: [
421
+ CommonModule
422
+ ],
423
+ exports: [
424
+ AlertComponent
425
+ ]
426
+ }]
427
+ }] });
428
+
429
+ class ButtonComponent {
430
+ variant = 'primary';
431
+ type = 'button';
432
+ disabled = false;
433
+ // Customization Inputs
434
+ width;
435
+ height;
436
+ borderRadius;
437
+ fontSize;
438
+ fontWeight;
439
+ backgroundColor;
440
+ color;
441
+ border;
442
+ icon = '';
443
+ constructor() { }
444
+ ngOnInit() {
445
+ }
446
+ get isDefaultIcon() {
447
+ return this.icon === true;
448
+ }
449
+ get isStringIcon() {
450
+ return typeof this.icon === 'string' && this.icon !== '';
451
+ }
452
+ get isImgIcon() {
453
+ const icon = this.icon;
454
+ if (typeof icon === 'string') {
455
+ return icon.includes('/') || icon.includes('.') || icon.startsWith('http');
456
+ }
457
+ return typeof icon === 'object' && icon !== null && !!icon.value && (icon.type === 'img' || icon.value.includes('/') || icon.value.includes('.') || icon.value.startsWith('http'));
458
+ }
459
+ get isObjectIcon() {
460
+ return typeof this.icon === 'object' && this.icon !== null;
461
+ }
462
+ get iconString() {
463
+ return typeof this.icon === 'string' ? this.icon : '';
464
+ }
465
+ get iconObject() {
466
+ return typeof this.icon === 'object' ? this.icon : { type: '', value: '' };
467
+ }
468
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
469
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ButtonComponent, isStandalone: false, selector: "lib-button", inputs: { variant: "variant", type: "type", disabled: "disabled", width: "width", height: "height", borderRadius: "borderRadius", fontSize: "fontSize", fontWeight: "fontWeight", backgroundColor: "backgroundColor", color: "color", border: "border", icon: "icon" }, ngImport: i0, template: "<button [type]=\"type\" [disabled]=\"disabled\" class=\"cc-btn\" [ngClass]=\"'cc-btn-' + variant\" [style.width]=\"width\"\r\n [style.height]=\"height\" [style.border-radius]=\"borderRadius\" [style.font-size]=\"fontSize\"\r\n [style.font-weight]=\"fontWeight\" [style.background-color]=\"backgroundColor\" [style.color]=\"color\"\r\n [style.border]=\"border\">\r\n <div class=\"cc-btn-icon-wrapper\" *ngIf=\"icon\">\r\n <!-- String Icons -->\r\n <ng-container *ngIf=\"isStringIcon\">\r\n <i *ngIf=\"!isImgIcon\" [ngClass]=\"iconString\" class=\"cc-btn-icon\"></i>\r\n <img *ngIf=\"isImgIcon\" [src]=\"iconString\" alt=\"button icon\" class=\"cc-btn-icon cc-btn-img-icon\" />\r\n </ng-container>\r\n\r\n <!-- Object Icons -->\r\n <ng-container *ngIf=\"isObjectIcon\">\r\n <i *ngIf=\"iconObject.type === 'fontawesome'\" [ngClass]=\"iconObject.value\" class=\"cc-btn-icon\"></i>\r\n <span *ngIf=\"iconObject.type === 'material'\" class=\"material-icons cc-btn-icon\">{{ iconObject.value }}</span>\r\n <img *ngIf=\"iconObject.type === 'img'\" [src]=\"iconObject.value\" alt=\"button icon\"\r\n class=\"cc-btn-icon cc-btn-img-icon\" />\r\n </ng-container>\r\n </div>\r\n <ng-content></ng-content>\r\n</button>", styles: [".cc-btn{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;cursor:pointer;transition:all .2s ease-in-out;font-family:var(--cc-btn-font-family);font-weight:var(--cc-btn-font-weight);font-size:var(--cc-btn-font-size);padding:var(--cc-btn-padding)}.cc-btn:disabled{opacity:var(--cc-btn-disabled-opacity);cursor:var(--cc-btn-disabled-cursor);pointer-events:none}.cc-btn.cc-btn-primary{background-color:var(--cc-btn-primary-bg);color:var(--cc-btn-primary-color);border-radius:var(--cc-btn-primary-radius);border:var(--cc-btn-primary-border)}.cc-btn.cc-btn-warning{background-color:var(--cc-btn-warning-bg);color:var(--cc-btn-warning-color);border-radius:var(--cc-btn-warning-radius);border:var(--cc-btn-warning-border)}.cc-btn.cc-btn-outline{background-color:var(--cc-btn-outline-bg);color:var(--cc-btn-outline-color);border-radius:var(--cc-btn-outline-radius);border:var(--cc-btn-outline-border)}.cc-btn.cc-btn-secondary{background-color:var(--cc-btn-secondary-bg);color:var(--cc-btn-secondary-color);border-radius:var(--cc-btn-secondary-radius);border:var(--cc-btn-secondary-border)}.cc-btn.cc-btn-success{background-color:var(--cc-btn-success-bg);color:var(--cc-btn-success-color);border-radius:var(--cc-btn-success-radius);border:var(--cc-btn-success-border)}.cc-btn.cc-btn-danger{background-color:var(--cc-btn-danger-bg);color:var(--cc-btn-danger-color);border-radius:var(--cc-btn-danger-radius);border:var(--cc-btn-danger-border)}.cc-btn.cc-btn-danger-outline{background-color:var(--cc-btn-danger-outline-bg);color:var(--cc-btn-danger-outline-color);border-radius:var(--cc-btn-danger-outline-radius);border:var(--cc-btn-danger-outline-border)}.cc-btn .cc-btn-icon-wrapper{display:inline-flex;align-items:center;margin-right:.5rem}.cc-btn .cc-btn-icon{font-size:1.1em;line-height:1}.cc-btn .cc-btn-img-icon{width:1.25rem;height:1.25rem;object-fit:contain}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
470
+ }
471
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonComponent, decorators: [{
472
+ type: Component,
473
+ args: [{ selector: 'lib-button', standalone: false, template: "<button [type]=\"type\" [disabled]=\"disabled\" class=\"cc-btn\" [ngClass]=\"'cc-btn-' + variant\" [style.width]=\"width\"\r\n [style.height]=\"height\" [style.border-radius]=\"borderRadius\" [style.font-size]=\"fontSize\"\r\n [style.font-weight]=\"fontWeight\" [style.background-color]=\"backgroundColor\" [style.color]=\"color\"\r\n [style.border]=\"border\">\r\n <div class=\"cc-btn-icon-wrapper\" *ngIf=\"icon\">\r\n <!-- String Icons -->\r\n <ng-container *ngIf=\"isStringIcon\">\r\n <i *ngIf=\"!isImgIcon\" [ngClass]=\"iconString\" class=\"cc-btn-icon\"></i>\r\n <img *ngIf=\"isImgIcon\" [src]=\"iconString\" alt=\"button icon\" class=\"cc-btn-icon cc-btn-img-icon\" />\r\n </ng-container>\r\n\r\n <!-- Object Icons -->\r\n <ng-container *ngIf=\"isObjectIcon\">\r\n <i *ngIf=\"iconObject.type === 'fontawesome'\" [ngClass]=\"iconObject.value\" class=\"cc-btn-icon\"></i>\r\n <span *ngIf=\"iconObject.type === 'material'\" class=\"material-icons cc-btn-icon\">{{ iconObject.value }}</span>\r\n <img *ngIf=\"iconObject.type === 'img'\" [src]=\"iconObject.value\" alt=\"button icon\"\r\n class=\"cc-btn-icon cc-btn-img-icon\" />\r\n </ng-container>\r\n </div>\r\n <ng-content></ng-content>\r\n</button>", styles: [".cc-btn{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;cursor:pointer;transition:all .2s ease-in-out;font-family:var(--cc-btn-font-family);font-weight:var(--cc-btn-font-weight);font-size:var(--cc-btn-font-size);padding:var(--cc-btn-padding)}.cc-btn:disabled{opacity:var(--cc-btn-disabled-opacity);cursor:var(--cc-btn-disabled-cursor);pointer-events:none}.cc-btn.cc-btn-primary{background-color:var(--cc-btn-primary-bg);color:var(--cc-btn-primary-color);border-radius:var(--cc-btn-primary-radius);border:var(--cc-btn-primary-border)}.cc-btn.cc-btn-warning{background-color:var(--cc-btn-warning-bg);color:var(--cc-btn-warning-color);border-radius:var(--cc-btn-warning-radius);border:var(--cc-btn-warning-border)}.cc-btn.cc-btn-outline{background-color:var(--cc-btn-outline-bg);color:var(--cc-btn-outline-color);border-radius:var(--cc-btn-outline-radius);border:var(--cc-btn-outline-border)}.cc-btn.cc-btn-secondary{background-color:var(--cc-btn-secondary-bg);color:var(--cc-btn-secondary-color);border-radius:var(--cc-btn-secondary-radius);border:var(--cc-btn-secondary-border)}.cc-btn.cc-btn-success{background-color:var(--cc-btn-success-bg);color:var(--cc-btn-success-color);border-radius:var(--cc-btn-success-radius);border:var(--cc-btn-success-border)}.cc-btn.cc-btn-danger{background-color:var(--cc-btn-danger-bg);color:var(--cc-btn-danger-color);border-radius:var(--cc-btn-danger-radius);border:var(--cc-btn-danger-border)}.cc-btn.cc-btn-danger-outline{background-color:var(--cc-btn-danger-outline-bg);color:var(--cc-btn-danger-outline-color);border-radius:var(--cc-btn-danger-outline-radius);border:var(--cc-btn-danger-outline-border)}.cc-btn .cc-btn-icon-wrapper{display:inline-flex;align-items:center;margin-right:.5rem}.cc-btn .cc-btn-icon{font-size:1.1em;line-height:1}.cc-btn .cc-btn-img-icon{width:1.25rem;height:1.25rem;object-fit:contain}\n"] }]
474
+ }], ctorParameters: () => [], propDecorators: { variant: [{
475
+ type: Input
476
+ }], type: [{
477
+ type: Input
478
+ }], disabled: [{
479
+ type: Input
480
+ }], width: [{
481
+ type: Input
482
+ }], height: [{
483
+ type: Input
484
+ }], borderRadius: [{
485
+ type: Input
486
+ }], fontSize: [{
487
+ type: Input
488
+ }], fontWeight: [{
489
+ type: Input
490
+ }], backgroundColor: [{
491
+ type: Input
492
+ }], color: [{
493
+ type: Input
494
+ }], border: [{
495
+ type: Input
496
+ }], icon: [{
497
+ type: Input
498
+ }] } });
499
+
500
+ class ButtonModule {
501
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
502
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: ButtonModule, declarations: [ButtonComponent], imports: [CommonModule], exports: [ButtonComponent] });
503
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonModule, imports: [CommonModule] });
504
+ }
505
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonModule, decorators: [{
506
+ type: NgModule,
507
+ args: [{
508
+ declarations: [
509
+ ButtonComponent
510
+ ],
511
+ imports: [
512
+ CommonModule
513
+ ],
514
+ exports: [
515
+ ButtonComponent
516
+ ]
517
+ }]
518
+ }] });
519
+
520
+ class ConfirmationModalComponent {
521
+ config;
522
+ isOpen = false;
523
+ confirm = new EventEmitter();
524
+ cancel = new EventEmitter();
525
+ close = new EventEmitter();
526
+ showCodeSnippet = new EventEmitter();
527
+ // Default configuration
528
+ defaultConfig = {
529
+ headerTheme: 'dark', // Changed to dark as per new default requirement
530
+ width: '560px',
531
+ size: 'md',
532
+ closeOnBackdrop: true,
533
+ closeOnEsc: true,
534
+ showCloseButton: true,
535
+ cancelButton: {
536
+ label: 'Cancel',
537
+ show: true
538
+ }
539
+ };
540
+ mergedConfig;
541
+ previousActiveElement = null;
542
+ ngOnInit() {
543
+ this.updateConfig();
544
+ // Store currently focused element
545
+ this.previousActiveElement = document.activeElement;
546
+ // Prevent body scroll when modal is open
547
+ if (this.isOpen) {
548
+ this.toggleBodyScroll(true);
549
+ }
550
+ }
551
+ ngOnChanges() {
552
+ this.updateConfig();
553
+ if (this.isOpen !== undefined) {
554
+ this.toggleBodyScroll(this.isOpen);
555
+ }
556
+ }
557
+ updateConfig() {
558
+ // Merge user config with defaults
559
+ this.mergedConfig = {
560
+ ...this.defaultConfig,
561
+ ...this.config,
562
+ cancelButton: {
563
+ ...this.defaultConfig.cancelButton,
564
+ ...this.config.cancelButton
565
+ },
566
+ confirmButton: {
567
+ ...this.config.confirmButton
568
+ }
569
+ };
570
+ }
571
+ ngOnDestroy() {
572
+ // Restore body scroll
573
+ this.toggleBodyScroll(false);
574
+ // Restore focus to previous element
575
+ if (this.previousActiveElement) {
576
+ this.previousActiveElement.focus();
577
+ }
578
+ }
579
+ toggleBodyScroll(disable) {
580
+ if (disable) {
581
+ document.body.style.overflow = 'hidden';
582
+ }
583
+ else {
584
+ document.body.style.overflow = '';
585
+ }
586
+ }
587
+ handleEscape(event) {
588
+ if (this.isOpen && this.mergedConfig.closeOnEsc) {
589
+ event.preventDefault();
590
+ this.onClose();
591
+ }
592
+ }
593
+ onBackdropClick(event) {
594
+ // Only close if clicking directly on backdrop, not modal content
595
+ if (this.mergedConfig.closeOnBackdrop &&
596
+ event.target === event.currentTarget) {
597
+ this.onClose();
598
+ }
599
+ }
600
+ onConfirm() {
601
+ if (!this.mergedConfig.confirmButton.disabled &&
602
+ !this.mergedConfig.confirmButton.loading) {
603
+ this.confirm.emit();
604
+ }
605
+ }
606
+ onCancel() {
607
+ this.cancel.emit();
608
+ }
609
+ onClose() {
610
+ this.close.emit();
611
+ }
612
+ onShowCodeSnippet() {
613
+ this.showCodeSnippet.emit();
614
+ }
615
+ getModalWidth() {
616
+ if (this.mergedConfig.size) {
617
+ const sizeMap = {
618
+ sm: '400px',
619
+ md: '560px',
620
+ lg: '720px'
621
+ };
622
+ return sizeMap[this.mergedConfig.size];
623
+ }
624
+ return this.mergedConfig.width || '560px';
625
+ }
626
+ getConfirmButtonClass() {
627
+ const typeMap = {
628
+ primary: 'cc-btn-primary',
629
+ danger: 'cc-btn-danger',
630
+ warning: 'cc-btn-warning'
631
+ };
632
+ return `cc-btn ${typeMap[this.mergedConfig.confirmButton.type]}`;
633
+ }
634
+ getHeaderClass() {
635
+ return `modal-header modal-header--${this.mergedConfig.headerTheme}`;
636
+ }
637
+ resolveIconType(icon) {
638
+ if (typeof icon === 'string') {
639
+ if (icon.includes('/') || icon.includes('.') || icon.startsWith('http')) {
640
+ return 'img';
641
+ }
642
+ return 'material';
643
+ }
644
+ if (icon && typeof icon === 'object') {
645
+ if (icon.type === 'custom' || (icon.value && (icon.value.includes('/') || icon.value.includes('.') || icon.value.startsWith('http')))) {
646
+ return 'custom';
647
+ }
648
+ return icon.type || 'material';
649
+ }
650
+ return 'material';
651
+ }
652
+ getIconValue(icon) {
653
+ return typeof icon === 'string' ? icon : icon?.value;
654
+ }
655
+ getIconColor(icon) {
656
+ return typeof icon === 'object' ? icon.color : undefined;
657
+ }
658
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
659
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ConfirmationModalComponent, isStandalone: false, selector: "cc-confirmation-modal", inputs: { config: "config", isOpen: "isOpen" }, outputs: { confirm: "confirm", cancel: "cancel", close: "close", showCodeSnippet: "showCodeSnippet" }, host: { listeners: { "document:keydown.escape": "handleEscape($event)" } }, usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"isOpen\" class=\"cc-modal-backdrop\" (click)=\"onBackdropClick($event)\" role=\"dialog\" [attr.aria-modal]=\"true\"\r\n [attr.aria-labelledby]=\"'modal-title-' + mergedConfig.title\" [attr.aria-label]=\"mergedConfig.ariaLabel\"\r\n [attr.aria-describedby]=\"mergedConfig.ariaDescribedBy\">\r\n\r\n <div class=\"cc-modal-container {{ mergedConfig.customClass }}\" [style.width]=\"getModalWidth()\"\r\n [style.background-color]=\"mergedConfig.backgroundColor\" [style.border-radius]=\"mergedConfig.borderRadius\"\r\n [style.border-top-left-radius]=\"mergedConfig.borderTopLeftRadius\"\r\n [style.border-top-right-radius]=\"mergedConfig.borderTopRightRadius\"\r\n [style.border-bottom-left-radius]=\"mergedConfig.borderBottomLeftRadius\"\r\n [style.border-bottom-right-radius]=\"mergedConfig.borderBottomRightRadius\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header -->\r\n <div [ngClass]=\"getHeaderClass()\" [style.background-color]=\"mergedConfig.headerBackgroundColor\"\r\n [style.border-bottom]=\"mergedConfig.headerBorderBottom\">\r\n <div class=\"modal-header__content\">\r\n <!-- Icon (Optional) -->\r\n <span *ngIf=\"mergedConfig.icon\" class=\"modal-header__icon\">\r\n <ng-container [ngSwitch]=\"resolveIconType(mergedConfig.icon)\">\r\n <mat-icon *ngSwitchCase=\"'material'\" [style.color]=\"getIconColor(mergedConfig.icon)\">\r\n {{ getIconValue(mergedConfig.icon) }}\r\n </mat-icon>\r\n <img *ngSwitchCase=\"'custom'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [alt]=\"mergedConfig.title + ' icon'\" class=\"modal-header__custom-icon\">\r\n <img *ngSwitchCase=\"'img'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [alt]=\"mergedConfig.title + ' icon'\" class=\"modal-header__custom-icon\">\r\n </ng-container>\r\n </span>\r\n\r\n <!-- Title -->\r\n <h2 class=\"modal-header__title\" [id]=\"'modal-title-' + mergedConfig.title\"\r\n [style.color]=\"mergedConfig.headerTextColor\">\r\n {{ mergedConfig.title }}\r\n </h2>\r\n </div>\r\n\r\n <!-- Code Snippet Button -->\r\n <button *ngIf=\"mergedConfig.showCodeSnippetButton\" type=\"button\" class=\"modal-header__code-btn\"\r\n (click)=\"onShowCodeSnippet()\" aria-label=\"Show code snippet\" title=\"Show Code Snippet\">\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n\r\n <!-- Close Button -->\r\n <button *ngIf=\"mergedConfig.showCloseButton\" type=\"button\" class=\"modal-header__close\" (click)=\"onClose()\"\r\n aria-label=\"Close modal\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Body (Content Projection) -->\r\n <div class=\"cc-modal-body\" [style.padding]=\"mergedConfig.padding\" [style.color]=\"mergedConfig.bodyTextColor\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-modal-footer\" [style.background-color]=\"mergedConfig.footerBackgroundColor\"\r\n [style.border-top]=\"mergedConfig.footerBorderTop\">\r\n\r\n <ng-container *ngIf=\"!mergedConfig.customFooter\">\r\n <button *ngIf=\"mergedConfig.cancelButton?.show\" type=\"button\" class=\"cc-btn cc-btn-secondary\"\r\n (click)=\"onCancel()\">\r\n {{ mergedConfig.cancelButton?.label || 'Cancel' }}\r\n </button>\r\n\r\n <button type=\"button\" [ngClass]=\"getConfirmButtonClass()\"\r\n [disabled]=\"mergedConfig.confirmButton.disabled || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"mergedConfig.confirmButton.loading\" class=\"cc-btn-spinner\"></span>\r\n {{ mergedConfig.confirmButton.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <ng-content select=\"[cc-modal-footer]\"></ng-content>\r\n </div>\r\n </div>\r\n</div>", styles: [".cc-modal-backdrop{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn .2s ease-in-out}.cc-modal-container{background:var(--cc-modal-bg);border-radius:var(--cc-modal-radius);box-shadow:var(--cc-modal-shadow);border:var(--cc-modal-border, none);display:flex;flex-direction:column;max-height:90vh;max-width:90vw;animation:slideIn .3s ease-out;overflow:hidden}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--cc-modal-header-padding);border-bottom:var(--cc-modal-header-border-bottom)}.modal-header__content{display:flex;align-items:center;gap:.75rem;flex:1}.modal-header__icon{display:flex;align-items:center;justify-content:center}.modal-header__icon mat-icon{font-size:var(--cc-modal-icon-size, 1.5rem);width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem)}.modal-header__custom-icon{width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem);object-fit:contain}.modal-header__title{margin:0;font-size:var(--cc-modal-title-size);font-weight:var(--cc-modal-title-weight);line-height:1.4;color:var(--cc-modal-title-color)}.modal-header__close{background:none;border:none;padding:.25rem;cursor:pointer;color:#6b7280;transition:color .2s;display:flex;align-items:center}.modal-header__close:hover{color:#111827}.modal-header__close mat-icon{font-size:var(--cc-modal-close-icon-size, 1.25rem);width:var(--cc-modal-close-icon-size, 1.25rem);height:var(--cc-modal-close-icon-size, 1.25rem)}.modal-header__code-btn{background:none;border:none;padding:.25rem;margin-right:.5rem;cursor:pointer;color:#6b7280;transition:all .2s;display:flex;align-items:center}.modal-header__code-btn:hover{color:#ef4444;transform:scale(1.1)}.modal-header__code-btn mat-icon{font-size:1.15rem;width:1.15rem;height:1.15rem}.modal-header--dark{background-color:var(--cc-modal-header-bg-dark);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark)}.modal-header--dark .modal-header__close{color:#ffffffb3}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:#ffffffb3}.modal-header--dark .modal-header__code-btn:hover{color:#fff}.cc-modal-body{padding:var(--cc-modal-body-padding);overflow-y:auto;flex:1;color:var(--cc-modal-body-color);font-size:.875rem;line-height:1.6}.cc-modal-body ::ng-deep input[type=text],.cc-modal-body ::ng-deep textarea,.cc-modal-body ::ng-deep select{width:100%;padding:var(--cc-modal-input-padding, .625rem .75rem);border:.0625rem solid #D1D5DB;border-radius:var(--cc-modal-input-radius, .375rem);font-size:var(--cc-modal-input-font-size, .875rem);transition:border-color .2s}.cc-modal-body ::ng-deep input[type=text]:focus,.cc-modal-body ::ng-deep textarea:focus,.cc-modal-body ::ng-deep select:focus{outline:none;border-color:var(--cc-btn-primary-bg, #3b82f6);box-shadow:0 0 0 .1875rem #3b82f61a}.cc-modal-body ::ng-deep textarea{resize:vertical;min-height:var(--cc-modal-textarea-min-height, 6.25rem)}.cc-modal-body ::ng-deep label{display:block;margin-bottom:var(--cc-modal-label-margin-bottom, .5rem);font-weight:500;color:var(--cc-modal-body-color)}.cc-modal-body ::ng-deep .required:after{content:\" *\";color:#ef4444}.cc-modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:.75rem;padding:var(--cc-modal-footer-padding);border-top:var(--cc-modal-footer-border-top);background:var(--cc-modal-footer-bg)}.cc-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:var(--cc-btn-padding, .5rem 1rem);font-family:var(--cc-btn-font-family, inherit);font-weight:var(--cc-btn-font-weight, 500);font-size:var(--cc-btn-font-size, .875rem);cursor:pointer;transition:all .2s;min-width:5rem}.cc-btn:disabled{opacity:var(--cc-btn-disabled-opacity, .6);cursor:var(--cc-btn-disabled-cursor, not-allowed)}.cc-btn-secondary{background:var(--cc-btn-secondary-bg);color:var(--cc-btn-secondary-color);border:var(--cc-btn-secondary-border);border-radius:var(--cc-btn-secondary-radius)}.cc-btn-primary{background:var(--cc-btn-primary-bg);color:var(--cc-btn-primary-color);border:var(--cc-btn-primary-border);border-radius:var(--cc-btn-primary-radius)}.cc-btn-danger{background:var(--cc-btn-danger-bg);color:var(--cc-btn-danger-color);border:var(--cc-btn-danger-border);border-radius:var(--cc-btn-danger-radius)}.cc-btn-warning{background:var(--cc-btn-warning-bg);color:var(--cc-btn-warning-color);border:var(--cc-btn-warning-border);border-radius:var(--cc-btn-warning-radius)}.cc-btn-spinner{width:var(--cc-modal-spinner-size, 1rem);height:var(--cc-modal-spinner-size, 1rem);border:.125rem solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{transform:translateY(-1.25rem);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@media(max-width:40rem){.cc-modal-container{width:95vw!important;max-height:95vh}.modal-header,.cc-modal-body{padding:1rem}.cc-modal-footer{padding:.75rem 1rem;flex-direction:column}.cc-modal-footer .cc-btn{width:100%}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
660
+ }
661
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalComponent, decorators: [{
662
+ type: Component,
663
+ args: [{ selector: 'cc-confirmation-modal', standalone: false, template: "<div *ngIf=\"isOpen\" class=\"cc-modal-backdrop\" (click)=\"onBackdropClick($event)\" role=\"dialog\" [attr.aria-modal]=\"true\"\r\n [attr.aria-labelledby]=\"'modal-title-' + mergedConfig.title\" [attr.aria-label]=\"mergedConfig.ariaLabel\"\r\n [attr.aria-describedby]=\"mergedConfig.ariaDescribedBy\">\r\n\r\n <div class=\"cc-modal-container {{ mergedConfig.customClass }}\" [style.width]=\"getModalWidth()\"\r\n [style.background-color]=\"mergedConfig.backgroundColor\" [style.border-radius]=\"mergedConfig.borderRadius\"\r\n [style.border-top-left-radius]=\"mergedConfig.borderTopLeftRadius\"\r\n [style.border-top-right-radius]=\"mergedConfig.borderTopRightRadius\"\r\n [style.border-bottom-left-radius]=\"mergedConfig.borderBottomLeftRadius\"\r\n [style.border-bottom-right-radius]=\"mergedConfig.borderBottomRightRadius\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header -->\r\n <div [ngClass]=\"getHeaderClass()\" [style.background-color]=\"mergedConfig.headerBackgroundColor\"\r\n [style.border-bottom]=\"mergedConfig.headerBorderBottom\">\r\n <div class=\"modal-header__content\">\r\n <!-- Icon (Optional) -->\r\n <span *ngIf=\"mergedConfig.icon\" class=\"modal-header__icon\">\r\n <ng-container [ngSwitch]=\"resolveIconType(mergedConfig.icon)\">\r\n <mat-icon *ngSwitchCase=\"'material'\" [style.color]=\"getIconColor(mergedConfig.icon)\">\r\n {{ getIconValue(mergedConfig.icon) }}\r\n </mat-icon>\r\n <img *ngSwitchCase=\"'custom'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [alt]=\"mergedConfig.title + ' icon'\" class=\"modal-header__custom-icon\">\r\n <img *ngSwitchCase=\"'img'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [alt]=\"mergedConfig.title + ' icon'\" class=\"modal-header__custom-icon\">\r\n </ng-container>\r\n </span>\r\n\r\n <!-- Title -->\r\n <h2 class=\"modal-header__title\" [id]=\"'modal-title-' + mergedConfig.title\"\r\n [style.color]=\"mergedConfig.headerTextColor\">\r\n {{ mergedConfig.title }}\r\n </h2>\r\n </div>\r\n\r\n <!-- Code Snippet Button -->\r\n <button *ngIf=\"mergedConfig.showCodeSnippetButton\" type=\"button\" class=\"modal-header__code-btn\"\r\n (click)=\"onShowCodeSnippet()\" aria-label=\"Show code snippet\" title=\"Show Code Snippet\">\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n\r\n <!-- Close Button -->\r\n <button *ngIf=\"mergedConfig.showCloseButton\" type=\"button\" class=\"modal-header__close\" (click)=\"onClose()\"\r\n aria-label=\"Close modal\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Body (Content Projection) -->\r\n <div class=\"cc-modal-body\" [style.padding]=\"mergedConfig.padding\" [style.color]=\"mergedConfig.bodyTextColor\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-modal-footer\" [style.background-color]=\"mergedConfig.footerBackgroundColor\"\r\n [style.border-top]=\"mergedConfig.footerBorderTop\">\r\n\r\n <ng-container *ngIf=\"!mergedConfig.customFooter\">\r\n <button *ngIf=\"mergedConfig.cancelButton?.show\" type=\"button\" class=\"cc-btn cc-btn-secondary\"\r\n (click)=\"onCancel()\">\r\n {{ mergedConfig.cancelButton?.label || 'Cancel' }}\r\n </button>\r\n\r\n <button type=\"button\" [ngClass]=\"getConfirmButtonClass()\"\r\n [disabled]=\"mergedConfig.confirmButton.disabled || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"mergedConfig.confirmButton.loading\" class=\"cc-btn-spinner\"></span>\r\n {{ mergedConfig.confirmButton.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <ng-content select=\"[cc-modal-footer]\"></ng-content>\r\n </div>\r\n </div>\r\n</div>", styles: [".cc-modal-backdrop{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn .2s ease-in-out}.cc-modal-container{background:var(--cc-modal-bg);border-radius:var(--cc-modal-radius);box-shadow:var(--cc-modal-shadow);border:var(--cc-modal-border, none);display:flex;flex-direction:column;max-height:90vh;max-width:90vw;animation:slideIn .3s ease-out;overflow:hidden}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:var(--cc-modal-header-padding);border-bottom:var(--cc-modal-header-border-bottom)}.modal-header__content{display:flex;align-items:center;gap:.75rem;flex:1}.modal-header__icon{display:flex;align-items:center;justify-content:center}.modal-header__icon mat-icon{font-size:var(--cc-modal-icon-size, 1.5rem);width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem)}.modal-header__custom-icon{width:var(--cc-modal-icon-size, 1.5rem);height:var(--cc-modal-icon-size, 1.5rem);object-fit:contain}.modal-header__title{margin:0;font-size:var(--cc-modal-title-size);font-weight:var(--cc-modal-title-weight);line-height:1.4;color:var(--cc-modal-title-color)}.modal-header__close{background:none;border:none;padding:.25rem;cursor:pointer;color:#6b7280;transition:color .2s;display:flex;align-items:center}.modal-header__close:hover{color:#111827}.modal-header__close mat-icon{font-size:var(--cc-modal-close-icon-size, 1.25rem);width:var(--cc-modal-close-icon-size, 1.25rem);height:var(--cc-modal-close-icon-size, 1.25rem)}.modal-header__code-btn{background:none;border:none;padding:.25rem;margin-right:.5rem;cursor:pointer;color:#6b7280;transition:all .2s;display:flex;align-items:center}.modal-header__code-btn:hover{color:#ef4444;transform:scale(1.1)}.modal-header__code-btn mat-icon{font-size:1.15rem;width:1.15rem;height:1.15rem}.modal-header--dark{background-color:var(--cc-modal-header-bg-dark);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark)}.modal-header--dark .modal-header__close{color:#ffffffb3}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:#ffffffb3}.modal-header--dark .modal-header__code-btn:hover{color:#fff}.cc-modal-body{padding:var(--cc-modal-body-padding);overflow-y:auto;flex:1;color:var(--cc-modal-body-color);font-size:.875rem;line-height:1.6}.cc-modal-body ::ng-deep input[type=text],.cc-modal-body ::ng-deep textarea,.cc-modal-body ::ng-deep select{width:100%;padding:var(--cc-modal-input-padding, .625rem .75rem);border:.0625rem solid #D1D5DB;border-radius:var(--cc-modal-input-radius, .375rem);font-size:var(--cc-modal-input-font-size, .875rem);transition:border-color .2s}.cc-modal-body ::ng-deep input[type=text]:focus,.cc-modal-body ::ng-deep textarea:focus,.cc-modal-body ::ng-deep select:focus{outline:none;border-color:var(--cc-btn-primary-bg, #3b82f6);box-shadow:0 0 0 .1875rem #3b82f61a}.cc-modal-body ::ng-deep textarea{resize:vertical;min-height:var(--cc-modal-textarea-min-height, 6.25rem)}.cc-modal-body ::ng-deep label{display:block;margin-bottom:var(--cc-modal-label-margin-bottom, .5rem);font-weight:500;color:var(--cc-modal-body-color)}.cc-modal-body ::ng-deep .required:after{content:\" *\";color:#ef4444}.cc-modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:.75rem;padding:var(--cc-modal-footer-padding);border-top:var(--cc-modal-footer-border-top);background:var(--cc-modal-footer-bg)}.cc-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;padding:var(--cc-btn-padding, .5rem 1rem);font-family:var(--cc-btn-font-family, inherit);font-weight:var(--cc-btn-font-weight, 500);font-size:var(--cc-btn-font-size, .875rem);cursor:pointer;transition:all .2s;min-width:5rem}.cc-btn:disabled{opacity:var(--cc-btn-disabled-opacity, .6);cursor:var(--cc-btn-disabled-cursor, not-allowed)}.cc-btn-secondary{background:var(--cc-btn-secondary-bg);color:var(--cc-btn-secondary-color);border:var(--cc-btn-secondary-border);border-radius:var(--cc-btn-secondary-radius)}.cc-btn-primary{background:var(--cc-btn-primary-bg);color:var(--cc-btn-primary-color);border:var(--cc-btn-primary-border);border-radius:var(--cc-btn-primary-radius)}.cc-btn-danger{background:var(--cc-btn-danger-bg);color:var(--cc-btn-danger-color);border:var(--cc-btn-danger-border);border-radius:var(--cc-btn-danger-radius)}.cc-btn-warning{background:var(--cc-btn-warning-bg);color:var(--cc-btn-warning-color);border:var(--cc-btn-warning-border);border-radius:var(--cc-btn-warning-radius)}.cc-btn-spinner{width:var(--cc-modal-spinner-size, 1rem);height:var(--cc-modal-spinner-size, 1rem);border:.125rem solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideIn{0%{transform:translateY(-1.25rem);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes spin{to{transform:rotate(360deg)}}@media(max-width:40rem){.cc-modal-container{width:95vw!important;max-height:95vh}.modal-header,.cc-modal-body{padding:1rem}.cc-modal-footer{padding:.75rem 1rem;flex-direction:column}.cc-modal-footer .cc-btn{width:100%}}\n"] }]
664
+ }], propDecorators: { config: [{
665
+ type: Input
666
+ }], isOpen: [{
667
+ type: Input
668
+ }], confirm: [{
669
+ type: Output
670
+ }], cancel: [{
671
+ type: Output
672
+ }], close: [{
673
+ type: Output
674
+ }], showCodeSnippet: [{
675
+ type: Output
676
+ }], handleEscape: [{
677
+ type: HostListener,
678
+ args: ['document:keydown.escape', ['$event']]
679
+ }] } });
680
+
681
+ class ConfirmationModalModule {
682
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
683
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, declarations: [ConfirmationModalComponent], imports: [CommonModule,
684
+ MatIconModule, // For material icons support
685
+ FormsModule // For ngModel in user examples (although mostly projected content, user might need it)
686
+ ], exports: [ConfirmationModalComponent] });
687
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, imports: [CommonModule,
688
+ MatIconModule, // For material icons support
689
+ FormsModule // For ngModel in user examples (although mostly projected content, user might need it)
690
+ ] });
691
+ }
692
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, decorators: [{
693
+ type: NgModule,
694
+ args: [{
695
+ declarations: [
696
+ ConfirmationModalComponent
697
+ ],
698
+ imports: [
699
+ CommonModule,
700
+ MatIconModule, // For material icons support
701
+ FormsModule // For ngModel in user examples (although mostly projected content, user might need it)
702
+ ],
703
+ exports: [
704
+ ConfirmationModalComponent
705
+ ]
706
+ }]
707
+ }] });
708
+
709
+ class FilterSidebarComponent {
710
+ router;
711
+ route;
712
+ config;
713
+ initialFilters = {};
714
+ filterChange = new EventEmitter();
715
+ filterApply = new EventEmitter();
716
+ filterClear = new EventEmitter();
717
+ tabChange = new EventEmitter();
718
+ showCodeSnippet = new EventEmitter();
719
+ filters = {};
720
+ selectedTabId = null;
721
+ // ControlValueAccessor callbacks
722
+ onChange = () => { };
723
+ onTouched = () => { };
724
+ constructor(router, route) {
725
+ this.router = router;
726
+ this.route = route;
727
+ }
728
+ ngOnInit() {
729
+ if (this.initialFilters) {
730
+ this.filters = { ...this.initialFilters };
731
+ }
732
+ // Initialize from URL query params
733
+ this.route.queryParams.subscribe(params => {
734
+ if (Object.keys(params).length > 0) {
735
+ // Merge params into filters, handling potential array/string conversions if needed
736
+ // For now assuming direct mapping or basic string values
737
+ this.filters = { ...this.filters, ...params };
738
+ }
739
+ });
740
+ // Initialize Tabs
741
+ if (this.config?.tabs?.items?.length) {
742
+ if (this.config.tabs.defaultActive) {
743
+ this.selectedTabId = this.config.tabs.defaultActive;
744
+ }
745
+ else {
746
+ this.selectedTabId = this.config.tabs.items[0].id;
747
+ }
748
+ }
749
+ }
750
+ // ControlValueAccessor Implementation
751
+ writeValue(value) {
752
+ if (value) {
753
+ this.filters = { ...value };
754
+ }
755
+ else {
756
+ this.filters = {};
757
+ }
758
+ }
759
+ registerOnChange(fn) {
760
+ this.onChange = fn;
761
+ }
762
+ registerOnTouched(fn) {
763
+ this.onTouched = fn;
764
+ }
765
+ // Component Logic
766
+ onTabClick(tab) {
767
+ this.selectedTabId = tab.id;
768
+ this.tabChange.emit(tab.id);
769
+ }
770
+ onFilterChange(key, value, isMulti = false) {
771
+ if (isMulti) {
772
+ this.toggleFilterValue(key, value);
773
+ }
774
+ else {
775
+ this.filters[key] = value;
776
+ }
777
+ // Notify Generic Change
778
+ this.notifyChanges(key, this.filters[key]);
779
+ }
780
+ toggleFilterValue(key, value) {
781
+ const currentValues = this.filters[key] || [];
782
+ if (Array.isArray(currentValues)) {
783
+ const index = currentValues.indexOf(value);
784
+ if (index > -1) {
785
+ // Remove value
786
+ this.filters[key] = currentValues.filter((v) => v !== value);
787
+ }
788
+ else {
789
+ // Add value
790
+ this.filters[key] = [...currentValues, value];
791
+ }
792
+ }
793
+ else {
794
+ // Initialize array if undefined
795
+ this.filters[key] = [value];
796
+ }
797
+ }
798
+ notifyChanges(key, value) {
799
+ this.onChange(this.filters);
800
+ // Update URL
801
+ this.updateUrl();
802
+ this.filterChange.emit({
803
+ key,
804
+ value,
805
+ allFilters: this.filters
806
+ });
807
+ }
808
+ updateUrl() {
809
+ this.router.navigate([], {
810
+ relativeTo: this.route,
811
+ queryParams: this.filters,
812
+ queryParamsHandling: 'merge', // Merge with existing params
813
+ replaceUrl: true // Don't create new history entry for every filter change
814
+ });
815
+ }
816
+ applyFilters() {
817
+ this.filterApply.emit(this.filters);
818
+ }
819
+ clearFilters() {
820
+ this.filters = {};
821
+ this.onChange(this.filters);
822
+ // Clear URL params (navigate with empty queryParams to clear, or reset to defaults)
823
+ // Since we don't know "defaults" specifically for URL here without config,
824
+ // we'll remove the keys currently in filters from the URL.
825
+ // Actually, easiest way to clear specific params is passing null.
826
+ // However, to clear ALL filter related params, we might need a more robust strategy
827
+ // if there are other params we want to keep.
828
+ // For this task, we will just navigate with empty paramsObject for the keys in `filters`
829
+ // or just clear all if that's the intention.
830
+ // Let's try to clear only the keys we know about from the config if possible,
831
+ // but since `filters` is dynamic, let's clear the keys present in the current state before clearing.
832
+ // A safer approach for "Clear All" in a filter sidebar is often to strip query params.
833
+ this.router.navigate([], {
834
+ relativeTo: this.route,
835
+ queryParams: {}, // Clear all query params
836
+ // queryParamsHandling: 'merge' // attributes to merge would need to be null to remove
837
+ });
838
+ this.filterClear.emit();
839
+ }
840
+ trackByFn(index, item) {
841
+ return item.key || index;
842
+ }
843
+ onShowCodeSnippet() {
844
+ this.showCodeSnippet.emit();
845
+ }
846
+ isImgUrl(icon) {
847
+ return icon.includes('/') || icon.includes('.') || icon.startsWith('http');
848
+ }
849
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarComponent, deps: [{ token: i1$1.Router }, { token: i1$1.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
850
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FilterSidebarComponent, isStandalone: false, selector: "lib-filter-sidebar", inputs: { config: "config", initialFilters: "initialFilters" }, outputs: { filterChange: "filterChange", filterApply: "filterApply", filterClear: "filterClear", tabChange: "tabChange", showCodeSnippet: "showCodeSnippet" }, providers: [
851
+ {
852
+ provide: NG_VALUE_ACCESSOR,
853
+ useExisting: forwardRef(() => FilterSidebarComponent),
854
+ multi: true
855
+ }
856
+ ], ngImport: i0, template: "<div class=\"cc-filter-sidebar\">\r\n\r\n <!-- Header with Code Snippet Button -->\r\n <div class=\"cc-filter-header\" *ngIf=\"config?.settings?.showCodeSnippet\">\r\n <button mat-icon-button class=\"cc-code-snippet-btn\" (click)=\"onShowCodeSnippet()\" title=\"Show Code Snippet\">\r\n <i class=\"fas fa-code\"></i>\r\n </button>\r\n </div>\r\n\r\n <!-- Tabs Section -->\r\n <div *ngIf=\"config?.tabs?.items?.length\" class=\"cc-filter-tabs\">\r\n <div *ngFor=\"let tab of config.tabs!.items\" class=\"cc-filter-tab\" [class.active]=\"tab.id === selectedTabId\"\r\n (click)=\"onTabClick(tab)\">\r\n <i *ngIf=\"tab.icon && !isImgUrl(tab.icon)\" [class]=\"tab.icon\"></i>\r\n <img *ngIf=\"tab.icon && isImgUrl(tab.icon)\" [src]=\"tab.icon\" alt=\"icon\" class=\"cc-filter-tab-icon\">\r\n <span>{{ tab.label }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Content -->\r\n <div class=\"cc-filter-content\">\r\n\r\n <ng-container *ngFor=\"let section of config.sections; trackBy: trackByFn\">\r\n\r\n <!-- Accordion Section -->\r\n <mat-accordion *ngIf=\"section.type === 'accordion'\" class=\"cc-filter-accordion\">\r\n <mat-expansion-panel [expanded]=\"section.expanded\" class=\"mat-elevation-z0\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>\r\n {{ section.title }}\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n\r\n <!-- Content of Accordion -->\r\n <ng-container *ngIf=\"section.options\">\r\n <div class=\"cc-filter-group\">\r\n <mat-checkbox *ngFor=\"let option of section.options\"\r\n [checked]=\"filters[section.key]?.includes(option.value)\"\r\n (change)=\"onFilterChange(section.key, option.value, true)\">\r\n {{ option.label }}\r\n </mat-checkbox>\r\n </div>\r\n </ng-container>\r\n </mat-expansion-panel>\r\n </mat-accordion>\r\n\r\n <!-- Select Section -->\r\n <div *ngIf=\"section.type === 'select'\" class=\"cc-filter-section\">\r\n <label *ngIf=\"section.title\" class=\"cc-filter-label\">{{ section.title }}</label>\r\n <mat-form-field appearance=\"outline\" class=\"cc-filter-full-width\">\r\n <mat-select [placeholder]=\"section.placeholder || 'Select'\" [(value)]=\"filters[section.key]\"\r\n [multiple]=\"section.multi\"\r\n (selectionChange)=\"onFilterChange(section.key, $event.value, section.multi)\">\r\n <mat-option *ngFor=\"let option of section.options\" [value]=\"option.value\">\r\n {{ option.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- Radio Group Section -->\r\n <div *ngIf=\"section.type === 'radio-group'\" class=\"cc-filter-section\">\r\n <label *ngIf=\"section.title\" class=\"cc-filter-label\">{{ section.title }}</label>\r\n <mat-radio-group [(ngModel)]=\"filters[section.key]\" (change)=\"onFilterChange(section.key, $event.value)\"\r\n class=\"cc-filter-radio-group\">\r\n <mat-radio-button *ngFor=\"let option of section.options\" [value]=\"option.value\">\r\n {{ option.label }}\r\n </mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n\r\n <!-- Checkbox Group Section (Standalone) -->\r\n <div *ngIf=\"section.type === 'checkbox-group'\" class=\"cc-filter-section\">\r\n <label *ngIf=\"section.title\" class=\"cc-filter-label\">{{ section.title }}</label>\r\n <div class=\"cc-filter-group\">\r\n <mat-checkbox *ngFor=\"let option of section.options\"\r\n [checked]=\"filters[section.key]?.includes(option.value)\"\r\n (change)=\"onFilterChange(section.key, option.value, true)\">\r\n {{ option.label }}\r\n </mat-checkbox>\r\n </div>\r\n </div>\r\n\r\n </ng-container>\r\n\r\n </div>\r\n\r\n <!-- Actions Footer -->\r\n <div class=\"cc-filter-actions\" *ngIf=\"config.actions\">\r\n <button mat-button class=\"cc-btn-text text-danger\" *ngIf=\"config.actions?.clear?.visible !== false\"\r\n (click)=\"clearFilters()\">\r\n {{ config.actions?.clear?.label || 'Clear Filter' }}\r\n </button>\r\n <button mat-flat-button color=\"warn\" class=\"cc-btn-primary\" *ngIf=\"config.actions?.apply?.visible !== false\"\r\n [disabled]=\"config.actions?.apply?.disabled\" (click)=\"applyFilters()\">\r\n {{ config.actions?.apply?.label || 'Apply Filter' }}\r\n </button>\r\n </div>\r\n</div>", styles: [".cc-filter-sidebar{display:flex;flex-direction:column;height:100%;background-color:var(--cc-filter-bg, #ffffff);border-right:1px solid var(--cc-filter-border-color, #E5E7EB);width:var(--cc-filter-width, 320px);box-shadow:2px 0 12px #0000000a;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.cc-filter-header{display:flex;justify-content:flex-end;align-items:center;padding:.75rem 1rem;border-bottom:1px solid #f0f0f0;background-color:var(--cc-filter-header-bg, #fafafa)}.cc-filter-header .cc-code-snippet-btn{color:var(--cc-primary-color, #EF4444);transition:all .2s ease}.cc-filter-header .cc-code-snippet-btn:hover{background-color:#ef444414;transform:scale(1.05)}.cc-filter-header .cc-code-snippet-btn i{font-size:1.1rem}.cc-filter-tabs{display:flex;flex-direction:column;padding:1rem 1.25rem;gap:.625rem;border-bottom:1px solid #E5E7EB;background-color:var(--cc-filter-header-bg, #ffffff)}.cc-filter-tabs .cc-filter-tab{padding:.875rem 1.125rem;border-radius:10px;cursor:pointer;display:flex;align-items:center;gap:.75rem;color:var(--cc-filter-tab-color, #6B7280);font-weight:500;font-size:.9375rem;transition:all .25s cubic-bezier(.4,0,.2,1);border:1.5px solid transparent;position:relative}.cc-filter-tabs .cc-filter-tab:hover{background-color:var(--cc-filter-tab-hover-bg, #F9FAFB);color:var(--cc-filter-tab-hover-color, #374151);transform:translate(2px)}.cc-filter-tabs .cc-filter-tab.active{background:linear-gradient(135deg,#fef2f2,#fee2e2);color:var(--cc-filter-tab-active-color, #DC2626);border-color:var(--cc-filter-tab-active-border, #FECACA);box-shadow:0 2px 8px #ef44441f;font-weight:600}.cc-filter-tabs .cc-filter-tab.active:before{content:\"\";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:60%;background-color:#ef4444;border-radius:0 2px 2px 0}.cc-filter-tabs .cc-filter-tab i{font-size:1.125rem;opacity:.9}.cc-filter-tabs .cc-filter-tab .cc-filter-tab-icon{width:1.125rem;height:1.125rem;object-fit:contain}.cc-filter-content{flex:1;overflow-y:auto;padding:1.5rem;display:flex;flex-direction:column;gap:1.5rem}.cc-filter-section{display:flex;flex-direction:column;gap:.625rem}.cc-filter-group{display:flex;flex-direction:column;gap:.75rem}::ng-deep .cc-filter-group .mat-mdc-checkbox,::ng-deep .cc-filter-group .mat-mdc-radio-button,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button{margin-bottom:.5rem}::ng-deep .cc-filter-group .mat-mdc-checkbox .mdc-checkbox,::ng-deep .cc-filter-group .mat-mdc-checkbox .mdc-radio,::ng-deep .cc-filter-group .mat-mdc-radio-button .mdc-checkbox,::ng-deep .cc-filter-group .mat-mdc-radio-button .mdc-radio,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox .mdc-checkbox,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox .mdc-radio,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button .mdc-checkbox,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button .mdc-radio{padding:8px}::ng-deep .cc-filter-group .mat-mdc-checkbox .mdc-label,::ng-deep .cc-filter-group .mat-mdc-radio-button .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button .mdc-label{font-size:.9375rem;color:#374151;padding-left:8px}::ng-deep .cc-filter-group .mat-mdc-checkbox:hover .mdc-label,::ng-deep .cc-filter-group .mat-mdc-radio-button:hover .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox:hover .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button:hover .mdc-label{color:#111827}::ng-deep .cc-filter-group .mat-mdc-checkbox-checked .mdc-label,::ng-deep .cc-filter-group .mat-mdc-radio-checked .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox-checked .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-radio-checked .mdc-label{font-weight:500;color:#dc2626}.cc-filter-label{font-size:.875rem;font-weight:500;color:var(--cc-filter-section-title-color, #374151);margin-bottom:.25rem}.cc-filter-full-width{width:100%}::ng-deep .cc-filter-accordion .mat-expansion-panel{box-shadow:none!important;background:transparent;border-radius:8px;margin-bottom:.5rem}::ng-deep .cc-filter-accordion .mat-expansion-panel:hover{background-color:#00000003}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header{padding:12px 0;height:auto;min-height:48px;border-radius:8px;transition:all .2s ease}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header.mat-expanded{height:auto;background-color:#ef444405}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header:hover{background-color:#ef44440a!important}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header .mat-content{font-weight:600;color:var(--cc-filter-accordion-title-color, #374151);text-transform:uppercase;font-size:.8125rem;letter-spacing:.05em}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:#ef4444}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-body{padding:.75rem 0 .5rem}.cc-filter-content::-webkit-scrollbar{width:6px}.cc-filter-content::-webkit-scrollbar-track{background:transparent}.cc-filter-content::-webkit-scrollbar-thumb{background-color:#0000001a;border-radius:3px}.cc-filter-content:hover::-webkit-scrollbar-thumb{background-color:#0003}::ng-deep .cc-filter-full-width.mat-mdc-form-field{width:100%}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-text-field-wrapper{background-color:#fff!important;border-radius:8px;padding:0}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mdc-notched-outline__leading,::ng-deep .cc-filter-full-width.mat-mdc-form-field .mdc-notched-outline__notch,::ng-deep .cc-filter-full-width.mat-mdc-form-field .mdc-notched-outline__trailing{border-color:#e2e8f0;border-width:1px;transition:border-color .2s ease}::ng-deep .cc-filter-full-width.mat-mdc-form-field:hover .mdc-notched-outline__leading,::ng-deep .cc-filter-full-width.mat-mdc-form-field:hover .mdc-notched-outline__notch,::ng-deep .cc-filter-full-width.mat-mdc-form-field:hover .mdc-notched-outline__trailing{border-color:#94a3b8}::ng-deep .cc-filter-full-width.mat-mdc-form-field.mat-focused .mdc-notched-outline__leading,::ng-deep .cc-filter-full-width.mat-mdc-form-field.mat-focused .mdc-notched-outline__notch,::ng-deep .cc-filter-full-width.mat-mdc-form-field.mat-focused .mdc-notched-outline__trailing{border-color:var(--cc-primary-color, #EF4444);border-width:2px}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-form-field-flex{padding:0 12px;align-items:center;height:48px}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-form-field-infix{padding:8px 0!important;min-height:unset!important;display:flex;align-items:center}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-select-value{color:#1e293b;font-weight:500;font-size:.9375rem}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-select-placeholder{color:#94a3b8}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-select-arrow{color:#64748b}::ng-deep .mat-mdc-select-panel{background-color:#fff!important;border-radius:8px!important;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d!important;padding:6px 0!important;border:1px solid #E2E8F0;min-width:100%!important;margin-top:4px}::ng-deep .mat-mdc-select-panel .mat-mdc-option{padding:0 16px;height:40px;font-size:.9375rem;color:#334155;transition:background-color .15s ease}::ng-deep .mat-mdc-select-panel .mat-mdc-option:hover{background-color:#f8fafc!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option.mat-mdc-option-active,::ng-deep .mat-mdc-select-panel .mat-mdc-option.mdc-list-item--selected{background-color:#fef2f2!important;color:#ef4444!important;font-weight:500}::ng-deep .mat-mdc-select-panel .mat-mdc-option .mdc-list-item__primary-text{color:inherit}.cc-filter-actions{padding:1.25rem 1.5rem;display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--cc-filter-footer-border-color, #E5E7EB);background:linear-gradient(to bottom,#fafafa,#fff);box-shadow:0 -2px 8px #00000008}.cc-filter-actions button{font-weight:500;border-radius:8px;padding:10px 20px;transition:all .25s ease;text-transform:none;font-size:.9375rem}.cc-filter-actions button.cc-btn-primary{background:linear-gradient(135deg,#ef4444,#dc2626)!important;color:#fff!important;box-shadow:0 2px 8px #ef444440}.cc-filter-actions button.cc-btn-primary:hover{box-shadow:0 4px 12px #ef444459;transform:translateY(-1px)}.cc-filter-actions button.cc-btn-primary:active{transform:translateY(0)}.cc-filter-actions button.cc-btn-text{color:#ef4444!important;font-weight:600}.cc-filter-actions button.cc-btn-text:hover{background-color:#ef444414!important}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i6.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i6.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: i7.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: i8.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i8.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i8.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i8.MatExpansionPanelTitle, selector: "mat-panel-title" }] });
857
+ }
858
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarComponent, decorators: [{
859
+ type: Component,
860
+ args: [{ selector: 'lib-filter-sidebar', standalone: false, providers: [
861
+ {
862
+ provide: NG_VALUE_ACCESSOR,
863
+ useExisting: forwardRef(() => FilterSidebarComponent),
864
+ multi: true
865
+ }
866
+ ], template: "<div class=\"cc-filter-sidebar\">\r\n\r\n <!-- Header with Code Snippet Button -->\r\n <div class=\"cc-filter-header\" *ngIf=\"config?.settings?.showCodeSnippet\">\r\n <button mat-icon-button class=\"cc-code-snippet-btn\" (click)=\"onShowCodeSnippet()\" title=\"Show Code Snippet\">\r\n <i class=\"fas fa-code\"></i>\r\n </button>\r\n </div>\r\n\r\n <!-- Tabs Section -->\r\n <div *ngIf=\"config?.tabs?.items?.length\" class=\"cc-filter-tabs\">\r\n <div *ngFor=\"let tab of config.tabs!.items\" class=\"cc-filter-tab\" [class.active]=\"tab.id === selectedTabId\"\r\n (click)=\"onTabClick(tab)\">\r\n <i *ngIf=\"tab.icon && !isImgUrl(tab.icon)\" [class]=\"tab.icon\"></i>\r\n <img *ngIf=\"tab.icon && isImgUrl(tab.icon)\" [src]=\"tab.icon\" alt=\"icon\" class=\"cc-filter-tab-icon\">\r\n <span>{{ tab.label }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Content -->\r\n <div class=\"cc-filter-content\">\r\n\r\n <ng-container *ngFor=\"let section of config.sections; trackBy: trackByFn\">\r\n\r\n <!-- Accordion Section -->\r\n <mat-accordion *ngIf=\"section.type === 'accordion'\" class=\"cc-filter-accordion\">\r\n <mat-expansion-panel [expanded]=\"section.expanded\" class=\"mat-elevation-z0\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>\r\n {{ section.title }}\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n\r\n <!-- Content of Accordion -->\r\n <ng-container *ngIf=\"section.options\">\r\n <div class=\"cc-filter-group\">\r\n <mat-checkbox *ngFor=\"let option of section.options\"\r\n [checked]=\"filters[section.key]?.includes(option.value)\"\r\n (change)=\"onFilterChange(section.key, option.value, true)\">\r\n {{ option.label }}\r\n </mat-checkbox>\r\n </div>\r\n </ng-container>\r\n </mat-expansion-panel>\r\n </mat-accordion>\r\n\r\n <!-- Select Section -->\r\n <div *ngIf=\"section.type === 'select'\" class=\"cc-filter-section\">\r\n <label *ngIf=\"section.title\" class=\"cc-filter-label\">{{ section.title }}</label>\r\n <mat-form-field appearance=\"outline\" class=\"cc-filter-full-width\">\r\n <mat-select [placeholder]=\"section.placeholder || 'Select'\" [(value)]=\"filters[section.key]\"\r\n [multiple]=\"section.multi\"\r\n (selectionChange)=\"onFilterChange(section.key, $event.value, section.multi)\">\r\n <mat-option *ngFor=\"let option of section.options\" [value]=\"option.value\">\r\n {{ option.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- Radio Group Section -->\r\n <div *ngIf=\"section.type === 'radio-group'\" class=\"cc-filter-section\">\r\n <label *ngIf=\"section.title\" class=\"cc-filter-label\">{{ section.title }}</label>\r\n <mat-radio-group [(ngModel)]=\"filters[section.key]\" (change)=\"onFilterChange(section.key, $event.value)\"\r\n class=\"cc-filter-radio-group\">\r\n <mat-radio-button *ngFor=\"let option of section.options\" [value]=\"option.value\">\r\n {{ option.label }}\r\n </mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n\r\n <!-- Checkbox Group Section (Standalone) -->\r\n <div *ngIf=\"section.type === 'checkbox-group'\" class=\"cc-filter-section\">\r\n <label *ngIf=\"section.title\" class=\"cc-filter-label\">{{ section.title }}</label>\r\n <div class=\"cc-filter-group\">\r\n <mat-checkbox *ngFor=\"let option of section.options\"\r\n [checked]=\"filters[section.key]?.includes(option.value)\"\r\n (change)=\"onFilterChange(section.key, option.value, true)\">\r\n {{ option.label }}\r\n </mat-checkbox>\r\n </div>\r\n </div>\r\n\r\n </ng-container>\r\n\r\n </div>\r\n\r\n <!-- Actions Footer -->\r\n <div class=\"cc-filter-actions\" *ngIf=\"config.actions\">\r\n <button mat-button class=\"cc-btn-text text-danger\" *ngIf=\"config.actions?.clear?.visible !== false\"\r\n (click)=\"clearFilters()\">\r\n {{ config.actions?.clear?.label || 'Clear Filter' }}\r\n </button>\r\n <button mat-flat-button color=\"warn\" class=\"cc-btn-primary\" *ngIf=\"config.actions?.apply?.visible !== false\"\r\n [disabled]=\"config.actions?.apply?.disabled\" (click)=\"applyFilters()\">\r\n {{ config.actions?.apply?.label || 'Apply Filter' }}\r\n </button>\r\n </div>\r\n</div>", styles: [".cc-filter-sidebar{display:flex;flex-direction:column;height:100%;background-color:var(--cc-filter-bg, #ffffff);border-right:1px solid var(--cc-filter-border-color, #E5E7EB);width:var(--cc-filter-width, 320px);box-shadow:2px 0 12px #0000000a;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.cc-filter-header{display:flex;justify-content:flex-end;align-items:center;padding:.75rem 1rem;border-bottom:1px solid #f0f0f0;background-color:var(--cc-filter-header-bg, #fafafa)}.cc-filter-header .cc-code-snippet-btn{color:var(--cc-primary-color, #EF4444);transition:all .2s ease}.cc-filter-header .cc-code-snippet-btn:hover{background-color:#ef444414;transform:scale(1.05)}.cc-filter-header .cc-code-snippet-btn i{font-size:1.1rem}.cc-filter-tabs{display:flex;flex-direction:column;padding:1rem 1.25rem;gap:.625rem;border-bottom:1px solid #E5E7EB;background-color:var(--cc-filter-header-bg, #ffffff)}.cc-filter-tabs .cc-filter-tab{padding:.875rem 1.125rem;border-radius:10px;cursor:pointer;display:flex;align-items:center;gap:.75rem;color:var(--cc-filter-tab-color, #6B7280);font-weight:500;font-size:.9375rem;transition:all .25s cubic-bezier(.4,0,.2,1);border:1.5px solid transparent;position:relative}.cc-filter-tabs .cc-filter-tab:hover{background-color:var(--cc-filter-tab-hover-bg, #F9FAFB);color:var(--cc-filter-tab-hover-color, #374151);transform:translate(2px)}.cc-filter-tabs .cc-filter-tab.active{background:linear-gradient(135deg,#fef2f2,#fee2e2);color:var(--cc-filter-tab-active-color, #DC2626);border-color:var(--cc-filter-tab-active-border, #FECACA);box-shadow:0 2px 8px #ef44441f;font-weight:600}.cc-filter-tabs .cc-filter-tab.active:before{content:\"\";position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:60%;background-color:#ef4444;border-radius:0 2px 2px 0}.cc-filter-tabs .cc-filter-tab i{font-size:1.125rem;opacity:.9}.cc-filter-tabs .cc-filter-tab .cc-filter-tab-icon{width:1.125rem;height:1.125rem;object-fit:contain}.cc-filter-content{flex:1;overflow-y:auto;padding:1.5rem;display:flex;flex-direction:column;gap:1.5rem}.cc-filter-section{display:flex;flex-direction:column;gap:.625rem}.cc-filter-group{display:flex;flex-direction:column;gap:.75rem}::ng-deep .cc-filter-group .mat-mdc-checkbox,::ng-deep .cc-filter-group .mat-mdc-radio-button,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button{margin-bottom:.5rem}::ng-deep .cc-filter-group .mat-mdc-checkbox .mdc-checkbox,::ng-deep .cc-filter-group .mat-mdc-checkbox .mdc-radio,::ng-deep .cc-filter-group .mat-mdc-radio-button .mdc-checkbox,::ng-deep .cc-filter-group .mat-mdc-radio-button .mdc-radio,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox .mdc-checkbox,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox .mdc-radio,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button .mdc-checkbox,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button .mdc-radio{padding:8px}::ng-deep .cc-filter-group .mat-mdc-checkbox .mdc-label,::ng-deep .cc-filter-group .mat-mdc-radio-button .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button .mdc-label{font-size:.9375rem;color:#374151;padding-left:8px}::ng-deep .cc-filter-group .mat-mdc-checkbox:hover .mdc-label,::ng-deep .cc-filter-group .mat-mdc-radio-button:hover .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox:hover .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-radio-button:hover .mdc-label{color:#111827}::ng-deep .cc-filter-group .mat-mdc-checkbox-checked .mdc-label,::ng-deep .cc-filter-group .mat-mdc-radio-checked .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-checkbox-checked .mdc-label,::ng-deep .cc-filter-radio-group .mat-mdc-radio-checked .mdc-label{font-weight:500;color:#dc2626}.cc-filter-label{font-size:.875rem;font-weight:500;color:var(--cc-filter-section-title-color, #374151);margin-bottom:.25rem}.cc-filter-full-width{width:100%}::ng-deep .cc-filter-accordion .mat-expansion-panel{box-shadow:none!important;background:transparent;border-radius:8px;margin-bottom:.5rem}::ng-deep .cc-filter-accordion .mat-expansion-panel:hover{background-color:#00000003}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header{padding:12px 0;height:auto;min-height:48px;border-radius:8px;transition:all .2s ease}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header.mat-expanded{height:auto;background-color:#ef444405}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header:hover{background-color:#ef44440a!important}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header .mat-content{font-weight:600;color:var(--cc-filter-accordion-title-color, #374151);text-transform:uppercase;font-size:.8125rem;letter-spacing:.05em}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-header .mat-expansion-indicator:after{color:#ef4444}::ng-deep .cc-filter-accordion .mat-expansion-panel .mat-expansion-panel-body{padding:.75rem 0 .5rem}.cc-filter-content::-webkit-scrollbar{width:6px}.cc-filter-content::-webkit-scrollbar-track{background:transparent}.cc-filter-content::-webkit-scrollbar-thumb{background-color:#0000001a;border-radius:3px}.cc-filter-content:hover::-webkit-scrollbar-thumb{background-color:#0003}::ng-deep .cc-filter-full-width.mat-mdc-form-field{width:100%}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-text-field-wrapper{background-color:#fff!important;border-radius:8px;padding:0}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mdc-notched-outline__leading,::ng-deep .cc-filter-full-width.mat-mdc-form-field .mdc-notched-outline__notch,::ng-deep .cc-filter-full-width.mat-mdc-form-field .mdc-notched-outline__trailing{border-color:#e2e8f0;border-width:1px;transition:border-color .2s ease}::ng-deep .cc-filter-full-width.mat-mdc-form-field:hover .mdc-notched-outline__leading,::ng-deep .cc-filter-full-width.mat-mdc-form-field:hover .mdc-notched-outline__notch,::ng-deep .cc-filter-full-width.mat-mdc-form-field:hover .mdc-notched-outline__trailing{border-color:#94a3b8}::ng-deep .cc-filter-full-width.mat-mdc-form-field.mat-focused .mdc-notched-outline__leading,::ng-deep .cc-filter-full-width.mat-mdc-form-field.mat-focused .mdc-notched-outline__notch,::ng-deep .cc-filter-full-width.mat-mdc-form-field.mat-focused .mdc-notched-outline__trailing{border-color:var(--cc-primary-color, #EF4444);border-width:2px}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-form-field-flex{padding:0 12px;align-items:center;height:48px}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-form-field-infix{padding:8px 0!important;min-height:unset!important;display:flex;align-items:center}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-select-value{color:#1e293b;font-weight:500;font-size:.9375rem}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-select-placeholder{color:#94a3b8}::ng-deep .cc-filter-full-width.mat-mdc-form-field .mat-mdc-select-arrow{color:#64748b}::ng-deep .mat-mdc-select-panel{background-color:#fff!important;border-radius:8px!important;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d!important;padding:6px 0!important;border:1px solid #E2E8F0;min-width:100%!important;margin-top:4px}::ng-deep .mat-mdc-select-panel .mat-mdc-option{padding:0 16px;height:40px;font-size:.9375rem;color:#334155;transition:background-color .15s ease}::ng-deep .mat-mdc-select-panel .mat-mdc-option:hover{background-color:#f8fafc!important}::ng-deep .mat-mdc-select-panel .mat-mdc-option.mat-mdc-option-active,::ng-deep .mat-mdc-select-panel .mat-mdc-option.mdc-list-item--selected{background-color:#fef2f2!important;color:#ef4444!important;font-weight:500}::ng-deep .mat-mdc-select-panel .mat-mdc-option .mdc-list-item__primary-text{color:inherit}.cc-filter-actions{padding:1.25rem 1.5rem;display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--cc-filter-footer-border-color, #E5E7EB);background:linear-gradient(to bottom,#fafafa,#fff);box-shadow:0 -2px 8px #00000008}.cc-filter-actions button{font-weight:500;border-radius:8px;padding:10px 20px;transition:all .25s ease;text-transform:none;font-size:.9375rem}.cc-filter-actions button.cc-btn-primary{background:linear-gradient(135deg,#ef4444,#dc2626)!important;color:#fff!important;box-shadow:0 2px 8px #ef444440}.cc-filter-actions button.cc-btn-primary:hover{box-shadow:0 4px 12px #ef444459;transform:translateY(-1px)}.cc-filter-actions button.cc-btn-primary:active{transform:translateY(0)}.cc-filter-actions button.cc-btn-text{color:#ef4444!important;font-weight:600}.cc-filter-actions button.cc-btn-text:hover{background-color:#ef444414!important}\n"] }]
867
+ }], ctorParameters: () => [{ type: i1$1.Router }, { type: i1$1.ActivatedRoute }], propDecorators: { config: [{
868
+ type: Input
869
+ }], initialFilters: [{
870
+ type: Input
871
+ }], filterChange: [{
872
+ type: Output
873
+ }], filterApply: [{
874
+ type: Output
875
+ }], filterClear: [{
876
+ type: Output
877
+ }], tabChange: [{
878
+ type: Output
879
+ }], showCodeSnippet: [{
880
+ type: Output
881
+ }] } });
882
+
883
+ class FilterSidebarModule {
884
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
885
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarModule, declarations: [FilterSidebarComponent], imports: [CommonModule,
886
+ FormsModule,
887
+ ReactiveFormsModule,
888
+ MaterialModule], exports: [FilterSidebarComponent] });
889
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarModule, imports: [CommonModule,
890
+ FormsModule,
891
+ ReactiveFormsModule,
892
+ MaterialModule] });
893
+ }
894
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarModule, decorators: [{
895
+ type: NgModule,
896
+ args: [{
897
+ declarations: [
898
+ FilterSidebarComponent
899
+ ],
900
+ imports: [
901
+ CommonModule,
902
+ FormsModule,
903
+ ReactiveFormsModule,
904
+ MaterialModule
905
+ ],
906
+ exports: [
907
+ FilterSidebarComponent
908
+ ]
909
+ }]
910
+ }] });
911
+
912
+ class SummaryCardComponent {
913
+ config;
914
+ theme = 'theme-1';
915
+ cardClick = new EventEmitter();
916
+ get hostClasses() {
917
+ return `${this.theme} ${this.config?.isDisabled ? 'disabled' : ''} ${this.config?.isClickable !== false && !this.config?.isDisabled ? 'clickable' : ''}`;
918
+ }
919
+ constructor() { }
920
+ onCardClick() {
921
+ if (this.config?.isDisabled || this.config?.isClickable === false) {
922
+ return;
923
+ }
924
+ this.cardClick.emit();
925
+ }
926
+ get cardClasses() {
927
+ return {
928
+ 'disabled': !!this.config?.isDisabled,
929
+ 'clickable': this.config?.isClickable !== false && !this.config?.isDisabled
930
+ };
931
+ }
932
+ get iconStyles() {
933
+ const styles = {};
934
+ if (this.config.iconBackgroundColor) {
935
+ styles['backgroundColor'] = this.config.iconBackgroundColor;
936
+ }
937
+ if (this.config.iconColor) {
938
+ styles['color'] = this.config.iconColor;
939
+ }
940
+ return styles;
941
+ }
942
+ get headerStyles() {
943
+ const styles = {};
944
+ if (this.config.headerColor) {
945
+ styles['color'] = this.config.headerColor;
946
+ }
947
+ return styles;
948
+ }
949
+ get valueStyles() {
950
+ const styles = {};
951
+ if (this.config.valueColor) {
952
+ styles['color'] = this.config.valueColor;
953
+ }
954
+ return styles;
955
+ }
956
+ get descriptionStyles() {
957
+ const styles = {};
958
+ if (this.config.descriptionColor) {
959
+ styles['color'] = this.config.descriptionColor;
960
+ }
961
+ return styles;
962
+ }
963
+ get isDescriptionInline() {
964
+ return this.config.descriptionPosition === 'inline';
965
+ }
966
+ getMetaStyles(meta) {
967
+ const styles = {};
968
+ if (meta.color) {
969
+ styles['color'] = meta.color;
970
+ }
971
+ if (meta.backgroundColor && meta.type === 'pill') {
972
+ styles['backgroundColor'] = meta.backgroundColor;
973
+ }
974
+ return styles;
975
+ }
976
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SummaryCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
977
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SummaryCardComponent, isStandalone: false, selector: "lib-summary-card", inputs: { config: "config", theme: "theme" }, outputs: { cardClick: "cardClick" }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "<div class=\"cc-summary-card\" (click)=\"onCardClick()\">\r\n <!-- Icon Section (Left Side) -->\r\n <div class=\"icon-section\" *ngIf=\"config.icon || config.iconImage\" [ngClass]=\"config.iconClass\"\r\n [ngStyle]=\"iconStyles\">\r\n <mat-icon *ngIf=\"config.icon\">{{ config.icon }}</mat-icon>\r\n <img *ngIf=\"!config.icon && config.iconImage\" [src]=\"config.iconImage\" alt=\"icon\">\r\n </div>\r\n\r\n <!-- Right Section (Header + Value/Meta) -->\r\n <div class=\"right-section\">\r\n <!-- Header (Full Width on Right) -->\r\n <div class=\"header\" [ngClass]=\"config.headerClass\" [ngStyle]=\"headerStyles\">\r\n {{ config.header }}\r\n </div>\r\n\r\n <!-- Value and Meta Row -->\r\n <div class=\"value-meta-row\">\r\n <!-- Content Section -->\r\n <div class=\"content-section\">\r\n <!-- Value Row (with optional inline description) -->\r\n <div class=\"value-row\" [class.inline-layout]=\"isDescriptionInline\">\r\n <div class=\"value-container\">\r\n <div class=\"value\" [ngClass]=\"config.valueClass\" [ngStyle]=\"valueStyles\">\r\n {{ config.value }}\r\n <span *ngIf=\"config.valueSubtext\" class=\"value-subtext\">{{ config.valueSubtext }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Description (inline or bottom based on config) -->\r\n <div class=\"description\" *ngIf=\"config.description\" [ngClass]=\"config.descriptionClass\"\r\n [ngStyle]=\"descriptionStyles\">\r\n {{ config.description }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Meta/Status Section (Aligned with Value) -->\r\n <div class=\"meta-section\" *ngIf=\"config.metaData && config.metaData.length > 0\">\r\n <div *ngFor=\"let meta of config.metaData\" class=\"meta-item\"\r\n [ngClass]=\"[meta.type === 'pill' ? 'meta-pill' : 'meta-text', meta.cssClass || '']\"\r\n [ngStyle]=\"getMetaStyles(meta)\">\r\n {{ meta.text }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [":host{display:block;width:100%}.cc-summary-card{display:flex;flex-direction:row;align-items:stretch;box-sizing:border-box;font-family:var(--cc-sc-font-family, \"Inter\", sans-serif);background-color:var(--cc-sc-bg-color, #ffffff);border-radius:var(--cc-sc-border-radius, 8px);border:var(--cc-sc-border, 1px solid #e0e0e0);padding:var(--cc-sc-padding, 16px);box-shadow:var(--cc-sc-shadow, 0 2px 4px rgba(0, 0, 0, .05));transition:all var(--cc-sc-transition-duration, .2s) ease;height:100%;width:100%;overflow:hidden;gap:var(--cc-sc-icon-margin, 1rem)}.cc-summary-card.clickable{cursor:pointer}.cc-summary-card.clickable:hover{transform:var(--cc-sc-hover-transform);box-shadow:var(--cc-sc-hover-shadow)}.cc-summary-card.disabled{opacity:var(--cc-sc-disabled-opacity);cursor:not-allowed;pointer-events:none}.cc-summary-card .icon-section{width:var(--cc-sc-icon-box-size);height:var(--cc-sc-icon-box-size);min-width:var(--cc-sc-icon-box-size);display:flex;align-items:center;justify-content:center;border-radius:var(--cc-sc-icon-radius);background-color:var(--cc-sc-icon-bg);color:var(--cc-sc-icon-color);flex-shrink:0;align-self:center}.cc-summary-card .icon-section mat-icon{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);font-size:var(--cc-sc-icon-size);line-height:var(--cc-sc-icon-size)}.cc-summary-card .icon-section img{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);object-fit:contain}.cc-summary-card .right-section{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--cc-sc-content-gap, .5rem)}.cc-summary-card .right-section .header{font-size:var(--cc-sc-header-size);font-weight:var(--cc-sc-header-weight);text-transform:var(--cc-sc-header-transform);color:var(--cc-sc-header-color);letter-spacing:var(--cc-sc-header-letter-spacing);line-height:var(--cc-sc-header-line-height);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%}.cc-summary-card .right-section .value-meta-row{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1rem;flex:1}.cc-summary-card .right-section .value-meta-row .content-section{display:flex;flex-direction:column;justify-content:flex-start;flex:1;min-width:0}.cc-summary-card .right-section .value-meta-row .content-section .value-row{display:flex;flex-direction:column;gap:var(--cc-sc-value-desc-gap)}.cc-summary-card .right-section .value-meta-row .content-section .value-row.inline-layout{flex-direction:row;align-items:baseline;flex-wrap:wrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value{font-size:var(--cc-sc-value-size);font-weight:var(--cc-sc-value-weight);color:var(--cc-sc-value-color);line-height:var(--cc-sc-value-line-height);white-space:nowrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value .value-subtext{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);margin-left:4px}.cc-summary-card .right-section .value-meta-row .content-section .value-row .description{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);line-height:var(--cc-sc-desc-line-height)}.cc-summary-card .right-section .value-meta-row .meta-section{display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-start;flex-shrink:0;gap:6px}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item{font-size:.8125rem;line-height:1.4;white-space:nowrap;text-align:right;flex-shrink:0}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-text{color:var(--cc-sc-desc-color, #64748b);font-weight:500}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-pill{display:inline-flex;align-items:center;justify-content:center;padding:var(--cc-sc-meta-pill-padding, 4px 12px);border-radius:var(--cc-sc-meta-pill-radius, 20px);font-size:var(--cc-sc-meta-pill-font-size, .75rem);font-weight:var(--cc-sc-meta-pill-font-weight, 600);line-height:1.2;background-color:var(--cc-sc-meta-pill-bg, #f1f5f9);color:var(--cc-sc-meta-pill-color, #475569)}@media(max-width:600px){.cc-summary-card .icon-section{margin-right:var(--cc-sc-icon-margin-mobile, .75rem)}.cc-summary-card .content-section .header{font-size:var(--cc-sc-header-size-mobile, .7rem)}.cc-summary-card .content-section .value-row .value{font-size:var(--cc-sc-value-size-mobile, 1.25rem)}.cc-summary-card .content-section .value-row .description{font-size:var(--cc-sc-desc-size-mobile, .7rem)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
978
+ }
979
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SummaryCardComponent, decorators: [{
980
+ type: Component,
981
+ args: [{ selector: 'lib-summary-card', standalone: false, template: "<div class=\"cc-summary-card\" (click)=\"onCardClick()\">\r\n <!-- Icon Section (Left Side) -->\r\n <div class=\"icon-section\" *ngIf=\"config.icon || config.iconImage\" [ngClass]=\"config.iconClass\"\r\n [ngStyle]=\"iconStyles\">\r\n <mat-icon *ngIf=\"config.icon\">{{ config.icon }}</mat-icon>\r\n <img *ngIf=\"!config.icon && config.iconImage\" [src]=\"config.iconImage\" alt=\"icon\">\r\n </div>\r\n\r\n <!-- Right Section (Header + Value/Meta) -->\r\n <div class=\"right-section\">\r\n <!-- Header (Full Width on Right) -->\r\n <div class=\"header\" [ngClass]=\"config.headerClass\" [ngStyle]=\"headerStyles\">\r\n {{ config.header }}\r\n </div>\r\n\r\n <!-- Value and Meta Row -->\r\n <div class=\"value-meta-row\">\r\n <!-- Content Section -->\r\n <div class=\"content-section\">\r\n <!-- Value Row (with optional inline description) -->\r\n <div class=\"value-row\" [class.inline-layout]=\"isDescriptionInline\">\r\n <div class=\"value-container\">\r\n <div class=\"value\" [ngClass]=\"config.valueClass\" [ngStyle]=\"valueStyles\">\r\n {{ config.value }}\r\n <span *ngIf=\"config.valueSubtext\" class=\"value-subtext\">{{ config.valueSubtext }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Description (inline or bottom based on config) -->\r\n <div class=\"description\" *ngIf=\"config.description\" [ngClass]=\"config.descriptionClass\"\r\n [ngStyle]=\"descriptionStyles\">\r\n {{ config.description }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Meta/Status Section (Aligned with Value) -->\r\n <div class=\"meta-section\" *ngIf=\"config.metaData && config.metaData.length > 0\">\r\n <div *ngFor=\"let meta of config.metaData\" class=\"meta-item\"\r\n [ngClass]=\"[meta.type === 'pill' ? 'meta-pill' : 'meta-text', meta.cssClass || '']\"\r\n [ngStyle]=\"getMetaStyles(meta)\">\r\n {{ meta.text }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [":host{display:block;width:100%}.cc-summary-card{display:flex;flex-direction:row;align-items:stretch;box-sizing:border-box;font-family:var(--cc-sc-font-family, \"Inter\", sans-serif);background-color:var(--cc-sc-bg-color, #ffffff);border-radius:var(--cc-sc-border-radius, 8px);border:var(--cc-sc-border, 1px solid #e0e0e0);padding:var(--cc-sc-padding, 16px);box-shadow:var(--cc-sc-shadow, 0 2px 4px rgba(0, 0, 0, .05));transition:all var(--cc-sc-transition-duration, .2s) ease;height:100%;width:100%;overflow:hidden;gap:var(--cc-sc-icon-margin, 1rem)}.cc-summary-card.clickable{cursor:pointer}.cc-summary-card.clickable:hover{transform:var(--cc-sc-hover-transform);box-shadow:var(--cc-sc-hover-shadow)}.cc-summary-card.disabled{opacity:var(--cc-sc-disabled-opacity);cursor:not-allowed;pointer-events:none}.cc-summary-card .icon-section{width:var(--cc-sc-icon-box-size);height:var(--cc-sc-icon-box-size);min-width:var(--cc-sc-icon-box-size);display:flex;align-items:center;justify-content:center;border-radius:var(--cc-sc-icon-radius);background-color:var(--cc-sc-icon-bg);color:var(--cc-sc-icon-color);flex-shrink:0;align-self:center}.cc-summary-card .icon-section mat-icon{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);font-size:var(--cc-sc-icon-size);line-height:var(--cc-sc-icon-size)}.cc-summary-card .icon-section img{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);object-fit:contain}.cc-summary-card .right-section{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--cc-sc-content-gap, .5rem)}.cc-summary-card .right-section .header{font-size:var(--cc-sc-header-size);font-weight:var(--cc-sc-header-weight);text-transform:var(--cc-sc-header-transform);color:var(--cc-sc-header-color);letter-spacing:var(--cc-sc-header-letter-spacing);line-height:var(--cc-sc-header-line-height);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%}.cc-summary-card .right-section .value-meta-row{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1rem;flex:1}.cc-summary-card .right-section .value-meta-row .content-section{display:flex;flex-direction:column;justify-content:flex-start;flex:1;min-width:0}.cc-summary-card .right-section .value-meta-row .content-section .value-row{display:flex;flex-direction:column;gap:var(--cc-sc-value-desc-gap)}.cc-summary-card .right-section .value-meta-row .content-section .value-row.inline-layout{flex-direction:row;align-items:baseline;flex-wrap:wrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value{font-size:var(--cc-sc-value-size);font-weight:var(--cc-sc-value-weight);color:var(--cc-sc-value-color);line-height:var(--cc-sc-value-line-height);white-space:nowrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value .value-subtext{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);margin-left:4px}.cc-summary-card .right-section .value-meta-row .content-section .value-row .description{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);line-height:var(--cc-sc-desc-line-height)}.cc-summary-card .right-section .value-meta-row .meta-section{display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-start;flex-shrink:0;gap:6px}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item{font-size:.8125rem;line-height:1.4;white-space:nowrap;text-align:right;flex-shrink:0}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-text{color:var(--cc-sc-desc-color, #64748b);font-weight:500}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-pill{display:inline-flex;align-items:center;justify-content:center;padding:var(--cc-sc-meta-pill-padding, 4px 12px);border-radius:var(--cc-sc-meta-pill-radius, 20px);font-size:var(--cc-sc-meta-pill-font-size, .75rem);font-weight:var(--cc-sc-meta-pill-font-weight, 600);line-height:1.2;background-color:var(--cc-sc-meta-pill-bg, #f1f5f9);color:var(--cc-sc-meta-pill-color, #475569)}@media(max-width:600px){.cc-summary-card .icon-section{margin-right:var(--cc-sc-icon-margin-mobile, .75rem)}.cc-summary-card .content-section .header{font-size:var(--cc-sc-header-size-mobile, .7rem)}.cc-summary-card .content-section .value-row .value{font-size:var(--cc-sc-value-size-mobile, 1.25rem)}.cc-summary-card .content-section .value-row .description{font-size:var(--cc-sc-desc-size-mobile, .7rem)}}\n"] }]
982
+ }], ctorParameters: () => [], propDecorators: { config: [{
983
+ type: Input
984
+ }], theme: [{
985
+ type: Input
986
+ }], cardClick: [{
987
+ type: Output
988
+ }], hostClasses: [{
989
+ type: HostBinding,
990
+ args: ['class']
991
+ }] } });
992
+
993
+ class SummaryCardModule {
994
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SummaryCardModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
995
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: SummaryCardModule, declarations: [SummaryCardComponent], imports: [CommonModule,
996
+ MatIconModule], exports: [SummaryCardComponent] });
997
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SummaryCardModule, imports: [CommonModule,
998
+ MatIconModule] });
999
+ }
1000
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SummaryCardModule, decorators: [{
1001
+ type: NgModule,
1002
+ args: [{
1003
+ declarations: [
1004
+ SummaryCardComponent
1005
+ ],
1006
+ imports: [
1007
+ CommonModule,
1008
+ MatIconModule
1009
+ ],
1010
+ exports: [
1011
+ SummaryCardComponent
1012
+ ]
1013
+ }]
1014
+ }] });
1015
+
1016
+ class ConfigurableFormComponent {
1017
+ fb;
1018
+ snackBar;
1019
+ http;
1020
+ config;
1021
+ jsonConfig;
1022
+ data = {};
1023
+ baseApiUrl = '';
1024
+ formSubmit = new EventEmitter();
1025
+ formCancel = new EventEmitter();
1026
+ optionsLoad = new EventEmitter();
1027
+ form;
1028
+ processedConfig;
1029
+ fieldVisibilityMap = new Map();
1030
+ constructor(fb, snackBar, http) {
1031
+ this.fb = fb;
1032
+ this.snackBar = snackBar;
1033
+ this.http = http;
1034
+ }
1035
+ ngOnInit() {
1036
+ this.initializeForm();
1037
+ }
1038
+ ngOnChanges(changes) {
1039
+ if (changes['config'] || changes['jsonConfig']) {
1040
+ this.initializeForm();
1041
+ }
1042
+ if (changes['data'] && this.form) {
1043
+ this.form.patchValue(this.data);
1044
+ }
1045
+ }
1046
+ initializeForm() {
1047
+ // Transform JSON config if provided, otherwise use config directly
1048
+ if (this.jsonConfig) {
1049
+ this.processedConfig = this.transformJsonConfig(this.jsonConfig);
1050
+ }
1051
+ else if (this.config) {
1052
+ this.processedConfig = JSON.parse(JSON.stringify(this.config));
1053
+ }
1054
+ else {
1055
+ return;
1056
+ }
1057
+ this.normalizeFields();
1058
+ this.initializeFieldVisibility();
1059
+ this.buildForm();
1060
+ this.setupDependencies();
1061
+ // Patch initial data if provided
1062
+ if (this.data && Object.keys(this.data).length > 0) {
1063
+ this.form.patchValue(this.data);
1064
+ }
1065
+ }
1066
+ // Transform JSON config format to internal FormConfig format
1067
+ transformJsonConfig(jsonConfig) {
1068
+ const fields = jsonConfig.jsonConfig
1069
+ .sort((a, b) => a.sequence - b.sequence)
1070
+ .map(field => this.transformJsonField(field));
1071
+ return {
1072
+ sections: [{
1073
+ sectionTitle: jsonConfig.label,
1074
+ fields: fields
1075
+ }],
1076
+ entityType: jsonConfig.entityType
1077
+ };
1078
+ }
1079
+ // Transform individual JSON field to FormField
1080
+ transformJsonField(jsonField) {
1081
+ const fieldType = this.mapUISubTypeToFieldType(jsonField.uiConfig.subType);
1082
+ return {
1083
+ name: jsonField.jsonKey,
1084
+ jsonKey: jsonField.jsonKey,
1085
+ label: jsonField.label,
1086
+ type: fieldType,
1087
+ sequence: jsonField.sequence,
1088
+ keyType: jsonField.keyType,
1089
+ uiConfig: jsonField.uiConfig,
1090
+ validationRules: jsonField.validationRules,
1091
+ required: jsonField.validationRules?.isMandatory || jsonField.validationRules?.isRequired,
1092
+ mandatory: jsonField.validationRules?.isMandatory,
1093
+ dependsOn: undefined, // Will be set based on dependent array
1094
+ dependent: jsonField.uiConfig.dependent,
1095
+ optionConfigs: jsonField.uiConfig.optionConfigs,
1096
+ class: 'col-12'
1097
+ };
1098
+ }
1099
+ // Map UI subtype to field type
1100
+ mapUISubTypeToFieldType(subType) {
1101
+ switch (subType) {
1102
+ case 'UI_SUBTYPE.SHORT_TEXT':
1103
+ return 'text';
1104
+ case 'UI_SUBTYPE.LONG_TEXT':
1105
+ return 'textarea';
1106
+ case 'UI_SUBTYPE.NUMBER':
1107
+ return 'number';
1108
+ case 'UI_SUBTYPE.EMAIL':
1109
+ return 'email';
1110
+ case 'UI_SUBTYPE.PHONE':
1111
+ return 'tel';
1112
+ case 'UI_SUBTYPE.URL':
1113
+ return 'url';
1114
+ default:
1115
+ return 'text';
1116
+ }
1117
+ }
1118
+ // Normalize fields to ensure all required properties exist
1119
+ normalizeFields() {
1120
+ this.processedConfig.sections.forEach(section => {
1121
+ section.fields.forEach(field => {
1122
+ // Set default type if not specified
1123
+ if (!field.type) {
1124
+ field.type = 'text';
1125
+ }
1126
+ // Merge uiConfig with field-level properties
1127
+ if (field.uiConfig) {
1128
+ if (field.uiConfig.type === 'UI_TYPE.DROP_DOWN') {
1129
+ field.type = 'dropdown';
1130
+ }
1131
+ if (field.uiConfig.optionConfigs) {
1132
+ field.optionConfigs = field.uiConfig.optionConfigs;
1133
+ }
1134
+ if (field.uiConfig.dependent) {
1135
+ field.dependent = field.uiConfig.dependent;
1136
+ }
1137
+ }
1138
+ // Initialize visibility
1139
+ if (field.visible === undefined) {
1140
+ field.visible = true;
1141
+ }
1142
+ // Load options for dropdowns
1143
+ if ((field.type === 'dropdown' || field.type === 'select') && field.optionConfigs) {
1144
+ this.loadFieldOptions(field);
1145
+ }
1146
+ });
1147
+ });
1148
+ }
1149
+ // Initialize field visibility map
1150
+ initializeFieldVisibility() {
1151
+ this.processedConfig.sections.forEach(section => {
1152
+ section.fields.forEach(field => {
1153
+ this.fieldVisibilityMap.set(field.name, field.visible !== false);
1154
+ });
1155
+ });
1156
+ }
1157
+ buildForm() {
1158
+ const formGroupConfig = {};
1159
+ this.processedConfig.sections.forEach(section => {
1160
+ if (section.isRepeater) {
1161
+ // Create FormArray for repeater sections
1162
+ const arrayName = section.formArrayName || 'items';
1163
+ const minItems = section.minItems || 1;
1164
+ const initialItems = [];
1165
+ for (let i = 0; i < minItems; i++) {
1166
+ initialItems.push(this.createGroup(section.fields));
1167
+ }
1168
+ formGroupConfig[arrayName] = this.fb.array(initialItems);
1169
+ }
1170
+ else {
1171
+ // Add regular fields to form group
1172
+ section.fields.forEach(field => {
1173
+ if (field.subFields) {
1174
+ // Composite field - add all sub-fields
1175
+ field.subFields.forEach(subField => {
1176
+ if (field.required || field.mandatory) {
1177
+ subField.required = true;
1178
+ }
1179
+ formGroupConfig[subField.name] = this.createControl(subField);
1180
+ });
1181
+ }
1182
+ else {
1183
+ formGroupConfig[field.name] = this.createControl(field);
1184
+ }
1185
+ });
1186
+ }
1187
+ });
1188
+ this.form = this.fb.group(formGroupConfig);
1189
+ // Apply composite validators to the root form group
1190
+ this.processedConfig.sections.forEach(section => {
1191
+ if (!section.isRepeater) {
1192
+ section.fields.forEach(field => {
1193
+ if (field.type === 'composite' && field.compositeValidationRule && field.subFields) {
1194
+ this.form.addValidators(this.createCompositeValidator(field));
1195
+ }
1196
+ });
1197
+ }
1198
+ });
1199
+ this.form.updateValueAndValidity();
1200
+ }
1201
+ createCompositeValidator(field) {
1202
+ return (control) => {
1203
+ const group = control;
1204
+ if (!field.subFields || field.subFields.length < 2)
1205
+ return null;
1206
+ if (field.compositeValidationRule === 'minMax') {
1207
+ const minControl = group.get(field.subFields[0].name);
1208
+ const maxControl = group.get(field.subFields[1].name);
1209
+ if (minControl && maxControl && minControl.value !== null && maxControl.value !== null) {
1210
+ if (Number(minControl.value) > Number(maxControl.value)) {
1211
+ return { [`invalid_minMax_${field.name}`]: true };
1212
+ }
1213
+ }
1214
+ }
1215
+ if (field.compositeValidationRule === 'percentageTotal') {
1216
+ let total = 0;
1217
+ let allPresent = true;
1218
+ field.subFields.forEach(sub => {
1219
+ const ctrl = group.get(sub.name);
1220
+ if (ctrl && ctrl.value !== null && ctrl.value !== '') {
1221
+ total += Number(ctrl.value);
1222
+ }
1223
+ else {
1224
+ allPresent = false;
1225
+ }
1226
+ });
1227
+ if (allPresent && total !== 100) {
1228
+ return { [`invalid_percentageTotal_${field.name}`]: true };
1229
+ }
1230
+ }
1231
+ return null;
1232
+ };
1233
+ }
1234
+ createControl(field) {
1235
+ const validators = [];
1236
+ // Add validators based on field configuration
1237
+ if (field.required || field.mandatory || field.validationRules?.isMandatory || field.validationRules?.isRequired) {
1238
+ validators.push(Validators.required);
1239
+ }
1240
+ if (field.validationRules?.minLength) {
1241
+ validators.push(Validators.minLength(field.validationRules.minLength));
1242
+ }
1243
+ if (field.validationRules?.maxLength) {
1244
+ validators.push(Validators.maxLength(field.validationRules.maxLength));
1245
+ }
1246
+ if (field.validationRules?.pattern) {
1247
+ validators.push(Validators.pattern(field.validationRules.pattern));
1248
+ }
1249
+ if (field.validationRules?.min !== undefined) {
1250
+ validators.push(Validators.min(field.validationRules.min));
1251
+ }
1252
+ if (field.validationRules?.max !== undefined) {
1253
+ validators.push(Validators.max(field.validationRules.max));
1254
+ }
1255
+ if (field.type === 'email') {
1256
+ validators.push(Validators.email);
1257
+ }
1258
+ const initialValue = field.value !== undefined ? field.value : '';
1259
+ return this.fb.control({ value: initialValue, disabled: field.disabled || false }, validators);
1260
+ }
1261
+ createGroup(fields) {
1262
+ const groupConfig = {};
1263
+ fields.forEach(field => {
1264
+ if (field.subFields) {
1265
+ field.subFields.forEach(subField => {
1266
+ groupConfig[subField.name] = this.createControl(subField);
1267
+ });
1268
+ }
1269
+ else {
1270
+ groupConfig[field.name] = this.createControl(field);
1271
+ }
1272
+ });
1273
+ return this.fb.group(groupConfig);
1274
+ }
1275
+ getFormArray(name) {
1276
+ return this.form.get(name);
1277
+ }
1278
+ addRepeaterItem(section) {
1279
+ const arrayName = section.formArrayName || 'items';
1280
+ const formArray = this.getFormArray(arrayName);
1281
+ // Check max items
1282
+ if (section.maxItems && formArray.length >= section.maxItems) {
1283
+ this.snackBar.open(`Maximum ${section.maxItems} items allowed`, 'Close', { duration: 3000 });
1284
+ return;
1285
+ }
1286
+ formArray.push(this.createGroup(section.fields));
1287
+ }
1288
+ removeRepeaterItem(sectionName, index) {
1289
+ const formArray = this.getFormArray(sectionName);
1290
+ formArray.removeAt(index);
1291
+ }
1292
+ onSubmit() {
1293
+ if (this.form.invalid) {
1294
+ this.form.markAllAsTouched();
1295
+ this.scrollToFirstInvalidControl();
1296
+ this.snackBar.open('Please fill all required fields', 'Close', { duration: 3000 });
1297
+ return;
1298
+ }
1299
+ this.formSubmit.emit(this.form.value);
1300
+ }
1301
+ scrollToFirstInvalidControl() {
1302
+ const firstInvalidControl = document.querySelector('.is-invalid');
1303
+ if (firstInvalidControl) {
1304
+ firstInvalidControl.scrollIntoView({ behavior: 'smooth', block: 'center' });
1305
+ }
1306
+ }
1307
+ setupDependencies() {
1308
+ this.processedConfig.sections.forEach(section => {
1309
+ section.fields.forEach(field => {
1310
+ if (field.dependsOn) {
1311
+ const control = this.form.get(field.dependsOn);
1312
+ if (control) {
1313
+ control.valueChanges.subscribe(value => {
1314
+ this.onFieldValueChange(field, value);
1315
+ });
1316
+ }
1317
+ }
1318
+ // Also setup for fields with dependent array
1319
+ if (field.dependent && field.dependent.length > 0) {
1320
+ const control = this.form.get(field.name);
1321
+ if (control) {
1322
+ control.valueChanges.subscribe(value => {
1323
+ this.onFieldValueChange(field, value);
1324
+ });
1325
+ }
1326
+ }
1327
+ });
1328
+ });
1329
+ }
1330
+ onFieldValueChange(field, value) {
1331
+ // Handle dependent fields
1332
+ if (field.dependent && field.dependent.length > 0) {
1333
+ field.dependent.forEach(dependentFieldName => {
1334
+ const dependentField = this.findFieldByName(dependentFieldName);
1335
+ if (dependentField) {
1336
+ // Clear the dependent field value
1337
+ const control = this.form.get(dependentFieldName);
1338
+ if (control) {
1339
+ control.setValue('');
1340
+ control.markAsUntouched();
1341
+ }
1342
+ // Load new options for the dependent field
1343
+ if (value) {
1344
+ this.loadFieldOptions(dependentField, { [field.name]: value });
1345
+ }
1346
+ else {
1347
+ // Clear options if parent value is cleared
1348
+ dependentField.loadedOptions = [];
1349
+ }
1350
+ }
1351
+ });
1352
+ }
1353
+ }
1354
+ // Load options for a dropdown field
1355
+ loadFieldOptions(field, parentValues) {
1356
+ // Emit event for parent to notify about options load request
1357
+ // Allow parent to mark as handled to skip internal API call
1358
+ const event = { field, parentValue: parentValues, handled: false };
1359
+ this.optionsLoad.emit(event);
1360
+ if (event.handled) {
1361
+ return;
1362
+ }
1363
+ if (!field.optionConfigs) {
1364
+ return;
1365
+ }
1366
+ const config = field.optionConfigs;
1367
+ // Handle static options
1368
+ if (config.optionDTO === 'OPTION_DTO.STATIC' && config.staticOptions) {
1369
+ field.loadedOptions = config.staticOptions;
1370
+ return;
1371
+ }
1372
+ // Handle API-based options
1373
+ if (config.optionDTO === 'OPTION_DTO.REF_DATA' && config.url) {
1374
+ let url = config.url;
1375
+ // Replace placeholders in URL with parent values
1376
+ if (parentValues) {
1377
+ Object.keys(parentValues).forEach(key => {
1378
+ url = url.replace(`{${key}}`, parentValues[key]);
1379
+ });
1380
+ }
1381
+ // Prepend base API URL if provided
1382
+ if (this.baseApiUrl && !url.startsWith('http')) {
1383
+ url = `${this.baseApiUrl}/${url}`;
1384
+ }
1385
+ this.http.get(url).subscribe({
1386
+ next: (response) => {
1387
+ // Extract data from response
1388
+ const data = response.data || response.content || response;
1389
+ field.loadedOptions = this.extractOptions(data, config);
1390
+ },
1391
+ error: (error) => {
1392
+ console.error('Error loading options:', error);
1393
+ field.loadedOptions = [];
1394
+ }
1395
+ });
1396
+ }
1397
+ }
1398
+ // Extract options from API response
1399
+ extractOptions(data, config) {
1400
+ if (!Array.isArray(data)) {
1401
+ return [];
1402
+ }
1403
+ return data.map(item => ({
1404
+ label: item[config.labelKey || 'name'],
1405
+ value: item[config.requestKey || 'code'] || item[config.valueKey || 'id'],
1406
+ code: item.code,
1407
+ name: item.name
1408
+ }));
1409
+ }
1410
+ // Get options for a field (either static or loaded)
1411
+ getFieldOptions(field) {
1412
+ return field.loadedOptions || field.options || [];
1413
+ }
1414
+ // Check if field is visible
1415
+ isFieldVisible(field) {
1416
+ return this.fieldVisibilityMap.get(field.name) !== false;
1417
+ }
1418
+ // Toggle field visibility
1419
+ toggleFieldVisibility(field, visible) {
1420
+ this.fieldVisibilityMap.set(field.name, visible);
1421
+ const control = this.form.get(field.name);
1422
+ if (control) {
1423
+ if (visible) {
1424
+ // Re-enable and restore validators
1425
+ control.enable();
1426
+ this.updateControlValidators(control, field);
1427
+ }
1428
+ else {
1429
+ // Disable and clear validators
1430
+ control.disable();
1431
+ control.clearValidators();
1432
+ control.updateValueAndValidity();
1433
+ }
1434
+ }
1435
+ }
1436
+ // Update control validators based on field config
1437
+ updateControlValidators(control, field) {
1438
+ const validators = [];
1439
+ if (field.required || field.mandatory || field.validationRules?.isMandatory) {
1440
+ validators.push(Validators.required);
1441
+ }
1442
+ if (field.validationRules?.minLength) {
1443
+ validators.push(Validators.minLength(field.validationRules.minLength));
1444
+ }
1445
+ if (field.validationRules?.maxLength) {
1446
+ validators.push(Validators.maxLength(field.validationRules.maxLength));
1447
+ }
1448
+ if (field.validationRules?.pattern) {
1449
+ validators.push(Validators.pattern(field.validationRules.pattern));
1450
+ }
1451
+ control.setValidators(validators);
1452
+ control.updateValueAndValidity();
1453
+ }
1454
+ onFileChange(event, field) {
1455
+ const files = event.target.files;
1456
+ if (!files || files.length === 0) {
1457
+ return;
1458
+ }
1459
+ // Initialize uploadedFiles if not present
1460
+ // Initialize uploadedFiles if not present
1461
+ if (!field.uploadedFiles) {
1462
+ field.uploadedFiles = [];
1463
+ }
1464
+ const uploadedFiles = [];
1465
+ // Handle files
1466
+ for (let i = 0; i < files.length; i++) {
1467
+ const file = files[i];
1468
+ // Check file size (5MB limit)
1469
+ if (file.size > 5 * 1024 * 1024) {
1470
+ this.snackBar.open(`File ${file.name} exceeds 5MB limit`, 'Close', { duration: 3000 });
1471
+ continue;
1472
+ }
1473
+ uploadedFiles.push({
1474
+ name: file.name,
1475
+ size: file.size,
1476
+ type: file.type,
1477
+ file: file
1478
+ });
1479
+ }
1480
+ if (field.multiple) {
1481
+ field.uploadedFiles.push(...uploadedFiles);
1482
+ }
1483
+ else {
1484
+ field.uploadedFiles = uploadedFiles;
1485
+ }
1486
+ // Update form control value for validation
1487
+ this.updateFileControlValue(field);
1488
+ // Clear the input
1489
+ event.target.value = '';
1490
+ }
1491
+ // Remove uploaded file
1492
+ removeFile(field, index) {
1493
+ if (field.uploadedFiles) {
1494
+ field.uploadedFiles.splice(index, 1);
1495
+ this.updateFileControlValue(field);
1496
+ }
1497
+ }
1498
+ // Update file control value for validation
1499
+ updateFileControlValue(field) {
1500
+ const control = this.form.get(field.name);
1501
+ if (control) {
1502
+ const hasFiles = field.uploadedFiles && field.uploadedFiles.length > 0;
1503
+ control.setValue(hasFiles ? field.uploadedFiles : null);
1504
+ control.markAsTouched();
1505
+ }
1506
+ }
1507
+ // Get character count for text field
1508
+ getCharacterCount(fieldName) {
1509
+ const control = this.form.get(fieldName);
1510
+ if (control && control.value) {
1511
+ return control.value.toString().length;
1512
+ }
1513
+ return 0;
1514
+ }
1515
+ // Toggle section collapse
1516
+ toggleSection(section) {
1517
+ section.collapsed = !section.collapsed;
1518
+ }
1519
+ onCancel() {
1520
+ this.formCancel.emit();
1521
+ }
1522
+ // Helper method to find field by name
1523
+ findFieldByName(name) {
1524
+ for (const section of this.processedConfig.sections) {
1525
+ const field = section.fields.find(f => f.name === name);
1526
+ if (field) {
1527
+ return field;
1528
+ }
1529
+ }
1530
+ return undefined;
1531
+ }
1532
+ // Get the processed config for template use
1533
+ get sections() {
1534
+ return this.processedConfig?.sections || [];
1535
+ }
1536
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormComponent, deps: [{ token: i1$2.FormBuilder }, { token: i2$1.MatSnackBar }, { token: i3.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
1537
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ConfigurableFormComponent, isStandalone: true, selector: "lib-configurable-form", inputs: { config: "config", jsonConfig: "jsonConfig", data: "data", baseApiUrl: "baseApiUrl" }, outputs: { formSubmit: "formSubmit", formCancel: "formCancel", optionsLoad: "optionsLoad" }, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\" class=\"configurable-form-container\" *ngIf=\"form\">\r\n\r\n <ng-container *ngFor=\"let section of sections\">\r\n\r\n <!-- Repeater Section -->\r\n <div *ngIf=\"section.isRepeater; else normalSection\"\r\n [ngClass]=\"section.noCardLayout ? 'section-no-card' : 'section-card'\">\r\n <div class=\"section-header\" *ngIf=\"section.sectionTitle\">\r\n <h3 class=\"section-title\">{{ section.sectionTitle }}</h3>\r\n <button *ngIf=\"section.collapsible\" mat-icon-button type=\"button\" (click)=\"toggleSection(section)\">\r\n <mat-icon>{{ section.collapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div [formArrayName]=\"section.formArrayName || 'items'\" *ngIf=\"!section.collapsed\">\r\n <div *ngFor=\"let item of getFormArray(section.formArrayName!).controls; let i = index\"\r\n [formGroupName]=\"i\" class=\"repeater-item\">\r\n <div class=\"repeater-item-header\" *ngIf=\"getFormArray(section.formArrayName!).length > 1\">\r\n <span class=\"text-small\">{{ section.repeaterItemLabel || 'Item' }} {{i + 1}}</span>\r\n <button mat-icon-button color=\"warn\" type=\"button\"\r\n (click)=\"removeRepeaterItem(section.formArrayName!, i)\"\r\n [disabled]=\"section.minItems && getFormArray(section.formArrayName!).length <= section.minItems\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Fields Grid -->\r\n <div class=\"form-grid\">\r\n <div *ngFor=\"let field of section.fields\" [ngClass]=\"['form-col', field.class || 'col-12']\"\r\n [hidden]=\"!isFieldVisible(field)\">\r\n <ng-container\r\n *ngTemplateOutlet=\"fieldTemplate; context: {field: field, group: item}\"></ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"repeater-separator\" *ngIf=\"i < getFormArray(section.formArrayName!).length - 1\"></div>\r\n </div>\r\n </div>\r\n\r\n <button mat-button color=\"primary\" type=\"button\" (click)=\"addRepeaterItem(section)\" class=\"add-btn\"\r\n *ngIf=\"!section.collapsed\"\r\n [disabled]=\"section.maxItems && getFormArray(section.formArrayName!).length >= section.maxItems\">\r\n <mat-icon>add_circle_outline</mat-icon> {{ section.addLabel || 'Add More' }}\r\n </button>\r\n </div>\r\n\r\n <!-- Normal Section -->\r\n <ng-template #normalSection>\r\n <div [ngClass]=\"section.noCardLayout ? 'section-no-card' : 'section-card'\">\r\n <div class=\"section-header\" *ngIf=\"section.sectionTitle\">\r\n <h3 class=\"section-title\">{{ section.sectionTitle }}</h3>\r\n <button *ngIf=\"section.collapsible\" mat-icon-button type=\"button\" (click)=\"toggleSection(section)\">\r\n <mat-icon>{{ section.collapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\r\n </button>\r\n </div>\r\n <div class=\"form-grid\" *ngIf=\"!section.collapsed\">\r\n <div *ngFor=\"let field of section.fields\" [ngClass]=\"['form-col', field.class || 'col-12']\"\r\n [hidden]=\"!isFieldVisible(field)\">\r\n <!-- Pass the root form group to the template -->\r\n <ng-container\r\n *ngTemplateOutlet=\"fieldTemplate; context: {field: field, group: form}\"></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n </ng-container>\r\n\r\n <div class=\"btn-row\">\r\n <button mat-stroked-button type=\"button\" (click)=\"onCancel()\" *ngIf=\"processedConfig?.cancelLabel\">{{\r\n processedConfig.cancelLabel\r\n }}</button>\r\n <button mat-stroked-button type=\"button\" *ngIf=\"processedConfig?.saveDraftLabel\">{{\r\n processedConfig.saveDraftLabel }}</button>\r\n <button mat-flat-button color=\"primary\" type=\"submit\">{{ processedConfig?.submitLabel || 'Submit' }}</button>\r\n </div>\r\n\r\n</form>\r\n\r\n<!-- Reusable Field Template -->\r\n<ng-template #fieldTemplate let-field=\"field\" let-group=\"group\">\r\n <div [formGroup]=\"group\">\r\n\r\n <!-- Text / Email / Number / Tel / Password / URL -->\r\n <div *ngIf=\"['text', 'email', 'number', 'tel', 'password', 'url'].includes(field.type || '')\"\r\n class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <div class=\"input-wrapper\">\r\n <input [type]=\"field.type\" [formControlName]=\"field.name\" [placeholder]=\"field.placeholder || ''\"\r\n [readonly]=\"field.readonly\" class=\"form-input\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\"\r\n [maxlength]=\"field.validationRules?.maxLength || field.uiConfig?.maxCharacters\">\r\n <div class=\"input-suffix\">\r\n <span class=\"suffix-text\" *ngIf=\"field.suffixText\">{{ field.suffixText }}</span>\r\n <mat-icon *ngIf=\"field.suffixIcon\">{{ field.suffixIcon }}</mat-icon>\r\n <mat-icon *ngIf=\"field.icon\">{{ field.icon }}</mat-icon>\r\n <mat-icon *ngIf=\"field.readonly\" class=\"lock-icon\">lock_outline</mat-icon>\r\n </div>\r\n </div>\r\n <!-- Character count -->\r\n <div class=\"char-count-row\" *ngIf=\"field.uiConfig?.maxCharacters || field.validationRules?.maxLength\">\r\n <div class=\"hint-text\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n <div class=\"char-count\">\r\n {{ getCharacterCount(field.name) }} / {{ field.uiConfig?.maxCharacters ||\r\n field.validationRules?.maxLength }} Characters\r\n </div>\r\n </div>\r\n <div class=\"hint-text mt-2\"\r\n *ngIf=\"(field.hint || field.helpText) && !field.uiConfig?.maxCharacters && !field.validationRules?.maxLength\">\r\n {{ field.hint || field.helpText }}\r\n </div>\r\n </div>\r\n\r\n <!-- Textarea -->\r\n <div *ngIf=\"field.type === 'textarea'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <textarea [formControlName]=\"field.name\" [placeholder]=\"field.placeholder || ''\" [readonly]=\"field.readonly\"\r\n class=\"form-input form-textarea\" rows=\"4\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\"\r\n [maxlength]=\"field.validationRules?.maxLength || field.uiConfig?.maxCharacters\"></textarea>\r\n <!-- Character count -->\r\n <div class=\"char-count-row\" *ngIf=\"field.uiConfig?.maxCharacters || field.validationRules?.maxLength\">\r\n <div class=\"hint-text\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n <div class=\"char-count\">\r\n {{ getCharacterCount(field.name) }} / {{ field.uiConfig?.maxCharacters ||\r\n field.validationRules?.maxLength }} Characters\r\n </div>\r\n </div>\r\n <div class=\"hint-text mt-2\"\r\n *ngIf=\"(field.hint || field.helpText) && !field.uiConfig?.maxCharacters && !field.validationRules?.maxLength\">\r\n {{ field.hint || field.helpText }}\r\n </div>\r\n </div>\r\n\r\n <!-- Select / Dropdown -->\r\n <div *ngIf=\"field.type === 'select' || field.type === 'dropdown'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <select [formControlName]=\"field.name\" class=\"form-input\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\">\r\n <option value=\"\" disabled selected *ngIf=\"field.placeholder\">{{ field.placeholder }}</option>\r\n <option value=\"\" disabled selected *ngIf=\"!field.placeholder\">Select</option>\r\n <option *ngFor=\"let opt of getFieldOptions(field)\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <div class=\"hint-text mt-2\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n </div>\r\n\r\n <!-- Date -->\r\n <div *ngIf=\"field.type === 'date'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <div class=\"relative\">\r\n <input matInput [matDatepicker]=\"picker\" [formControlName]=\"field.name\"\r\n [placeholder]=\"field.placeholder || ''\" class=\"form-input\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\">\r\n <mat-datepicker-toggle matSuffix [for]=\"picker\" class=\"date-toggle\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </div>\r\n <div class=\"hint-text mt-2\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n </div>\r\n\r\n <!-- Radio -->\r\n <div *ngIf=\"field.type === 'radio'\" class=\"radio-group-container\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\">\r\n <label class=\"field-label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </label>\r\n <mat-radio-group [formControlName]=\"field.name\" class=\"radio-group\">\r\n <mat-radio-button *ngFor=\"let opt of getFieldOptions(field)\" [value]=\"opt.value\" class=\"radio-button\">\r\n {{ opt.label }}\r\n </mat-radio-button>\r\n </mat-radio-group>\r\n <div class=\"hint-text mt-2\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n </div>\r\n\r\n <!-- Composite Field (Sub-groups) -->\r\n <div *ngIf=\"field.type === 'composite'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <div class=\"composite-container\">\r\n <ng-container *ngFor=\"let sub of field.subFields; let last = last\">\r\n <div class=\"composite-sub-field\" style=\"flex: 1;\">\r\n <div class=\"field-label\" *ngIf=\"sub.label\"\r\n style=\"font-size: 0.75rem; font-weight: normal; margin-bottom: 0.25rem;\">\r\n {{ sub.label }}\r\n </div>\r\n <div class=\"input-wrapper\">\r\n <input [type]=\"sub.type\" [formControlName]=\"sub.name\" [placeholder]=\"sub.placeholder || ''\"\r\n [readonly]=\"sub.readonly\" class=\"form-input\"\r\n [class.is-invalid]=\"group.get(sub.name)?.touched && group.get(sub.name)?.invalid\">\r\n <div class=\"input-suffix\" [class.color-suffix]=\"sub.suffixText === '%'\">\r\n <span class=\"suffix-text\" *ngIf=\"sub.suffixText\">{{ sub.suffixText }}</span>\r\n <mat-icon *ngIf=\"sub.readonly\" class=\"lock-icon\">lock_outline</mat-icon>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Adjust separator alignment if labels are present -->\r\n <span class=\"separator\" *ngIf=\"!last && field.separator\"\r\n [style.padding-top]=\"sub.label ? '1.25rem' : '0'\">{{ field.separator }}</span>\r\n </ng-container>\r\n </div>\r\n <div class=\"hint-text mt-2\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n <div class=\"error-text text-danger text-small mt-1\" *ngIf=\"group.errors?.['invalid_minMax_' + field.name]\">\r\n Min value cannot be greater than Max value.\r\n </div>\r\n <div class=\"error-text text-danger text-small mt-1\"\r\n *ngIf=\"group.errors?.['invalid_percentageTotal_' + field.name]\">\r\n Total percentage must be 100%.\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- File Upload -->\r\n <div *ngIf=\"field.type === 'file'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n\r\n <!-- Upload Box -->\r\n <div class=\"upload-box\" (click)=\"fileInput.click()\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\"\r\n *ngIf=\"!field.uploadedFiles || field.uploadedFiles.length === 0 || field.multiple\">\r\n <mat-icon class=\"upload-icon\">cloud_upload</mat-icon>\r\n <div class=\"upload-text\">Click to upload File</div>\r\n <div class=\"upload-hint\">PDF, DOCX, JPG, PNG (Max 5MB)</div>\r\n <input #fileInput type=\"file\" [attr.multiple]=\"field.multiple ? true : null\" [attr.accept]=\"field.accept\"\r\n (change)=\"onFileChange($event, field)\" style=\"display: none;\">\r\n </div>\r\n\r\n <!-- Uploaded Files List -->\r\n <div class=\"uploaded-files-list\" *ngIf=\"field.uploadedFiles && field.uploadedFiles.length > 0\">\r\n <div class=\"uploaded-file-item\" *ngFor=\"let file of field.uploadedFiles; let i = index\">\r\n <div class=\"file-icon\">\r\n <mat-icon class=\"pdf-icon\" *ngIf=\"file.type === 'application/pdf'\">picture_as_pdf</mat-icon>\r\n <mat-icon class=\"doc-icon\"\r\n *ngIf=\"file.type.includes('word') || file.type.includes('document')\">description</mat-icon>\r\n <mat-icon class=\"img-icon\" *ngIf=\"file.type.includes('image')\">image</mat-icon>\r\n <mat-icon class=\"file-icon-default\"\r\n *ngIf=\"!file.type.includes('pdf') && !file.type.includes('word') && !file.type.includes('document') && !file.type.includes('image')\">insert_drive_file</mat-icon>\r\n </div>\r\n <div class=\"file-info\">\r\n <div class=\"file-name\">{{ file.name }}</div>\r\n <div class=\"file-size\">{{ (file.size / 1024).toFixed(2) }} KB</div>\r\n </div>\r\n <button mat-icon-button color=\"warn\" type=\"button\" (click)=\"removeFile(field, i)\"\r\n class=\"remove-file-btn\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n</ng-template>", styles: [":host{display:block;width:100%}.configurable-form-container{padding:0;font-family:var(--cf-font-family, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif)}.configurable-form-container .section-card{background:var(--cf-surface-background, #ffffff);border:1px solid var(--cf-border-color, #D1D5DB);border-radius:var(--cf-section-radius, 12px);padding:var(--cf-section-padding, 2rem);margin-bottom:var(--cf-section-spacing, 1.5rem);box-shadow:var(--cf-section-shadow, 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px 0 rgba(0, 0, 0, .06))}.configurable-form-container .section-card:last-of-type{margin-bottom:0}.configurable-form-container .section-no-card{margin-bottom:var(--cf-section-spacing, 1.5rem)}.configurable-form-container .section-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--cf-section-spacing, 1.5rem);padding-bottom:1rem;border-bottom:2px solid var(--cf-border-color, #D1D5DB)}.configurable-form-container .section-title{font-size:var(--cf-section-title-size, 1.25rem);font-weight:var(--cf-section-title-weight, 600);color:var(--cf-text-primary, #111827);margin:0;letter-spacing:-.025em}.configurable-form-container .form-grid{display:flex;flex-wrap:wrap;margin-left:-.625rem;margin-right:-.625rem}.configurable-form-container .form-col{position:relative;width:100%;padding-left:.625rem;padding-right:.625rem;margin-bottom:1.25rem}.configurable-form-container .col-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.configurable-form-container .col-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.configurable-form-container .col-3{flex:0 0 25%;max-width:25%}.configurable-form-container .col-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.configurable-form-container .col-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.configurable-form-container .col-6{flex:0 0 50%;max-width:50%}.configurable-form-container .col-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.configurable-form-container .col-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.configurable-form-container .col-9{flex:0 0 75%;max-width:75%}.configurable-form-container .col-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.configurable-form-container .col-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.configurable-form-container .col-12{flex:0 0 100%;max-width:100%}@media(min-width:769px){.configurable-form-container .col-md-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.configurable-form-container .col-md-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.configurable-form-container .col-md-3{flex:0 0 25%;max-width:25%}.configurable-form-container .col-md-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.configurable-form-container .col-md-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.configurable-form-container .col-md-6{flex:0 0 50%;max-width:50%}.configurable-form-container .col-md-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.configurable-form-container .col-md-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.configurable-form-container .col-md-9{flex:0 0 75%;max-width:75%}.configurable-form-container .col-md-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.configurable-form-container .col-md-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.configurable-form-container .col-md-12{flex:0 0 100%;max-width:100%}}.configurable-form-container .field-container{margin-bottom:0}.configurable-form-container .field-label{display:block;font-size:var(--cf-label-size, .875rem);font-weight:var(--cf-label-weight, 600);color:var(--cf-text-primary, #111827);margin-bottom:.5rem;line-height:1.25rem}.configurable-form-container .field-label .text-danger{color:var(--cf-error-color, #DC2626);margin-left:.125rem}.configurable-form-container .input-wrapper{position:relative;display:flex;align-items:center}.configurable-form-container .form-input{width:100%;padding:var(--cf-input-padding-y, .625rem) var(--cf-input-padding-x, .875rem);font-size:var(--cf-input-font-size, .875rem);line-height:1.5;color:var(--cf-text-primary, #111827);background-color:var(--cf-input-bg, #ffffff);border:1.5px solid var(--cf-border-color, #D1D5DB);border-radius:var(--cf-input-radius, 8px);transition:all .2s ease;font-family:inherit}.configurable-form-container .form-input:hover:not(:disabled):not([readonly]){border-color:var(--cf-input-hover-border-color, #9CA3AF)}.configurable-form-container .form-input:focus{outline:none;border-color:var(--cf-primary-color, #3B82F6);box-shadow:0 0 0 3px #3b82f61a}.configurable-form-container .form-input::placeholder{color:#9ca3af}.configurable-form-container .form-input:disabled,.configurable-form-container .form-input[readonly]{background-color:var(--cf-disabled-background, #F3F4F6);color:var(--cf-text-secondary, #6B7280);cursor:not-allowed;border-color:#e5e7eb}.configurable-form-container .form-input.is-invalid{border-color:var(--cf-error-color, #DC2626);background-color:#fef2f2}.configurable-form-container .form-input.is-invalid:focus{box-shadow:0 0 0 3px #dc26261a}.configurable-form-container select.form-input{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E\");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;cursor:pointer}.configurable-form-container select.form-input:disabled{cursor:not-allowed}.configurable-form-container .form-textarea{resize:vertical;min-height:100px;font-family:inherit}.configurable-form-container .input-suffix{position:absolute;right:.75rem;display:flex;align-items:center;gap:.5rem;pointer-events:none}.configurable-form-container .input-suffix .suffix-text{font-size:.875rem;color:var(--cf-text-secondary, #6B7280);font-weight:500}.configurable-form-container .input-suffix mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem;color:var(--cf-text-secondary, #6B7280)}.configurable-form-container .input-suffix .lock-icon{color:#9ca3af}.configurable-form-container .input-suffix.color-suffix .suffix-text{color:var(--cf-primary-color, #3B82F6);font-weight:600}.configurable-form-container .char-count-row{display:flex;justify-content:space-between;align-items:center;margin-top:.5rem}.configurable-form-container .char-count{font-size:.75rem;color:var(--cf-text-secondary, #6B7280);font-weight:500}.configurable-form-container .hint-text{font-size:var(--cf-hint-size, .75rem);color:var(--cf-text-secondary, #6B7280);margin-top:.375rem;line-height:1.25rem}.configurable-form-container .mt-2{margin-top:.5rem}.configurable-form-container .radio-group-container.is-invalid .field-label{color:var(--cf-error-color, #DC2626)}.configurable-form-container .radio-group{display:flex;gap:2rem;flex-wrap:wrap;margin-top:.5rem}.configurable-form-container .radio-button{margin:0}.configurable-form-container .composite-container{display:flex;align-items:center;gap:.75rem}.configurable-form-container .composite-container .separator{font-size:.875rem;color:var(--cf-text-secondary, #6B7280);font-weight:500}.configurable-form-container .composite-container .input-wrapper{flex:1}.configurable-form-container .upload-box{border:2px dashed var(--cf-border-color, #D1D5DB);border-radius:var(--cf-section-radius, 12px);padding:2.5rem;text-align:center;cursor:pointer;transition:all .2s ease;background-color:var(--cf-hover-background, #F9FAFB)}.configurable-form-container .upload-box:hover{border-color:var(--cf-primary-color, #3B82F6);background-color:#3b82f608}.configurable-form-container .upload-box.is-invalid{border-color:var(--cf-error-color, #DC2626);background-color:#fef2f2}.configurable-form-container .upload-box .upload-icon{font-size:3rem;width:3rem;height:3rem;color:var(--cf-primary-color, #3B82F6);margin-bottom:.75rem}.configurable-form-container .upload-box .upload-text{font-size:.875rem;color:var(--cf-text-primary, #111827);font-weight:500;margin-bottom:.375rem}.configurable-form-container .upload-box .upload-hint{font-size:.75rem;color:var(--cf-text-secondary, #6B7280)}.configurable-form-container .uploaded-files-list{margin-top:1rem}.configurable-form-container .uploaded-file-item{display:flex;align-items:center;gap:.75rem;padding:.875rem;border:1.5px solid var(--cf-border-color, #D1D5DB);border-radius:8px;margin-bottom:.5rem;background-color:var(--cf-hover-background, #F9FAFB);transition:all .2s ease}.configurable-form-container .uploaded-file-item:hover{border-color:#9ca3af;box-shadow:0 1px 3px #0000001a}.configurable-form-container .uploaded-file-item .file-icon mat-icon{font-size:2rem;width:2rem;height:2rem}.configurable-form-container .uploaded-file-item .file-icon mat-icon.pdf-icon{color:#dc2626}.configurable-form-container .uploaded-file-item .file-icon mat-icon.doc-icon{color:#2563eb}.configurable-form-container .uploaded-file-item .file-icon mat-icon.img-icon{color:#059669}.configurable-form-container .uploaded-file-item .file-icon mat-icon.file-icon-default{color:var(--cf-text-secondary, #6B7280)}.configurable-form-container .uploaded-file-item .file-info{flex:1}.configurable-form-container .uploaded-file-item .file-info .file-name{font-size:.875rem;color:var(--cf-text-primary, #111827);font-weight:500;margin-bottom:.125rem}.configurable-form-container .uploaded-file-item .file-info .file-size{font-size:.75rem;color:var(--cf-text-secondary, #6B7280)}.configurable-form-container .uploaded-file-item .remove-file-btn mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem}.configurable-form-container .relative{position:relative}.configurable-form-container .date-toggle{position:absolute;right:0;top:50%;transform:translateY(-50%)}.configurable-form-container .repeater-item{padding:1.5rem;border:1.5px solid var(--cf-border-color, #D1D5DB);border-radius:10px;margin-bottom:1rem;background-color:var(--cf-hover-background, #F9FAFB);transition:all .2s ease}.configurable-form-container .repeater-item:hover{border-color:#9ca3af;box-shadow:0 2px 4px #0000000d}.configurable-form-container .repeater-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.25rem;padding-bottom:.75rem;border-bottom:1.5px solid var(--cf-border-color, #D1D5DB)}.configurable-form-container .repeater-item-header .text-small{font-size:.875rem;font-weight:600;color:var(--cf-text-primary, #111827);text-transform:uppercase;letter-spacing:.025em}.configurable-form-container .repeater-separator{height:1px;background-color:var(--cf-border-color, #D1D5DB);margin:1.5rem 0}.configurable-form-container .add-btn{margin-top:1rem;display:inline-flex;align-items:center;gap:.5rem;padding:.625rem 1.25rem;background-color:transparent;color:var(--cf-primary-color, #3B82F6);border:1.5px solid var(--cf-primary-color, #3B82F6);border-radius:8px;font-size:.875rem;font-weight:600;cursor:pointer;transition:all .2s ease}.configurable-form-container .add-btn:hover:not(:disabled){background-color:var(--cf-primary-color, #3B82F6);color:#fff}.configurable-form-container .add-btn:disabled{opacity:.5;cursor:not-allowed;border-color:var(--cf-disabled-background, #E5E7EB)}.configurable-form-container .add-btn mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem}.configurable-form-container .btn-row{display:flex;justify-content:flex-end;gap:1rem;margin-top:2rem;padding-top:1.5rem;border-top:2px solid var(--cf-border-color, #D1D5DB)}.configurable-form-container .btn-row button{padding:.625rem 1.5rem;font-size:.875rem;font-weight:600;border-radius:8px;cursor:pointer;transition:all .2s ease;border:none;font-family:inherit}.configurable-form-container .btn-row button[mat-stroked-button]{background-color:transparent;color:var(--cf-text-primary, #111827);border:1.5px solid var(--cf-border-color, #D1D5DB)}.configurable-form-container .btn-row button[mat-stroked-button]:hover{background-color:var(--cf-hover-background, #F9FAFB);border-color:#9ca3af}.configurable-form-container .btn-row button[mat-flat-button]{background-color:var(--cf-primary-color, #3B82F6);color:#fff;box-shadow:0 1px 3px #0000001a}.configurable-form-container .btn-row button[mat-flat-button]:hover{background-color:#2563eb;box-shadow:0 4px 6px -1px #0000001a}.configurable-form-container .btn-row button[mat-flat-button]:active{background-color:#1d4ed8}@media(max-width:768px){.configurable-form-container .section-card{padding:1.25rem;border-radius:8px}.configurable-form-container .form-grid{margin-left:-.5rem;margin-right:-.5rem}.configurable-form-container .form-col{padding-left:.5rem;padding-right:.5rem;margin-bottom:1rem}.configurable-form-container .btn-row{flex-direction:column-reverse}.configurable-form-container .btn-row button{width:100%}.configurable-form-container .radio-group{flex-direction:column;gap:.75rem}.configurable-form-container .composite-container{flex-direction:column;align-items:stretch}.configurable-form-container .composite-container .separator{text-align:center}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: MaterialModule }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i6.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i6.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: i7$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i7$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i7$1.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i8$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i7.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
1538
+ }
1539
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormComponent, decorators: [{
1540
+ type: Component,
1541
+ args: [{ selector: 'lib-configurable-form', standalone: true, imports: [CommonModule, ReactiveFormsModule, MaterialModule], template: "<form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\" class=\"configurable-form-container\" *ngIf=\"form\">\r\n\r\n <ng-container *ngFor=\"let section of sections\">\r\n\r\n <!-- Repeater Section -->\r\n <div *ngIf=\"section.isRepeater; else normalSection\"\r\n [ngClass]=\"section.noCardLayout ? 'section-no-card' : 'section-card'\">\r\n <div class=\"section-header\" *ngIf=\"section.sectionTitle\">\r\n <h3 class=\"section-title\">{{ section.sectionTitle }}</h3>\r\n <button *ngIf=\"section.collapsible\" mat-icon-button type=\"button\" (click)=\"toggleSection(section)\">\r\n <mat-icon>{{ section.collapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div [formArrayName]=\"section.formArrayName || 'items'\" *ngIf=\"!section.collapsed\">\r\n <div *ngFor=\"let item of getFormArray(section.formArrayName!).controls; let i = index\"\r\n [formGroupName]=\"i\" class=\"repeater-item\">\r\n <div class=\"repeater-item-header\" *ngIf=\"getFormArray(section.formArrayName!).length > 1\">\r\n <span class=\"text-small\">{{ section.repeaterItemLabel || 'Item' }} {{i + 1}}</span>\r\n <button mat-icon-button color=\"warn\" type=\"button\"\r\n (click)=\"removeRepeaterItem(section.formArrayName!, i)\"\r\n [disabled]=\"section.minItems && getFormArray(section.formArrayName!).length <= section.minItems\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Fields Grid -->\r\n <div class=\"form-grid\">\r\n <div *ngFor=\"let field of section.fields\" [ngClass]=\"['form-col', field.class || 'col-12']\"\r\n [hidden]=\"!isFieldVisible(field)\">\r\n <ng-container\r\n *ngTemplateOutlet=\"fieldTemplate; context: {field: field, group: item}\"></ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"repeater-separator\" *ngIf=\"i < getFormArray(section.formArrayName!).length - 1\"></div>\r\n </div>\r\n </div>\r\n\r\n <button mat-button color=\"primary\" type=\"button\" (click)=\"addRepeaterItem(section)\" class=\"add-btn\"\r\n *ngIf=\"!section.collapsed\"\r\n [disabled]=\"section.maxItems && getFormArray(section.formArrayName!).length >= section.maxItems\">\r\n <mat-icon>add_circle_outline</mat-icon> {{ section.addLabel || 'Add More' }}\r\n </button>\r\n </div>\r\n\r\n <!-- Normal Section -->\r\n <ng-template #normalSection>\r\n <div [ngClass]=\"section.noCardLayout ? 'section-no-card' : 'section-card'\">\r\n <div class=\"section-header\" *ngIf=\"section.sectionTitle\">\r\n <h3 class=\"section-title\">{{ section.sectionTitle }}</h3>\r\n <button *ngIf=\"section.collapsible\" mat-icon-button type=\"button\" (click)=\"toggleSection(section)\">\r\n <mat-icon>{{ section.collapsed ? 'expand_more' : 'expand_less' }}</mat-icon>\r\n </button>\r\n </div>\r\n <div class=\"form-grid\" *ngIf=\"!section.collapsed\">\r\n <div *ngFor=\"let field of section.fields\" [ngClass]=\"['form-col', field.class || 'col-12']\"\r\n [hidden]=\"!isFieldVisible(field)\">\r\n <!-- Pass the root form group to the template -->\r\n <ng-container\r\n *ngTemplateOutlet=\"fieldTemplate; context: {field: field, group: form}\"></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n </ng-container>\r\n\r\n <div class=\"btn-row\">\r\n <button mat-stroked-button type=\"button\" (click)=\"onCancel()\" *ngIf=\"processedConfig?.cancelLabel\">{{\r\n processedConfig.cancelLabel\r\n }}</button>\r\n <button mat-stroked-button type=\"button\" *ngIf=\"processedConfig?.saveDraftLabel\">{{\r\n processedConfig.saveDraftLabel }}</button>\r\n <button mat-flat-button color=\"primary\" type=\"submit\">{{ processedConfig?.submitLabel || 'Submit' }}</button>\r\n </div>\r\n\r\n</form>\r\n\r\n<!-- Reusable Field Template -->\r\n<ng-template #fieldTemplate let-field=\"field\" let-group=\"group\">\r\n <div [formGroup]=\"group\">\r\n\r\n <!-- Text / Email / Number / Tel / Password / URL -->\r\n <div *ngIf=\"['text', 'email', 'number', 'tel', 'password', 'url'].includes(field.type || '')\"\r\n class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <div class=\"input-wrapper\">\r\n <input [type]=\"field.type\" [formControlName]=\"field.name\" [placeholder]=\"field.placeholder || ''\"\r\n [readonly]=\"field.readonly\" class=\"form-input\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\"\r\n [maxlength]=\"field.validationRules?.maxLength || field.uiConfig?.maxCharacters\">\r\n <div class=\"input-suffix\">\r\n <span class=\"suffix-text\" *ngIf=\"field.suffixText\">{{ field.suffixText }}</span>\r\n <mat-icon *ngIf=\"field.suffixIcon\">{{ field.suffixIcon }}</mat-icon>\r\n <mat-icon *ngIf=\"field.icon\">{{ field.icon }}</mat-icon>\r\n <mat-icon *ngIf=\"field.readonly\" class=\"lock-icon\">lock_outline</mat-icon>\r\n </div>\r\n </div>\r\n <!-- Character count -->\r\n <div class=\"char-count-row\" *ngIf=\"field.uiConfig?.maxCharacters || field.validationRules?.maxLength\">\r\n <div class=\"hint-text\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n <div class=\"char-count\">\r\n {{ getCharacterCount(field.name) }} / {{ field.uiConfig?.maxCharacters ||\r\n field.validationRules?.maxLength }} Characters\r\n </div>\r\n </div>\r\n <div class=\"hint-text mt-2\"\r\n *ngIf=\"(field.hint || field.helpText) && !field.uiConfig?.maxCharacters && !field.validationRules?.maxLength\">\r\n {{ field.hint || field.helpText }}\r\n </div>\r\n </div>\r\n\r\n <!-- Textarea -->\r\n <div *ngIf=\"field.type === 'textarea'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <textarea [formControlName]=\"field.name\" [placeholder]=\"field.placeholder || ''\" [readonly]=\"field.readonly\"\r\n class=\"form-input form-textarea\" rows=\"4\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\"\r\n [maxlength]=\"field.validationRules?.maxLength || field.uiConfig?.maxCharacters\"></textarea>\r\n <!-- Character count -->\r\n <div class=\"char-count-row\" *ngIf=\"field.uiConfig?.maxCharacters || field.validationRules?.maxLength\">\r\n <div class=\"hint-text\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n <div class=\"char-count\">\r\n {{ getCharacterCount(field.name) }} / {{ field.uiConfig?.maxCharacters ||\r\n field.validationRules?.maxLength }} Characters\r\n </div>\r\n </div>\r\n <div class=\"hint-text mt-2\"\r\n *ngIf=\"(field.hint || field.helpText) && !field.uiConfig?.maxCharacters && !field.validationRules?.maxLength\">\r\n {{ field.hint || field.helpText }}\r\n </div>\r\n </div>\r\n\r\n <!-- Select / Dropdown -->\r\n <div *ngIf=\"field.type === 'select' || field.type === 'dropdown'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <select [formControlName]=\"field.name\" class=\"form-input\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\">\r\n <option value=\"\" disabled selected *ngIf=\"field.placeholder\">{{ field.placeholder }}</option>\r\n <option value=\"\" disabled selected *ngIf=\"!field.placeholder\">Select</option>\r\n <option *ngFor=\"let opt of getFieldOptions(field)\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <div class=\"hint-text mt-2\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n </div>\r\n\r\n <!-- Date -->\r\n <div *ngIf=\"field.type === 'date'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <div class=\"relative\">\r\n <input matInput [matDatepicker]=\"picker\" [formControlName]=\"field.name\"\r\n [placeholder]=\"field.placeholder || ''\" class=\"form-input\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\">\r\n <mat-datepicker-toggle matSuffix [for]=\"picker\" class=\"date-toggle\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </div>\r\n <div class=\"hint-text mt-2\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n </div>\r\n\r\n <!-- Radio -->\r\n <div *ngIf=\"field.type === 'radio'\" class=\"radio-group-container\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\">\r\n <label class=\"field-label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </label>\r\n <mat-radio-group [formControlName]=\"field.name\" class=\"radio-group\">\r\n <mat-radio-button *ngFor=\"let opt of getFieldOptions(field)\" [value]=\"opt.value\" class=\"radio-button\">\r\n {{ opt.label }}\r\n </mat-radio-button>\r\n </mat-radio-group>\r\n <div class=\"hint-text mt-2\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n </div>\r\n\r\n <!-- Composite Field (Sub-groups) -->\r\n <div *ngIf=\"field.type === 'composite'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n <div class=\"composite-container\">\r\n <ng-container *ngFor=\"let sub of field.subFields; let last = last\">\r\n <div class=\"composite-sub-field\" style=\"flex: 1;\">\r\n <div class=\"field-label\" *ngIf=\"sub.label\"\r\n style=\"font-size: 0.75rem; font-weight: normal; margin-bottom: 0.25rem;\">\r\n {{ sub.label }}\r\n </div>\r\n <div class=\"input-wrapper\">\r\n <input [type]=\"sub.type\" [formControlName]=\"sub.name\" [placeholder]=\"sub.placeholder || ''\"\r\n [readonly]=\"sub.readonly\" class=\"form-input\"\r\n [class.is-invalid]=\"group.get(sub.name)?.touched && group.get(sub.name)?.invalid\">\r\n <div class=\"input-suffix\" [class.color-suffix]=\"sub.suffixText === '%'\">\r\n <span class=\"suffix-text\" *ngIf=\"sub.suffixText\">{{ sub.suffixText }}</span>\r\n <mat-icon *ngIf=\"sub.readonly\" class=\"lock-icon\">lock_outline</mat-icon>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- Adjust separator alignment if labels are present -->\r\n <span class=\"separator\" *ngIf=\"!last && field.separator\"\r\n [style.padding-top]=\"sub.label ? '1.25rem' : '0'\">{{ field.separator }}</span>\r\n </ng-container>\r\n </div>\r\n <div class=\"hint-text mt-2\" *ngIf=\"field.hint || field.helpText\">{{ field.hint || field.helpText }}</div>\r\n <div class=\"error-text text-danger text-small mt-1\" *ngIf=\"group.errors?.['invalid_minMax_' + field.name]\">\r\n Min value cannot be greater than Max value.\r\n </div>\r\n <div class=\"error-text text-danger text-small mt-1\"\r\n *ngIf=\"group.errors?.['invalid_percentageTotal_' + field.name]\">\r\n Total percentage must be 100%.\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- File Upload -->\r\n <div *ngIf=\"field.type === 'file'\" class=\"field-container\">\r\n <div class=\"field-label\" *ngIf=\"field.label\">\r\n {{ field.label }}\r\n <span class=\"text-danger\" *ngIf=\"field.required || field.mandatory\">*</span>\r\n </div>\r\n\r\n <!-- Upload Box -->\r\n <div class=\"upload-box\" (click)=\"fileInput.click()\"\r\n [class.is-invalid]=\"group.get(field.name)?.touched && group.get(field.name)?.invalid\"\r\n *ngIf=\"!field.uploadedFiles || field.uploadedFiles.length === 0 || field.multiple\">\r\n <mat-icon class=\"upload-icon\">cloud_upload</mat-icon>\r\n <div class=\"upload-text\">Click to upload File</div>\r\n <div class=\"upload-hint\">PDF, DOCX, JPG, PNG (Max 5MB)</div>\r\n <input #fileInput type=\"file\" [attr.multiple]=\"field.multiple ? true : null\" [attr.accept]=\"field.accept\"\r\n (change)=\"onFileChange($event, field)\" style=\"display: none;\">\r\n </div>\r\n\r\n <!-- Uploaded Files List -->\r\n <div class=\"uploaded-files-list\" *ngIf=\"field.uploadedFiles && field.uploadedFiles.length > 0\">\r\n <div class=\"uploaded-file-item\" *ngFor=\"let file of field.uploadedFiles; let i = index\">\r\n <div class=\"file-icon\">\r\n <mat-icon class=\"pdf-icon\" *ngIf=\"file.type === 'application/pdf'\">picture_as_pdf</mat-icon>\r\n <mat-icon class=\"doc-icon\"\r\n *ngIf=\"file.type.includes('word') || file.type.includes('document')\">description</mat-icon>\r\n <mat-icon class=\"img-icon\" *ngIf=\"file.type.includes('image')\">image</mat-icon>\r\n <mat-icon class=\"file-icon-default\"\r\n *ngIf=\"!file.type.includes('pdf') && !file.type.includes('word') && !file.type.includes('document') && !file.type.includes('image')\">insert_drive_file</mat-icon>\r\n </div>\r\n <div class=\"file-info\">\r\n <div class=\"file-name\">{{ file.name }}</div>\r\n <div class=\"file-size\">{{ (file.size / 1024).toFixed(2) }} KB</div>\r\n </div>\r\n <button mat-icon-button color=\"warn\" type=\"button\" (click)=\"removeFile(field, i)\"\r\n class=\"remove-file-btn\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n</ng-template>", styles: [":host{display:block;width:100%}.configurable-form-container{padding:0;font-family:var(--cf-font-family, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif)}.configurable-form-container .section-card{background:var(--cf-surface-background, #ffffff);border:1px solid var(--cf-border-color, #D1D5DB);border-radius:var(--cf-section-radius, 12px);padding:var(--cf-section-padding, 2rem);margin-bottom:var(--cf-section-spacing, 1.5rem);box-shadow:var(--cf-section-shadow, 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px 0 rgba(0, 0, 0, .06))}.configurable-form-container .section-card:last-of-type{margin-bottom:0}.configurable-form-container .section-no-card{margin-bottom:var(--cf-section-spacing, 1.5rem)}.configurable-form-container .section-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--cf-section-spacing, 1.5rem);padding-bottom:1rem;border-bottom:2px solid var(--cf-border-color, #D1D5DB)}.configurable-form-container .section-title{font-size:var(--cf-section-title-size, 1.25rem);font-weight:var(--cf-section-title-weight, 600);color:var(--cf-text-primary, #111827);margin:0;letter-spacing:-.025em}.configurable-form-container .form-grid{display:flex;flex-wrap:wrap;margin-left:-.625rem;margin-right:-.625rem}.configurable-form-container .form-col{position:relative;width:100%;padding-left:.625rem;padding-right:.625rem;margin-bottom:1.25rem}.configurable-form-container .col-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.configurable-form-container .col-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.configurable-form-container .col-3{flex:0 0 25%;max-width:25%}.configurable-form-container .col-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.configurable-form-container .col-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.configurable-form-container .col-6{flex:0 0 50%;max-width:50%}.configurable-form-container .col-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.configurable-form-container .col-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.configurable-form-container .col-9{flex:0 0 75%;max-width:75%}.configurable-form-container .col-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.configurable-form-container .col-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.configurable-form-container .col-12{flex:0 0 100%;max-width:100%}@media(min-width:769px){.configurable-form-container .col-md-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.configurable-form-container .col-md-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.configurable-form-container .col-md-3{flex:0 0 25%;max-width:25%}.configurable-form-container .col-md-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.configurable-form-container .col-md-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.configurable-form-container .col-md-6{flex:0 0 50%;max-width:50%}.configurable-form-container .col-md-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.configurable-form-container .col-md-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.configurable-form-container .col-md-9{flex:0 0 75%;max-width:75%}.configurable-form-container .col-md-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.configurable-form-container .col-md-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.configurable-form-container .col-md-12{flex:0 0 100%;max-width:100%}}.configurable-form-container .field-container{margin-bottom:0}.configurable-form-container .field-label{display:block;font-size:var(--cf-label-size, .875rem);font-weight:var(--cf-label-weight, 600);color:var(--cf-text-primary, #111827);margin-bottom:.5rem;line-height:1.25rem}.configurable-form-container .field-label .text-danger{color:var(--cf-error-color, #DC2626);margin-left:.125rem}.configurable-form-container .input-wrapper{position:relative;display:flex;align-items:center}.configurable-form-container .form-input{width:100%;padding:var(--cf-input-padding-y, .625rem) var(--cf-input-padding-x, .875rem);font-size:var(--cf-input-font-size, .875rem);line-height:1.5;color:var(--cf-text-primary, #111827);background-color:var(--cf-input-bg, #ffffff);border:1.5px solid var(--cf-border-color, #D1D5DB);border-radius:var(--cf-input-radius, 8px);transition:all .2s ease;font-family:inherit}.configurable-form-container .form-input:hover:not(:disabled):not([readonly]){border-color:var(--cf-input-hover-border-color, #9CA3AF)}.configurable-form-container .form-input:focus{outline:none;border-color:var(--cf-primary-color, #3B82F6);box-shadow:0 0 0 3px #3b82f61a}.configurable-form-container .form-input::placeholder{color:#9ca3af}.configurable-form-container .form-input:disabled,.configurable-form-container .form-input[readonly]{background-color:var(--cf-disabled-background, #F3F4F6);color:var(--cf-text-secondary, #6B7280);cursor:not-allowed;border-color:#e5e7eb}.configurable-form-container .form-input.is-invalid{border-color:var(--cf-error-color, #DC2626);background-color:#fef2f2}.configurable-form-container .form-input.is-invalid:focus{box-shadow:0 0 0 3px #dc26261a}.configurable-form-container select.form-input{appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E\");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;cursor:pointer}.configurable-form-container select.form-input:disabled{cursor:not-allowed}.configurable-form-container .form-textarea{resize:vertical;min-height:100px;font-family:inherit}.configurable-form-container .input-suffix{position:absolute;right:.75rem;display:flex;align-items:center;gap:.5rem;pointer-events:none}.configurable-form-container .input-suffix .suffix-text{font-size:.875rem;color:var(--cf-text-secondary, #6B7280);font-weight:500}.configurable-form-container .input-suffix mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem;color:var(--cf-text-secondary, #6B7280)}.configurable-form-container .input-suffix .lock-icon{color:#9ca3af}.configurable-form-container .input-suffix.color-suffix .suffix-text{color:var(--cf-primary-color, #3B82F6);font-weight:600}.configurable-form-container .char-count-row{display:flex;justify-content:space-between;align-items:center;margin-top:.5rem}.configurable-form-container .char-count{font-size:.75rem;color:var(--cf-text-secondary, #6B7280);font-weight:500}.configurable-form-container .hint-text{font-size:var(--cf-hint-size, .75rem);color:var(--cf-text-secondary, #6B7280);margin-top:.375rem;line-height:1.25rem}.configurable-form-container .mt-2{margin-top:.5rem}.configurable-form-container .radio-group-container.is-invalid .field-label{color:var(--cf-error-color, #DC2626)}.configurable-form-container .radio-group{display:flex;gap:2rem;flex-wrap:wrap;margin-top:.5rem}.configurable-form-container .radio-button{margin:0}.configurable-form-container .composite-container{display:flex;align-items:center;gap:.75rem}.configurable-form-container .composite-container .separator{font-size:.875rem;color:var(--cf-text-secondary, #6B7280);font-weight:500}.configurable-form-container .composite-container .input-wrapper{flex:1}.configurable-form-container .upload-box{border:2px dashed var(--cf-border-color, #D1D5DB);border-radius:var(--cf-section-radius, 12px);padding:2.5rem;text-align:center;cursor:pointer;transition:all .2s ease;background-color:var(--cf-hover-background, #F9FAFB)}.configurable-form-container .upload-box:hover{border-color:var(--cf-primary-color, #3B82F6);background-color:#3b82f608}.configurable-form-container .upload-box.is-invalid{border-color:var(--cf-error-color, #DC2626);background-color:#fef2f2}.configurable-form-container .upload-box .upload-icon{font-size:3rem;width:3rem;height:3rem;color:var(--cf-primary-color, #3B82F6);margin-bottom:.75rem}.configurable-form-container .upload-box .upload-text{font-size:.875rem;color:var(--cf-text-primary, #111827);font-weight:500;margin-bottom:.375rem}.configurable-form-container .upload-box .upload-hint{font-size:.75rem;color:var(--cf-text-secondary, #6B7280)}.configurable-form-container .uploaded-files-list{margin-top:1rem}.configurable-form-container .uploaded-file-item{display:flex;align-items:center;gap:.75rem;padding:.875rem;border:1.5px solid var(--cf-border-color, #D1D5DB);border-radius:8px;margin-bottom:.5rem;background-color:var(--cf-hover-background, #F9FAFB);transition:all .2s ease}.configurable-form-container .uploaded-file-item:hover{border-color:#9ca3af;box-shadow:0 1px 3px #0000001a}.configurable-form-container .uploaded-file-item .file-icon mat-icon{font-size:2rem;width:2rem;height:2rem}.configurable-form-container .uploaded-file-item .file-icon mat-icon.pdf-icon{color:#dc2626}.configurable-form-container .uploaded-file-item .file-icon mat-icon.doc-icon{color:#2563eb}.configurable-form-container .uploaded-file-item .file-icon mat-icon.img-icon{color:#059669}.configurable-form-container .uploaded-file-item .file-icon mat-icon.file-icon-default{color:var(--cf-text-secondary, #6B7280)}.configurable-form-container .uploaded-file-item .file-info{flex:1}.configurable-form-container .uploaded-file-item .file-info .file-name{font-size:.875rem;color:var(--cf-text-primary, #111827);font-weight:500;margin-bottom:.125rem}.configurable-form-container .uploaded-file-item .file-info .file-size{font-size:.75rem;color:var(--cf-text-secondary, #6B7280)}.configurable-form-container .uploaded-file-item .remove-file-btn mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem}.configurable-form-container .relative{position:relative}.configurable-form-container .date-toggle{position:absolute;right:0;top:50%;transform:translateY(-50%)}.configurable-form-container .repeater-item{padding:1.5rem;border:1.5px solid var(--cf-border-color, #D1D5DB);border-radius:10px;margin-bottom:1rem;background-color:var(--cf-hover-background, #F9FAFB);transition:all .2s ease}.configurable-form-container .repeater-item:hover{border-color:#9ca3af;box-shadow:0 2px 4px #0000000d}.configurable-form-container .repeater-item-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.25rem;padding-bottom:.75rem;border-bottom:1.5px solid var(--cf-border-color, #D1D5DB)}.configurable-form-container .repeater-item-header .text-small{font-size:.875rem;font-weight:600;color:var(--cf-text-primary, #111827);text-transform:uppercase;letter-spacing:.025em}.configurable-form-container .repeater-separator{height:1px;background-color:var(--cf-border-color, #D1D5DB);margin:1.5rem 0}.configurable-form-container .add-btn{margin-top:1rem;display:inline-flex;align-items:center;gap:.5rem;padding:.625rem 1.25rem;background-color:transparent;color:var(--cf-primary-color, #3B82F6);border:1.5px solid var(--cf-primary-color, #3B82F6);border-radius:8px;font-size:.875rem;font-weight:600;cursor:pointer;transition:all .2s ease}.configurable-form-container .add-btn:hover:not(:disabled){background-color:var(--cf-primary-color, #3B82F6);color:#fff}.configurable-form-container .add-btn:disabled{opacity:.5;cursor:not-allowed;border-color:var(--cf-disabled-background, #E5E7EB)}.configurable-form-container .add-btn mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem}.configurable-form-container .btn-row{display:flex;justify-content:flex-end;gap:1rem;margin-top:2rem;padding-top:1.5rem;border-top:2px solid var(--cf-border-color, #D1D5DB)}.configurable-form-container .btn-row button{padding:.625rem 1.5rem;font-size:.875rem;font-weight:600;border-radius:8px;cursor:pointer;transition:all .2s ease;border:none;font-family:inherit}.configurable-form-container .btn-row button[mat-stroked-button]{background-color:transparent;color:var(--cf-text-primary, #111827);border:1.5px solid var(--cf-border-color, #D1D5DB)}.configurable-form-container .btn-row button[mat-stroked-button]:hover{background-color:var(--cf-hover-background, #F9FAFB);border-color:#9ca3af}.configurable-form-container .btn-row button[mat-flat-button]{background-color:var(--cf-primary-color, #3B82F6);color:#fff;box-shadow:0 1px 3px #0000001a}.configurable-form-container .btn-row button[mat-flat-button]:hover{background-color:#2563eb;box-shadow:0 4px 6px -1px #0000001a}.configurable-form-container .btn-row button[mat-flat-button]:active{background-color:#1d4ed8}@media(max-width:768px){.configurable-form-container .section-card{padding:1.25rem;border-radius:8px}.configurable-form-container .form-grid{margin-left:-.5rem;margin-right:-.5rem}.configurable-form-container .form-col{padding-left:.5rem;padding-right:.5rem;margin-bottom:1rem}.configurable-form-container .btn-row{flex-direction:column-reverse}.configurable-form-container .btn-row button{width:100%}.configurable-form-container .radio-group{flex-direction:column;gap:.75rem}.configurable-form-container .composite-container{flex-direction:column;align-items:stretch}.configurable-form-container .composite-container .separator{text-align:center}}\n"] }]
1542
+ }], ctorParameters: () => [{ type: i1$2.FormBuilder }, { type: i2$1.MatSnackBar }, { type: i3.HttpClient }], propDecorators: { config: [{
1543
+ type: Input
1544
+ }], jsonConfig: [{
1545
+ type: Input
1546
+ }], data: [{
1547
+ type: Input
1548
+ }], baseApiUrl: [{
1549
+ type: Input
1550
+ }], formSubmit: [{
1551
+ type: Output
1552
+ }], formCancel: [{
1553
+ type: Output
1554
+ }], optionsLoad: [{
1555
+ type: Output
1556
+ }] } });
1557
+
1558
+ class ConfigurableFormModule {
1559
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1560
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormModule, imports: [CommonModule,
1561
+ ReactiveFormsModule,
1562
+ HttpClientModule,
1563
+ MaterialModule,
1564
+ ConfigurableFormComponent], exports: [ConfigurableFormComponent] });
1565
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormModule, imports: [CommonModule,
1566
+ ReactiveFormsModule,
1567
+ HttpClientModule,
1568
+ MaterialModule,
1569
+ ConfigurableFormComponent] });
1570
+ }
1571
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormModule, decorators: [{
1572
+ type: NgModule,
1573
+ args: [{
1574
+ declarations: [],
1575
+ imports: [
1576
+ CommonModule,
1577
+ ReactiveFormsModule,
1578
+ HttpClientModule,
1579
+ MaterialModule,
1580
+ ConfigurableFormComponent
1581
+ ],
1582
+ exports: [
1583
+ ConfigurableFormComponent
1584
+ ]
1585
+ }]
1586
+ }] });
1587
+
1588
+ class SharedUiModule {
1589
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SharedUiModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1590
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: SharedUiModule, imports: [CommonModule,
1591
+ MaterialModule,
1592
+ CardsModule, AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
1593
+ SummaryCardModule,
1594
+ ConfigurableFormModule], exports: [MaterialModule,
1595
+ CardsModule, AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
1596
+ SummaryCardModule,
1597
+ ConfigurableFormModule] });
1598
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SharedUiModule, imports: [CommonModule,
1599
+ MaterialModule,
1600
+ CardsModule, AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
1601
+ SummaryCardModule,
1602
+ ConfigurableFormModule, MaterialModule,
1603
+ CardsModule, AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
1604
+ SummaryCardModule,
1605
+ ConfigurableFormModule] });
1606
+ }
1607
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SharedUiModule, decorators: [{
1608
+ type: NgModule,
1609
+ args: [{
1610
+ declarations: [],
1611
+ imports: [
1612
+ CommonModule,
1613
+ MaterialModule,
1614
+ CardsModule, AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
1615
+ SummaryCardModule,
1616
+ ConfigurableFormModule,
1617
+ ],
1618
+ exports: [
1619
+ MaterialModule,
1620
+ CardsModule, AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
1621
+ SummaryCardModule,
1622
+ ConfigurableFormModule,
1623
+ ],
1624
+ }]
1625
+ }] });
1626
+
1627
+ /**
1628
+ * Utility functions for LocalStorage operations
1629
+ */
1630
+ const getLocalStorageItem = (key) => {
1631
+ return localStorage.getItem(key);
1632
+ };
1633
+ const setLocalStorageItem = (key, value) => {
1634
+ localStorage.setItem(key, value);
1635
+ };
1636
+ const removeLocalStorageItem = (key) => {
1637
+ localStorage.removeItem(key);
1638
+ };
1639
+ const clearLocalStorage = () => {
1640
+ localStorage.clear();
1641
+ };
1642
+ /**
1643
+ * Utility functions for SessionStorage operations
1644
+ */
1645
+ const getSessionStorageItem = (key) => {
1646
+ return sessionStorage.getItem(key);
1647
+ };
1648
+ const setSessionStorageItem = (key, value) => {
1649
+ sessionStorage.setItem(key, value);
1650
+ };
1651
+ const removeSessionStorageItem = (key) => {
1652
+ sessionStorage.removeItem(key);
1653
+ };
1654
+ const clearSessionStorage = () => {
1655
+ sessionStorage.clear();
1656
+ };
1657
+
1658
+ /**
1659
+ * Example: Basic Form Configuration
1660
+ * This is a generic example for testing and demonstration purposes.
1661
+ */
1662
+ const EXAMPLE_FORM_CONFIG = {
1663
+ sections: [
1664
+ {
1665
+ sectionTitle: 'User Information',
1666
+ fields: [
1667
+ {
1668
+ name: 'fullName',
1669
+ label: 'Full Name',
1670
+ type: 'text',
1671
+ placeholder: 'Enter full name',
1672
+ required: true,
1673
+ class: 'col-12'
1674
+ },
1675
+ {
1676
+ name: 'email',
1677
+ label: 'Email Address',
1678
+ type: 'email',
1679
+ placeholder: 'Enter email address',
1680
+ required: true,
1681
+ class: 'col-6'
1682
+ },
1683
+ {
1684
+ name: 'phone',
1685
+ label: 'Phone Number',
1686
+ type: 'tel',
1687
+ placeholder: '+91 9999999999',
1688
+ class: 'col-6'
1689
+ },
1690
+ {
1691
+ name: 'role',
1692
+ label: 'Role',
1693
+ type: 'dropdown',
1694
+ placeholder: 'Select Role',
1695
+ options: [
1696
+ { label: 'Admin', value: 'admin' },
1697
+ { label: 'User', value: 'user' },
1698
+ { label: 'Guest', value: 'guest' }
1699
+ ],
1700
+ class: 'col-12'
1701
+ }
1702
+ ]
1703
+ },
1704
+ {
1705
+ sectionTitle: 'Preferences',
1706
+ fields: [
1707
+ {
1708
+ name: 'notifications',
1709
+ label: 'Receive Notifications',
1710
+ type: 'radio',
1711
+ options: [
1712
+ { label: 'Yes', value: 'yes' },
1713
+ { label: 'No', value: 'no' }
1714
+ ],
1715
+ value: 'yes',
1716
+ class: 'col-12'
1717
+ }
1718
+ ]
1719
+ },
1720
+ {
1721
+ sectionTitle: 'Documents',
1722
+ fields: [
1723
+ {
1724
+ name: 'profilePicture',
1725
+ label: 'Profile Picture',
1726
+ type: 'file',
1727
+ accept: '.jpg,.png',
1728
+ multiple: false,
1729
+ helpText: 'Upload a single profile picture (Max 5MB)',
1730
+ class: 'col-12'
1731
+ },
1732
+ {
1733
+ name: 'certificates',
1734
+ label: 'Certificates',
1735
+ type: 'file',
1736
+ accept: '.pdf,.doc,.docx',
1737
+ multiple: true,
1738
+ helpText: 'Upload multiple certificates (Max 5MB each)',
1739
+ class: 'col-12'
1740
+ }
1741
+ ]
1742
+ }
1743
+ ],
1744
+ submitLabel: 'Save',
1745
+ cancelLabel: 'Cancel',
1746
+ entityType: 'User'
1747
+ };
1748
+ /**
1749
+ * Example: Target Group Configuration
1750
+ * Demonstrates composite fields for Age Group and Gender Split
1751
+ */
1752
+ const TARGET_GROUP_CONFIG = {
1753
+ sections: [
1754
+ {
1755
+ sectionTitle: 'Target Group Settings',
1756
+ fields: [
1757
+ {
1758
+ name: 'targetAgeGroup',
1759
+ label: 'Target Age Group',
1760
+ type: 'composite',
1761
+ separator: '-',
1762
+ subFields: [
1763
+ {
1764
+ label: "Min Age",
1765
+ name: 'minAge',
1766
+ type: 'number',
1767
+ placeholder: 'Min Age',
1768
+ validationRules: { min: 0 }
1769
+ },
1770
+ {
1771
+ label: "Max Age",
1772
+ name: 'maxAge',
1773
+ type: 'number',
1774
+ placeholder: 'Max Age',
1775
+ validationRules: { min: 0 }
1776
+ }
1777
+ ],
1778
+ compositeValidationRule: 'minMax',
1779
+ class: 'col-12'
1780
+ },
1781
+ {
1782
+ name: 'genderSplit',
1783
+ label: 'Target Gender Split',
1784
+ type: 'composite',
1785
+ subFields: [
1786
+ {
1787
+ label: "Male",
1788
+ name: 'malePercentage',
1789
+ type: 'number',
1790
+ placeholder: 'Male',
1791
+ suffixText: '%',
1792
+ validationRules: { min: 0, max: 100 }
1793
+ },
1794
+ {
1795
+ label: "Female",
1796
+ name: 'femalePercentage',
1797
+ type: 'number',
1798
+ placeholder: 'Female',
1799
+ suffixText: '%',
1800
+ validationRules: { min: 0, max: 100 }
1801
+ }
1802
+ ],
1803
+ compositeValidationRule: 'percentageTotal',
1804
+ class: 'col-12'
1805
+ }
1806
+ ]
1807
+ }
1808
+ ],
1809
+ submitLabel: 'Save Configuration',
1810
+ cancelLabel: 'Cancel'
1811
+ };
1812
+
1813
+ var configurableForm_examples = /*#__PURE__*/Object.freeze({
1814
+ __proto__: null,
1815
+ EXAMPLE_FORM_CONFIG: EXAMPLE_FORM_CONFIG,
1816
+ TARGET_GROUP_CONFIG: TARGET_GROUP_CONFIG
1817
+ });
1818
+
1819
+ const DEFAULT_ITEMS_PER_PAGE = 10;
1820
+ const DEFAULT_PAGE_SIZE_OPTIONS = [10, 20, 50];
1821
+ const PAGINATION_THEME_DEFAULT = 'theme-1';
1822
+ const PAGINATION_THEME_DARK = 'theme-2';
1823
+ // Nav
1824
+ const NAV_VARIANT_DEFAULT = 'filled';
1825
+ const NAV_ORIENTATION_DEFAULT = 'horizontal';
1826
+
1827
+ class PaginationComponent {
1828
+ totalItems = 0;
1829
+ itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
1830
+ currentPage = 1;
1831
+ pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS;
1832
+ theme = PAGINATION_THEME_DEFAULT;
1833
+ labels = {
1834
+ items: 'items',
1835
+ of: 'of',
1836
+ perPage: 'Per Page'
1837
+ };
1838
+ pageChange = new EventEmitter();
1839
+ itemsPerPageChange = new EventEmitter();
1840
+ totalPages = 0;
1841
+ pages = [];
1842
+ startItem = 0;
1843
+ endItem = 0;
1844
+ constructor() { }
1845
+ ngOnInit() {
1846
+ this.calculatePagination();
1847
+ }
1848
+ ngOnChanges(changes) {
1849
+ if (changes['totalItems'] || changes['itemsPerPage'] || changes['currentPage']) {
1850
+ this.calculatePagination();
1851
+ }
1852
+ }
1853
+ calculatePagination() {
1854
+ this.totalPages = Math.ceil(this.totalItems / this.itemsPerPage);
1855
+ // Ensure current page is valid
1856
+ if (this.currentPage < 1) {
1857
+ this.currentPage = 1;
1858
+ }
1859
+ else if (this.currentPage > this.totalPages && this.totalPages > 0) {
1860
+ this.currentPage = this.totalPages;
1861
+ }
1862
+ this.startItem = (this.currentPage - 1) * this.itemsPerPage + 1;
1863
+ this.endItem = Math.min(this.currentPage * this.itemsPerPage, this.totalItems);
1864
+ if (this.totalItems === 0) {
1865
+ this.startItem = 0;
1866
+ this.endItem = 0;
1867
+ }
1868
+ this.pages = this.getVisiblePages(this.currentPage, this.totalPages);
1869
+ }
1870
+ getVisiblePages(current, total) {
1871
+ if (total <= 7) {
1872
+ return Array.from({ length: total }, (_, i) => i + 1);
1873
+ }
1874
+ if (current <= 4) {
1875
+ return [1, 2, 3, 4, 5, '...', total];
1876
+ }
1877
+ if (current >= total - 3) {
1878
+ return [1, '...', total - 4, total - 3, total - 2, total - 1, total];
1879
+ }
1880
+ return [1, '...', current - 1, current, current + 1, '...', total];
1881
+ }
1882
+ onPageChange(page) {
1883
+ if (typeof page === 'string')
1884
+ return;
1885
+ if (page < 1 || page > this.totalPages || page === this.currentPage)
1886
+ return;
1887
+ this.pageChange.emit(page);
1888
+ }
1889
+ onItemsPerPageChange(event) {
1890
+ const target = event.target;
1891
+ const newSize = Number(target.value);
1892
+ this.itemsPerPageChange.emit(newSize);
1893
+ }
1894
+ nextPage() {
1895
+ if (this.currentPage < this.totalPages) {
1896
+ this.onPageChange(this.currentPage + 1);
1897
+ }
1898
+ }
1899
+ prevPage() {
1900
+ if (this.currentPage > 1) {
1901
+ this.onPageChange(this.currentPage - 1);
1902
+ }
1903
+ }
1904
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1905
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: PaginationComponent, isStandalone: false, selector: "lib-pagination", inputs: { totalItems: "totalItems", itemsPerPage: "itemsPerPage", currentPage: "currentPage", pageSizeOptions: "pageSizeOptions", theme: "theme", labels: "labels" }, outputs: { pageChange: "pageChange", itemsPerPageChange: "itemsPerPageChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-pagination\" [ngClass]=\"theme\">\n <!-- Left Side: Items Info & Per Page -->\n <div class=\"pagination-left\" *ngIf=\"pageSizeOptions.length > 1 || totalItems > 0\">\n <span class=\"items-info\">\n {{ startItem }}-{{ endItem }} {{ labels.of }} {{ totalItems }} {{ labels.items }}\n </span>\n\n <div class=\"per-page-selector\" *ngIf=\"pageSizeOptions.length > 1\">\n <div class=\"select-wrapper\">\n <select [value]=\"itemsPerPage\" (change)=\"onItemsPerPageChange($event)\">\n <option *ngFor=\"let option of pageSizeOptions\" [value]=\"option\">\n {{ option }}\n </option>\n </select>\n <span class=\"select-arrow\"></span>\n </div>\n <span class=\"per-page-label\">{{ labels.perPage }}</span>\n </div>\n </div>\n\n <!-- Right Side: Page Controls -->\n <div class=\"pagination-right\">\n <button \n class=\"page-btn prev-btn\" \n [disabled]=\"currentPage === 1\" \n (click)=\"prevPage()\"\n aria-label=\"Previous Page\">\n <span class=\"icon\">&lsaquo;</span>\n </button>\n\n <div class=\"page-numbers\">\n <ng-container *ngFor=\"let page of pages\">\n <button \n *ngIf=\"page !== '...'\"\n class=\"page-btn number-btn\" \n [class.active]=\"page === currentPage\"\n (click)=\"onPageChange(page)\">\n {{ page }}\n </button>\n <span *ngIf=\"page === '...'\" class=\"ellipsis\">...</span>\n </ng-container>\n </div>\n\n <button \n class=\"page-btn next-btn\" \n [disabled]=\"currentPage === totalPages || totalPages === 0\" \n (click)=\"nextPage()\"\n aria-label=\"Next Page\">\n <span class=\"icon\">&rsaquo;</span>\n </button>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.cc-pagination{display:flex;justify-content:space-between;align-items:center;padding:1rem;font-family:var(--cc-pagination-font-family);color:var(--cc-pagination-text-color);font-size:var(--cc-pagination-font-size);flex-wrap:wrap;gap:1rem;width:100%;box-sizing:border-box}.cc-pagination .pagination-left{display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap}.cc-pagination .pagination-left .items-info{white-space:nowrap}.cc-pagination .pagination-left .per-page-selector{display:flex;align-items:center;gap:.5rem}.cc-pagination .pagination-left .per-page-selector .select-wrapper{position:relative;display:inline-block}.cc-pagination .pagination-left .per-page-selector .select-wrapper select{appearance:none;background-color:var(--cc-pagination-select-bg);border:var(--cc-pagination-select-border);border-radius:var(--cc-pagination-select-radius);padding:var(--cc-pagination-select-padding);padding-right:2rem;color:var(--cc-pagination-select-text-color);font-family:inherit;font-size:inherit;cursor:pointer;min-width:60px}.cc-pagination .pagination-left .per-page-selector .select-wrapper select:focus{outline:none;box-shadow:0 0 0 2px #0000001a}.cc-pagination .pagination-left .per-page-selector .select-wrapper:after{content:\"\\25bc\";position:absolute;right:10px;top:50%;transform:translateY(-50%);font-size:.7em;color:var(--cc-pagination-select-arrow-color);pointer-events:none}.cc-pagination .pagination-left .per-page-selector .per-page-label{white-space:nowrap}.cc-pagination .pagination-right{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .page-btn{display:flex;align-items:center;justify-content:center;min-width:var(--cc-pagination-btn-size);height:var(--cc-pagination-btn-size);background-color:var(--cc-pagination-btn-bg);border:var(--cc-pagination-btn-border);border-radius:var(--cc-pagination-btn-radius);color:var(--cc-pagination-btn-text-color);font-family:inherit;cursor:pointer;transition:all .2s ease;padding:0 .5rem;-webkit-user-select:none;user-select:none}.cc-pagination .pagination-right .page-btn:hover:not(:disabled){background-color:var(--cc-pagination-btn-hover-bg)}.cc-pagination .pagination-right .page-btn:disabled{opacity:var(--cc-pagination-disabled-opacity);background-color:var(--cc-pagination-disabled-bg);cursor:not-allowed}.cc-pagination .pagination-right .page-btn.active{background-color:var(--cc-pagination-btn-active-bg);border:var(--cc-pagination-btn-active-border);color:var(--cc-pagination-btn-active-text);font-weight:700}.cc-pagination .pagination-right .page-btn .icon{font-size:1.2em;line-height:1}.cc-pagination .pagination-right .page-numbers{display:flex;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .ellipsis{display:flex;align-items:center;justify-content:center;color:var(--cc-pagination-text-color);width:20px}@media(max-width:600px){.cc-pagination{flex-direction:column;align-items:center;gap:1.5rem}.cc-pagination .pagination-left{width:100%;justify-content:space-between;order:2}.cc-pagination .pagination-right{width:100%;justify-content:center;order:1}.cc-pagination .pagination-right .page-numbers{justify-content:center}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
1906
+ }
1907
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginationComponent, decorators: [{
1908
+ type: Component,
1909
+ args: [{ selector: 'lib-pagination', standalone: false, template: "<div class=\"cc-pagination\" [ngClass]=\"theme\">\n <!-- Left Side: Items Info & Per Page -->\n <div class=\"pagination-left\" *ngIf=\"pageSizeOptions.length > 1 || totalItems > 0\">\n <span class=\"items-info\">\n {{ startItem }}-{{ endItem }} {{ labels.of }} {{ totalItems }} {{ labels.items }}\n </span>\n\n <div class=\"per-page-selector\" *ngIf=\"pageSizeOptions.length > 1\">\n <div class=\"select-wrapper\">\n <select [value]=\"itemsPerPage\" (change)=\"onItemsPerPageChange($event)\">\n <option *ngFor=\"let option of pageSizeOptions\" [value]=\"option\">\n {{ option }}\n </option>\n </select>\n <span class=\"select-arrow\"></span>\n </div>\n <span class=\"per-page-label\">{{ labels.perPage }}</span>\n </div>\n </div>\n\n <!-- Right Side: Page Controls -->\n <div class=\"pagination-right\">\n <button \n class=\"page-btn prev-btn\" \n [disabled]=\"currentPage === 1\" \n (click)=\"prevPage()\"\n aria-label=\"Previous Page\">\n <span class=\"icon\">&lsaquo;</span>\n </button>\n\n <div class=\"page-numbers\">\n <ng-container *ngFor=\"let page of pages\">\n <button \n *ngIf=\"page !== '...'\"\n class=\"page-btn number-btn\" \n [class.active]=\"page === currentPage\"\n (click)=\"onPageChange(page)\">\n {{ page }}\n </button>\n <span *ngIf=\"page === '...'\" class=\"ellipsis\">...</span>\n </ng-container>\n </div>\n\n <button \n class=\"page-btn next-btn\" \n [disabled]=\"currentPage === totalPages || totalPages === 0\" \n (click)=\"nextPage()\"\n aria-label=\"Next Page\">\n <span class=\"icon\">&rsaquo;</span>\n </button>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.cc-pagination{display:flex;justify-content:space-between;align-items:center;padding:1rem;font-family:var(--cc-pagination-font-family);color:var(--cc-pagination-text-color);font-size:var(--cc-pagination-font-size);flex-wrap:wrap;gap:1rem;width:100%;box-sizing:border-box}.cc-pagination .pagination-left{display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap}.cc-pagination .pagination-left .items-info{white-space:nowrap}.cc-pagination .pagination-left .per-page-selector{display:flex;align-items:center;gap:.5rem}.cc-pagination .pagination-left .per-page-selector .select-wrapper{position:relative;display:inline-block}.cc-pagination .pagination-left .per-page-selector .select-wrapper select{appearance:none;background-color:var(--cc-pagination-select-bg);border:var(--cc-pagination-select-border);border-radius:var(--cc-pagination-select-radius);padding:var(--cc-pagination-select-padding);padding-right:2rem;color:var(--cc-pagination-select-text-color);font-family:inherit;font-size:inherit;cursor:pointer;min-width:60px}.cc-pagination .pagination-left .per-page-selector .select-wrapper select:focus{outline:none;box-shadow:0 0 0 2px #0000001a}.cc-pagination .pagination-left .per-page-selector .select-wrapper:after{content:\"\\25bc\";position:absolute;right:10px;top:50%;transform:translateY(-50%);font-size:.7em;color:var(--cc-pagination-select-arrow-color);pointer-events:none}.cc-pagination .pagination-left .per-page-selector .per-page-label{white-space:nowrap}.cc-pagination .pagination-right{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .page-btn{display:flex;align-items:center;justify-content:center;min-width:var(--cc-pagination-btn-size);height:var(--cc-pagination-btn-size);background-color:var(--cc-pagination-btn-bg);border:var(--cc-pagination-btn-border);border-radius:var(--cc-pagination-btn-radius);color:var(--cc-pagination-btn-text-color);font-family:inherit;cursor:pointer;transition:all .2s ease;padding:0 .5rem;-webkit-user-select:none;user-select:none}.cc-pagination .pagination-right .page-btn:hover:not(:disabled){background-color:var(--cc-pagination-btn-hover-bg)}.cc-pagination .pagination-right .page-btn:disabled{opacity:var(--cc-pagination-disabled-opacity);background-color:var(--cc-pagination-disabled-bg);cursor:not-allowed}.cc-pagination .pagination-right .page-btn.active{background-color:var(--cc-pagination-btn-active-bg);border:var(--cc-pagination-btn-active-border);color:var(--cc-pagination-btn-active-text);font-weight:700}.cc-pagination .pagination-right .page-btn .icon{font-size:1.2em;line-height:1}.cc-pagination .pagination-right .page-numbers{display:flex;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .ellipsis{display:flex;align-items:center;justify-content:center;color:var(--cc-pagination-text-color);width:20px}@media(max-width:600px){.cc-pagination{flex-direction:column;align-items:center;gap:1.5rem}.cc-pagination .pagination-left{width:100%;justify-content:space-between;order:2}.cc-pagination .pagination-right{width:100%;justify-content:center;order:1}.cc-pagination .pagination-right .page-numbers{justify-content:center}}\n"] }]
1910
+ }], ctorParameters: () => [], propDecorators: { totalItems: [{
1911
+ type: Input
1912
+ }], itemsPerPage: [{
1913
+ type: Input
1914
+ }], currentPage: [{
1915
+ type: Input
1916
+ }], pageSizeOptions: [{
1917
+ type: Input
1918
+ }], theme: [{
1919
+ type: Input
1920
+ }], labels: [{
1921
+ type: Input
1922
+ }], pageChange: [{
1923
+ type: Output
1924
+ }], itemsPerPageChange: [{
1925
+ type: Output
1926
+ }] } });
1927
+
1928
+ class PaginationModule {
1929
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1930
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: PaginationModule, declarations: [PaginationComponent], imports: [CommonModule], exports: [PaginationComponent] });
1931
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginationModule, imports: [CommonModule] });
1932
+ }
1933
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginationModule, decorators: [{
1934
+ type: NgModule,
1935
+ args: [{
1936
+ declarations: [
1937
+ PaginationComponent
1938
+ ],
1939
+ imports: [
1940
+ CommonModule
1941
+ ],
1942
+ exports: [
1943
+ PaginationComponent
1944
+ ]
1945
+ }]
1946
+ }] });
1947
+
1948
+ class NavComponent {
1949
+ items = [];
1950
+ activeId = null;
1951
+ variant = NAV_VARIANT_DEFAULT;
1952
+ orientation = NAV_ORIENTATION_DEFAULT;
1953
+ styleConfig = {};
1954
+ selectionChange = new EventEmitter();
1955
+ ngOnChanges(changes) {
1956
+ if (changes['styleConfig']) {
1957
+ console.log(' [NavComponent] styleConfig changed:', this.styleConfig);
1958
+ console.log(' [NavComponent] computedStyles:', this.computedStyles);
1959
+ }
1960
+ }
1961
+ get computedStyles() {
1962
+ const c = this.styleConfig;
1963
+ return {
1964
+ // Container (direct CSS)
1965
+ 'width': c.width,
1966
+ 'box-shadow': c.boxShadow,
1967
+ // Container (CSS Variables)
1968
+ '--cc-nav-container-bg': c.backgroundColor,
1969
+ '--cc-nav-container-radius': c.borderRadius,
1970
+ '--cc-nav-container-border': c.border,
1971
+ '--cc-nav-container-padding': c.padding,
1972
+ '--cc-nav-container-gap': c.gap,
1973
+ // Item (CSS Variables)
1974
+ '--cc-nav-font-size': c.fontSize,
1975
+ '--cc-nav-font-weight': c.fontWeight,
1976
+ '--cc-nav-item-color': c.itemColor,
1977
+ '--cc-nav-item-radius': c.itemRadius,
1978
+ '--cc-nav-item-padding': c.itemPadding,
1979
+ // Active Item (CSS Variables)
1980
+ '--cc-nav-item-active-bg': c.activeItemBg,
1981
+ '--cc-nav-item-active-color': c.activeItemColor,
1982
+ '--cc-nav-item-active-font-weight': c.activeItemFontWeight,
1983
+ '--cc-nav-item-active-border-color': c.activeItemBorderColor,
1984
+ // Hover Item (CSS Variables)
1985
+ '--cc-nav-item-hover-bg': c.hoverItemBg,
1986
+ '--cc-nav-item-hover-color': c.hoverItemColor,
1987
+ // Badge (CSS Variables)
1988
+ '--cc-nav-badge-bg': c.badgeBg,
1989
+ '--cc-nav-badge-color': c.badgeColor,
1990
+ };
1991
+ }
1992
+ onItemClick(item) {
1993
+ if (item.disabled)
1994
+ return;
1995
+ if (item.id === this.activeId)
1996
+ return;
1997
+ this.selectionChange.emit(item);
1998
+ }
1999
+ trackById(index, item) {
2000
+ return item.id;
2001
+ }
2002
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2003
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: NavComponent, isStandalone: false, selector: "lib-nav", inputs: { items: "items", activeId: "activeId", variant: "variant", orientation: "orientation", styleConfig: "styleConfig" }, outputs: { selectionChange: "selectionChange" }, usesOnChanges: true, ngImport: i0, template: "<nav\r\n class=\"cc-nav\"\r\n [ngClass]=\"[variant, orientation]\"\r\n [ngStyle]=\"computedStyles\"\r\n role=\"tablist\"\r\n [attr.aria-orientation]=\"orientation\">\r\n\r\n <button\r\n *ngFor=\"let item of items; trackBy: trackById\"\r\n class=\"cc-nav-item\"\r\n [class.active]=\"item.id === activeId\"\r\n [class.disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"item.id === activeId\"\r\n [attr.aria-disabled]=\"item.disabled || null\"\r\n (click)=\"onItemClick(item)\">\r\n\r\n <!-- Icon (optional) -->\r\n <span *ngIf=\"item.icon\" class=\"cc-nav-item-icon\">\r\n <i [ngClass]=\"item.icon\"></i>\r\n </span>\r\n\r\n <!-- Label -->\r\n <span class=\"cc-nav-item-label\">{{ item.label }}</span>\r\n\r\n <!-- Badge (optional) -->\r\n <span *ngIf=\"item.badge != null\" class=\"cc-nav-item-badge\">\r\n {{ item.badge }}\r\n </span>\r\n\r\n </button>\r\n\r\n</nav>\r\n", styles: [".cc-nav{display:flex;align-items:center;background-color:var(--cc-nav-container-bg);padding:var(--cc-nav-container-padding);border-radius:var(--cc-nav-container-radius);border:var(--cc-nav-container-border);gap:var(--cc-nav-container-gap);font-family:var(--cc-nav-font-family);font-size:var(--cc-nav-font-size);box-sizing:border-box;width:100%}.cc-nav.horizontal{flex-direction:row;overflow-x:auto;-ms-overflow-style:none;scrollbar-width:none}.cc-nav.horizontal::-webkit-scrollbar{display:none}.cc-nav.vertical{flex-direction:column;align-items:stretch}.cc-nav .cc-nav-item{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-nav-item-padding);border-radius:var(--cc-nav-item-radius);border:var(--cc-nav-item-border);background-color:var(--cc-nav-item-bg);color:var(--cc-nav-item-color);font-family:inherit;font-size:inherit;font-weight:var(--cc-nav-font-weight);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:all .2s ease;position:relative;outline:none}.cc-nav .cc-nav-item:hover:not(:disabled):not(.active){background-color:var(--cc-nav-item-hover-bg);color:var(--cc-nav-item-hover-color)}.cc-nav .cc-nav-item.active{background-color:var(--cc-nav-item-active-bg);color:var(--cc-nav-item-active-color);font-weight:var(--cc-nav-item-active-font-weight);box-shadow:var(--cc-nav-item-active-shadow)}.cc-nav .cc-nav-item:disabled,.cc-nav .cc-nav-item.disabled{opacity:var(--cc-nav-disabled-opacity);cursor:not-allowed}.cc-nav .cc-nav-item .cc-nav-item-icon{display:inline-flex;align-items:center;font-size:1.1em;line-height:1}.cc-nav .cc-nav-item .cc-nav-item-badge{display:inline-flex;align-items:center;justify-content:center;min-width:var(--cc-nav-badge-size);height:var(--cc-nav-badge-size);border-radius:50%;background-color:var(--cc-nav-badge-bg);color:var(--cc-nav-badge-color);font-size:var(--cc-nav-badge-font-size);font-weight:var(--cc-nav-badge-font-weight, 600);padding:0 4px;line-height:1}.cc-nav.filled .cc-nav-item.active{border-bottom:var(--cc-nav-item-active-border-width) solid var(--cc-nav-item-active-border-color)}.cc-nav.underline{background-color:transparent;border-radius:0;padding:0;border-bottom:1px solid #e0e0e0}.cc-nav.underline .cc-nav-item{background-color:transparent;border-radius:0;border:none;border-bottom:var(--cc-nav-item-active-border-width) solid transparent;box-shadow:none}.cc-nav.underline .cc-nav-item:hover:not(:disabled):not(.active){background-color:transparent;border-bottom-color:#ccc}.cc-nav.underline .cc-nav-item.active{background-color:transparent;border-bottom-color:var(--cc-nav-item-active-border-color);box-shadow:none}.cc-nav.pills{background-color:transparent;padding:0}.cc-nav.pills .cc-nav-item,.cc-nav.pills .cc-nav-item.active{border-radius:999px}@media(max-width:600px){.cc-nav.horizontal{gap:2px}.cc-nav.horizontal .cc-nav-item{padding:6px 12px;font-size:13px}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
2004
+ }
2005
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NavComponent, decorators: [{
2006
+ type: Component,
2007
+ args: [{ selector: 'lib-nav', standalone: false, template: "<nav\r\n class=\"cc-nav\"\r\n [ngClass]=\"[variant, orientation]\"\r\n [ngStyle]=\"computedStyles\"\r\n role=\"tablist\"\r\n [attr.aria-orientation]=\"orientation\">\r\n\r\n <button\r\n *ngFor=\"let item of items; trackBy: trackById\"\r\n class=\"cc-nav-item\"\r\n [class.active]=\"item.id === activeId\"\r\n [class.disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"item.id === activeId\"\r\n [attr.aria-disabled]=\"item.disabled || null\"\r\n (click)=\"onItemClick(item)\">\r\n\r\n <!-- Icon (optional) -->\r\n <span *ngIf=\"item.icon\" class=\"cc-nav-item-icon\">\r\n <i [ngClass]=\"item.icon\"></i>\r\n </span>\r\n\r\n <!-- Label -->\r\n <span class=\"cc-nav-item-label\">{{ item.label }}</span>\r\n\r\n <!-- Badge (optional) -->\r\n <span *ngIf=\"item.badge != null\" class=\"cc-nav-item-badge\">\r\n {{ item.badge }}\r\n </span>\r\n\r\n </button>\r\n\r\n</nav>\r\n", styles: [".cc-nav{display:flex;align-items:center;background-color:var(--cc-nav-container-bg);padding:var(--cc-nav-container-padding);border-radius:var(--cc-nav-container-radius);border:var(--cc-nav-container-border);gap:var(--cc-nav-container-gap);font-family:var(--cc-nav-font-family);font-size:var(--cc-nav-font-size);box-sizing:border-box;width:100%}.cc-nav.horizontal{flex-direction:row;overflow-x:auto;-ms-overflow-style:none;scrollbar-width:none}.cc-nav.horizontal::-webkit-scrollbar{display:none}.cc-nav.vertical{flex-direction:column;align-items:stretch}.cc-nav .cc-nav-item{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-nav-item-padding);border-radius:var(--cc-nav-item-radius);border:var(--cc-nav-item-border);background-color:var(--cc-nav-item-bg);color:var(--cc-nav-item-color);font-family:inherit;font-size:inherit;font-weight:var(--cc-nav-font-weight);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:all .2s ease;position:relative;outline:none}.cc-nav .cc-nav-item:hover:not(:disabled):not(.active){background-color:var(--cc-nav-item-hover-bg);color:var(--cc-nav-item-hover-color)}.cc-nav .cc-nav-item.active{background-color:var(--cc-nav-item-active-bg);color:var(--cc-nav-item-active-color);font-weight:var(--cc-nav-item-active-font-weight);box-shadow:var(--cc-nav-item-active-shadow)}.cc-nav .cc-nav-item:disabled,.cc-nav .cc-nav-item.disabled{opacity:var(--cc-nav-disabled-opacity);cursor:not-allowed}.cc-nav .cc-nav-item .cc-nav-item-icon{display:inline-flex;align-items:center;font-size:1.1em;line-height:1}.cc-nav .cc-nav-item .cc-nav-item-badge{display:inline-flex;align-items:center;justify-content:center;min-width:var(--cc-nav-badge-size);height:var(--cc-nav-badge-size);border-radius:50%;background-color:var(--cc-nav-badge-bg);color:var(--cc-nav-badge-color);font-size:var(--cc-nav-badge-font-size);font-weight:var(--cc-nav-badge-font-weight, 600);padding:0 4px;line-height:1}.cc-nav.filled .cc-nav-item.active{border-bottom:var(--cc-nav-item-active-border-width) solid var(--cc-nav-item-active-border-color)}.cc-nav.underline{background-color:transparent;border-radius:0;padding:0;border-bottom:1px solid #e0e0e0}.cc-nav.underline .cc-nav-item{background-color:transparent;border-radius:0;border:none;border-bottom:var(--cc-nav-item-active-border-width) solid transparent;box-shadow:none}.cc-nav.underline .cc-nav-item:hover:not(:disabled):not(.active){background-color:transparent;border-bottom-color:#ccc}.cc-nav.underline .cc-nav-item.active{background-color:transparent;border-bottom-color:var(--cc-nav-item-active-border-color);box-shadow:none}.cc-nav.pills{background-color:transparent;padding:0}.cc-nav.pills .cc-nav-item,.cc-nav.pills .cc-nav-item.active{border-radius:999px}@media(max-width:600px){.cc-nav.horizontal{gap:2px}.cc-nav.horizontal .cc-nav-item{padding:6px 12px;font-size:13px}}\n"] }]
2008
+ }], propDecorators: { items: [{
2009
+ type: Input
2010
+ }], activeId: [{
2011
+ type: Input
2012
+ }], variant: [{
2013
+ type: Input
2014
+ }], orientation: [{
2015
+ type: Input
2016
+ }], styleConfig: [{
2017
+ type: Input
2018
+ }], selectionChange: [{
2019
+ type: Output
2020
+ }] } });
2021
+
2022
+ class NavModule {
2023
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NavModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2024
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: NavModule, declarations: [NavComponent], imports: [CommonModule], exports: [NavComponent] });
2025
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NavModule, imports: [CommonModule] });
2026
+ }
2027
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NavModule, decorators: [{
2028
+ type: NgModule,
2029
+ args: [{
2030
+ declarations: [
2031
+ NavComponent
2032
+ ],
2033
+ imports: [
2034
+ CommonModule
2035
+ ],
2036
+ exports: [
2037
+ NavComponent
2038
+ ]
2039
+ }]
2040
+ }] });
2041
+
2042
+ /*
2043
+ * Public API Surface of shared-ui
2044
+ */
2045
+
2046
+ /**
2047
+ * Generated bundle index. Do not edit.
2048
+ */
2049
+
2050
+ export { AlertComponent, AlertModule, ButtonComponent, ButtonModule, CardType1Component, CardType2Component, CardsModule, ConfigurableFormComponent, configurableForm_examples as ConfigurableFormExamples, ConfigurableFormModule, ConfirmationModalComponent, ConfirmationModalModule, DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE_SIZE_OPTIONS, FilterSidebarComponent, FilterSidebarModule, MaterialModule, NAV_ORIENTATION_DEFAULT, NAV_VARIANT_DEFAULT, NavComponent, NavModule, PAGINATION_THEME_DARK, PAGINATION_THEME_DEFAULT, PaginationComponent, PaginationModule, SharedUiModule, SummaryCardComponent, SummaryCardModule, clearLocalStorage, clearSessionStorage, getLocalStorageItem, getSessionStorageItem, removeLocalStorageItem, removeSessionStorageItem, setLocalStorageItem, setSessionStorageItem };
2051
+ //# sourceMappingURL=commons-shared-web-ui.mjs.map