commons-shared-web-ui 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/commons-shared-web-ui.mjs +2416 -173
- package/fesm2022/commons-shared-web-ui.mjs.map +1 -1
- package/index.d.ts +957 -51
- package/package.json +1 -1
- package/src/lib/modules/filter/filter.theme.scss +92 -0
- package/src/lib/modules/filter-sidebar/filter-sidebar.theme.scss +28 -40
- package/src/lib/modules/form-components/components/checkbox/_theme.scss +63 -0
- package/src/lib/modules/form-components/components/datepicker/_theme.scss +82 -0
- package/src/lib/modules/form-components/components/dropdown/_theme.scss +91 -0
- package/src/lib/modules/form-components/components/input/_theme.scss +77 -0
- package/src/lib/modules/form-components/components/radio/_theme.scss +61 -0
- package/src/lib/modules/form-components/components/search/_theme.scss +73 -0
- package/src/lib/modules/form-components/components/toggle/_theme.scss +45 -0
- package/src/lib/modules/form-components/form-components.theme.scss +25 -0
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { NgModule, Input, Component, EventEmitter, HostListener, Output, forwardRef, Injectable, inject, LOCALE_ID, ViewChildren } from '@angular/core';
|
|
2
|
+
import { NgModule, Input, Component, EventEmitter, HostListener, Output, forwardRef, Directive, ViewChild, Injectable, inject, LOCALE_ID, ViewChildren } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { CommonModule, formatDate } from '@angular/common';
|
|
5
5
|
import { MatCardModule } from '@angular/material/card';
|
|
6
|
-
import * as i2$
|
|
6
|
+
import * as i2$2 from '@angular/material/snack-bar';
|
|
7
7
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
8
|
-
import * as i4 from '@angular/material/checkbox';
|
|
9
8
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
10
9
|
import { MatDividerModule } from '@angular/material/divider';
|
|
11
10
|
import * as i6 from '@angular/material/radio';
|
|
@@ -14,14 +13,14 @@ import { MatDialogModule } from '@angular/material/dialog';
|
|
|
14
13
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
15
14
|
import * as i2 from '@angular/material/icon';
|
|
16
15
|
import { MatIconModule } from '@angular/material/icon';
|
|
17
|
-
import * as
|
|
16
|
+
import * as i10 from '@angular/material/button';
|
|
18
17
|
import { MatButtonModule } from '@angular/material/button';
|
|
19
18
|
import { MatMenuModule } from '@angular/material/menu';
|
|
20
|
-
import * as i7
|
|
19
|
+
import * as i7 from '@angular/material/datepicker';
|
|
21
20
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
22
21
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
23
22
|
import { MatNativeDateModule } from '@angular/material/core';
|
|
24
|
-
import * as i8
|
|
23
|
+
import * as i8 from '@angular/material/input';
|
|
25
24
|
import { MatInputModule } from '@angular/material/input';
|
|
26
25
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
27
26
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
@@ -33,7 +32,6 @@ import { MatListModule } from '@angular/material/list';
|
|
|
33
32
|
import { MatChipsModule } from '@angular/material/chips';
|
|
34
33
|
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
35
34
|
import { MatTableModule } from '@angular/material/table';
|
|
36
|
-
import * as i8 from '@angular/material/expansion';
|
|
37
35
|
import { MatExpansionModule } from '@angular/material/expansion';
|
|
38
36
|
import { CdkAccordionModule } from '@angular/cdk/accordion';
|
|
39
37
|
import { MatSortModule } from '@angular/material/sort';
|
|
@@ -43,10 +41,12 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
|
43
41
|
import * as i1$2 from '@angular/forms';
|
|
44
42
|
import { FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
45
43
|
import * as i1$1 from '@angular/router';
|
|
44
|
+
import * as i2$1 from '@angular/cdk/scrolling';
|
|
45
|
+
import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
|
|
46
|
+
import { Subject, BehaviorSubject, combineLatest, forkJoin, of } from 'rxjs';
|
|
47
|
+
import { debounceTime, distinctUntilChanged, takeUntil, map, finalize, catchError } from 'rxjs/operators';
|
|
46
48
|
import * as i3 from '@angular/common/http';
|
|
47
49
|
import { HttpParams } from '@angular/common/http';
|
|
48
|
-
import { BehaviorSubject, Subject, combineLatest, forkJoin, of } from 'rxjs';
|
|
49
|
-
import { takeUntil, debounceTime, distinctUntilChanged, map, finalize, catchError } from 'rxjs/operators';
|
|
50
50
|
|
|
51
51
|
class MaterialModule {
|
|
52
52
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -233,6 +233,7 @@ class AlertComponent {
|
|
|
233
233
|
message = '';
|
|
234
234
|
icon = true;
|
|
235
235
|
customIcon = ''; // New input for custom class
|
|
236
|
+
labels;
|
|
236
237
|
// Customization Inputs
|
|
237
238
|
width;
|
|
238
239
|
height;
|
|
@@ -286,11 +287,11 @@ class AlertComponent {
|
|
|
286
287
|
}
|
|
287
288
|
}
|
|
288
289
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
289
|
-
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\"
|
|
290
|
+
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", labels: "labels", 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\"\r\n [attr.alt]=\"labels?.iconAltText || '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\"\r\n [attr.alt]=\"labels?.iconAltText || '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"] }] });
|
|
290
291
|
}
|
|
291
292
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: AlertComponent, decorators: [{
|
|
292
293
|
type: Component,
|
|
293
|
-
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\"
|
|
294
|
+
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\"\r\n [attr.alt]=\"labels?.iconAltText || '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\"\r\n [attr.alt]=\"labels?.iconAltText || '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"] }]
|
|
294
295
|
}], ctorParameters: () => [], propDecorators: { variant: [{
|
|
295
296
|
type: Input
|
|
296
297
|
}], title: [{
|
|
@@ -301,6 +302,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
301
302
|
type: Input
|
|
302
303
|
}], customIcon: [{
|
|
303
304
|
type: Input
|
|
305
|
+
}], labels: [{
|
|
306
|
+
type: Input
|
|
304
307
|
}], width: [{
|
|
305
308
|
type: Input
|
|
306
309
|
}], height: [{
|
|
@@ -367,6 +370,7 @@ class ButtonComponent {
|
|
|
367
370
|
color;
|
|
368
371
|
border;
|
|
369
372
|
icon = '';
|
|
373
|
+
labels;
|
|
370
374
|
constructor() { }
|
|
371
375
|
ngOnInit() {
|
|
372
376
|
}
|
|
@@ -393,11 +397,11 @@ class ButtonComponent {
|
|
|
393
397
|
return typeof this.icon === 'object' ? this.icon : { type: '', value: '' };
|
|
394
398
|
}
|
|
395
399
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
396
|
-
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\"
|
|
400
|
+
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", labels: "labels" }, 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\" [attr.alt]=\"labels?.iconAltText || 'button icon'\"\r\n 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\" [attr.alt]=\"labels?.iconAltText || '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"] }] });
|
|
397
401
|
}
|
|
398
402
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonComponent, decorators: [{
|
|
399
403
|
type: Component,
|
|
400
|
-
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\"
|
|
404
|
+
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\" [attr.alt]=\"labels?.iconAltText || 'button icon'\"\r\n 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\" [attr.alt]=\"labels?.iconAltText || '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"] }]
|
|
401
405
|
}], ctorParameters: () => [], propDecorators: { variant: [{
|
|
402
406
|
type: Input
|
|
403
407
|
}], type: [{
|
|
@@ -422,6 +426,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
422
426
|
type: Input
|
|
423
427
|
}], icon: [{
|
|
424
428
|
type: Input
|
|
429
|
+
}], labels: [{
|
|
430
|
+
type: Input
|
|
425
431
|
}] } });
|
|
426
432
|
|
|
427
433
|
class ButtonModule {
|
|
@@ -460,7 +466,7 @@ class ConfirmationModalComponent {
|
|
|
460
466
|
closeOnEsc: true,
|
|
461
467
|
showCloseButton: true,
|
|
462
468
|
cancelButton: {
|
|
463
|
-
label: '
|
|
469
|
+
label: '',
|
|
464
470
|
show: true
|
|
465
471
|
}
|
|
466
472
|
};
|
|
@@ -576,63 +582,2009 @@ class ConfirmationModalComponent {
|
|
|
576
582
|
}
|
|
577
583
|
return 'material';
|
|
578
584
|
}
|
|
579
|
-
getIconValue(icon) {
|
|
580
|
-
return typeof icon === 'string' ? icon : icon?.value;
|
|
585
|
+
getIconValue(icon) {
|
|
586
|
+
return typeof icon === 'string' ? icon : icon?.value;
|
|
587
|
+
}
|
|
588
|
+
getIconColor(icon) {
|
|
589
|
+
return typeof icon === 'object' ? icon.color : undefined;
|
|
590
|
+
}
|
|
591
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
592
|
+
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 [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n <img *ngSwitchCase=\"'img'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n 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()\" [attr.aria-label]=\"mergedConfig.labels?.codeSnippetAriaLabel\"\r\n [attr.title]=\"mergedConfig.labels?.codeSnippetTitle\">\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 [attr.aria-label]=\"mergedConfig.labels?.closeAriaLabel\">\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 }}\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"] }] });
|
|
593
|
+
}
|
|
594
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalComponent, decorators: [{
|
|
595
|
+
type: Component,
|
|
596
|
+
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 [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n class=\"modal-header__custom-icon\">\r\n <img *ngSwitchCase=\"'img'\" [src]=\"getIconValue(mergedConfig.icon)\"\r\n [attr.alt]=\"mergedConfig.labels?.iconAltText || mergedConfig.title + ' icon'\"\r\n 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()\" [attr.aria-label]=\"mergedConfig.labels?.codeSnippetAriaLabel\"\r\n [attr.title]=\"mergedConfig.labels?.codeSnippetTitle\">\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 [attr.aria-label]=\"mergedConfig.labels?.closeAriaLabel\">\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 }}\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"] }]
|
|
597
|
+
}], propDecorators: { config: [{
|
|
598
|
+
type: Input
|
|
599
|
+
}], isOpen: [{
|
|
600
|
+
type: Input
|
|
601
|
+
}], confirm: [{
|
|
602
|
+
type: Output
|
|
603
|
+
}], cancel: [{
|
|
604
|
+
type: Output
|
|
605
|
+
}], close: [{
|
|
606
|
+
type: Output
|
|
607
|
+
}], showCodeSnippet: [{
|
|
608
|
+
type: Output
|
|
609
|
+
}], handleEscape: [{
|
|
610
|
+
type: HostListener,
|
|
611
|
+
args: ['document:keydown.escape', ['$event']]
|
|
612
|
+
}] } });
|
|
613
|
+
|
|
614
|
+
class ConfirmationModalModule {
|
|
615
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
616
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, declarations: [ConfirmationModalComponent], imports: [CommonModule,
|
|
617
|
+
MatIconModule, // For material icons support
|
|
618
|
+
FormsModule // For ngModel in user examples (although mostly projected content, user might need it)
|
|
619
|
+
], exports: [ConfirmationModalComponent] });
|
|
620
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, imports: [CommonModule,
|
|
621
|
+
MatIconModule, // For material icons support
|
|
622
|
+
FormsModule // For ngModel in user examples (although mostly projected content, user might need it)
|
|
623
|
+
] });
|
|
624
|
+
}
|
|
625
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, decorators: [{
|
|
626
|
+
type: NgModule,
|
|
627
|
+
args: [{
|
|
628
|
+
declarations: [
|
|
629
|
+
ConfirmationModalComponent
|
|
630
|
+
],
|
|
631
|
+
imports: [
|
|
632
|
+
CommonModule,
|
|
633
|
+
MatIconModule, // For material icons support
|
|
634
|
+
FormsModule // For ngModel in user examples (although mostly projected content, user might need it)
|
|
635
|
+
],
|
|
636
|
+
exports: [
|
|
637
|
+
ConfirmationModalComponent
|
|
638
|
+
]
|
|
639
|
+
}]
|
|
640
|
+
}] });
|
|
641
|
+
|
|
642
|
+
class InputComponent {
|
|
643
|
+
config;
|
|
644
|
+
labels;
|
|
645
|
+
type = 'text';
|
|
646
|
+
label = '';
|
|
647
|
+
placeholder = '';
|
|
648
|
+
disabled = false;
|
|
649
|
+
required = false;
|
|
650
|
+
readonly = false;
|
|
651
|
+
clearable = true;
|
|
652
|
+
maxLength;
|
|
653
|
+
minLength;
|
|
654
|
+
min;
|
|
655
|
+
max;
|
|
656
|
+
pattern;
|
|
657
|
+
errorMessage = '';
|
|
658
|
+
helperText = '';
|
|
659
|
+
rows = 3;
|
|
660
|
+
prefixIcon;
|
|
661
|
+
suffixIcon;
|
|
662
|
+
value = '';
|
|
663
|
+
// Style inputs
|
|
664
|
+
width;
|
|
665
|
+
height;
|
|
666
|
+
borderRadius;
|
|
667
|
+
fontSize;
|
|
668
|
+
gap;
|
|
669
|
+
fontFamily;
|
|
670
|
+
labelColor;
|
|
671
|
+
labelFontSize;
|
|
672
|
+
labelFontWeight;
|
|
673
|
+
backgroundColor;
|
|
674
|
+
borderColor;
|
|
675
|
+
borderWidth;
|
|
676
|
+
padding;
|
|
677
|
+
fontWeight;
|
|
678
|
+
color;
|
|
679
|
+
placeholderColor;
|
|
680
|
+
focusBorderColor;
|
|
681
|
+
errorColor;
|
|
682
|
+
disabledBackgroundColor;
|
|
683
|
+
disabledColor;
|
|
684
|
+
boxShadow;
|
|
685
|
+
valueChange = new EventEmitter();
|
|
686
|
+
inputBlur = new EventEmitter();
|
|
687
|
+
inputFocus = new EventEmitter();
|
|
688
|
+
showPassword = false;
|
|
689
|
+
focused = false;
|
|
690
|
+
onChange = () => { };
|
|
691
|
+
onTouched = () => { };
|
|
692
|
+
ngOnInit() {
|
|
693
|
+
this.updateFromConfig();
|
|
694
|
+
this.updateFromLabels();
|
|
695
|
+
}
|
|
696
|
+
ngOnChanges(changes) {
|
|
697
|
+
if (changes['config']) {
|
|
698
|
+
this.updateFromConfig();
|
|
699
|
+
}
|
|
700
|
+
if (changes['labels']) {
|
|
701
|
+
this.updateFromLabels();
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
updateFromConfig() {
|
|
705
|
+
if (this.config) {
|
|
706
|
+
this.type = this.config.type ?? this.type;
|
|
707
|
+
this.label = this.config.label ?? this.label;
|
|
708
|
+
this.placeholder = this.config.placeholder ?? this.placeholder;
|
|
709
|
+
this.disabled = this.config.disabled ?? this.disabled;
|
|
710
|
+
this.required = this.config.required ?? this.required;
|
|
711
|
+
this.readonly = this.config.readonly ?? this.readonly;
|
|
712
|
+
this.maxLength = this.config.maxLength ?? this.maxLength;
|
|
713
|
+
this.minLength = this.config.minLength ?? this.minLength;
|
|
714
|
+
this.min = this.config.min ?? this.min;
|
|
715
|
+
this.max = this.config.max ?? this.max;
|
|
716
|
+
this.pattern = this.config.pattern ?? this.pattern;
|
|
717
|
+
this.errorMessage = this.config.errorMessage ?? this.errorMessage;
|
|
718
|
+
this.helperText = this.config.helperText ?? this.helperText;
|
|
719
|
+
this.rows = this.config.rows ?? this.rows;
|
|
720
|
+
this.prefixIcon = this.config.prefixIcon ?? this.prefixIcon;
|
|
721
|
+
this.suffixIcon = this.config.suffixIcon ?? this.suffixIcon;
|
|
722
|
+
// Style inputs
|
|
723
|
+
this.width = this.config.width ?? this.width;
|
|
724
|
+
this.height = this.config.height ?? this.height;
|
|
725
|
+
this.borderRadius = this.config.borderRadius ?? this.borderRadius;
|
|
726
|
+
this.fontSize = this.config.fontSize ?? this.fontSize;
|
|
727
|
+
this.gap = this.config.gap ?? this.gap;
|
|
728
|
+
this.fontFamily = this.config.fontFamily ?? this.fontFamily;
|
|
729
|
+
this.labelColor = this.config.labelColor ?? this.labelColor;
|
|
730
|
+
this.labelFontSize = this.config.labelFontSize ?? this.labelFontSize;
|
|
731
|
+
this.labelFontWeight = this.config.labelFontWeight ?? this.labelFontWeight;
|
|
732
|
+
this.backgroundColor = this.config.backgroundColor ?? this.backgroundColor;
|
|
733
|
+
this.borderColor = this.config.borderColor ?? this.borderColor;
|
|
734
|
+
this.borderWidth = this.config.borderWidth ?? this.borderWidth;
|
|
735
|
+
this.padding = this.config.padding ?? this.padding;
|
|
736
|
+
this.fontWeight = this.config.fontWeight ?? this.fontWeight;
|
|
737
|
+
this.color = this.config.color ?? this.color;
|
|
738
|
+
this.placeholderColor = this.config.placeholderColor ?? this.placeholderColor;
|
|
739
|
+
this.focusBorderColor = this.config.focusBorderColor ?? this.focusBorderColor;
|
|
740
|
+
this.errorColor = this.config.errorColor ?? this.errorColor;
|
|
741
|
+
this.disabledBackgroundColor = this.config.disabledBackgroundColor ?? this.disabledBackgroundColor;
|
|
742
|
+
this.disabledColor = this.config.disabledColor ?? this.disabledColor;
|
|
743
|
+
this.boxShadow = this.config.boxShadow ?? this.boxShadow;
|
|
744
|
+
if (this.config.value !== undefined) {
|
|
745
|
+
this.value = this.config.value;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
updateFromLabels() {
|
|
750
|
+
if (this.labels) {
|
|
751
|
+
this.label = this.labels.label || this.label;
|
|
752
|
+
this.placeholder = this.labels.placeholder || this.placeholder;
|
|
753
|
+
this.errorMessage = this.labels.errorMessage || this.errorMessage;
|
|
754
|
+
this.helperText = this.labels.helperText || this.helperText;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
get requiredMarker() {
|
|
758
|
+
return this.labels?.requiredMarker || '*';
|
|
759
|
+
}
|
|
760
|
+
writeValue(value) {
|
|
761
|
+
this.value = value;
|
|
762
|
+
}
|
|
763
|
+
registerOnChange(fn) {
|
|
764
|
+
this.onChange = fn;
|
|
765
|
+
}
|
|
766
|
+
registerOnTouched(fn) {
|
|
767
|
+
this.onTouched = fn;
|
|
768
|
+
}
|
|
769
|
+
setDisabledState(isDisabled) {
|
|
770
|
+
this.disabled = isDisabled;
|
|
771
|
+
}
|
|
772
|
+
onInputChange(event) {
|
|
773
|
+
const value = event.target.value;
|
|
774
|
+
this.value = this.type === 'number' ? (value ? Number(value) : null) : value;
|
|
775
|
+
this.onChange(this.value);
|
|
776
|
+
this.valueChange.emit(this.value);
|
|
777
|
+
}
|
|
778
|
+
onBlur() {
|
|
779
|
+
this.focused = false;
|
|
780
|
+
this.onTouched();
|
|
781
|
+
this.inputBlur.emit();
|
|
782
|
+
}
|
|
783
|
+
onFocus() {
|
|
784
|
+
this.focused = true;
|
|
785
|
+
this.inputFocus.emit();
|
|
786
|
+
}
|
|
787
|
+
togglePasswordVisibility() {
|
|
788
|
+
this.showPassword = !this.showPassword;
|
|
789
|
+
}
|
|
790
|
+
getIconType(icon) {
|
|
791
|
+
if (!icon)
|
|
792
|
+
return 'none';
|
|
793
|
+
if (typeof icon === 'string') {
|
|
794
|
+
if (icon.includes('/') || icon.includes('.') || icon.startsWith('http')) {
|
|
795
|
+
return 'img';
|
|
796
|
+
}
|
|
797
|
+
return 'material';
|
|
798
|
+
}
|
|
799
|
+
return icon.type || 'material';
|
|
800
|
+
}
|
|
801
|
+
getIconValue(icon) {
|
|
802
|
+
if (typeof icon === 'string')
|
|
803
|
+
return icon;
|
|
804
|
+
return icon?.value || '';
|
|
805
|
+
}
|
|
806
|
+
get inputType() {
|
|
807
|
+
if (this.type === 'password' && this.showPassword) {
|
|
808
|
+
return 'text';
|
|
809
|
+
}
|
|
810
|
+
return this.type === 'textarea' ? 'text' : this.type;
|
|
811
|
+
}
|
|
812
|
+
getStyleValue(value) {
|
|
813
|
+
return value ? `${value}` : undefined;
|
|
814
|
+
}
|
|
815
|
+
get wrapperStyles() {
|
|
816
|
+
return {
|
|
817
|
+
'width': this.getStyleValue(this.width),
|
|
818
|
+
'--cc-input-label-gap': this.getStyleValue(this.gap),
|
|
819
|
+
'--cc-input-font-family': this.getStyleValue(this.fontFamily)
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
get labelStyles() {
|
|
823
|
+
return {
|
|
824
|
+
'--cc-input-label-color': this.getStyleValue(this.labelColor),
|
|
825
|
+
'--cc-input-label-font-size': this.getStyleValue(this.labelFontSize),
|
|
826
|
+
'--cc-input-label-font-weight': this.getStyleValue(this.labelFontWeight)
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
get fieldStyles() {
|
|
830
|
+
return {
|
|
831
|
+
'--cc-input-bg': this.getStyleValue(this.backgroundColor),
|
|
832
|
+
'--cc-input-border-radius': this.getStyleValue(this.borderRadius),
|
|
833
|
+
'--cc-input-border-color': this.getStyleValue(this.borderColor),
|
|
834
|
+
'--cc-input-border-width': this.getStyleValue(this.borderWidth),
|
|
835
|
+
'--cc-input-height': this.getStyleValue(this.height),
|
|
836
|
+
'--cc-input-padding': this.getStyleValue(this.padding),
|
|
837
|
+
'--cc-input-font-size': this.getStyleValue(this.fontSize),
|
|
838
|
+
'--cc-input-font-weight': this.getStyleValue(this.fontWeight),
|
|
839
|
+
'--cc-input-color': this.getStyleValue(this.color),
|
|
840
|
+
'--cc-input-placeholder-color': this.getStyleValue(this.placeholderColor),
|
|
841
|
+
'--cc-input-focus-border-color': this.getStyleValue(this.focusBorderColor),
|
|
842
|
+
'--cc-input-error-color': this.getStyleValue(this.errorColor),
|
|
843
|
+
'--cc-input-disabled-bg': this.getStyleValue(this.disabledBackgroundColor),
|
|
844
|
+
'--cc-input-disabled-color': this.getStyleValue(this.disabledColor),
|
|
845
|
+
'box-shadow': this.getStyleValue(this.boxShadow)
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: InputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
849
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: InputComponent, isStandalone: false, selector: "lib-input", inputs: { config: "config", labels: "labels", type: "type", label: "label", placeholder: "placeholder", disabled: "disabled", required: "required", readonly: "readonly", clearable: "clearable", maxLength: "maxLength", minLength: "minLength", min: "min", max: "max", pattern: "pattern", errorMessage: "errorMessage", helperText: "helperText", rows: "rows", prefixIcon: "prefixIcon", suffixIcon: "suffixIcon", value: "value", width: "width", height: "height", borderRadius: "borderRadius", fontSize: "fontSize", gap: "gap", fontFamily: "fontFamily", labelColor: "labelColor", labelFontSize: "labelFontSize", labelFontWeight: "labelFontWeight", backgroundColor: "backgroundColor", borderColor: "borderColor", borderWidth: "borderWidth", padding: "padding", fontWeight: "fontWeight", color: "color", placeholderColor: "placeholderColor", focusBorderColor: "focusBorderColor", errorColor: "errorColor", disabledBackgroundColor: "disabledBackgroundColor", disabledColor: "disabledColor", boxShadow: "boxShadow" }, outputs: { valueChange: "valueChange", inputBlur: "inputBlur", inputFocus: "inputFocus" }, providers: [
|
|
850
|
+
{
|
|
851
|
+
provide: NG_VALUE_ACCESSOR,
|
|
852
|
+
useExisting: forwardRef(() => InputComponent),
|
|
853
|
+
multi: true
|
|
854
|
+
}
|
|
855
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-input-container\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-input-label\" [ngStyle]=\"labelStyles\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <div class=\"cc-input-wrapper\" [class.focused]=\"focused\" [class.disabled]=\"disabled\" [class.error]=\"errorMessage\"\r\n [ngStyle]=\"fieldStyles\">\r\n\r\n <!-- Prefix Icon -->\r\n <span class=\"cc-input-prefix\" *ngIf=\"prefixIcon\">\r\n <span class=\"material-icons\" *ngIf=\"getIconType(prefixIcon) === 'material'\">{{ getIconValue(prefixIcon)\r\n }}</span>\r\n <i *ngIf=\"getIconType(prefixIcon) === 'fontawesome'\" [class]=\"getIconValue(prefixIcon)\"></i>\r\n <img *ngIf=\"getIconType(prefixIcon) === 'img'\" [src]=\"getIconValue(prefixIcon)\" class=\"cc-icon-img\"\r\n [attr.alt]=\"labels?.prefixAltText || 'prefix'\" />\r\n </span>\r\n\r\n <!-- Input -->\r\n <input *ngIf=\"type !== 'textarea'\" class=\"cc-input-element\" [type]=\"inputType\" [value]=\"value\"\r\n [placeholder]=\"placeholder\" [disabled]=\"disabled\" [required]=\"required\" [readonly]=\"readonly\"\r\n [maxLength]=\"maxLength || 524288\" [minLength]=\"minLength || 0\" [min]=\"min\" [max]=\"max\" [pattern]=\"pattern\"\r\n (input)=\"onInputChange($event)\" (blur)=\"onBlur()\" (focus)=\"onFocus()\" [attr.aria-invalid]=\"!!errorMessage\"\r\n [attr.aria-describedby]=\"helperText ? 'helper-text' : null\" />\r\n\r\n <!-- Textarea -->\r\n <textarea *ngIf=\"type === 'textarea'\" class=\"cc-input-element cc-textarea\" [value]=\"value\"\r\n [placeholder]=\"placeholder\" [disabled]=\"disabled\" [required]=\"required\" [readonly]=\"readonly\"\r\n [maxLength]=\"maxLength || 524288\" [minLength]=\"minLength || 0\" [rows]=\"rows\" (input)=\"onInputChange($event)\"\r\n (blur)=\"onBlur()\" (focus)=\"onFocus()\" [attr.aria-invalid]=\"!!errorMessage\"></textarea>\r\n\r\n <!-- Suffix Icon / Password Toggle -->\r\n <span class=\"cc-input-suffix\">\r\n <button *ngIf=\"type === 'password'\" type=\"button\" class=\"cc-icon-btn\" (click)=\"togglePasswordVisibility()\"\r\n [attr.aria-label]=\"labels?.passwordToggleAriaLabel\">\r\n <span class=\"material-icons\">{{ showPassword ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n\r\n <ng-container *ngIf=\"suffixIcon && type !== 'password'\">\r\n <span class=\"material-icons\" *ngIf=\"getIconType(suffixIcon) === 'material'\">{{ getIconValue(suffixIcon)\r\n }}</span>\r\n <i *ngIf=\"getIconType(suffixIcon) === 'fontawesome'\" [class]=\"getIconValue(suffixIcon)\"></i>\r\n <img *ngIf=\"getIconType(suffixIcon) === 'img'\" [src]=\"getIconValue(suffixIcon)\" class=\"cc-icon-img\"\r\n [attr.alt]=\"labels?.suffixAltText || 'suffix'\" />\r\n </ng-container>\r\n </span>\r\n </div>\r\n\r\n <div class=\"cc-helper-text\" *ngIf=\"helperText\" id=\"helper-text\">{{ helperText }}</div>\r\n <div class=\"cc-error-message\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\r\n</div>", styles: [".cc-input-container{display:flex;flex-direction:column;gap:var(--cc-input-label-gap, .5rem);width:100%;font-family:var(--cc-input-font-family, inherit)}.cc-input-label{font-size:var(--cc-input-label-font-size, .875rem);font-weight:var(--cc-input-label-font-weight, 500);color:var(--cc-input-label-color, #202124);margin:0;line-height:1.4}.cc-required{color:var(--cc-input-required-color, #D93025);margin-left:.25rem}.cc-input-wrapper{display:flex;align-items:center;width:100%;box-sizing:border-box;background-color:var(--cc-input-bg, #FEFEFE);border:var(--cc-input-border-width, 1px) solid var(--cc-input-border-color, #BDC1C6);border-radius:var(--cc-input-border-radius, .4375rem);padding:var(--cc-input-padding, .5rem .75rem);min-height:var(--cc-input-height, 2.5rem);transition:border-color .2s,box-shadow .2s}.cc-input-wrapper.focused{border-color:var(--cc-input-focus-border-color, #1A73E8)}.cc-input-wrapper.error{border-color:var(--cc-input-error-color, #D93025)}.cc-input-wrapper.disabled{background-color:var(--cc-input-disabled-bg, #F1F3F4);cursor:not-allowed}.cc-input-wrapper.disabled .cc-input-element{cursor:not-allowed;color:var(--cc-input-disabled-color, #80868B)}.cc-input-wrapper.disabled .material-icons,.cc-input-wrapper.disabled i,.cc-input-wrapper.disabled img{opacity:.5}.cc-input-element{flex:1;border:none;background:none;outline:none;font-family:inherit;font-size:var(--cc-input-font-size, .875rem);font-weight:var(--cc-input-font-weight, 400);color:var(--cc-input-color, #202124);padding:0;margin:0;width:100%}.cc-input-element::placeholder{color:var(--cc-input-placeholder-color, #80868B)}.cc-input-element.cc-textarea{resize:vertical;min-height:4rem}.cc-input-prefix,.cc-input-suffix{display:flex;align-items:center;color:var(--cc-input-icon-color, #5F6368)}.cc-input-prefix{margin-right:.5rem}.cc-input-suffix{margin-left:.5rem}.cc-icon-img{width:1.25rem;height:1.25rem;object-fit:contain}.cc-icon-btn{background:none;border:none;cursor:pointer;padding:0;display:flex;align-items:center;color:inherit}.cc-icon-btn:focus{outline:none}.cc-helper-text{font-size:.75rem;color:#5f6368;margin-top:.25rem}.cc-error-message{font-size:.75rem;color:var(--cc-input-error-color, #D93025);margin-top:.25rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
856
|
+
}
|
|
857
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: InputComponent, decorators: [{
|
|
858
|
+
type: Component,
|
|
859
|
+
args: [{ selector: 'lib-input', standalone: false, providers: [
|
|
860
|
+
{
|
|
861
|
+
provide: NG_VALUE_ACCESSOR,
|
|
862
|
+
useExisting: forwardRef(() => InputComponent),
|
|
863
|
+
multi: true
|
|
864
|
+
}
|
|
865
|
+
], template: "<div class=\"cc-input-container\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-input-label\" [ngStyle]=\"labelStyles\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <div class=\"cc-input-wrapper\" [class.focused]=\"focused\" [class.disabled]=\"disabled\" [class.error]=\"errorMessage\"\r\n [ngStyle]=\"fieldStyles\">\r\n\r\n <!-- Prefix Icon -->\r\n <span class=\"cc-input-prefix\" *ngIf=\"prefixIcon\">\r\n <span class=\"material-icons\" *ngIf=\"getIconType(prefixIcon) === 'material'\">{{ getIconValue(prefixIcon)\r\n }}</span>\r\n <i *ngIf=\"getIconType(prefixIcon) === 'fontawesome'\" [class]=\"getIconValue(prefixIcon)\"></i>\r\n <img *ngIf=\"getIconType(prefixIcon) === 'img'\" [src]=\"getIconValue(prefixIcon)\" class=\"cc-icon-img\"\r\n [attr.alt]=\"labels?.prefixAltText || 'prefix'\" />\r\n </span>\r\n\r\n <!-- Input -->\r\n <input *ngIf=\"type !== 'textarea'\" class=\"cc-input-element\" [type]=\"inputType\" [value]=\"value\"\r\n [placeholder]=\"placeholder\" [disabled]=\"disabled\" [required]=\"required\" [readonly]=\"readonly\"\r\n [maxLength]=\"maxLength || 524288\" [minLength]=\"minLength || 0\" [min]=\"min\" [max]=\"max\" [pattern]=\"pattern\"\r\n (input)=\"onInputChange($event)\" (blur)=\"onBlur()\" (focus)=\"onFocus()\" [attr.aria-invalid]=\"!!errorMessage\"\r\n [attr.aria-describedby]=\"helperText ? 'helper-text' : null\" />\r\n\r\n <!-- Textarea -->\r\n <textarea *ngIf=\"type === 'textarea'\" class=\"cc-input-element cc-textarea\" [value]=\"value\"\r\n [placeholder]=\"placeholder\" [disabled]=\"disabled\" [required]=\"required\" [readonly]=\"readonly\"\r\n [maxLength]=\"maxLength || 524288\" [minLength]=\"minLength || 0\" [rows]=\"rows\" (input)=\"onInputChange($event)\"\r\n (blur)=\"onBlur()\" (focus)=\"onFocus()\" [attr.aria-invalid]=\"!!errorMessage\"></textarea>\r\n\r\n <!-- Suffix Icon / Password Toggle -->\r\n <span class=\"cc-input-suffix\">\r\n <button *ngIf=\"type === 'password'\" type=\"button\" class=\"cc-icon-btn\" (click)=\"togglePasswordVisibility()\"\r\n [attr.aria-label]=\"labels?.passwordToggleAriaLabel\">\r\n <span class=\"material-icons\">{{ showPassword ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n\r\n <ng-container *ngIf=\"suffixIcon && type !== 'password'\">\r\n <span class=\"material-icons\" *ngIf=\"getIconType(suffixIcon) === 'material'\">{{ getIconValue(suffixIcon)\r\n }}</span>\r\n <i *ngIf=\"getIconType(suffixIcon) === 'fontawesome'\" [class]=\"getIconValue(suffixIcon)\"></i>\r\n <img *ngIf=\"getIconType(suffixIcon) === 'img'\" [src]=\"getIconValue(suffixIcon)\" class=\"cc-icon-img\"\r\n [attr.alt]=\"labels?.suffixAltText || 'suffix'\" />\r\n </ng-container>\r\n </span>\r\n </div>\r\n\r\n <div class=\"cc-helper-text\" *ngIf=\"helperText\" id=\"helper-text\">{{ helperText }}</div>\r\n <div class=\"cc-error-message\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\r\n</div>", styles: [".cc-input-container{display:flex;flex-direction:column;gap:var(--cc-input-label-gap, .5rem);width:100%;font-family:var(--cc-input-font-family, inherit)}.cc-input-label{font-size:var(--cc-input-label-font-size, .875rem);font-weight:var(--cc-input-label-font-weight, 500);color:var(--cc-input-label-color, #202124);margin:0;line-height:1.4}.cc-required{color:var(--cc-input-required-color, #D93025);margin-left:.25rem}.cc-input-wrapper{display:flex;align-items:center;width:100%;box-sizing:border-box;background-color:var(--cc-input-bg, #FEFEFE);border:var(--cc-input-border-width, 1px) solid var(--cc-input-border-color, #BDC1C6);border-radius:var(--cc-input-border-radius, .4375rem);padding:var(--cc-input-padding, .5rem .75rem);min-height:var(--cc-input-height, 2.5rem);transition:border-color .2s,box-shadow .2s}.cc-input-wrapper.focused{border-color:var(--cc-input-focus-border-color, #1A73E8)}.cc-input-wrapper.error{border-color:var(--cc-input-error-color, #D93025)}.cc-input-wrapper.disabled{background-color:var(--cc-input-disabled-bg, #F1F3F4);cursor:not-allowed}.cc-input-wrapper.disabled .cc-input-element{cursor:not-allowed;color:var(--cc-input-disabled-color, #80868B)}.cc-input-wrapper.disabled .material-icons,.cc-input-wrapper.disabled i,.cc-input-wrapper.disabled img{opacity:.5}.cc-input-element{flex:1;border:none;background:none;outline:none;font-family:inherit;font-size:var(--cc-input-font-size, .875rem);font-weight:var(--cc-input-font-weight, 400);color:var(--cc-input-color, #202124);padding:0;margin:0;width:100%}.cc-input-element::placeholder{color:var(--cc-input-placeholder-color, #80868B)}.cc-input-element.cc-textarea{resize:vertical;min-height:4rem}.cc-input-prefix,.cc-input-suffix{display:flex;align-items:center;color:var(--cc-input-icon-color, #5F6368)}.cc-input-prefix{margin-right:.5rem}.cc-input-suffix{margin-left:.5rem}.cc-icon-img{width:1.25rem;height:1.25rem;object-fit:contain}.cc-icon-btn{background:none;border:none;cursor:pointer;padding:0;display:flex;align-items:center;color:inherit}.cc-icon-btn:focus{outline:none}.cc-helper-text{font-size:.75rem;color:#5f6368;margin-top:.25rem}.cc-error-message{font-size:.75rem;color:var(--cc-input-error-color, #D93025);margin-top:.25rem}\n"] }]
|
|
866
|
+
}], propDecorators: { config: [{
|
|
867
|
+
type: Input
|
|
868
|
+
}], labels: [{
|
|
869
|
+
type: Input
|
|
870
|
+
}], type: [{
|
|
871
|
+
type: Input
|
|
872
|
+
}], label: [{
|
|
873
|
+
type: Input
|
|
874
|
+
}], placeholder: [{
|
|
875
|
+
type: Input
|
|
876
|
+
}], disabled: [{
|
|
877
|
+
type: Input
|
|
878
|
+
}], required: [{
|
|
879
|
+
type: Input
|
|
880
|
+
}], readonly: [{
|
|
881
|
+
type: Input
|
|
882
|
+
}], clearable: [{
|
|
883
|
+
type: Input
|
|
884
|
+
}], maxLength: [{
|
|
885
|
+
type: Input
|
|
886
|
+
}], minLength: [{
|
|
887
|
+
type: Input
|
|
888
|
+
}], min: [{
|
|
889
|
+
type: Input
|
|
890
|
+
}], max: [{
|
|
891
|
+
type: Input
|
|
892
|
+
}], pattern: [{
|
|
893
|
+
type: Input
|
|
894
|
+
}], errorMessage: [{
|
|
895
|
+
type: Input
|
|
896
|
+
}], helperText: [{
|
|
897
|
+
type: Input
|
|
898
|
+
}], rows: [{
|
|
899
|
+
type: Input
|
|
900
|
+
}], prefixIcon: [{
|
|
901
|
+
type: Input
|
|
902
|
+
}], suffixIcon: [{
|
|
903
|
+
type: Input
|
|
904
|
+
}], value: [{
|
|
905
|
+
type: Input
|
|
906
|
+
}], width: [{
|
|
907
|
+
type: Input
|
|
908
|
+
}], height: [{
|
|
909
|
+
type: Input
|
|
910
|
+
}], borderRadius: [{
|
|
911
|
+
type: Input
|
|
912
|
+
}], fontSize: [{
|
|
913
|
+
type: Input
|
|
914
|
+
}], gap: [{
|
|
915
|
+
type: Input
|
|
916
|
+
}], fontFamily: [{
|
|
917
|
+
type: Input
|
|
918
|
+
}], labelColor: [{
|
|
919
|
+
type: Input
|
|
920
|
+
}], labelFontSize: [{
|
|
921
|
+
type: Input
|
|
922
|
+
}], labelFontWeight: [{
|
|
923
|
+
type: Input
|
|
924
|
+
}], backgroundColor: [{
|
|
925
|
+
type: Input
|
|
926
|
+
}], borderColor: [{
|
|
927
|
+
type: Input
|
|
928
|
+
}], borderWidth: [{
|
|
929
|
+
type: Input
|
|
930
|
+
}], padding: [{
|
|
931
|
+
type: Input
|
|
932
|
+
}], fontWeight: [{
|
|
933
|
+
type: Input
|
|
934
|
+
}], color: [{
|
|
935
|
+
type: Input
|
|
936
|
+
}], placeholderColor: [{
|
|
937
|
+
type: Input
|
|
938
|
+
}], focusBorderColor: [{
|
|
939
|
+
type: Input
|
|
940
|
+
}], errorColor: [{
|
|
941
|
+
type: Input
|
|
942
|
+
}], disabledBackgroundColor: [{
|
|
943
|
+
type: Input
|
|
944
|
+
}], disabledColor: [{
|
|
945
|
+
type: Input
|
|
946
|
+
}], boxShadow: [{
|
|
947
|
+
type: Input
|
|
948
|
+
}], valueChange: [{
|
|
949
|
+
type: Output
|
|
950
|
+
}], inputBlur: [{
|
|
951
|
+
type: Output
|
|
952
|
+
}], inputFocus: [{
|
|
953
|
+
type: Output
|
|
954
|
+
}] } });
|
|
955
|
+
|
|
956
|
+
class ClickOutsideDirective {
|
|
957
|
+
elementRef;
|
|
958
|
+
libClickOutside = new EventEmitter();
|
|
959
|
+
constructor(elementRef) {
|
|
960
|
+
this.elementRef = elementRef;
|
|
961
|
+
}
|
|
962
|
+
onClick(target) {
|
|
963
|
+
const clickedInside = this.elementRef.nativeElement.contains(target);
|
|
964
|
+
if (!clickedInside) {
|
|
965
|
+
this.libClickOutside.emit();
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ClickOutsideDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
969
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: ClickOutsideDirective, isStandalone: false, selector: "[libClickOutside]", outputs: { libClickOutside: "libClickOutside" }, host: { listeners: { "document:click": "onClick($event.target)" } }, ngImport: i0 });
|
|
970
|
+
}
|
|
971
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ClickOutsideDirective, decorators: [{
|
|
972
|
+
type: Directive,
|
|
973
|
+
args: [{
|
|
974
|
+
selector: '[libClickOutside]',
|
|
975
|
+
standalone: false
|
|
976
|
+
}]
|
|
977
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { libClickOutside: [{
|
|
978
|
+
type: Output
|
|
979
|
+
}], onClick: [{
|
|
980
|
+
type: HostListener,
|
|
981
|
+
args: ['document:click', ['$event.target']]
|
|
982
|
+
}] } });
|
|
983
|
+
|
|
984
|
+
class DropdownComponent {
|
|
985
|
+
config;
|
|
986
|
+
labels;
|
|
987
|
+
options = [];
|
|
988
|
+
placeholder = '';
|
|
989
|
+
label = '';
|
|
990
|
+
multiple = false;
|
|
991
|
+
searchable = false;
|
|
992
|
+
clearable = false;
|
|
993
|
+
disabled = false;
|
|
994
|
+
required = false;
|
|
995
|
+
errorMessage = '';
|
|
996
|
+
// Configurable styles
|
|
997
|
+
width;
|
|
998
|
+
height;
|
|
999
|
+
borderRadius;
|
|
1000
|
+
fontSize;
|
|
1001
|
+
// Additional style inputs inferred from template/getters
|
|
1002
|
+
gap;
|
|
1003
|
+
fontFamily;
|
|
1004
|
+
labelColor;
|
|
1005
|
+
labelFontSize;
|
|
1006
|
+
labelFontWeight;
|
|
1007
|
+
backgroundColor;
|
|
1008
|
+
borderColor;
|
|
1009
|
+
borderWidth;
|
|
1010
|
+
padding;
|
|
1011
|
+
fontWeight;
|
|
1012
|
+
color;
|
|
1013
|
+
placeholderColor;
|
|
1014
|
+
focusBorderColor;
|
|
1015
|
+
errorColor;
|
|
1016
|
+
disabledBackgroundColor;
|
|
1017
|
+
disabledColor;
|
|
1018
|
+
boxShadow;
|
|
1019
|
+
selectionChange = new EventEmitter();
|
|
1020
|
+
viewport;
|
|
1021
|
+
searchInput;
|
|
1022
|
+
filteredOptions = [];
|
|
1023
|
+
searchTerm = '';
|
|
1024
|
+
value = null;
|
|
1025
|
+
isOpen = false;
|
|
1026
|
+
focusedIndex = -1;
|
|
1027
|
+
onChange = () => { };
|
|
1028
|
+
onTouched = () => { };
|
|
1029
|
+
ngOnInit() {
|
|
1030
|
+
this.updateFromConfig();
|
|
1031
|
+
this.updateFromLabels();
|
|
1032
|
+
this.filteredOptions = [...this.options];
|
|
1033
|
+
}
|
|
1034
|
+
ngOnChanges(changes) {
|
|
1035
|
+
if (changes['config']) {
|
|
1036
|
+
this.updateFromConfig();
|
|
1037
|
+
}
|
|
1038
|
+
if (changes['labels']) {
|
|
1039
|
+
this.updateFromLabels();
|
|
1040
|
+
}
|
|
1041
|
+
if (changes['config'] || changes['options']) {
|
|
1042
|
+
this.filteredOptions = [...this.options];
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
updateFromConfig() {
|
|
1046
|
+
if (this.config) {
|
|
1047
|
+
this.options = this.config.options || this.options;
|
|
1048
|
+
this.placeholder = this.config.placeholder ?? this.placeholder;
|
|
1049
|
+
this.label = this.config.label ?? this.label;
|
|
1050
|
+
this.multiple = this.config.multiple ?? this.multiple;
|
|
1051
|
+
this.searchable = this.config.searchable ?? this.searchable;
|
|
1052
|
+
this.clearable = this.config.clearable ?? this.clearable;
|
|
1053
|
+
this.disabled = this.config.disabled ?? this.disabled;
|
|
1054
|
+
this.required = this.config.required ?? this.required;
|
|
1055
|
+
this.errorMessage = this.config.errorMessage ?? this.errorMessage;
|
|
1056
|
+
this.width = this.config.width ?? this.width;
|
|
1057
|
+
this.height = this.config.height ?? this.height;
|
|
1058
|
+
this.borderRadius = this.config.borderRadius ?? this.borderRadius;
|
|
1059
|
+
this.fontSize = this.config.fontSize ?? this.fontSize;
|
|
1060
|
+
this.gap = this.config.gap ?? this.gap;
|
|
1061
|
+
this.fontFamily = this.config.fontFamily ?? this.fontFamily;
|
|
1062
|
+
this.labelColor = this.config.labelColor ?? this.labelColor;
|
|
1063
|
+
this.labelFontSize = this.config.labelFontSize ?? this.labelFontSize;
|
|
1064
|
+
this.labelFontWeight = this.config.labelFontWeight ?? this.labelFontWeight;
|
|
1065
|
+
this.backgroundColor = this.config.backgroundColor ?? this.backgroundColor;
|
|
1066
|
+
this.borderColor = this.config.borderColor ?? this.borderColor;
|
|
1067
|
+
this.borderWidth = this.config.borderWidth ?? this.borderWidth;
|
|
1068
|
+
this.padding = this.config.padding ?? this.padding;
|
|
1069
|
+
this.fontWeight = this.config.fontWeight ?? this.fontWeight;
|
|
1070
|
+
this.color = this.config.color ?? this.color;
|
|
1071
|
+
this.placeholderColor = this.config.placeholderColor ?? this.placeholderColor;
|
|
1072
|
+
this.focusBorderColor = this.config.focusBorderColor ?? this.focusBorderColor;
|
|
1073
|
+
this.errorColor = this.config.errorColor ?? this.errorColor;
|
|
1074
|
+
this.disabledBackgroundColor = this.config.disabledBackgroundColor ?? this.disabledBackgroundColor;
|
|
1075
|
+
this.disabledColor = this.config.disabledColor ?? this.disabledColor;
|
|
1076
|
+
this.boxShadow = this.config.boxShadow ?? this.boxShadow;
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
updateFromLabels() {
|
|
1080
|
+
if (this.labels) {
|
|
1081
|
+
this.label = this.labels.label || this.label;
|
|
1082
|
+
this.placeholder = this.labels.placeholder || this.placeholder;
|
|
1083
|
+
this.errorMessage = this.labels.errorMessage || this.errorMessage;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
get requiredMarker() {
|
|
1087
|
+
return this.labels?.requiredMarker || '*';
|
|
1088
|
+
}
|
|
1089
|
+
get searchPlaceholder() {
|
|
1090
|
+
return this.labels?.searchPlaceholder || 'Search...';
|
|
1091
|
+
}
|
|
1092
|
+
get selectedSuffix() {
|
|
1093
|
+
return this.labels?.selectedSuffix || 'selected';
|
|
1094
|
+
}
|
|
1095
|
+
get clearAriaLabel() {
|
|
1096
|
+
return this.labels?.clearAriaLabel || 'Clear selection';
|
|
1097
|
+
}
|
|
1098
|
+
writeValue(value) {
|
|
1099
|
+
this.value = value;
|
|
1100
|
+
}
|
|
1101
|
+
registerOnChange(fn) {
|
|
1102
|
+
this.onChange = fn;
|
|
1103
|
+
}
|
|
1104
|
+
registerOnTouched(fn) {
|
|
1105
|
+
this.onTouched = fn;
|
|
1106
|
+
}
|
|
1107
|
+
setDisabledState(isDisabled) {
|
|
1108
|
+
this.disabled = isDisabled;
|
|
1109
|
+
}
|
|
1110
|
+
toggle() {
|
|
1111
|
+
if (this.disabled)
|
|
1112
|
+
return;
|
|
1113
|
+
this.isOpen = !this.isOpen;
|
|
1114
|
+
if (this.isOpen) {
|
|
1115
|
+
this.focusedIndex = -1;
|
|
1116
|
+
setTimeout(() => {
|
|
1117
|
+
if (this.searchable && this.searchInput) {
|
|
1118
|
+
this.searchInput.nativeElement.focus();
|
|
1119
|
+
}
|
|
1120
|
+
else if (this.viewport) {
|
|
1121
|
+
this.viewport.elementRef.nativeElement.focus();
|
|
1122
|
+
}
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
else {
|
|
1126
|
+
this.onTouched();
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
close() {
|
|
1130
|
+
if (this.isOpen) {
|
|
1131
|
+
this.isOpen = false;
|
|
1132
|
+
this.onTouched();
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
selectOption(option) {
|
|
1136
|
+
if (option.disabled)
|
|
1137
|
+
return;
|
|
1138
|
+
if (this.multiple) {
|
|
1139
|
+
const currentValues = Array.isArray(this.value) ? [...this.value] : [];
|
|
1140
|
+
const index = currentValues.indexOf(option.value);
|
|
1141
|
+
if (index > -1) {
|
|
1142
|
+
currentValues.splice(index, 1);
|
|
1143
|
+
}
|
|
1144
|
+
else {
|
|
1145
|
+
currentValues.push(option.value);
|
|
1146
|
+
}
|
|
1147
|
+
this.value = currentValues;
|
|
1148
|
+
}
|
|
1149
|
+
else {
|
|
1150
|
+
this.value = option.value;
|
|
1151
|
+
this.close();
|
|
1152
|
+
}
|
|
1153
|
+
this.onChange(this.value);
|
|
1154
|
+
this.selectionChange.emit(this.value);
|
|
1155
|
+
}
|
|
1156
|
+
isSelected(option) {
|
|
1157
|
+
if (this.multiple) {
|
|
1158
|
+
return Array.isArray(this.value) && this.value.includes(option.value);
|
|
1159
|
+
}
|
|
1160
|
+
return this.value === option.value;
|
|
1161
|
+
}
|
|
1162
|
+
onSearch(term) {
|
|
1163
|
+
this.searchTerm = term;
|
|
1164
|
+
if (!term) {
|
|
1165
|
+
this.filteredOptions = [...this.options];
|
|
1166
|
+
}
|
|
1167
|
+
else {
|
|
1168
|
+
this.filteredOptions = this.options.filter(option => option.label.toLowerCase().includes(term.toLowerCase()));
|
|
1169
|
+
}
|
|
1170
|
+
this.focusedIndex = -1;
|
|
1171
|
+
}
|
|
1172
|
+
clearSelection(event) {
|
|
1173
|
+
if (event) {
|
|
1174
|
+
event.stopPropagation();
|
|
1175
|
+
}
|
|
1176
|
+
this.value = this.multiple ? [] : null;
|
|
1177
|
+
this.onChange(this.value);
|
|
1178
|
+
this.selectionChange.emit(this.value);
|
|
1179
|
+
}
|
|
1180
|
+
getIconType(icon) {
|
|
1181
|
+
if (!icon)
|
|
1182
|
+
return 'none';
|
|
1183
|
+
if (typeof icon === 'string') {
|
|
1184
|
+
if (icon.includes('/') || icon.includes('.') || icon.startsWith('http')) {
|
|
1185
|
+
return 'img';
|
|
1186
|
+
}
|
|
1187
|
+
return 'material';
|
|
1188
|
+
}
|
|
1189
|
+
return icon.type || 'material';
|
|
1190
|
+
}
|
|
1191
|
+
getIconValue(icon) {
|
|
1192
|
+
if (typeof icon === 'string')
|
|
1193
|
+
return icon;
|
|
1194
|
+
return icon?.value || '';
|
|
1195
|
+
}
|
|
1196
|
+
getSelectedLabel() {
|
|
1197
|
+
if (this.multiple) {
|
|
1198
|
+
const count = Array.isArray(this.value) ? this.value.length : 0;
|
|
1199
|
+
return count > 0 ? `${count} ${this.selectedSuffix}` : '';
|
|
1200
|
+
}
|
|
1201
|
+
if (!this.value)
|
|
1202
|
+
return '';
|
|
1203
|
+
const selected = this.options.find(opt => opt.value === this.value);
|
|
1204
|
+
return selected?.label || '';
|
|
1205
|
+
}
|
|
1206
|
+
hasValue() {
|
|
1207
|
+
if (this.multiple) {
|
|
1208
|
+
return Array.isArray(this.value) && this.value.length > 0;
|
|
1209
|
+
}
|
|
1210
|
+
return this.value !== null && this.value !== undefined && this.value !== '';
|
|
1211
|
+
}
|
|
1212
|
+
handleKeyboardEvent(event) {
|
|
1213
|
+
if (this.disabled)
|
|
1214
|
+
return;
|
|
1215
|
+
if (event.key === 'Escape') {
|
|
1216
|
+
this.close();
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
if (!this.isOpen && (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown')) {
|
|
1220
|
+
this.toggle();
|
|
1221
|
+
event.preventDefault();
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
if (!this.isOpen)
|
|
1225
|
+
return;
|
|
1226
|
+
switch (event.key) {
|
|
1227
|
+
case 'ArrowDown':
|
|
1228
|
+
this.focusedIndex = Math.min(this.focusedIndex + 1, this.filteredOptions.length - 1);
|
|
1229
|
+
this.scrollToIndex(this.focusedIndex);
|
|
1230
|
+
event.preventDefault();
|
|
1231
|
+
break;
|
|
1232
|
+
case 'ArrowUp':
|
|
1233
|
+
this.focusedIndex = Math.max(this.focusedIndex - 1, 0);
|
|
1234
|
+
this.scrollToIndex(this.focusedIndex);
|
|
1235
|
+
event.preventDefault();
|
|
1236
|
+
break;
|
|
1237
|
+
case 'Enter':
|
|
1238
|
+
if (this.focusedIndex > -1) {
|
|
1239
|
+
this.selectOption(this.filteredOptions[this.focusedIndex]);
|
|
1240
|
+
}
|
|
1241
|
+
event.preventDefault();
|
|
1242
|
+
break;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
scrollToIndex(index) {
|
|
1246
|
+
if (this.viewport) {
|
|
1247
|
+
this.viewport.scrollToIndex(index);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
getStyleValue(value) {
|
|
1251
|
+
return value ? `${value}` : undefined;
|
|
1252
|
+
}
|
|
1253
|
+
get wrapperStyles() {
|
|
1254
|
+
return {
|
|
1255
|
+
'width': this.getStyleValue(this.width),
|
|
1256
|
+
'--cc-dropdown-label-gap': this.getStyleValue(this.gap),
|
|
1257
|
+
'--cc-dropdown-font-family': this.getStyleValue(this.fontFamily)
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
get labelStyles() {
|
|
1261
|
+
return {
|
|
1262
|
+
'--cc-dropdown-label-color': this.getStyleValue(this.labelColor),
|
|
1263
|
+
'--cc-dropdown-font-size': this.getStyleValue(this.labelFontSize),
|
|
1264
|
+
'--cc-dropdown-font-weight': this.getStyleValue(this.labelFontWeight)
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
get fieldStyles() {
|
|
1268
|
+
return {
|
|
1269
|
+
'--cc-dropdown-bg': this.getStyleValue(this.backgroundColor),
|
|
1270
|
+
'--cc-dropdown-border-radius': this.getStyleValue(this.borderRadius),
|
|
1271
|
+
'--cc-dropdown-border-color': this.getStyleValue(this.borderColor),
|
|
1272
|
+
'--cc-dropdown-border-width': this.getStyleValue(this.borderWidth),
|
|
1273
|
+
'--cc-dropdown-height': this.getStyleValue(this.height),
|
|
1274
|
+
'--cc-dropdown-padding': this.getStyleValue(this.padding),
|
|
1275
|
+
'--cc-dropdown-font-size': this.getStyleValue(this.fontSize),
|
|
1276
|
+
'--cc-dropdown-font-weight': this.getStyleValue(this.fontWeight),
|
|
1277
|
+
'--cc-dropdown-color': this.getStyleValue(this.color),
|
|
1278
|
+
'--cc-dropdown-placeholder-color': this.getStyleValue(this.placeholderColor),
|
|
1279
|
+
'--cc-dropdown-focus-border-color': this.getStyleValue(this.focusBorderColor),
|
|
1280
|
+
'--cc-dropdown-error-color': this.getStyleValue(this.errorColor),
|
|
1281
|
+
'--cc-dropdown-disabled-bg': this.getStyleValue(this.disabledBackgroundColor),
|
|
1282
|
+
'--cc-dropdown-disabled-color': this.getStyleValue(this.disabledColor),
|
|
1283
|
+
'box-shadow': this.getStyleValue(this.boxShadow)
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1287
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: DropdownComponent, isStandalone: false, selector: "lib-dropdown", inputs: { config: "config", labels: "labels", options: "options", placeholder: "placeholder", label: "label", multiple: "multiple", searchable: "searchable", clearable: "clearable", disabled: "disabled", required: "required", errorMessage: "errorMessage", width: "width", height: "height", borderRadius: "borderRadius", fontSize: "fontSize", gap: "gap", fontFamily: "fontFamily", labelColor: "labelColor", labelFontSize: "labelFontSize", labelFontWeight: "labelFontWeight", backgroundColor: "backgroundColor", borderColor: "borderColor", borderWidth: "borderWidth", padding: "padding", fontWeight: "fontWeight", color: "color", placeholderColor: "placeholderColor", focusBorderColor: "focusBorderColor", errorColor: "errorColor", disabledBackgroundColor: "disabledBackgroundColor", disabledColor: "disabledColor", boxShadow: "boxShadow" }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "keydown": "handleKeyboardEvent($event)" } }, providers: [
|
|
1288
|
+
{
|
|
1289
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1290
|
+
useExisting: forwardRef(() => DropdownComponent),
|
|
1291
|
+
multi: true
|
|
1292
|
+
}
|
|
1293
|
+
], viewQueries: [{ propertyName: "viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-dropdown-wrapper\" [ngStyle]=\"wrapperStyles\" libClickOutside (libClickOutside)=\"close()\">\r\n <!-- Label -->\r\n <label *ngIf=\"label\" class=\"cc-dropdown-label\" [ngStyle]=\"labelStyles\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <!-- Trigger -->\r\n <div class=\"cc-dropdown-trigger\" [class.disabled]=\"disabled\" [class.open]=\"isOpen\" [class.error]=\"errorMessage\"\r\n (click)=\"toggle()\" tabindex=\"0\" (keydown)=\"handleKeyboardEvent($event)\" [ngStyle]=\"fieldStyles\">\r\n\r\n <div class=\"cc-selected-value\" *ngIf=\"hasValue()\">\r\n {{ multiple ? value.length + ' ' + selectedSuffix : getSelectedLabel() }}\r\n </div>\r\n <div class=\"cc-placeholder\" *ngIf=\"!hasValue()\">{{ placeholder }}</div>\r\n\r\n <div class=\"cc-actions\">\r\n <span *ngIf=\"clearable && hasValue() && !disabled\" class=\"cc-clear-btn\" (click)=\"clearSelection($event)\"\r\n [attr.aria-label]=\"clearAriaLabel\">\r\n <span class=\"material-icons\">close</span>\r\n </span>\r\n <span class=\"cc-arrow material-icons\">expand_more</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Dropdown Menu -->\r\n <div class=\"cc-dropdown-menu\" *ngIf=\"isOpen\">\r\n <!-- Search -->\r\n <div class=\"cc-search-container\" *ngIf=\"searchable\">\r\n <input type=\"text\" #searchInput [placeholder]=\"searchPlaceholder\"\r\n (input)=\"onSearch($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\r\n class=\"cc-dropdown-search-input\" />\r\n </div>\r\n\r\n <!-- Options Virtual Scroll -->\r\n <cdk-virtual-scroll-viewport itemSize=\"40\" class=\"cc-virtual-scroll\"\r\n [style.height.px]=\"filteredOptions.length * 40 > 240 ? 240 : (filteredOptions.length * 40 || 40)\">\r\n\r\n <div *cdkVirtualFor=\"let option of filteredOptions; let i = index\" class=\"cc-option\"\r\n [class.selected]=\"isSelected(option)\" [class.focused]=\"i === focusedIndex\"\r\n [class.disabled]=\"option.disabled\" (click)=\"selectOption(option)\">\r\n\r\n <!-- Multi-select checkbox visual -->\r\n <span class=\"cc-multi-check\" *ngIf=\"multiple\">\r\n <span class=\"material-icons\" *ngIf=\"isSelected(option)\">check_box</span>\r\n <span class=\"material-icons\" *ngIf=\"!isSelected(option)\">check_box_outline_blank</span>\r\n </span>\r\n\r\n <!-- Icon -->\r\n <span class=\"cc-option-icon-wrapper\" *ngIf=\"option.icon\">\r\n <span class=\"material-icons\" *ngIf=\"getIconType(option.icon) === 'material'\">{{\r\n getIconValue(option.icon) }}</span>\r\n <i *ngIf=\"getIconType(option.icon) === 'fontawesome'\" [class]=\"getIconValue(option.icon)\"></i>\r\n <img *ngIf=\"getIconType(option.icon) === 'img'\" [src]=\"getIconValue(option.icon)\"\r\n class=\"cc-option-img\" alt=\"icon\" />\r\n </span>\r\n\r\n <span class=\"cc-option-label\">{{ option.label }}</span>\r\n\r\n <!-- Single-select check visual -->\r\n <span class=\"cc-single-check\" *ngIf=\"!multiple && isSelected(option)\">\r\n <span class=\"material-icons\">check</span>\r\n </span>\r\n </div>\r\n\r\n <div *ngIf=\"filteredOptions.length === 0\" class=\"cc-no-results\">{{ labels?.noResultsFound || 'No results\r\n found' }}</div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n\r\n <!-- Error Message -->\r\n <div class=\"cc-error-message\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\r\n</div>", styles: [".cc-dropdown-wrapper{display:flex;flex-direction:column;width:100%;position:relative;font-family:var(--cc-dropdown-font-family, inherit);gap:var(--cc-dropdown-label-gap, .5rem)}.cc-dropdown-label{font-size:var(--cc-dropdown-font-size, .875rem);font-weight:var(--cc-dropdown-font-weight, 500);color:var(--cc-dropdown-label-color, #202124);margin:0;line-height:1.4}.cc-required{color:var(--cc-dropdown-required-color, #D93025);margin-left:.25rem}.cc-dropdown-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;min-height:var(--cc-dropdown-height, 2.5rem);padding:var(--cc-dropdown-padding, .5rem .75rem);background-color:var(--cc-dropdown-bg, #FEFEFE);border:var(--cc-dropdown-border-width, 1px) solid var(--cc-dropdown-border-color, #BDC1C6);border-radius:var(--cc-dropdown-border-radius, .4375rem);cursor:pointer;-webkit-user-select:none;user-select:none;box-sizing:border-box;transition:all .2s}.cc-dropdown-trigger:focus{outline:none;border-color:var(--cc-dropdown-focus-border-color, #1A73E8)}.cc-dropdown-trigger.open{border-color:var(--cc-dropdown-focus-border-color, #1A73E8)}.cc-dropdown-trigger.error{border-color:var(--cc-dropdown-error-color, #D93025)}.cc-dropdown-trigger.disabled{background-color:var(--cc-dropdown-disabled-bg, #F1F3F4);cursor:not-allowed;color:var(--cc-dropdown-disabled-color, #80868B)}.cc-dropdown-trigger.disabled .cc-arrow,.cc-dropdown-trigger.disabled .cc-clear-btn{color:var(--cc-dropdown-disabled-color, #80868B)}.cc-selected-value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--cc-dropdown-color, #202124);font-size:var(--cc-dropdown-font-size, .875rem);font-weight:var(--cc-dropdown-font-weight, 400)}.cc-placeholder{flex:1;color:var(--cc-dropdown-placeholder-color, #80868B);font-size:var(--cc-dropdown-font-size, .875rem)}.cc-actions{display:flex;align-items:center;gap:.5rem}.cc-arrow{color:var(--cc-dropdown-arrow-color, #5F6368);transition:transform .2s;font-size:1.25rem}.cc-dropdown-trigger.open .cc-arrow{transform:rotate(180deg)}.cc-clear-btn{display:flex;align-items:center;justify-content:center;color:var(--cc-dropdown-arrow-color, #5F6368);cursor:pointer}.cc-clear-btn:hover{color:#202124}.cc-clear-btn .material-icons{font-size:1.125rem}.cc-dropdown-menu{position:absolute;top:100%;left:0;width:100%;background-color:#fff;border:1px solid #BDC1C6;border-radius:0 0 4px 4px;box-shadow:0 2px 4px #0000001a;z-index:1000;margin-top:2px;overflow:hidden;animation:fadeIn .1s ease-out}@keyframes fadeIn{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}.cc-search-container{padding:.5rem;border-bottom:1px solid var(--cc-dropdown-divider-color, #E0E0E0)}.cc-dropdown-search-input{width:100%;padding:.5rem;border:1px solid #BDC1C6;border-radius:4px;outline:none;box-sizing:border-box;font-size:.875rem}.cc-dropdown-search-input:focus{border-color:var(--cc-dropdown-focus-border-color, #1A73E8)}.cc-virtual-scroll{width:100%;max-height:240px}.cc-option{display:flex;align-items:center;padding:0 .75rem;height:40px;cursor:pointer;color:var(--cc-dropdown-color, #202124);font-size:var(--cc-dropdown-font-size, .875rem);transition:background-color .1s;box-sizing:border-box}.cc-option:hover,.cc-option.focused{background-color:#f1f3f4}.cc-option.selected{background-color:#e8f0fe;color:#1a73e8}.cc-option.disabled{opacity:.5;cursor:not-allowed;background-color:transparent}.cc-multi-check{margin-right:.5rem;color:var(--cc-dropdown-arrow-color, #5F6368);display:flex;align-items:center}.cc-multi-check .material-icons{font-size:1.25rem}.cc-option.selected .cc-multi-check{color:#1a73e8}.cc-option-icon-wrapper{margin-right:.5rem;display:flex;align-items:center}.cc-option-icon-wrapper .material-icons{font-size:1.25rem}.cc-option-img{width:1.25rem;height:1.25rem;object-fit:contain}.cc-option-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cc-single-check{margin-left:.5rem;color:#1a73e8;display:flex;align-items:center}.cc-single-check .material-icons{font-size:1.125rem}.cc-no-results{padding:.75rem;color:#80868b;text-align:center;font-size:.875rem}.cc-error-message{font-size:.75rem;color:var(--cc-dropdown-error-color, #D93025);margin-top:.25rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2$1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i2$1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i2$1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: ClickOutsideDirective, selector: "[libClickOutside]", outputs: ["libClickOutside"] }] });
|
|
1294
|
+
}
|
|
1295
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DropdownComponent, decorators: [{
|
|
1296
|
+
type: Component,
|
|
1297
|
+
args: [{ selector: 'lib-dropdown', standalone: false, providers: [
|
|
1298
|
+
{
|
|
1299
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1300
|
+
useExisting: forwardRef(() => DropdownComponent),
|
|
1301
|
+
multi: true
|
|
1302
|
+
}
|
|
1303
|
+
], template: "<div class=\"cc-dropdown-wrapper\" [ngStyle]=\"wrapperStyles\" libClickOutside (libClickOutside)=\"close()\">\r\n <!-- Label -->\r\n <label *ngIf=\"label\" class=\"cc-dropdown-label\" [ngStyle]=\"labelStyles\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <!-- Trigger -->\r\n <div class=\"cc-dropdown-trigger\" [class.disabled]=\"disabled\" [class.open]=\"isOpen\" [class.error]=\"errorMessage\"\r\n (click)=\"toggle()\" tabindex=\"0\" (keydown)=\"handleKeyboardEvent($event)\" [ngStyle]=\"fieldStyles\">\r\n\r\n <div class=\"cc-selected-value\" *ngIf=\"hasValue()\">\r\n {{ multiple ? value.length + ' ' + selectedSuffix : getSelectedLabel() }}\r\n </div>\r\n <div class=\"cc-placeholder\" *ngIf=\"!hasValue()\">{{ placeholder }}</div>\r\n\r\n <div class=\"cc-actions\">\r\n <span *ngIf=\"clearable && hasValue() && !disabled\" class=\"cc-clear-btn\" (click)=\"clearSelection($event)\"\r\n [attr.aria-label]=\"clearAriaLabel\">\r\n <span class=\"material-icons\">close</span>\r\n </span>\r\n <span class=\"cc-arrow material-icons\">expand_more</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Dropdown Menu -->\r\n <div class=\"cc-dropdown-menu\" *ngIf=\"isOpen\">\r\n <!-- Search -->\r\n <div class=\"cc-search-container\" *ngIf=\"searchable\">\r\n <input type=\"text\" #searchInput [placeholder]=\"searchPlaceholder\"\r\n (input)=\"onSearch($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\r\n class=\"cc-dropdown-search-input\" />\r\n </div>\r\n\r\n <!-- Options Virtual Scroll -->\r\n <cdk-virtual-scroll-viewport itemSize=\"40\" class=\"cc-virtual-scroll\"\r\n [style.height.px]=\"filteredOptions.length * 40 > 240 ? 240 : (filteredOptions.length * 40 || 40)\">\r\n\r\n <div *cdkVirtualFor=\"let option of filteredOptions; let i = index\" class=\"cc-option\"\r\n [class.selected]=\"isSelected(option)\" [class.focused]=\"i === focusedIndex\"\r\n [class.disabled]=\"option.disabled\" (click)=\"selectOption(option)\">\r\n\r\n <!-- Multi-select checkbox visual -->\r\n <span class=\"cc-multi-check\" *ngIf=\"multiple\">\r\n <span class=\"material-icons\" *ngIf=\"isSelected(option)\">check_box</span>\r\n <span class=\"material-icons\" *ngIf=\"!isSelected(option)\">check_box_outline_blank</span>\r\n </span>\r\n\r\n <!-- Icon -->\r\n <span class=\"cc-option-icon-wrapper\" *ngIf=\"option.icon\">\r\n <span class=\"material-icons\" *ngIf=\"getIconType(option.icon) === 'material'\">{{\r\n getIconValue(option.icon) }}</span>\r\n <i *ngIf=\"getIconType(option.icon) === 'fontawesome'\" [class]=\"getIconValue(option.icon)\"></i>\r\n <img *ngIf=\"getIconType(option.icon) === 'img'\" [src]=\"getIconValue(option.icon)\"\r\n class=\"cc-option-img\" alt=\"icon\" />\r\n </span>\r\n\r\n <span class=\"cc-option-label\">{{ option.label }}</span>\r\n\r\n <!-- Single-select check visual -->\r\n <span class=\"cc-single-check\" *ngIf=\"!multiple && isSelected(option)\">\r\n <span class=\"material-icons\">check</span>\r\n </span>\r\n </div>\r\n\r\n <div *ngIf=\"filteredOptions.length === 0\" class=\"cc-no-results\">{{ labels?.noResultsFound || 'No results\r\n found' }}</div>\r\n </cdk-virtual-scroll-viewport>\r\n </div>\r\n\r\n <!-- Error Message -->\r\n <div class=\"cc-error-message\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\r\n</div>", styles: [".cc-dropdown-wrapper{display:flex;flex-direction:column;width:100%;position:relative;font-family:var(--cc-dropdown-font-family, inherit);gap:var(--cc-dropdown-label-gap, .5rem)}.cc-dropdown-label{font-size:var(--cc-dropdown-font-size, .875rem);font-weight:var(--cc-dropdown-font-weight, 500);color:var(--cc-dropdown-label-color, #202124);margin:0;line-height:1.4}.cc-required{color:var(--cc-dropdown-required-color, #D93025);margin-left:.25rem}.cc-dropdown-trigger{display:flex;align-items:center;justify-content:space-between;width:100%;min-height:var(--cc-dropdown-height, 2.5rem);padding:var(--cc-dropdown-padding, .5rem .75rem);background-color:var(--cc-dropdown-bg, #FEFEFE);border:var(--cc-dropdown-border-width, 1px) solid var(--cc-dropdown-border-color, #BDC1C6);border-radius:var(--cc-dropdown-border-radius, .4375rem);cursor:pointer;-webkit-user-select:none;user-select:none;box-sizing:border-box;transition:all .2s}.cc-dropdown-trigger:focus{outline:none;border-color:var(--cc-dropdown-focus-border-color, #1A73E8)}.cc-dropdown-trigger.open{border-color:var(--cc-dropdown-focus-border-color, #1A73E8)}.cc-dropdown-trigger.error{border-color:var(--cc-dropdown-error-color, #D93025)}.cc-dropdown-trigger.disabled{background-color:var(--cc-dropdown-disabled-bg, #F1F3F4);cursor:not-allowed;color:var(--cc-dropdown-disabled-color, #80868B)}.cc-dropdown-trigger.disabled .cc-arrow,.cc-dropdown-trigger.disabled .cc-clear-btn{color:var(--cc-dropdown-disabled-color, #80868B)}.cc-selected-value{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--cc-dropdown-color, #202124);font-size:var(--cc-dropdown-font-size, .875rem);font-weight:var(--cc-dropdown-font-weight, 400)}.cc-placeholder{flex:1;color:var(--cc-dropdown-placeholder-color, #80868B);font-size:var(--cc-dropdown-font-size, .875rem)}.cc-actions{display:flex;align-items:center;gap:.5rem}.cc-arrow{color:var(--cc-dropdown-arrow-color, #5F6368);transition:transform .2s;font-size:1.25rem}.cc-dropdown-trigger.open .cc-arrow{transform:rotate(180deg)}.cc-clear-btn{display:flex;align-items:center;justify-content:center;color:var(--cc-dropdown-arrow-color, #5F6368);cursor:pointer}.cc-clear-btn:hover{color:#202124}.cc-clear-btn .material-icons{font-size:1.125rem}.cc-dropdown-menu{position:absolute;top:100%;left:0;width:100%;background-color:#fff;border:1px solid #BDC1C6;border-radius:0 0 4px 4px;box-shadow:0 2px 4px #0000001a;z-index:1000;margin-top:2px;overflow:hidden;animation:fadeIn .1s ease-out}@keyframes fadeIn{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}.cc-search-container{padding:.5rem;border-bottom:1px solid var(--cc-dropdown-divider-color, #E0E0E0)}.cc-dropdown-search-input{width:100%;padding:.5rem;border:1px solid #BDC1C6;border-radius:4px;outline:none;box-sizing:border-box;font-size:.875rem}.cc-dropdown-search-input:focus{border-color:var(--cc-dropdown-focus-border-color, #1A73E8)}.cc-virtual-scroll{width:100%;max-height:240px}.cc-option{display:flex;align-items:center;padding:0 .75rem;height:40px;cursor:pointer;color:var(--cc-dropdown-color, #202124);font-size:var(--cc-dropdown-font-size, .875rem);transition:background-color .1s;box-sizing:border-box}.cc-option:hover,.cc-option.focused{background-color:#f1f3f4}.cc-option.selected{background-color:#e8f0fe;color:#1a73e8}.cc-option.disabled{opacity:.5;cursor:not-allowed;background-color:transparent}.cc-multi-check{margin-right:.5rem;color:var(--cc-dropdown-arrow-color, #5F6368);display:flex;align-items:center}.cc-multi-check .material-icons{font-size:1.25rem}.cc-option.selected .cc-multi-check{color:#1a73e8}.cc-option-icon-wrapper{margin-right:.5rem;display:flex;align-items:center}.cc-option-icon-wrapper .material-icons{font-size:1.25rem}.cc-option-img{width:1.25rem;height:1.25rem;object-fit:contain}.cc-option-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cc-single-check{margin-left:.5rem;color:#1a73e8;display:flex;align-items:center}.cc-single-check .material-icons{font-size:1.125rem}.cc-no-results{padding:.75rem;color:#80868b;text-align:center;font-size:.875rem}.cc-error-message{font-size:.75rem;color:var(--cc-dropdown-error-color, #D93025);margin-top:.25rem}\n"] }]
|
|
1304
|
+
}], propDecorators: { config: [{
|
|
1305
|
+
type: Input
|
|
1306
|
+
}], labels: [{
|
|
1307
|
+
type: Input
|
|
1308
|
+
}], options: [{
|
|
1309
|
+
type: Input
|
|
1310
|
+
}], placeholder: [{
|
|
1311
|
+
type: Input
|
|
1312
|
+
}], label: [{
|
|
1313
|
+
type: Input
|
|
1314
|
+
}], multiple: [{
|
|
1315
|
+
type: Input
|
|
1316
|
+
}], searchable: [{
|
|
1317
|
+
type: Input
|
|
1318
|
+
}], clearable: [{
|
|
1319
|
+
type: Input
|
|
1320
|
+
}], disabled: [{
|
|
1321
|
+
type: Input
|
|
1322
|
+
}], required: [{
|
|
1323
|
+
type: Input
|
|
1324
|
+
}], errorMessage: [{
|
|
1325
|
+
type: Input
|
|
1326
|
+
}], width: [{
|
|
1327
|
+
type: Input
|
|
1328
|
+
}], height: [{
|
|
1329
|
+
type: Input
|
|
1330
|
+
}], borderRadius: [{
|
|
1331
|
+
type: Input
|
|
1332
|
+
}], fontSize: [{
|
|
1333
|
+
type: Input
|
|
1334
|
+
}], gap: [{
|
|
1335
|
+
type: Input
|
|
1336
|
+
}], fontFamily: [{
|
|
1337
|
+
type: Input
|
|
1338
|
+
}], labelColor: [{
|
|
1339
|
+
type: Input
|
|
1340
|
+
}], labelFontSize: [{
|
|
1341
|
+
type: Input
|
|
1342
|
+
}], labelFontWeight: [{
|
|
1343
|
+
type: Input
|
|
1344
|
+
}], backgroundColor: [{
|
|
1345
|
+
type: Input
|
|
1346
|
+
}], borderColor: [{
|
|
1347
|
+
type: Input
|
|
1348
|
+
}], borderWidth: [{
|
|
1349
|
+
type: Input
|
|
1350
|
+
}], padding: [{
|
|
1351
|
+
type: Input
|
|
1352
|
+
}], fontWeight: [{
|
|
1353
|
+
type: Input
|
|
1354
|
+
}], color: [{
|
|
1355
|
+
type: Input
|
|
1356
|
+
}], placeholderColor: [{
|
|
1357
|
+
type: Input
|
|
1358
|
+
}], focusBorderColor: [{
|
|
1359
|
+
type: Input
|
|
1360
|
+
}], errorColor: [{
|
|
1361
|
+
type: Input
|
|
1362
|
+
}], disabledBackgroundColor: [{
|
|
1363
|
+
type: Input
|
|
1364
|
+
}], disabledColor: [{
|
|
1365
|
+
type: Input
|
|
1366
|
+
}], boxShadow: [{
|
|
1367
|
+
type: Input
|
|
1368
|
+
}], selectionChange: [{
|
|
1369
|
+
type: Output
|
|
1370
|
+
}], viewport: [{
|
|
1371
|
+
type: ViewChild,
|
|
1372
|
+
args: [CdkVirtualScrollViewport]
|
|
1373
|
+
}], searchInput: [{
|
|
1374
|
+
type: ViewChild,
|
|
1375
|
+
args: ['searchInput']
|
|
1376
|
+
}], handleKeyboardEvent: [{
|
|
1377
|
+
type: HostListener,
|
|
1378
|
+
args: ['keydown', ['$event']]
|
|
1379
|
+
}] } });
|
|
1380
|
+
|
|
1381
|
+
class CheckboxComponent {
|
|
1382
|
+
config = {};
|
|
1383
|
+
labels;
|
|
1384
|
+
label = '';
|
|
1385
|
+
checked = false;
|
|
1386
|
+
disabled = false;
|
|
1387
|
+
required = false;
|
|
1388
|
+
indeterminate = false;
|
|
1389
|
+
options = [];
|
|
1390
|
+
labelPosition = 'after';
|
|
1391
|
+
color = '#007bff';
|
|
1392
|
+
borderRadius = '4px';
|
|
1393
|
+
value = null;
|
|
1394
|
+
errorMessage = '';
|
|
1395
|
+
// Style inputs
|
|
1396
|
+
width;
|
|
1397
|
+
height;
|
|
1398
|
+
fontSize;
|
|
1399
|
+
fontWeight;
|
|
1400
|
+
labelColor;
|
|
1401
|
+
labelFontSize;
|
|
1402
|
+
labelFontWeight;
|
|
1403
|
+
gap;
|
|
1404
|
+
fontFamily;
|
|
1405
|
+
backgroundColor;
|
|
1406
|
+
borderColor;
|
|
1407
|
+
borderWidth;
|
|
1408
|
+
padding;
|
|
1409
|
+
placeholderColor;
|
|
1410
|
+
focusBorderColor;
|
|
1411
|
+
errorColor;
|
|
1412
|
+
disabledBackgroundColor;
|
|
1413
|
+
disabledColor;
|
|
1414
|
+
boxShadow;
|
|
1415
|
+
size;
|
|
1416
|
+
checkedColor;
|
|
1417
|
+
uncheckedColor;
|
|
1418
|
+
groupLabelColor;
|
|
1419
|
+
groupLabelFontSize;
|
|
1420
|
+
groupLabelFontWeight;
|
|
1421
|
+
checkedChange = new EventEmitter();
|
|
1422
|
+
onChange = () => { };
|
|
1423
|
+
onTouched = () => { };
|
|
1424
|
+
ngOnInit() {
|
|
1425
|
+
this.updateFromConfig();
|
|
1426
|
+
this.updateFromLabels();
|
|
1427
|
+
if (this.isGroup) {
|
|
1428
|
+
this.value = this.options
|
|
1429
|
+
.filter(opt => opt.checked)
|
|
1430
|
+
.map(opt => opt.value);
|
|
1431
|
+
}
|
|
1432
|
+
else {
|
|
1433
|
+
this.value = this.checked;
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
ngOnChanges(changes) {
|
|
1437
|
+
if (changes['config']) {
|
|
1438
|
+
this.updateFromConfig();
|
|
1439
|
+
}
|
|
1440
|
+
if (changes['labels']) {
|
|
1441
|
+
this.updateFromLabels();
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
updateFromConfig() {
|
|
1445
|
+
if (this.config) {
|
|
1446
|
+
this.label = this.config.label ?? this.label;
|
|
1447
|
+
this.checked = this.config.checked ?? this.checked;
|
|
1448
|
+
this.disabled = this.config.disabled ?? this.disabled;
|
|
1449
|
+
this.required = this.config.required ?? this.required;
|
|
1450
|
+
this.indeterminate = this.config.indeterminate ?? this.indeterminate;
|
|
1451
|
+
this.options = this.config.options || this.options;
|
|
1452
|
+
this.labelPosition = this.config.labelPosition ?? this.labelPosition;
|
|
1453
|
+
this.color = this.config.color ?? this.color;
|
|
1454
|
+
this.borderRadius = this.config.borderRadius ?? this.borderRadius;
|
|
1455
|
+
this.size = this.config.size ?? this.size;
|
|
1456
|
+
this.checkedColor = this.config.checkedColor ?? this.checkedColor;
|
|
1457
|
+
this.uncheckedColor = this.config.uncheckedColor ?? this.uncheckedColor;
|
|
1458
|
+
this.groupLabelColor = this.config.groupLabelColor ?? this.groupLabelColor;
|
|
1459
|
+
this.groupLabelFontSize = this.config.groupLabelFontSize ?? this.groupLabelFontSize;
|
|
1460
|
+
this.groupLabelFontWeight = this.config.groupLabelFontWeight ?? this.groupLabelFontWeight;
|
|
1461
|
+
this.labelFontSize = this.config.labelFontSize ?? this.labelFontSize;
|
|
1462
|
+
this.labelFontWeight = this.config.labelFontWeight ?? this.labelFontWeight;
|
|
1463
|
+
this.labelColor = this.config.labelColor ?? this.labelColor;
|
|
1464
|
+
this.gap = this.config.gap ?? this.gap;
|
|
1465
|
+
this.fontFamily = this.config.fontFamily ?? this.fontFamily;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
updateFromLabels() {
|
|
1469
|
+
if (this.labels) {
|
|
1470
|
+
this.label = this.labels.label || this.label;
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
get isGroup() {
|
|
1474
|
+
return this.options && this.options.length > 0;
|
|
1475
|
+
}
|
|
1476
|
+
get requiredMarker() {
|
|
1477
|
+
return this.labels?.requiredMarker || '*';
|
|
1478
|
+
}
|
|
1479
|
+
writeValue(value) {
|
|
1480
|
+
if (this.isGroup) {
|
|
1481
|
+
this.value = Array.isArray(value) ? value : [];
|
|
1482
|
+
this.options.forEach(opt => {
|
|
1483
|
+
opt.checked = this.value.includes(opt.value);
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
else {
|
|
1487
|
+
this.value = !!value;
|
|
1488
|
+
this.checked = this.value;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
registerOnChange(fn) {
|
|
1492
|
+
this.onChange = fn;
|
|
1493
|
+
}
|
|
1494
|
+
registerOnTouched(fn) {
|
|
1495
|
+
this.onTouched = fn;
|
|
1496
|
+
}
|
|
1497
|
+
setDisabledState(isDisabled) {
|
|
1498
|
+
this.disabled = isDisabled;
|
|
1499
|
+
}
|
|
1500
|
+
onCheckboxChange(event) {
|
|
1501
|
+
const checked = event.target.checked;
|
|
1502
|
+
this.value = checked;
|
|
1503
|
+
this.checked = checked;
|
|
1504
|
+
this.onChange(this.value);
|
|
1505
|
+
this.onTouched();
|
|
1506
|
+
this.checkedChange.emit(this.value);
|
|
1507
|
+
}
|
|
1508
|
+
onGroupCheckboxChange(option, event) {
|
|
1509
|
+
const checked = event.target.checked;
|
|
1510
|
+
option.checked = checked;
|
|
1511
|
+
const valueArray = this.value;
|
|
1512
|
+
if (checked) {
|
|
1513
|
+
if (!valueArray.includes(option.value)) {
|
|
1514
|
+
this.value = [...valueArray, option.value];
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
else {
|
|
1518
|
+
this.value = valueArray.filter(v => v !== option.value);
|
|
1519
|
+
}
|
|
1520
|
+
this.onChange(this.value);
|
|
1521
|
+
this.onTouched();
|
|
1522
|
+
this.checkedChange.emit(this.value);
|
|
1523
|
+
}
|
|
1524
|
+
getStyleValue(value) {
|
|
1525
|
+
return value ? `${value}` : undefined;
|
|
1526
|
+
}
|
|
1527
|
+
get wrapperStyles() {
|
|
1528
|
+
return {
|
|
1529
|
+
'--cc-checkbox-font-family': this.getStyleValue(this.fontFamily),
|
|
1530
|
+
'--cc-checkbox-font-size': this.getStyleValue(this.fontSize),
|
|
1531
|
+
'--cc-checkbox-font-weight': this.getStyleValue(this.fontWeight),
|
|
1532
|
+
'--cc-checkbox-label-color': this.getStyleValue(this.labelColor),
|
|
1533
|
+
'--cc-checkbox-size': this.getStyleValue(this.size),
|
|
1534
|
+
'--cc-checkbox-checked-color': this.getStyleValue(this.checkedColor),
|
|
1535
|
+
'--cc-checkbox-unchecked-color': this.getStyleValue(this.uncheckedColor),
|
|
1536
|
+
'--cc-checkbox-disabled-color': this.getStyleValue(this.disabledColor),
|
|
1537
|
+
'--cc-checkbox-error-color': this.getStyleValue(this.errorColor),
|
|
1538
|
+
'--cc-checkbox-group-gap': this.getStyleValue(this.gap),
|
|
1539
|
+
'--cc-checkbox-group-label-color': this.getStyleValue(this.groupLabelColor),
|
|
1540
|
+
'--cc-checkbox-group-label-font-size': this.getStyleValue(this.groupLabelFontSize),
|
|
1541
|
+
'--cc-checkbox-group-label-font-weight': this.getStyleValue(this.groupLabelFontWeight),
|
|
1542
|
+
'--cc-checkbox-label-font-size': this.getStyleValue(this.labelFontSize),
|
|
1543
|
+
'--cc-checkbox-label-font-weight': this.getStyleValue(this.labelFontWeight),
|
|
1544
|
+
'--cc-checkbox-border-radius': this.getStyleValue(this.borderRadius)
|
|
1545
|
+
};
|
|
1546
|
+
}
|
|
1547
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1548
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: CheckboxComponent, isStandalone: false, selector: "lib-checkbox", inputs: { config: "config", labels: "labels", label: "label", checked: "checked", disabled: "disabled", required: "required", indeterminate: "indeterminate", options: "options", labelPosition: "labelPosition", color: "color", borderRadius: "borderRadius", value: "value", errorMessage: "errorMessage", width: "width", height: "height", fontSize: "fontSize", fontWeight: "fontWeight", labelColor: "labelColor", labelFontSize: "labelFontSize", labelFontWeight: "labelFontWeight", gap: "gap", fontFamily: "fontFamily", backgroundColor: "backgroundColor", borderColor: "borderColor", borderWidth: "borderWidth", padding: "padding", placeholderColor: "placeholderColor", focusBorderColor: "focusBorderColor", errorColor: "errorColor", disabledBackgroundColor: "disabledBackgroundColor", disabledColor: "disabledColor", boxShadow: "boxShadow", size: "size", checkedColor: "checkedColor", uncheckedColor: "uncheckedColor", groupLabelColor: "groupLabelColor", groupLabelFontSize: "groupLabelFontSize", groupLabelFontWeight: "groupLabelFontWeight" }, outputs: { checkedChange: "checkedChange" }, providers: [
|
|
1549
|
+
{
|
|
1550
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1551
|
+
useExisting: forwardRef(() => CheckboxComponent),
|
|
1552
|
+
multi: true
|
|
1553
|
+
}
|
|
1554
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-checkbox-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n\r\n <!-- Single Checkbox -->\r\n <label *ngIf=\"!isGroup\" class=\"cc-checkbox-label\" [class.label-before]=\"labelPosition === 'before'\"\r\n [class.disabled]=\"disabled\" [class.checked]=\"checked\">\r\n <input type=\"checkbox\" class=\"cc-native-checkbox\" [checked]=\"checked\" [disabled]=\"disabled\"\r\n [required]=\"required\" [indeterminate]=\"indeterminate\" (change)=\"onCheckboxChange($event)\" />\r\n <span class=\"cc-checkmark\"></span>\r\n <span class=\"cc-text\" *ngIf=\"label\">{{ label }}</span>\r\n </label>\r\n\r\n <!-- Checkbox Group -->\r\n <div *ngIf=\"isGroup\" class=\"cc-checkbox-group\">\r\n <label *ngIf=\"label\" class=\"cc-checkbox-group-label\" [class.label-before]=\"labelPosition === 'before'\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <label *ngFor=\"let option of options\" class=\"cc-checkbox-label\" [class.disabled]=\"disabled || option.disabled\"\r\n [class.checked]=\"option.checked\">\r\n <input type=\"checkbox\" class=\"cc-native-checkbox\" [checked]=\"option.checked\"\r\n [disabled]=\"disabled || option.disabled\" (change)=\"onGroupCheckboxChange(option, $event)\" />\r\n <span class=\"cc-checkmark\"></span>\r\n <span class=\"cc-text\">{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div class=\"cc-error-message\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\r\n</div>", styles: [".cc-checkbox-wrapper{display:flex;flex-direction:column;font-family:var(--cc-checkbox-font-family, inherit)}.cc-checkbox-label{display:inline-flex;align-items:center;position:relative;cursor:pointer;font-size:var(--cc-checkbox-label-font-size, var(--cc-checkbox-font-size, .875rem));font-weight:var(--cc-checkbox-label-font-weight, var(--cc-checkbox-font-weight, 400));color:var(--cc-checkbox-label-color, #202124);-webkit-user-select:none;user-select:none;margin-bottom:var(--cc-checkbox-margin-bottom, .5rem)}.cc-checkbox-label.label-before{flex-direction:row-reverse}.cc-checkbox-label.label-before .cc-checkmark{margin-right:0;margin-left:.5rem}.cc-checkbox-label.disabled{cursor:not-allowed;color:var(--cc-checkbox-disabled-color, #80868B)}.cc-checkbox-label.disabled .cc-checkmark{border-color:var(--cc-checkbox-disabled-color, #80868B);background-color:transparent}.cc-native-checkbox{position:absolute;opacity:0;cursor:pointer;height:0;width:0}.cc-native-checkbox:checked~.cc-checkmark{background-color:var(--cc-checkbox-checked-color, #1A73E8);border-color:var(--cc-checkbox-checked-color, #1A73E8)}.cc-native-checkbox:checked~.cc-checkmark:after{display:block}.cc-native-checkbox:disabled:checked~.cc-checkmark{background-color:var(--cc-checkbox-disabled-color, #80868B);border-color:var(--cc-checkbox-disabled-color, #80868B)}.cc-checkmark{position:relative;height:var(--cc-checkbox-size, 1.125rem);width:var(--cc-checkbox-size, 1.125rem);background-color:transparent;border:2px solid var(--cc-checkbox-unchecked-color, #BDC1C6);border-radius:var(--cc-checkbox-border-radius, 2px);transition:all .2s ease-in-out;margin-right:.5rem;flex-shrink:0}.cc-checkmark:after{content:\"\";position:absolute;display:none;left:50%;top:45%;width:30%;height:60%;border:solid white;border-width:0 2px 2px 0;transform:translate(-50%,-50%) rotate(45deg)}.cc-checkbox-group{display:flex;flex-direction:column;gap:var(--cc-checkbox-group-gap, .75rem)}.cc-checkbox-group-label{font-size:var(--cc-checkbox-group-label-font-size, .875rem);font-weight:var(--cc-checkbox-group-label-font-weight, 500);color:var(--cc-checkbox-group-label-color, #202124);margin-bottom:.5rem}.cc-required{color:var(--cc-checkbox-required-color, #D93025);margin-left:.25rem}.cc-error-message{font-size:.75rem;color:var(--cc-checkbox-error-color, #D93025);margin-top:.25rem}\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.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
1555
|
+
}
|
|
1556
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CheckboxComponent, decorators: [{
|
|
1557
|
+
type: Component,
|
|
1558
|
+
args: [{ selector: 'lib-checkbox', standalone: false, providers: [
|
|
1559
|
+
{
|
|
1560
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1561
|
+
useExisting: forwardRef(() => CheckboxComponent),
|
|
1562
|
+
multi: true
|
|
1563
|
+
}
|
|
1564
|
+
], template: "<div class=\"cc-checkbox-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n\r\n <!-- Single Checkbox -->\r\n <label *ngIf=\"!isGroup\" class=\"cc-checkbox-label\" [class.label-before]=\"labelPosition === 'before'\"\r\n [class.disabled]=\"disabled\" [class.checked]=\"checked\">\r\n <input type=\"checkbox\" class=\"cc-native-checkbox\" [checked]=\"checked\" [disabled]=\"disabled\"\r\n [required]=\"required\" [indeterminate]=\"indeterminate\" (change)=\"onCheckboxChange($event)\" />\r\n <span class=\"cc-checkmark\"></span>\r\n <span class=\"cc-text\" *ngIf=\"label\">{{ label }}</span>\r\n </label>\r\n\r\n <!-- Checkbox Group -->\r\n <div *ngIf=\"isGroup\" class=\"cc-checkbox-group\">\r\n <label *ngIf=\"label\" class=\"cc-checkbox-group-label\" [class.label-before]=\"labelPosition === 'before'\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <label *ngFor=\"let option of options\" class=\"cc-checkbox-label\" [class.disabled]=\"disabled || option.disabled\"\r\n [class.checked]=\"option.checked\">\r\n <input type=\"checkbox\" class=\"cc-native-checkbox\" [checked]=\"option.checked\"\r\n [disabled]=\"disabled || option.disabled\" (change)=\"onGroupCheckboxChange(option, $event)\" />\r\n <span class=\"cc-checkmark\"></span>\r\n <span class=\"cc-text\">{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div class=\"cc-error-message\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\r\n</div>", styles: [".cc-checkbox-wrapper{display:flex;flex-direction:column;font-family:var(--cc-checkbox-font-family, inherit)}.cc-checkbox-label{display:inline-flex;align-items:center;position:relative;cursor:pointer;font-size:var(--cc-checkbox-label-font-size, var(--cc-checkbox-font-size, .875rem));font-weight:var(--cc-checkbox-label-font-weight, var(--cc-checkbox-font-weight, 400));color:var(--cc-checkbox-label-color, #202124);-webkit-user-select:none;user-select:none;margin-bottom:var(--cc-checkbox-margin-bottom, .5rem)}.cc-checkbox-label.label-before{flex-direction:row-reverse}.cc-checkbox-label.label-before .cc-checkmark{margin-right:0;margin-left:.5rem}.cc-checkbox-label.disabled{cursor:not-allowed;color:var(--cc-checkbox-disabled-color, #80868B)}.cc-checkbox-label.disabled .cc-checkmark{border-color:var(--cc-checkbox-disabled-color, #80868B);background-color:transparent}.cc-native-checkbox{position:absolute;opacity:0;cursor:pointer;height:0;width:0}.cc-native-checkbox:checked~.cc-checkmark{background-color:var(--cc-checkbox-checked-color, #1A73E8);border-color:var(--cc-checkbox-checked-color, #1A73E8)}.cc-native-checkbox:checked~.cc-checkmark:after{display:block}.cc-native-checkbox:disabled:checked~.cc-checkmark{background-color:var(--cc-checkbox-disabled-color, #80868B);border-color:var(--cc-checkbox-disabled-color, #80868B)}.cc-checkmark{position:relative;height:var(--cc-checkbox-size, 1.125rem);width:var(--cc-checkbox-size, 1.125rem);background-color:transparent;border:2px solid var(--cc-checkbox-unchecked-color, #BDC1C6);border-radius:var(--cc-checkbox-border-radius, 2px);transition:all .2s ease-in-out;margin-right:.5rem;flex-shrink:0}.cc-checkmark:after{content:\"\";position:absolute;display:none;left:50%;top:45%;width:30%;height:60%;border:solid white;border-width:0 2px 2px 0;transform:translate(-50%,-50%) rotate(45deg)}.cc-checkbox-group{display:flex;flex-direction:column;gap:var(--cc-checkbox-group-gap, .75rem)}.cc-checkbox-group-label{font-size:var(--cc-checkbox-group-label-font-size, .875rem);font-weight:var(--cc-checkbox-group-label-font-weight, 500);color:var(--cc-checkbox-group-label-color, #202124);margin-bottom:.5rem}.cc-required{color:var(--cc-checkbox-required-color, #D93025);margin-left:.25rem}.cc-error-message{font-size:.75rem;color:var(--cc-checkbox-error-color, #D93025);margin-top:.25rem}\n"] }]
|
|
1565
|
+
}], propDecorators: { config: [{
|
|
1566
|
+
type: Input
|
|
1567
|
+
}], labels: [{
|
|
1568
|
+
type: Input
|
|
1569
|
+
}], label: [{
|
|
1570
|
+
type: Input
|
|
1571
|
+
}], checked: [{
|
|
1572
|
+
type: Input
|
|
1573
|
+
}], disabled: [{
|
|
1574
|
+
type: Input
|
|
1575
|
+
}], required: [{
|
|
1576
|
+
type: Input
|
|
1577
|
+
}], indeterminate: [{
|
|
1578
|
+
type: Input
|
|
1579
|
+
}], options: [{
|
|
1580
|
+
type: Input
|
|
1581
|
+
}], labelPosition: [{
|
|
1582
|
+
type: Input
|
|
1583
|
+
}], color: [{
|
|
1584
|
+
type: Input
|
|
1585
|
+
}], borderRadius: [{
|
|
1586
|
+
type: Input
|
|
1587
|
+
}], value: [{
|
|
1588
|
+
type: Input
|
|
1589
|
+
}], errorMessage: [{
|
|
1590
|
+
type: Input
|
|
1591
|
+
}], width: [{
|
|
1592
|
+
type: Input
|
|
1593
|
+
}], height: [{
|
|
1594
|
+
type: Input
|
|
1595
|
+
}], fontSize: [{
|
|
1596
|
+
type: Input
|
|
1597
|
+
}], fontWeight: [{
|
|
1598
|
+
type: Input
|
|
1599
|
+
}], labelColor: [{
|
|
1600
|
+
type: Input
|
|
1601
|
+
}], labelFontSize: [{
|
|
1602
|
+
type: Input
|
|
1603
|
+
}], labelFontWeight: [{
|
|
1604
|
+
type: Input
|
|
1605
|
+
}], gap: [{
|
|
1606
|
+
type: Input
|
|
1607
|
+
}], fontFamily: [{
|
|
1608
|
+
type: Input
|
|
1609
|
+
}], backgroundColor: [{
|
|
1610
|
+
type: Input
|
|
1611
|
+
}], borderColor: [{
|
|
1612
|
+
type: Input
|
|
1613
|
+
}], borderWidth: [{
|
|
1614
|
+
type: Input
|
|
1615
|
+
}], padding: [{
|
|
1616
|
+
type: Input
|
|
1617
|
+
}], placeholderColor: [{
|
|
1618
|
+
type: Input
|
|
1619
|
+
}], focusBorderColor: [{
|
|
1620
|
+
type: Input
|
|
1621
|
+
}], errorColor: [{
|
|
1622
|
+
type: Input
|
|
1623
|
+
}], disabledBackgroundColor: [{
|
|
1624
|
+
type: Input
|
|
1625
|
+
}], disabledColor: [{
|
|
1626
|
+
type: Input
|
|
1627
|
+
}], boxShadow: [{
|
|
1628
|
+
type: Input
|
|
1629
|
+
}], size: [{
|
|
1630
|
+
type: Input
|
|
1631
|
+
}], checkedColor: [{
|
|
1632
|
+
type: Input
|
|
1633
|
+
}], uncheckedColor: [{
|
|
1634
|
+
type: Input
|
|
1635
|
+
}], groupLabelColor: [{
|
|
1636
|
+
type: Input
|
|
1637
|
+
}], groupLabelFontSize: [{
|
|
1638
|
+
type: Input
|
|
1639
|
+
}], groupLabelFontWeight: [{
|
|
1640
|
+
type: Input
|
|
1641
|
+
}], checkedChange: [{
|
|
1642
|
+
type: Output
|
|
1643
|
+
}] } });
|
|
1644
|
+
|
|
1645
|
+
class RadioComponent {
|
|
1646
|
+
config;
|
|
1647
|
+
label = '';
|
|
1648
|
+
options = [];
|
|
1649
|
+
disabled = false;
|
|
1650
|
+
required = false;
|
|
1651
|
+
labelPosition = 'after';
|
|
1652
|
+
color = 'primary';
|
|
1653
|
+
layout = 'vertical';
|
|
1654
|
+
// i18n Labels
|
|
1655
|
+
labels = {};
|
|
1656
|
+
// Customization — Layout
|
|
1657
|
+
gap;
|
|
1658
|
+
// Customization — Colors
|
|
1659
|
+
labelColor;
|
|
1660
|
+
checkedColor;
|
|
1661
|
+
uncheckedColor;
|
|
1662
|
+
// Customization — Typography
|
|
1663
|
+
fontSize;
|
|
1664
|
+
fontWeight;
|
|
1665
|
+
fontFamily;
|
|
1666
|
+
// Customization — Group label
|
|
1667
|
+
groupLabelColor;
|
|
1668
|
+
groupLabelFontSize;
|
|
1669
|
+
groupLabelFontWeight;
|
|
1670
|
+
// Customization — States
|
|
1671
|
+
disabledColor;
|
|
1672
|
+
errorColor;
|
|
1673
|
+
// Customization — Size
|
|
1674
|
+
size;
|
|
1675
|
+
borderRadius;
|
|
1676
|
+
// Customization — Synonyms for Playground
|
|
1677
|
+
labelFontSize;
|
|
1678
|
+
labelFontWeight;
|
|
1679
|
+
selectionChange = new EventEmitter();
|
|
1680
|
+
value;
|
|
1681
|
+
uuid = `radio-group-${Math.random().toString(36).substr(2, 9)}`;
|
|
1682
|
+
onChange = () => { };
|
|
1683
|
+
onTouched = () => { };
|
|
1684
|
+
ngOnInit() {
|
|
1685
|
+
this.updateFromConfig();
|
|
1686
|
+
// i18n labels override
|
|
1687
|
+
if (this.labels) {
|
|
1688
|
+
this.label = this.labels.label || this.label;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
ngOnChanges(changes) {
|
|
1692
|
+
if (changes.config) {
|
|
1693
|
+
this.updateFromConfig();
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
updateFromConfig() {
|
|
1697
|
+
if (this.config) {
|
|
1698
|
+
this.label = this.config.label ?? this.label;
|
|
1699
|
+
this.options = this.config.options || this.options;
|
|
1700
|
+
this.disabled = this.config.disabled ?? this.disabled;
|
|
1701
|
+
this.required = this.config.required ?? this.required;
|
|
1702
|
+
this.labelPosition = this.config.labelPosition ?? this.labelPosition;
|
|
1703
|
+
this.color = this.config.color ?? this.color;
|
|
1704
|
+
this.layout = this.config.layout ?? this.layout;
|
|
1705
|
+
this.value = this.config.value;
|
|
1706
|
+
// Style mappings
|
|
1707
|
+
this.gap = this.config.gap ?? this.gap;
|
|
1708
|
+
this.labelColor = this.config.labelColor ?? this.labelColor;
|
|
1709
|
+
this.checkedColor = this.config.checkedColor ?? this.checkedColor;
|
|
1710
|
+
this.uncheckedColor = this.config.uncheckedColor ?? this.uncheckedColor;
|
|
1711
|
+
this.fontSize = this.config.fontSize ?? this.fontSize;
|
|
1712
|
+
this.fontWeight = this.config.fontWeight ?? this.fontWeight;
|
|
1713
|
+
this.fontFamily = this.config.fontFamily ?? this.fontFamily;
|
|
1714
|
+
this.groupLabelColor = this.config.groupLabelColor ?? this.groupLabelColor;
|
|
1715
|
+
this.groupLabelFontSize = this.config.groupLabelFontSize ?? this.groupLabelFontSize;
|
|
1716
|
+
this.groupLabelFontWeight = this.config.groupLabelFontWeight ?? this.groupLabelFontWeight;
|
|
1717
|
+
this.disabledColor = this.config.disabledColor ?? this.disabledColor;
|
|
1718
|
+
this.errorColor = this.config.errorColor ?? this.errorColor;
|
|
1719
|
+
this.size = this.config.size ?? this.size;
|
|
1720
|
+
this.borderRadius = this.config.borderRadius ?? this.borderRadius;
|
|
1721
|
+
this.labelFontSize = this.config.labelFontSize ?? this.labelFontSize;
|
|
1722
|
+
this.labelFontWeight = this.config.labelFontWeight ?? this.labelFontWeight;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
get requiredMarker() {
|
|
1726
|
+
return this.labels?.requiredMarker || '*';
|
|
1727
|
+
}
|
|
1728
|
+
writeValue(value) {
|
|
1729
|
+
this.value = value;
|
|
1730
|
+
}
|
|
1731
|
+
registerOnChange(fn) {
|
|
1732
|
+
this.onChange = fn;
|
|
1733
|
+
}
|
|
1734
|
+
registerOnTouched(fn) {
|
|
1735
|
+
this.onTouched = fn;
|
|
1736
|
+
}
|
|
1737
|
+
setDisabledState(isDisabled) {
|
|
1738
|
+
this.disabled = isDisabled;
|
|
1739
|
+
}
|
|
1740
|
+
onRadioChange(event) {
|
|
1741
|
+
this.value = event.target.value;
|
|
1742
|
+
this.onChange(this.value);
|
|
1743
|
+
this.onTouched();
|
|
1744
|
+
this.selectionChange.emit(this.value);
|
|
1745
|
+
}
|
|
1746
|
+
getStyleValue(value) {
|
|
1747
|
+
return value ? `${value}` : undefined;
|
|
1748
|
+
}
|
|
1749
|
+
get wrapperStyles() {
|
|
1750
|
+
return {
|
|
1751
|
+
'--cc-radio-font-family': this.getStyleValue(this.fontFamily),
|
|
1752
|
+
'--cc-radio-font-size': this.getStyleValue(this.fontSize || this.labelFontSize),
|
|
1753
|
+
'--cc-radio-font-weight': this.getStyleValue(this.fontWeight || this.labelFontWeight),
|
|
1754
|
+
'--cc-radio-label-color': this.getStyleValue(this.labelColor),
|
|
1755
|
+
'--cc-radio-size': this.getStyleValue(this.size),
|
|
1756
|
+
'--cc-radio-border-radius': this.getStyleValue(this.borderRadius),
|
|
1757
|
+
'--cc-radio-checked-color': this.getStyleValue(this.checkedColor),
|
|
1758
|
+
'--cc-radio-unchecked-color': this.getStyleValue(this.uncheckedColor),
|
|
1759
|
+
'--cc-radio-disabled-color': this.getStyleValue(this.disabledColor),
|
|
1760
|
+
'--cc-radio-error-color': this.getStyleValue(this.errorColor),
|
|
1761
|
+
'--cc-radio-group-gap': this.getStyleValue(this.gap),
|
|
1762
|
+
'--cc-radio-group-label-color': this.getStyleValue(this.groupLabelColor),
|
|
1763
|
+
'--cc-radio-group-label-font-size': this.getStyleValue(this.groupLabelFontSize),
|
|
1764
|
+
'--cc-radio-group-label-font-weight': this.getStyleValue(this.groupLabelFontWeight)
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: RadioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1768
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: RadioComponent, isStandalone: false, selector: "lib-radio", inputs: { config: "config", label: "label", options: "options", disabled: "disabled", required: "required", labelPosition: "labelPosition", color: "color", layout: "layout", labels: "labels", gap: "gap", labelColor: "labelColor", checkedColor: "checkedColor", uncheckedColor: "uncheckedColor", fontSize: "fontSize", fontWeight: "fontWeight", fontFamily: "fontFamily", groupLabelColor: "groupLabelColor", groupLabelFontSize: "groupLabelFontSize", groupLabelFontWeight: "groupLabelFontWeight", disabledColor: "disabledColor", errorColor: "errorColor", size: "size", borderRadius: "borderRadius", labelFontSize: "labelFontSize", labelFontWeight: "labelFontWeight" }, outputs: { selectionChange: "selectionChange" }, providers: [
|
|
1769
|
+
{
|
|
1770
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1771
|
+
useExisting: forwardRef(() => RadioComponent),
|
|
1772
|
+
multi: true
|
|
1773
|
+
}
|
|
1774
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-radio-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-radio-group-label\" [class.disabled]=\"disabled\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <div class=\"cc-radio-group\" [class.horizontal]=\"layout === 'horizontal'\" [class.vertical]=\"layout === 'vertical'\"\r\n role=\"radiogroup\">\r\n\r\n <label class=\"cc-radio-label\" *ngFor=\"let option of options; let i = index\"\r\n [class.disabled]=\"disabled || option.disabled\" [class.checked]=\"value === option.value\"\r\n [class.label-before]=\"labelPosition === 'before'\">\r\n\r\n <input type=\"radio\" [name]=\"uuid\" [value]=\"option.value\" [checked]=\"value === option.value\"\r\n [disabled]=\"disabled || option.disabled\" (change)=\"onRadioChange($event)\" class=\"cc-native-radio\"\r\n [id]=\"uuid + '-' + i\">\r\n\r\n <span class=\"cc-radio-circle\"></span>\r\n <span class=\"cc-text\">{{ option.label }}</span>\r\n </label>\r\n </div>\r\n</div>", styles: [".cc-radio-wrapper{display:block;width:100%;font-family:var(--cc-radio-font-family, inherit)}.cc-radio-group-label{display:block;font-size:var(--cc-radio-group-label-font-size, 14px);font-weight:var(--cc-radio-group-label-font-weight, 500);color:var(--cc-radio-group-label-color, #202124);margin-bottom:8px}.cc-radio-group{display:flex;gap:var(--cc-radio-group-gap, 12px)}.cc-radio-group.vertical{flex-direction:column}.cc-radio-group.horizontal{flex-direction:row;flex-wrap:wrap}.cc-radio-label{display:flex;align-items:center;cursor:pointer;font-size:var(--cc-radio-font-size, 14px);color:var(--cc-radio-label-color, #202124);-webkit-user-select:none;user-select:none;padding:4px 0}.cc-native-radio{position:absolute;left:-9999px}.cc-radio-circle{width:var(--cc-radio-size, 20px);height:var(--cc-radio-size, 20px);border:2px solid var(--cc-radio-unchecked-color, #5F6368);border-radius:var(--cc-radio-border-radius, 50%);margin-right:8px;flex-shrink:0;position:relative;background:#fff;box-sizing:border-box}.cc-radio-circle:after{content:\"\";width:calc(var(--cc-radio-size, 20px) * .5);height:calc(var(--cc-radio-size, 20px) * .5);background:var(--cc-radio-checked-color, #1A73E8);border-radius:var(--cc-radio-border-radius, 50%);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);transition:transform .2s}.cc-native-radio:checked+.cc-radio-circle{border-color:var(--cc-radio-checked-color, #1A73E8)}.cc-native-radio:checked+.cc-radio-circle:after{transform:translate(-50%,-50%) scale(1)}.cc-text{line-height:1.5}.cc-radio-label.disabled{opacity:.5;cursor:not-allowed}\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.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
1775
|
+
}
|
|
1776
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: RadioComponent, decorators: [{
|
|
1777
|
+
type: Component,
|
|
1778
|
+
args: [{ selector: 'lib-radio', standalone: false, providers: [
|
|
1779
|
+
{
|
|
1780
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1781
|
+
useExisting: forwardRef(() => RadioComponent),
|
|
1782
|
+
multi: true
|
|
1783
|
+
}
|
|
1784
|
+
], template: "<div class=\"cc-radio-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-radio-group-label\" [class.disabled]=\"disabled\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <div class=\"cc-radio-group\" [class.horizontal]=\"layout === 'horizontal'\" [class.vertical]=\"layout === 'vertical'\"\r\n role=\"radiogroup\">\r\n\r\n <label class=\"cc-radio-label\" *ngFor=\"let option of options; let i = index\"\r\n [class.disabled]=\"disabled || option.disabled\" [class.checked]=\"value === option.value\"\r\n [class.label-before]=\"labelPosition === 'before'\">\r\n\r\n <input type=\"radio\" [name]=\"uuid\" [value]=\"option.value\" [checked]=\"value === option.value\"\r\n [disabled]=\"disabled || option.disabled\" (change)=\"onRadioChange($event)\" class=\"cc-native-radio\"\r\n [id]=\"uuid + '-' + i\">\r\n\r\n <span class=\"cc-radio-circle\"></span>\r\n <span class=\"cc-text\">{{ option.label }}</span>\r\n </label>\r\n </div>\r\n</div>", styles: [".cc-radio-wrapper{display:block;width:100%;font-family:var(--cc-radio-font-family, inherit)}.cc-radio-group-label{display:block;font-size:var(--cc-radio-group-label-font-size, 14px);font-weight:var(--cc-radio-group-label-font-weight, 500);color:var(--cc-radio-group-label-color, #202124);margin-bottom:8px}.cc-radio-group{display:flex;gap:var(--cc-radio-group-gap, 12px)}.cc-radio-group.vertical{flex-direction:column}.cc-radio-group.horizontal{flex-direction:row;flex-wrap:wrap}.cc-radio-label{display:flex;align-items:center;cursor:pointer;font-size:var(--cc-radio-font-size, 14px);color:var(--cc-radio-label-color, #202124);-webkit-user-select:none;user-select:none;padding:4px 0}.cc-native-radio{position:absolute;left:-9999px}.cc-radio-circle{width:var(--cc-radio-size, 20px);height:var(--cc-radio-size, 20px);border:2px solid var(--cc-radio-unchecked-color, #5F6368);border-radius:var(--cc-radio-border-radius, 50%);margin-right:8px;flex-shrink:0;position:relative;background:#fff;box-sizing:border-box}.cc-radio-circle:after{content:\"\";width:calc(var(--cc-radio-size, 20px) * .5);height:calc(var(--cc-radio-size, 20px) * .5);background:var(--cc-radio-checked-color, #1A73E8);border-radius:var(--cc-radio-border-radius, 50%);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) scale(0);transition:transform .2s}.cc-native-radio:checked+.cc-radio-circle{border-color:var(--cc-radio-checked-color, #1A73E8)}.cc-native-radio:checked+.cc-radio-circle:after{transform:translate(-50%,-50%) scale(1)}.cc-text{line-height:1.5}.cc-radio-label.disabled{opacity:.5;cursor:not-allowed}\n"] }]
|
|
1785
|
+
}], propDecorators: { config: [{
|
|
1786
|
+
type: Input
|
|
1787
|
+
}], label: [{
|
|
1788
|
+
type: Input
|
|
1789
|
+
}], options: [{
|
|
1790
|
+
type: Input
|
|
1791
|
+
}], disabled: [{
|
|
1792
|
+
type: Input
|
|
1793
|
+
}], required: [{
|
|
1794
|
+
type: Input
|
|
1795
|
+
}], labelPosition: [{
|
|
1796
|
+
type: Input
|
|
1797
|
+
}], color: [{
|
|
1798
|
+
type: Input
|
|
1799
|
+
}], layout: [{
|
|
1800
|
+
type: Input
|
|
1801
|
+
}], labels: [{
|
|
1802
|
+
type: Input
|
|
1803
|
+
}], gap: [{
|
|
1804
|
+
type: Input
|
|
1805
|
+
}], labelColor: [{
|
|
1806
|
+
type: Input
|
|
1807
|
+
}], checkedColor: [{
|
|
1808
|
+
type: Input
|
|
1809
|
+
}], uncheckedColor: [{
|
|
1810
|
+
type: Input
|
|
1811
|
+
}], fontSize: [{
|
|
1812
|
+
type: Input
|
|
1813
|
+
}], fontWeight: [{
|
|
1814
|
+
type: Input
|
|
1815
|
+
}], fontFamily: [{
|
|
1816
|
+
type: Input
|
|
1817
|
+
}], groupLabelColor: [{
|
|
1818
|
+
type: Input
|
|
1819
|
+
}], groupLabelFontSize: [{
|
|
1820
|
+
type: Input
|
|
1821
|
+
}], groupLabelFontWeight: [{
|
|
1822
|
+
type: Input
|
|
1823
|
+
}], disabledColor: [{
|
|
1824
|
+
type: Input
|
|
1825
|
+
}], errorColor: [{
|
|
1826
|
+
type: Input
|
|
1827
|
+
}], size: [{
|
|
1828
|
+
type: Input
|
|
1829
|
+
}], borderRadius: [{
|
|
1830
|
+
type: Input
|
|
1831
|
+
}], labelFontSize: [{
|
|
1832
|
+
type: Input
|
|
1833
|
+
}], labelFontWeight: [{
|
|
1834
|
+
type: Input
|
|
1835
|
+
}], selectionChange: [{
|
|
1836
|
+
type: Output
|
|
1837
|
+
}] } });
|
|
1838
|
+
|
|
1839
|
+
class ToggleComponent {
|
|
1840
|
+
config;
|
|
1841
|
+
labels;
|
|
1842
|
+
label = '';
|
|
1843
|
+
checked = false;
|
|
1844
|
+
disabled = false;
|
|
1845
|
+
required = false;
|
|
1846
|
+
labelPosition = 'after';
|
|
1847
|
+
color = '#1A73E8';
|
|
1848
|
+
// Customization — Colors
|
|
1849
|
+
labelColor;
|
|
1850
|
+
uncheckedColor;
|
|
1851
|
+
checkedColor;
|
|
1852
|
+
thumbColor;
|
|
1853
|
+
checkedThumbColor;
|
|
1854
|
+
// Customization — Typography
|
|
1855
|
+
fontSize;
|
|
1856
|
+
fontWeight;
|
|
1857
|
+
fontFamily;
|
|
1858
|
+
// Customization — Size
|
|
1859
|
+
toggleWidth;
|
|
1860
|
+
toggleHeight;
|
|
1861
|
+
gap;
|
|
1862
|
+
// Customization — Slider
|
|
1863
|
+
sliderColor;
|
|
1864
|
+
// Customization — Label
|
|
1865
|
+
labelFontSize;
|
|
1866
|
+
labelFontWeight;
|
|
1867
|
+
// Customization — States
|
|
1868
|
+
disabledColor;
|
|
1869
|
+
toggleChange = new EventEmitter();
|
|
1870
|
+
value = false;
|
|
1871
|
+
onChange = () => { };
|
|
1872
|
+
onTouched = () => { };
|
|
1873
|
+
ngOnInit() {
|
|
1874
|
+
this.updateFromConfig();
|
|
1875
|
+
this.updateFromLabels();
|
|
1876
|
+
this.value = this.checked;
|
|
1877
|
+
}
|
|
1878
|
+
ngOnChanges(changes) {
|
|
1879
|
+
if (changes['config']) {
|
|
1880
|
+
this.updateFromConfig();
|
|
1881
|
+
}
|
|
1882
|
+
if (changes['labels']) {
|
|
1883
|
+
this.updateFromLabels();
|
|
1884
|
+
}
|
|
1885
|
+
if (changes['checked']) {
|
|
1886
|
+
this.value = this.checked;
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
updateFromConfig() {
|
|
1890
|
+
if (this.config) {
|
|
1891
|
+
this.label = this.config.label ?? this.label;
|
|
1892
|
+
this.checked = this.config.checked ?? this.checked;
|
|
1893
|
+
this.disabled = this.config.disabled ?? this.disabled;
|
|
1894
|
+
this.required = this.config.required ?? this.required;
|
|
1895
|
+
this.labelPosition = this.config.labelPosition ?? this.labelPosition;
|
|
1896
|
+
this.color = this.config.color ?? this.color;
|
|
1897
|
+
this.uncheckedColor = this.config.uncheckedColor ?? this.uncheckedColor;
|
|
1898
|
+
this.checkedColor = this.config.checkedColor ?? this.checkedColor;
|
|
1899
|
+
this.thumbColor = this.config.thumbColor ?? this.thumbColor;
|
|
1900
|
+
this.checkedThumbColor = this.config.checkedThumbColor ?? this.checkedThumbColor;
|
|
1901
|
+
this.fontSize = this.config.fontSize ?? this.fontSize;
|
|
1902
|
+
this.fontWeight = this.config.fontWeight ?? this.fontWeight;
|
|
1903
|
+
this.toggleWidth = this.config.toggleWidth ?? this.toggleWidth;
|
|
1904
|
+
this.toggleHeight = this.config.toggleHeight ?? this.toggleHeight;
|
|
1905
|
+
this.gap = this.config.gap ?? this.gap;
|
|
1906
|
+
this.fontFamily = this.config.fontFamily ?? this.fontFamily;
|
|
1907
|
+
this.labelColor = this.config.labelColor ?? this.labelColor;
|
|
1908
|
+
this.labelFontSize = this.config.labelFontSize ?? this.labelFontSize;
|
|
1909
|
+
this.labelFontWeight = this.config.labelFontWeight ?? this.labelFontWeight;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
updateFromLabels() {
|
|
1913
|
+
if (this.labels) {
|
|
1914
|
+
this.label = this.labels.label || this.label;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
writeValue(value) {
|
|
1918
|
+
this.value = !!value;
|
|
1919
|
+
this.checked = this.value;
|
|
1920
|
+
}
|
|
1921
|
+
registerOnChange(fn) {
|
|
1922
|
+
this.onChange = fn;
|
|
1923
|
+
}
|
|
1924
|
+
registerOnTouched(fn) {
|
|
1925
|
+
this.onTouched = fn;
|
|
1926
|
+
}
|
|
1927
|
+
setDisabledState(isDisabled) {
|
|
1928
|
+
this.disabled = isDisabled;
|
|
1929
|
+
}
|
|
1930
|
+
onToggleChange(event) {
|
|
1931
|
+
this.value = event.target.checked;
|
|
1932
|
+
this.checked = this.value;
|
|
1933
|
+
this.onChange(this.value);
|
|
1934
|
+
this.onTouched();
|
|
1935
|
+
this.toggleChange.emit(this.value);
|
|
1936
|
+
}
|
|
1937
|
+
getStyleValue(value) {
|
|
1938
|
+
return value ? `${value}` : undefined;
|
|
1939
|
+
}
|
|
1940
|
+
get wrapperStyles() {
|
|
1941
|
+
return {
|
|
1942
|
+
'--cc-toggle-font-family': this.getStyleValue(this.fontFamily),
|
|
1943
|
+
'--cc-toggle-font-size': this.getStyleValue(this.fontSize || this.labelFontSize),
|
|
1944
|
+
'--cc-toggle-font-weight': this.getStyleValue(this.fontWeight || this.labelFontWeight),
|
|
1945
|
+
'--cc-toggle-label-color': this.getStyleValue(this.labelColor),
|
|
1946
|
+
'--cc-toggle-width': this.getStyleValue(this.toggleWidth),
|
|
1947
|
+
'--cc-toggle-height': this.getStyleValue(this.toggleHeight),
|
|
1948
|
+
'--cc-toggle-gap': this.getStyleValue(this.gap),
|
|
1949
|
+
'--cc-toggle-unchecked-bg': this.getStyleValue(this.uncheckedColor),
|
|
1950
|
+
'--cc-toggle-checked-bg': this.getStyleValue(this.checkedColor || this.color),
|
|
1951
|
+
'--cc-toggle-thumb-color': this.getStyleValue(this.thumbColor || this.sliderColor),
|
|
1952
|
+
'--cc-toggle-checked-thumb-color': this.getStyleValue(this.checkedThumbColor),
|
|
1953
|
+
'--cc-toggle-disabled-color': this.getStyleValue(this.disabledColor)
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1957
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ToggleComponent, isStandalone: false, selector: "lib-toggle", inputs: { config: "config", labels: "labels", label: "label", checked: "checked", disabled: "disabled", required: "required", labelPosition: "labelPosition", color: "color", labelColor: "labelColor", uncheckedColor: "uncheckedColor", checkedColor: "checkedColor", thumbColor: "thumbColor", checkedThumbColor: "checkedThumbColor", fontSize: "fontSize", fontWeight: "fontWeight", fontFamily: "fontFamily", toggleWidth: "toggleWidth", toggleHeight: "toggleHeight", gap: "gap", sliderColor: "sliderColor", labelFontSize: "labelFontSize", labelFontWeight: "labelFontWeight", disabledColor: "disabledColor" }, outputs: { toggleChange: "toggleChange" }, providers: [
|
|
1958
|
+
{
|
|
1959
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1960
|
+
useExisting: forwardRef(() => ToggleComponent),
|
|
1961
|
+
multi: true
|
|
1962
|
+
}
|
|
1963
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-toggle-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label class=\"cc-toggle-label\" [class.label-before]=\"labelPosition === 'before'\" [class.disabled]=\"disabled\">\r\n\r\n <span class=\"cc-label-text\" *ngIf=\"label && labelPosition === 'before'\">{{ label }}</span>\r\n\r\n <span class=\"cc-toggle-switch\">\r\n <input type=\"checkbox\" class=\"cc-native-toggle\" [checked]=\"checked\" [disabled]=\"disabled\"\r\n (change)=\"onToggleChange($event)\" />\r\n <span class=\"cc-toggle-track\"></span>\r\n <span class=\"cc-toggle-thumb\"></span>\r\n </span>\r\n\r\n <span class=\"cc-label-text\" *ngIf=\"label && labelPosition === 'after'\">{{ label }}</span>\r\n </label>\r\n</div>", styles: [".cc-toggle-wrapper{display:flex;flex-direction:column;font-family:var(--cc-toggle-font-family, inherit)}.cc-toggle-label{display:inline-flex;align-items:center;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:var(--cc-toggle-font-size, .875rem);font-weight:var(--cc-toggle-font-weight, 400);color:var(--cc-toggle-label-color, #202124);gap:.5rem}.cc-toggle-label.disabled{cursor:not-allowed;color:var(--cc-toggle-disabled-color, #80868B)}.cc-toggle-label.disabled .cc-toggle-track{background-color:var(--cc-toggle-disabled-color, #E0E0E0);opacity:.5}.cc-toggle-label.disabled .cc-toggle-thumb{background-color:#bdbdbd}.cc-toggle-switch{position:relative;width:var(--cc-toggle-width, 2.25rem);height:var(--cc-toggle-height, 1.25rem)}.cc-native-toggle{position:absolute;opacity:0;width:0;height:0}.cc-native-toggle:checked~.cc-toggle-track{background-color:var(--cc-toggle-checked-bg, #1A73E8)}.cc-native-toggle:checked~.cc-toggle-thumb{left:calc(100% - var(--cc-toggle-height, 1.25rem) + 2px);background-color:var(--cc-toggle-checked-thumb-color, #FEFEFE)}.cc-toggle-track{position:absolute;inset:0;background-color:var(--cc-toggle-unchecked-bg, #BDC1C6);border-radius:1rem;transition:.2s}.cc-toggle-thumb{position:absolute;top:50%;left:2px;width:calc(var(--cc-toggle-height, 1.25rem) - 4px);height:calc(var(--cc-toggle-height, 1.25rem) - 4px);transform:translateY(-50%);background-color:var(--cc-toggle-thumb-color, #FEFEFE);border-radius:50%;transition:.2s;box-shadow:0 1px 3px #0003}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
1964
|
+
}
|
|
1965
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ToggleComponent, decorators: [{
|
|
1966
|
+
type: Component,
|
|
1967
|
+
args: [{ selector: 'lib-toggle', standalone: false, providers: [
|
|
1968
|
+
{
|
|
1969
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1970
|
+
useExisting: forwardRef(() => ToggleComponent),
|
|
1971
|
+
multi: true
|
|
1972
|
+
}
|
|
1973
|
+
], template: "<div class=\"cc-toggle-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label class=\"cc-toggle-label\" [class.label-before]=\"labelPosition === 'before'\" [class.disabled]=\"disabled\">\r\n\r\n <span class=\"cc-label-text\" *ngIf=\"label && labelPosition === 'before'\">{{ label }}</span>\r\n\r\n <span class=\"cc-toggle-switch\">\r\n <input type=\"checkbox\" class=\"cc-native-toggle\" [checked]=\"checked\" [disabled]=\"disabled\"\r\n (change)=\"onToggleChange($event)\" />\r\n <span class=\"cc-toggle-track\"></span>\r\n <span class=\"cc-toggle-thumb\"></span>\r\n </span>\r\n\r\n <span class=\"cc-label-text\" *ngIf=\"label && labelPosition === 'after'\">{{ label }}</span>\r\n </label>\r\n</div>", styles: [".cc-toggle-wrapper{display:flex;flex-direction:column;font-family:var(--cc-toggle-font-family, inherit)}.cc-toggle-label{display:inline-flex;align-items:center;cursor:pointer;-webkit-user-select:none;user-select:none;font-size:var(--cc-toggle-font-size, .875rem);font-weight:var(--cc-toggle-font-weight, 400);color:var(--cc-toggle-label-color, #202124);gap:.5rem}.cc-toggle-label.disabled{cursor:not-allowed;color:var(--cc-toggle-disabled-color, #80868B)}.cc-toggle-label.disabled .cc-toggle-track{background-color:var(--cc-toggle-disabled-color, #E0E0E0);opacity:.5}.cc-toggle-label.disabled .cc-toggle-thumb{background-color:#bdbdbd}.cc-toggle-switch{position:relative;width:var(--cc-toggle-width, 2.25rem);height:var(--cc-toggle-height, 1.25rem)}.cc-native-toggle{position:absolute;opacity:0;width:0;height:0}.cc-native-toggle:checked~.cc-toggle-track{background-color:var(--cc-toggle-checked-bg, #1A73E8)}.cc-native-toggle:checked~.cc-toggle-thumb{left:calc(100% - var(--cc-toggle-height, 1.25rem) + 2px);background-color:var(--cc-toggle-checked-thumb-color, #FEFEFE)}.cc-toggle-track{position:absolute;inset:0;background-color:var(--cc-toggle-unchecked-bg, #BDC1C6);border-radius:1rem;transition:.2s}.cc-toggle-thumb{position:absolute;top:50%;left:2px;width:calc(var(--cc-toggle-height, 1.25rem) - 4px);height:calc(var(--cc-toggle-height, 1.25rem) - 4px);transform:translateY(-50%);background-color:var(--cc-toggle-thumb-color, #FEFEFE);border-radius:50%;transition:.2s;box-shadow:0 1px 3px #0003}\n"] }]
|
|
1974
|
+
}], propDecorators: { config: [{
|
|
1975
|
+
type: Input
|
|
1976
|
+
}], labels: [{
|
|
1977
|
+
type: Input
|
|
1978
|
+
}], label: [{
|
|
1979
|
+
type: Input
|
|
1980
|
+
}], checked: [{
|
|
1981
|
+
type: Input
|
|
1982
|
+
}], disabled: [{
|
|
1983
|
+
type: Input
|
|
1984
|
+
}], required: [{
|
|
1985
|
+
type: Input
|
|
1986
|
+
}], labelPosition: [{
|
|
1987
|
+
type: Input
|
|
1988
|
+
}], color: [{
|
|
1989
|
+
type: Input
|
|
1990
|
+
}], labelColor: [{
|
|
1991
|
+
type: Input
|
|
1992
|
+
}], uncheckedColor: [{
|
|
1993
|
+
type: Input
|
|
1994
|
+
}], checkedColor: [{
|
|
1995
|
+
type: Input
|
|
1996
|
+
}], thumbColor: [{
|
|
1997
|
+
type: Input
|
|
1998
|
+
}], checkedThumbColor: [{
|
|
1999
|
+
type: Input
|
|
2000
|
+
}], fontSize: [{
|
|
2001
|
+
type: Input
|
|
2002
|
+
}], fontWeight: [{
|
|
2003
|
+
type: Input
|
|
2004
|
+
}], fontFamily: [{
|
|
2005
|
+
type: Input
|
|
2006
|
+
}], toggleWidth: [{
|
|
2007
|
+
type: Input
|
|
2008
|
+
}], toggleHeight: [{
|
|
2009
|
+
type: Input
|
|
2010
|
+
}], gap: [{
|
|
2011
|
+
type: Input
|
|
2012
|
+
}], sliderColor: [{
|
|
2013
|
+
type: Input
|
|
2014
|
+
}], labelFontSize: [{
|
|
2015
|
+
type: Input
|
|
2016
|
+
}], labelFontWeight: [{
|
|
2017
|
+
type: Input
|
|
2018
|
+
}], disabledColor: [{
|
|
2019
|
+
type: Input
|
|
2020
|
+
}], toggleChange: [{
|
|
2021
|
+
type: Output
|
|
2022
|
+
}] } });
|
|
2023
|
+
|
|
2024
|
+
class DatepickerComponent {
|
|
2025
|
+
config;
|
|
2026
|
+
labels;
|
|
2027
|
+
label = '';
|
|
2028
|
+
placeholder = '';
|
|
2029
|
+
disabled = false;
|
|
2030
|
+
required = false;
|
|
2031
|
+
minDate; // Support string for native input
|
|
2032
|
+
maxDate; // Support string for native input
|
|
2033
|
+
isRange = false;
|
|
2034
|
+
startView = 'month';
|
|
2035
|
+
value = null;
|
|
2036
|
+
startDate;
|
|
2037
|
+
endDate;
|
|
2038
|
+
errorMessage = '';
|
|
2039
|
+
// Style inputs
|
|
2040
|
+
width;
|
|
2041
|
+
height;
|
|
2042
|
+
borderRadius;
|
|
2043
|
+
fontSize;
|
|
2044
|
+
gap;
|
|
2045
|
+
fontFamily;
|
|
2046
|
+
labelColor;
|
|
2047
|
+
labelFontSize;
|
|
2048
|
+
labelFontWeight;
|
|
2049
|
+
backgroundColor;
|
|
2050
|
+
borderColor;
|
|
2051
|
+
borderWidth;
|
|
2052
|
+
padding;
|
|
2053
|
+
fontWeight;
|
|
2054
|
+
color;
|
|
2055
|
+
placeholderColor;
|
|
2056
|
+
focusBorderColor;
|
|
2057
|
+
errorColor;
|
|
2058
|
+
disabledBackgroundColor;
|
|
2059
|
+
disabledColor;
|
|
2060
|
+
boxShadow;
|
|
2061
|
+
dateChange = new EventEmitter();
|
|
2062
|
+
onChange = () => { };
|
|
2063
|
+
onTouched = () => { };
|
|
2064
|
+
focused = false;
|
|
2065
|
+
ngOnInit() {
|
|
2066
|
+
this.updateFromConfig();
|
|
2067
|
+
this.updateFromLabels();
|
|
2068
|
+
}
|
|
2069
|
+
ngOnChanges(changes) {
|
|
2070
|
+
if (changes['config']) {
|
|
2071
|
+
this.updateFromConfig();
|
|
2072
|
+
}
|
|
2073
|
+
if (changes['labels']) {
|
|
2074
|
+
this.updateFromLabels();
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
updateFromConfig() {
|
|
2078
|
+
if (this.config) {
|
|
2079
|
+
this.label = this.config.label ?? this.label;
|
|
2080
|
+
this.placeholder = this.config.placeholder ?? this.placeholder;
|
|
2081
|
+
this.disabled = this.config.disabled ?? this.disabled;
|
|
2082
|
+
this.required = this.config.required ?? this.required;
|
|
2083
|
+
this.minDate = this.config.minDate ?? this.minDate;
|
|
2084
|
+
this.maxDate = this.config.maxDate ?? this.maxDate;
|
|
2085
|
+
this.isRange = this.config.isRange ?? this.isRange;
|
|
2086
|
+
this.width = this.config.width ?? this.width;
|
|
2087
|
+
this.borderRadius = this.config.borderRadius ?? this.borderRadius;
|
|
2088
|
+
this.fontSize = this.config.fontSize ?? this.fontSize;
|
|
2089
|
+
this.errorMessage = this.config.errorMessage ?? this.errorMessage;
|
|
2090
|
+
this.gap = this.config.gap ?? this.gap;
|
|
2091
|
+
this.fontFamily = this.config.fontFamily ?? this.fontFamily;
|
|
2092
|
+
this.labelColor = this.config.labelColor ?? this.labelColor;
|
|
2093
|
+
this.labelFontSize = this.config.labelFontSize ?? this.labelFontSize;
|
|
2094
|
+
this.labelFontWeight = this.config.labelFontWeight ?? this.labelFontWeight;
|
|
2095
|
+
this.backgroundColor = this.config.backgroundColor ?? this.backgroundColor;
|
|
2096
|
+
this.borderColor = this.config.borderColor ?? this.borderColor;
|
|
2097
|
+
this.borderWidth = this.config.borderWidth ?? this.borderWidth;
|
|
2098
|
+
this.padding = this.config.padding ?? this.padding;
|
|
2099
|
+
this.fontWeight = this.config.fontWeight ?? this.fontWeight;
|
|
2100
|
+
this.color = this.config.color ?? this.color;
|
|
2101
|
+
this.placeholderColor = this.config.placeholderColor ?? this.placeholderColor;
|
|
2102
|
+
this.focusBorderColor = this.config.focusBorderColor ?? this.focusBorderColor;
|
|
2103
|
+
this.errorColor = this.config.errorColor ?? this.errorColor;
|
|
2104
|
+
this.disabledBackgroundColor = this.config.disabledBackgroundColor ?? this.disabledBackgroundColor;
|
|
2105
|
+
this.disabledColor = this.config.disabledColor ?? this.disabledColor;
|
|
2106
|
+
this.boxShadow = this.config.boxShadow ?? this.boxShadow;
|
|
2107
|
+
this.height = this.config.height ?? this.height;
|
|
2108
|
+
if (this.config.value !== undefined) {
|
|
2109
|
+
this.value = this.config.value;
|
|
2110
|
+
}
|
|
2111
|
+
if (this.config.startDate) {
|
|
2112
|
+
this.startDate = this.config.startDate;
|
|
2113
|
+
}
|
|
2114
|
+
if (this.config.endDate) {
|
|
2115
|
+
this.endDate = this.config.endDate;
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
updateFromLabels() {
|
|
2120
|
+
if (this.labels) {
|
|
2121
|
+
this.label = this.labels.label || this.label;
|
|
2122
|
+
this.placeholder = this.labels.placeholder || this.placeholder;
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
get requiredMarker() {
|
|
2126
|
+
return this.labels?.requiredMarker || '*';
|
|
2127
|
+
}
|
|
2128
|
+
get startDateLabel() {
|
|
2129
|
+
return this.labels?.startDateLabel || 'Start Date';
|
|
2130
|
+
}
|
|
2131
|
+
get endDateLabel() {
|
|
2132
|
+
return this.labels?.endDateLabel || 'End Date';
|
|
2133
|
+
}
|
|
2134
|
+
// Helper to format Date or string to YYYY-MM-DD for native input
|
|
2135
|
+
formatDate(date) {
|
|
2136
|
+
if (!date)
|
|
2137
|
+
return '';
|
|
2138
|
+
if (typeof date === 'string')
|
|
2139
|
+
return date; // Assume already formatted or ISO
|
|
2140
|
+
try {
|
|
2141
|
+
return date.toISOString().split('T')[0];
|
|
2142
|
+
}
|
|
2143
|
+
catch (e) {
|
|
2144
|
+
return '';
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
get formattedValue() {
|
|
2148
|
+
return this.formatDate(this.value);
|
|
2149
|
+
}
|
|
2150
|
+
get formattedStartDate() {
|
|
2151
|
+
return this.formatDate(this.startDate);
|
|
2152
|
+
}
|
|
2153
|
+
get formattedEndDate() {
|
|
2154
|
+
return this.formatDate(this.endDate);
|
|
2155
|
+
}
|
|
2156
|
+
get formattedMin() {
|
|
2157
|
+
return this.formatDate(this.minDate);
|
|
2158
|
+
}
|
|
2159
|
+
get formattedMax() {
|
|
2160
|
+
return this.formatDate(this.maxDate);
|
|
2161
|
+
}
|
|
2162
|
+
writeValue(value) {
|
|
2163
|
+
if (this.isRange && value && typeof value === 'object' && 'start' in value) {
|
|
2164
|
+
this.startDate = value.start;
|
|
2165
|
+
this.endDate = value.end;
|
|
2166
|
+
}
|
|
2167
|
+
else {
|
|
2168
|
+
this.value = value;
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
registerOnChange(fn) {
|
|
2172
|
+
this.onChange = fn;
|
|
2173
|
+
}
|
|
2174
|
+
registerOnTouched(fn) {
|
|
2175
|
+
this.onTouched = fn;
|
|
2176
|
+
}
|
|
2177
|
+
setDisabledState(isDisabled) {
|
|
2178
|
+
this.disabled = isDisabled;
|
|
2179
|
+
}
|
|
2180
|
+
onDateInput(event) {
|
|
2181
|
+
const value = event.target.value;
|
|
2182
|
+
this.value = value; // Keep as string or convert if needed
|
|
2183
|
+
this.onChange(this.value);
|
|
2184
|
+
this.dateChange.emit(this.value);
|
|
2185
|
+
}
|
|
2186
|
+
onBlur() {
|
|
2187
|
+
this.focused = false;
|
|
2188
|
+
this.onTouched();
|
|
2189
|
+
}
|
|
2190
|
+
onFocus() {
|
|
2191
|
+
this.focused = true;
|
|
2192
|
+
}
|
|
2193
|
+
onRangeStartInput(event) {
|
|
2194
|
+
this.startDate = event.target.value;
|
|
2195
|
+
this.updateRangeValue();
|
|
2196
|
+
}
|
|
2197
|
+
onRangeEndInput(event) {
|
|
2198
|
+
this.endDate = event.target.value;
|
|
2199
|
+
this.updateRangeValue();
|
|
2200
|
+
}
|
|
2201
|
+
updateRangeValue() {
|
|
2202
|
+
const rangeValue = { start: this.startDate, end: this.endDate };
|
|
2203
|
+
this.onChange(rangeValue);
|
|
2204
|
+
this.dateChange.emit(rangeValue);
|
|
2205
|
+
}
|
|
2206
|
+
getStyleValue(value) {
|
|
2207
|
+
return value ? `${value}` : undefined;
|
|
2208
|
+
}
|
|
2209
|
+
get wrapperStyles() {
|
|
2210
|
+
return {
|
|
2211
|
+
'width': this.getStyleValue(this.width),
|
|
2212
|
+
'--cc-datepicker-label-gap': this.getStyleValue(this.gap),
|
|
2213
|
+
'--cc-datepicker-font-family': this.getStyleValue(this.fontFamily)
|
|
2214
|
+
};
|
|
2215
|
+
}
|
|
2216
|
+
get labelStyles() {
|
|
2217
|
+
return {
|
|
2218
|
+
'--cc-datepicker-label-color': this.getStyleValue(this.labelColor),
|
|
2219
|
+
'--cc-datepicker-label-font-size': this.getStyleValue(this.labelFontSize),
|
|
2220
|
+
'--cc-datepicker-label-font-weight': this.getStyleValue(this.labelFontWeight)
|
|
2221
|
+
};
|
|
2222
|
+
}
|
|
2223
|
+
get fieldStyles() {
|
|
2224
|
+
return {
|
|
2225
|
+
'--cc-datepicker-bg': this.getStyleValue(this.backgroundColor),
|
|
2226
|
+
'--cc-datepicker-border-radius': this.getStyleValue(this.borderRadius),
|
|
2227
|
+
'--cc-datepicker-border-color': this.getStyleValue(this.borderColor),
|
|
2228
|
+
'--cc-datepicker-border-width': this.getStyleValue(this.borderWidth),
|
|
2229
|
+
'--cc-datepicker-height': this.getStyleValue(this.height),
|
|
2230
|
+
'--cc-datepicker-padding': this.getStyleValue(this.padding),
|
|
2231
|
+
'--cc-datepicker-font-size': this.getStyleValue(this.fontSize),
|
|
2232
|
+
'--cc-datepicker-font-weight': this.getStyleValue(this.fontWeight),
|
|
2233
|
+
'--cc-datepicker-color': this.getStyleValue(this.color),
|
|
2234
|
+
'--cc-datepicker-placeholder-color': this.getStyleValue(this.placeholderColor),
|
|
2235
|
+
'--cc-datepicker-focus-border-color': this.getStyleValue(this.focusBorderColor),
|
|
2236
|
+
'--cc-datepicker-error-color': this.getStyleValue(this.errorColor),
|
|
2237
|
+
'--cc-datepicker-disabled-bg': this.getStyleValue(this.disabledBackgroundColor),
|
|
2238
|
+
'--cc-datepicker-disabled-color': this.getStyleValue(this.disabledColor),
|
|
2239
|
+
'box-shadow': this.getStyleValue(this.boxShadow)
|
|
2240
|
+
};
|
|
2241
|
+
}
|
|
2242
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2243
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: DatepickerComponent, isStandalone: false, selector: "lib-datepicker", inputs: { config: "config", labels: "labels", label: "label", placeholder: "placeholder", disabled: "disabled", required: "required", minDate: "minDate", maxDate: "maxDate", isRange: "isRange", startView: "startView", value: "value", startDate: "startDate", endDate: "endDate", errorMessage: "errorMessage", width: "width", height: "height", borderRadius: "borderRadius", fontSize: "fontSize", gap: "gap", fontFamily: "fontFamily", labelColor: "labelColor", labelFontSize: "labelFontSize", labelFontWeight: "labelFontWeight", backgroundColor: "backgroundColor", borderColor: "borderColor", borderWidth: "borderWidth", padding: "padding", fontWeight: "fontWeight", color: "color", placeholderColor: "placeholderColor", focusBorderColor: "focusBorderColor", errorColor: "errorColor", disabledBackgroundColor: "disabledBackgroundColor", disabledColor: "disabledColor", boxShadow: "boxShadow" }, outputs: { dateChange: "dateChange" }, providers: [
|
|
2244
|
+
{
|
|
2245
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2246
|
+
useExisting: forwardRef(() => DatepickerComponent),
|
|
2247
|
+
multi: true
|
|
2248
|
+
}
|
|
2249
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-datepicker-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-datepicker-label\" [ngStyle]=\"labelStyles\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <!-- Single Date Picker -->\r\n <div *ngIf=\"!isRange\" class=\"cc-datepicker-field\" [class.focused]=\"focused\" [class.disabled]=\"disabled\"\r\n [class.error]=\"errorMessage\" [ngStyle]=\"fieldStyles\">\r\n\r\n <input type=\"date\" class=\"cc-datepicker-input\" #dateInput [value]=\"formattedValue\" [disabled]=\"disabled\"\r\n [required]=\"required\" [min]=\"formattedMin\" [max]=\"formattedMax\" [placeholder]=\"placeholder\"\r\n (input)=\"onDateInput($event)\" (blur)=\"onBlur()\" (focus)=\"onFocus()\" (click)=\"dateInput.showPicker()\" />\r\n\r\n <span class=\"cc-datepicker-icon material-icons\" (click)=\"dateInput.showPicker()\">calendar_today</span>\r\n </div>\r\n\r\n <!-- Range Date Picker -->\r\n <div *ngIf=\"isRange\" class=\"cc-datepicker-range\">\r\n <!-- Start Date -->\r\n <div class=\"cc-datepicker-subfield\">\r\n <label class=\"cc-datepicker-sublabel\">{{ startDateLabel }}</label>\r\n <div class=\"cc-datepicker-field\" [class.disabled]=\"disabled\" [ngStyle]=\"fieldStyles\">\r\n <input type=\"date\" class=\"cc-datepicker-input\" [value]=\"formattedStartDate\" [disabled]=\"disabled\"\r\n [required]=\"required\" [min]=\"formattedMin\" [max]=\"formattedEndDate || formattedMax\"\r\n (input)=\"onRangeStartInput($event)\" />\r\n </div>\r\n </div>\r\n\r\n <!-- End Date -->\r\n <div class=\"cc-datepicker-subfield\">\r\n <label class=\"cc-datepicker-sublabel\">{{ endDateLabel }}</label>\r\n <div class=\"cc-datepicker-field\" [class.disabled]=\"disabled\" [ngStyle]=\"fieldStyles\">\r\n <input type=\"date\" class=\"cc-datepicker-input\" [value]=\"formattedEndDate\" [disabled]=\"disabled\"\r\n [required]=\"required\" [min]=\"formattedStartDate || formattedMin\" [max]=\"formattedMax\"\r\n (input)=\"onRangeEndInput($event)\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"cc-error-message\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\r\n</div>", styles: [".cc-datepicker-wrapper{display:flex;flex-direction:column;gap:var(--cc-datepicker-label-gap, .5rem);width:100%;font-family:var(--cc-datepicker-font-family, inherit)}.cc-datepicker-label{font-size:var(--cc-datepicker-label-font-size, .875rem);font-weight:var(--cc-datepicker-label-font-weight, 500);color:var(--cc-datepicker-label-color, #202124);margin:0;line-height:1.4}.cc-required{color:var(--cc-datepicker-required-color, #D93025);margin-left:.25rem}.cc-datepicker-field{display:flex;align-items:center;width:100%;box-sizing:border-box;background-color:var(--cc-datepicker-bg, #FEFEFE);border:var(--cc-datepicker-border-width, 1px) solid var(--cc-datepicker-border-color, #BDC1C6);border-radius:var(--cc-datepicker-border-radius, .4375rem);padding:var(--cc-datepicker-padding, .5rem .75rem);min-height:var(--cc-datepicker-height, 2.5rem);transition:border-color .2s,box-shadow .2s;position:relative}.cc-datepicker-field.focused{border-color:var(--cc-datepicker-focus-border-color, #1A73E8)}.cc-datepicker-field.error{border-color:var(--cc-datepicker-error-color, #D93025)}.cc-datepicker-field.disabled{background-color:var(--cc-datepicker-disabled-bg, #F1F3F4);cursor:not-allowed}.cc-datepicker-field.disabled .cc-datepicker-input{cursor:not-allowed;color:var(--cc-datepicker-disabled-color, #80868B)}.cc-datepicker-field.disabled .cc-datepicker-icon{color:var(--cc-datepicker-disabled-color, #80868B)}.cc-datepicker-input{flex:1;border:none;background:transparent;outline:none;font-family:inherit;font-size:var(--cc-datepicker-font-size, .875rem);font-weight:var(--cc-datepicker-font-weight, 400);color:var(--cc-datepicker-color, #202124);padding:0;margin:0;width:100%;opacity:1}.cc-datepicker-input::-webkit-calendar-picker-indicator{opacity:0;position:absolute;right:0;top:0;bottom:0;width:2.5rem;height:100%;cursor:pointer;z-index:10}.cc-datepicker-icon{margin-left:.5rem;color:var(--cc-datepicker-icon-color, #5F6368);pointer-events:none}.cc-datepicker-range{display:flex;gap:1rem;align-items:flex-start}.cc-datepicker-range .cc-datepicker-subfield{flex:1;display:flex;flex-direction:column;gap:.25rem}.cc-datepicker-range .cc-datepicker-sublabel{font-size:.75rem;color:#5f6368}.cc-error-message{font-size:.75rem;color:var(--cc-datepicker-error-color, #D93025);margin-top:.25rem}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
2250
|
+
}
|
|
2251
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatepickerComponent, decorators: [{
|
|
2252
|
+
type: Component,
|
|
2253
|
+
args: [{ selector: 'lib-datepicker', standalone: false, providers: [
|
|
2254
|
+
{
|
|
2255
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2256
|
+
useExisting: forwardRef(() => DatepickerComponent),
|
|
2257
|
+
multi: true
|
|
2258
|
+
}
|
|
2259
|
+
], template: "<div class=\"cc-datepicker-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-datepicker-label\" [ngStyle]=\"labelStyles\">\r\n {{ label }}\r\n <span *ngIf=\"required\" class=\"cc-required\">{{ requiredMarker }}</span>\r\n </label>\r\n\r\n <!-- Single Date Picker -->\r\n <div *ngIf=\"!isRange\" class=\"cc-datepicker-field\" [class.focused]=\"focused\" [class.disabled]=\"disabled\"\r\n [class.error]=\"errorMessage\" [ngStyle]=\"fieldStyles\">\r\n\r\n <input type=\"date\" class=\"cc-datepicker-input\" #dateInput [value]=\"formattedValue\" [disabled]=\"disabled\"\r\n [required]=\"required\" [min]=\"formattedMin\" [max]=\"formattedMax\" [placeholder]=\"placeholder\"\r\n (input)=\"onDateInput($event)\" (blur)=\"onBlur()\" (focus)=\"onFocus()\" (click)=\"dateInput.showPicker()\" />\r\n\r\n <span class=\"cc-datepicker-icon material-icons\" (click)=\"dateInput.showPicker()\">calendar_today</span>\r\n </div>\r\n\r\n <!-- Range Date Picker -->\r\n <div *ngIf=\"isRange\" class=\"cc-datepicker-range\">\r\n <!-- Start Date -->\r\n <div class=\"cc-datepicker-subfield\">\r\n <label class=\"cc-datepicker-sublabel\">{{ startDateLabel }}</label>\r\n <div class=\"cc-datepicker-field\" [class.disabled]=\"disabled\" [ngStyle]=\"fieldStyles\">\r\n <input type=\"date\" class=\"cc-datepicker-input\" [value]=\"formattedStartDate\" [disabled]=\"disabled\"\r\n [required]=\"required\" [min]=\"formattedMin\" [max]=\"formattedEndDate || formattedMax\"\r\n (input)=\"onRangeStartInput($event)\" />\r\n </div>\r\n </div>\r\n\r\n <!-- End Date -->\r\n <div class=\"cc-datepicker-subfield\">\r\n <label class=\"cc-datepicker-sublabel\">{{ endDateLabel }}</label>\r\n <div class=\"cc-datepicker-field\" [class.disabled]=\"disabled\" [ngStyle]=\"fieldStyles\">\r\n <input type=\"date\" class=\"cc-datepicker-input\" [value]=\"formattedEndDate\" [disabled]=\"disabled\"\r\n [required]=\"required\" [min]=\"formattedStartDate || formattedMin\" [max]=\"formattedMax\"\r\n (input)=\"onRangeEndInput($event)\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"cc-error-message\" *ngIf=\"errorMessage\">{{ errorMessage }}</div>\r\n</div>", styles: [".cc-datepicker-wrapper{display:flex;flex-direction:column;gap:var(--cc-datepicker-label-gap, .5rem);width:100%;font-family:var(--cc-datepicker-font-family, inherit)}.cc-datepicker-label{font-size:var(--cc-datepicker-label-font-size, .875rem);font-weight:var(--cc-datepicker-label-font-weight, 500);color:var(--cc-datepicker-label-color, #202124);margin:0;line-height:1.4}.cc-required{color:var(--cc-datepicker-required-color, #D93025);margin-left:.25rem}.cc-datepicker-field{display:flex;align-items:center;width:100%;box-sizing:border-box;background-color:var(--cc-datepicker-bg, #FEFEFE);border:var(--cc-datepicker-border-width, 1px) solid var(--cc-datepicker-border-color, #BDC1C6);border-radius:var(--cc-datepicker-border-radius, .4375rem);padding:var(--cc-datepicker-padding, .5rem .75rem);min-height:var(--cc-datepicker-height, 2.5rem);transition:border-color .2s,box-shadow .2s;position:relative}.cc-datepicker-field.focused{border-color:var(--cc-datepicker-focus-border-color, #1A73E8)}.cc-datepicker-field.error{border-color:var(--cc-datepicker-error-color, #D93025)}.cc-datepicker-field.disabled{background-color:var(--cc-datepicker-disabled-bg, #F1F3F4);cursor:not-allowed}.cc-datepicker-field.disabled .cc-datepicker-input{cursor:not-allowed;color:var(--cc-datepicker-disabled-color, #80868B)}.cc-datepicker-field.disabled .cc-datepicker-icon{color:var(--cc-datepicker-disabled-color, #80868B)}.cc-datepicker-input{flex:1;border:none;background:transparent;outline:none;font-family:inherit;font-size:var(--cc-datepicker-font-size, .875rem);font-weight:var(--cc-datepicker-font-weight, 400);color:var(--cc-datepicker-color, #202124);padding:0;margin:0;width:100%;opacity:1}.cc-datepicker-input::-webkit-calendar-picker-indicator{opacity:0;position:absolute;right:0;top:0;bottom:0;width:2.5rem;height:100%;cursor:pointer;z-index:10}.cc-datepicker-icon{margin-left:.5rem;color:var(--cc-datepicker-icon-color, #5F6368);pointer-events:none}.cc-datepicker-range{display:flex;gap:1rem;align-items:flex-start}.cc-datepicker-range .cc-datepicker-subfield{flex:1;display:flex;flex-direction:column;gap:.25rem}.cc-datepicker-range .cc-datepicker-sublabel{font-size:.75rem;color:#5f6368}.cc-error-message{font-size:.75rem;color:var(--cc-datepicker-error-color, #D93025);margin-top:.25rem}\n"] }]
|
|
2260
|
+
}], propDecorators: { config: [{
|
|
2261
|
+
type: Input
|
|
2262
|
+
}], labels: [{
|
|
2263
|
+
type: Input
|
|
2264
|
+
}], label: [{
|
|
2265
|
+
type: Input
|
|
2266
|
+
}], placeholder: [{
|
|
2267
|
+
type: Input
|
|
2268
|
+
}], disabled: [{
|
|
2269
|
+
type: Input
|
|
2270
|
+
}], required: [{
|
|
2271
|
+
type: Input
|
|
2272
|
+
}], minDate: [{
|
|
2273
|
+
type: Input
|
|
2274
|
+
}], maxDate: [{
|
|
2275
|
+
type: Input
|
|
2276
|
+
}], isRange: [{
|
|
2277
|
+
type: Input
|
|
2278
|
+
}], startView: [{
|
|
2279
|
+
type: Input
|
|
2280
|
+
}], value: [{
|
|
2281
|
+
type: Input
|
|
2282
|
+
}], startDate: [{
|
|
2283
|
+
type: Input
|
|
2284
|
+
}], endDate: [{
|
|
2285
|
+
type: Input
|
|
2286
|
+
}], errorMessage: [{
|
|
2287
|
+
type: Input
|
|
2288
|
+
}], width: [{
|
|
2289
|
+
type: Input
|
|
2290
|
+
}], height: [{
|
|
2291
|
+
type: Input
|
|
2292
|
+
}], borderRadius: [{
|
|
2293
|
+
type: Input
|
|
2294
|
+
}], fontSize: [{
|
|
2295
|
+
type: Input
|
|
2296
|
+
}], gap: [{
|
|
2297
|
+
type: Input
|
|
2298
|
+
}], fontFamily: [{
|
|
2299
|
+
type: Input
|
|
2300
|
+
}], labelColor: [{
|
|
2301
|
+
type: Input
|
|
2302
|
+
}], labelFontSize: [{
|
|
2303
|
+
type: Input
|
|
2304
|
+
}], labelFontWeight: [{
|
|
2305
|
+
type: Input
|
|
2306
|
+
}], backgroundColor: [{
|
|
2307
|
+
type: Input
|
|
2308
|
+
}], borderColor: [{
|
|
2309
|
+
type: Input
|
|
2310
|
+
}], borderWidth: [{
|
|
2311
|
+
type: Input
|
|
2312
|
+
}], padding: [{
|
|
2313
|
+
type: Input
|
|
2314
|
+
}], fontWeight: [{
|
|
2315
|
+
type: Input
|
|
2316
|
+
}], color: [{
|
|
2317
|
+
type: Input
|
|
2318
|
+
}], placeholderColor: [{
|
|
2319
|
+
type: Input
|
|
2320
|
+
}], focusBorderColor: [{
|
|
2321
|
+
type: Input
|
|
2322
|
+
}], errorColor: [{
|
|
2323
|
+
type: Input
|
|
2324
|
+
}], disabledBackgroundColor: [{
|
|
2325
|
+
type: Input
|
|
2326
|
+
}], disabledColor: [{
|
|
2327
|
+
type: Input
|
|
2328
|
+
}], boxShadow: [{
|
|
2329
|
+
type: Input
|
|
2330
|
+
}], dateChange: [{
|
|
2331
|
+
type: Output
|
|
2332
|
+
}] } });
|
|
2333
|
+
|
|
2334
|
+
class SearchComponent {
|
|
2335
|
+
config;
|
|
2336
|
+
labels;
|
|
2337
|
+
placeholder = '';
|
|
2338
|
+
label = '';
|
|
2339
|
+
disabled = false;
|
|
2340
|
+
debounceMs = 300;
|
|
2341
|
+
clearable = true;
|
|
2342
|
+
value = '';
|
|
2343
|
+
// Style inputs
|
|
2344
|
+
width;
|
|
2345
|
+
height;
|
|
2346
|
+
borderRadius;
|
|
2347
|
+
fontSize;
|
|
2348
|
+
gap;
|
|
2349
|
+
fontFamily;
|
|
2350
|
+
labelColor;
|
|
2351
|
+
labelFontSize;
|
|
2352
|
+
labelFontWeight;
|
|
2353
|
+
backgroundColor;
|
|
2354
|
+
borderColor;
|
|
2355
|
+
borderWidth;
|
|
2356
|
+
border; // Shorthand
|
|
2357
|
+
padding;
|
|
2358
|
+
fontWeight;
|
|
2359
|
+
color;
|
|
2360
|
+
textColor; // Alias for color or specific text color
|
|
2361
|
+
iconColor;
|
|
2362
|
+
placeholderColor;
|
|
2363
|
+
focusBorderColor;
|
|
2364
|
+
disabledBackgroundColor;
|
|
2365
|
+
disabledColor;
|
|
2366
|
+
boxShadow;
|
|
2367
|
+
search = new EventEmitter();
|
|
2368
|
+
clear = new EventEmitter();
|
|
2369
|
+
searchSubject = new Subject();
|
|
2370
|
+
focused = false;
|
|
2371
|
+
onChange = () => { };
|
|
2372
|
+
onTouched = () => { };
|
|
2373
|
+
ngOnInit() {
|
|
2374
|
+
this.updateFromConfig();
|
|
2375
|
+
this.updateFromLabels();
|
|
2376
|
+
this.searchSubject.pipe(debounceTime(this.debounceMs), distinctUntilChanged()).subscribe(value => {
|
|
2377
|
+
this.search.emit(value);
|
|
2378
|
+
});
|
|
2379
|
+
}
|
|
2380
|
+
ngOnChanges(changes) {
|
|
2381
|
+
if (changes['config']) {
|
|
2382
|
+
this.updateFromConfig();
|
|
2383
|
+
}
|
|
2384
|
+
if (changes['labels']) {
|
|
2385
|
+
this.updateFromLabels();
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
updateFromConfig() {
|
|
2389
|
+
if (this.config) {
|
|
2390
|
+
this.placeholder = this.config.placeholder ?? this.placeholder;
|
|
2391
|
+
this.label = this.config.label ?? this.label;
|
|
2392
|
+
this.disabled = this.config.disabled ?? this.disabled;
|
|
2393
|
+
this.debounceMs = this.config.debounceTime ?? this.debounceMs;
|
|
2394
|
+
this.clearable = this.config.clearable ?? this.clearable;
|
|
2395
|
+
this.width = this.config.width ?? this.width;
|
|
2396
|
+
this.height = this.config.height ?? this.height;
|
|
2397
|
+
this.borderRadius = this.config.borderRadius ?? this.borderRadius;
|
|
2398
|
+
this.fontSize = this.config.fontSize ?? this.fontSize;
|
|
2399
|
+
this.gap = this.config.gap ?? this.gap;
|
|
2400
|
+
this.fontFamily = this.config.fontFamily ?? this.fontFamily;
|
|
2401
|
+
this.labelColor = this.config.labelColor ?? this.labelColor;
|
|
2402
|
+
this.labelFontSize = this.config.labelFontSize ?? this.labelFontSize;
|
|
2403
|
+
this.labelFontWeight = this.config.labelFontWeight ?? this.labelFontWeight;
|
|
2404
|
+
this.backgroundColor = this.config.backgroundColor ?? this.backgroundColor;
|
|
2405
|
+
this.borderColor = this.config.borderColor ?? this.borderColor;
|
|
2406
|
+
this.borderWidth = this.config.borderWidth ?? this.borderWidth;
|
|
2407
|
+
this.border = this.config.border ?? this.border;
|
|
2408
|
+
this.padding = this.config.padding ?? this.padding;
|
|
2409
|
+
this.fontWeight = this.config.fontWeight ?? this.fontWeight;
|
|
2410
|
+
this.color = this.config.color ?? this.color;
|
|
2411
|
+
this.textColor = this.config.textColor ?? this.textColor;
|
|
2412
|
+
this.iconColor = this.config.iconColor ?? this.iconColor;
|
|
2413
|
+
this.placeholderColor = this.config.placeholderColor ?? this.placeholderColor;
|
|
2414
|
+
this.focusBorderColor = this.config.focusBorderColor ?? this.focusBorderColor;
|
|
2415
|
+
this.disabledBackgroundColor = this.config.disabledBackgroundColor ?? this.disabledBackgroundColor;
|
|
2416
|
+
this.disabledColor = this.config.disabledColor ?? this.disabledColor;
|
|
2417
|
+
this.boxShadow = this.config.boxShadow ?? this.boxShadow;
|
|
2418
|
+
if (this.config.value) {
|
|
2419
|
+
this.value = this.config.value;
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
updateFromLabels() {
|
|
2424
|
+
if (this.labels) {
|
|
2425
|
+
this.label = this.labels.label || this.label;
|
|
2426
|
+
this.placeholder = this.labels.placeholder || this.placeholder;
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
ngOnDestroy() {
|
|
2430
|
+
this.searchSubject.complete();
|
|
2431
|
+
}
|
|
2432
|
+
get clearAriaLabel() {
|
|
2433
|
+
return this.labels?.clearAriaLabel || 'Clear search';
|
|
2434
|
+
}
|
|
2435
|
+
writeValue(value) {
|
|
2436
|
+
this.value = value || '';
|
|
2437
|
+
}
|
|
2438
|
+
registerOnChange(fn) {
|
|
2439
|
+
this.onChange = fn;
|
|
2440
|
+
}
|
|
2441
|
+
registerOnTouched(fn) {
|
|
2442
|
+
this.onTouched = fn;
|
|
2443
|
+
}
|
|
2444
|
+
setDisabledState(isDisabled) {
|
|
2445
|
+
this.disabled = isDisabled;
|
|
2446
|
+
}
|
|
2447
|
+
onInputChange(event) {
|
|
2448
|
+
this.value = event.target.value;
|
|
2449
|
+
this.onChange(this.value);
|
|
2450
|
+
this.searchSubject.next(this.value);
|
|
2451
|
+
}
|
|
2452
|
+
onClear() {
|
|
2453
|
+
this.value = '';
|
|
2454
|
+
this.onChange(this.value);
|
|
2455
|
+
this.searchSubject.next(this.value);
|
|
2456
|
+
this.clear.emit();
|
|
2457
|
+
}
|
|
2458
|
+
onBlur() {
|
|
2459
|
+
this.focused = false;
|
|
2460
|
+
this.onTouched();
|
|
581
2461
|
}
|
|
582
|
-
|
|
583
|
-
|
|
2462
|
+
onFocus() {
|
|
2463
|
+
this.focused = true;
|
|
584
2464
|
}
|
|
585
|
-
|
|
586
|
-
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"] }] });
|
|
2465
|
+
getStyleValue(value) {
|
|
2466
|
+
return value ? `${value}` : undefined;
|
|
2467
|
+
}
|
|
2468
|
+
get wrapperStyles() {
|
|
2469
|
+
return {
|
|
2470
|
+
'width': this.getStyleValue(this.width),
|
|
2471
|
+
'--cc-search-label-gap': this.getStyleValue(this.gap),
|
|
2472
|
+
'--cc-search-font-family': this.getStyleValue(this.fontFamily)
|
|
2473
|
+
};
|
|
2474
|
+
}
|
|
2475
|
+
get labelStyles() {
|
|
2476
|
+
return {
|
|
2477
|
+
'--cc-search-label-color': this.getStyleValue(this.labelColor),
|
|
2478
|
+
'--cc-search-label-font-size': this.getStyleValue(this.labelFontSize),
|
|
2479
|
+
'--cc-search-label-font-weight': this.getStyleValue(this.labelFontWeight)
|
|
2480
|
+
};
|
|
2481
|
+
}
|
|
2482
|
+
get fieldStyles() {
|
|
2483
|
+
return {
|
|
2484
|
+
'--cc-search-bg': this.getStyleValue(this.backgroundColor),
|
|
2485
|
+
'--cc-search-border-radius': this.getStyleValue(this.borderRadius),
|
|
2486
|
+
'--cc-search-border-color': this.getStyleValue(this.borderColor),
|
|
2487
|
+
'--cc-search-border-width': this.getStyleValue(this.borderWidth),
|
|
2488
|
+
'--cc-search-border': this.getStyleValue(this.border),
|
|
2489
|
+
'--cc-search-height': this.getStyleValue(this.height),
|
|
2490
|
+
'--cc-search-padding': this.getStyleValue(this.padding),
|
|
2491
|
+
'--cc-search-font-size': this.getStyleValue(this.fontSize),
|
|
2492
|
+
'--cc-search-font-weight': this.getStyleValue(this.fontWeight),
|
|
2493
|
+
'--cc-search-color': this.getStyleValue(this.color || this.textColor),
|
|
2494
|
+
'--cc-search-icon-color': this.getStyleValue(this.iconColor),
|
|
2495
|
+
'--cc-search-placeholder-color': this.getStyleValue(this.placeholderColor),
|
|
2496
|
+
'--cc-search-focus-border-color': this.getStyleValue(this.focusBorderColor),
|
|
2497
|
+
'--cc-search-disabled-bg': this.getStyleValue(this.disabledBackgroundColor),
|
|
2498
|
+
'--cc-search-disabled-color': this.getStyleValue(this.disabledColor),
|
|
2499
|
+
'box-shadow': this.getStyleValue(this.boxShadow)
|
|
2500
|
+
};
|
|
2501
|
+
}
|
|
2502
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2503
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SearchComponent, isStandalone: false, selector: "lib-search", inputs: { config: "config", labels: "labels", placeholder: "placeholder", label: "label", disabled: "disabled", debounceMs: "debounceMs", clearable: "clearable", value: "value", width: "width", height: "height", borderRadius: "borderRadius", fontSize: "fontSize", gap: "gap", fontFamily: "fontFamily", labelColor: "labelColor", labelFontSize: "labelFontSize", labelFontWeight: "labelFontWeight", backgroundColor: "backgroundColor", borderColor: "borderColor", borderWidth: "borderWidth", border: "border", padding: "padding", fontWeight: "fontWeight", color: "color", textColor: "textColor", iconColor: "iconColor", placeholderColor: "placeholderColor", focusBorderColor: "focusBorderColor", disabledBackgroundColor: "disabledBackgroundColor", disabledColor: "disabledColor", boxShadow: "boxShadow" }, outputs: { search: "search", clear: "clear" }, providers: [
|
|
2504
|
+
{
|
|
2505
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2506
|
+
useExisting: forwardRef(() => SearchComponent),
|
|
2507
|
+
multi: true
|
|
2508
|
+
}
|
|
2509
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-search-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-search-label\" [ngStyle]=\"labelStyles\">{{ label }}</label>\r\n\r\n <div class=\"cc-search-field\" [class.focused]=\"focused\" [class.disabled]=\"disabled\" [ngStyle]=\"fieldStyles\">\r\n <span class=\"cc-search-icon material-icons\">search</span>\r\n\r\n <input type=\"text\" class=\"cc-search-input\" [value]=\"value\" [placeholder]=\"placeholder\" [disabled]=\"disabled\"\r\n (input)=\"onInputChange($event)\" (blur)=\"onBlur()\" (focus)=\"onFocus()\" />\r\n\r\n <button *ngIf=\"clearable && value && !disabled\" type=\"button\" class=\"cc-clear-btn\" (click)=\"onClear()\"\r\n [attr.aria-label]=\"clearAriaLabel\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n </div>\r\n</div>", styles: [".cc-search-wrapper{display:flex;flex-direction:column;gap:var(--cc-search-label-gap, .5rem);width:100%;font-family:var(--cc-search-font-family, inherit)}.cc-search-label{font-size:var(--cc-search-label-font-size, .875rem);font-weight:var(--cc-search-label-font-weight, 500);color:var(--cc-search-label-color, #202124);margin:0;line-height:1.4}.cc-search-field{display:flex;align-items:center;width:100%;box-sizing:border-box;background-color:var(--cc-search-bg, #FEFEFE);border:var(--cc-search-border-width, 1px) solid var(--cc-search-border-color, #BDC1C6);border-radius:var(--cc-search-border-radius, .4375rem);padding:var(--cc-search-padding, .5rem .75rem);min-height:var(--cc-search-height, 2.5rem);transition:border-color .2s,box-shadow .2s}.cc-search-field.focused{border-color:var(--cc-search-focus-border-color, #1A73E8)}.cc-search-field.disabled{background-color:var(--cc-search-disabled-bg, #F1F3F4);cursor:not-allowed}.cc-search-field.disabled .cc-search-input{cursor:not-allowed;color:var(--cc-search-disabled-color, #80868B)}.cc-search-field.disabled .cc-search-icon,.cc-search-field.disabled .cc-clear-btn{color:var(--cc-search-disabled-color, #80868B)}.cc-search-icon{margin-right:.5rem;color:var(--cc-search-icon-color, #5F6368);display:flex;align-items:center}.cc-search-input{flex:1;border:none;background:none;outline:none;font-family:inherit;font-size:var(--cc-search-font-size, .875rem);font-weight:var(--cc-search-font-weight, 400);color:var(--cc-search-color, #202124);padding:0;margin:0;width:100%}.cc-search-input::placeholder{color:var(--cc-search-placeholder-color, #80868B)}.cc-clear-btn{background:none;border:none;cursor:pointer;padding:0;margin-left:.5rem;display:flex;align-items:center;color:var(--cc-search-icon-color, #5F6368)}.cc-clear-btn:focus{outline:none}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
587
2510
|
}
|
|
588
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type:
|
|
2511
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SearchComponent, decorators: [{
|
|
589
2512
|
type: Component,
|
|
590
|
-
args: [{ selector: '
|
|
2513
|
+
args: [{ selector: 'lib-search', standalone: false, providers: [
|
|
2514
|
+
{
|
|
2515
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2516
|
+
useExisting: forwardRef(() => SearchComponent),
|
|
2517
|
+
multi: true
|
|
2518
|
+
}
|
|
2519
|
+
], template: "<div class=\"cc-search-wrapper\" [ngStyle]=\"wrapperStyles\">\r\n <label *ngIf=\"label\" class=\"cc-search-label\" [ngStyle]=\"labelStyles\">{{ label }}</label>\r\n\r\n <div class=\"cc-search-field\" [class.focused]=\"focused\" [class.disabled]=\"disabled\" [ngStyle]=\"fieldStyles\">\r\n <span class=\"cc-search-icon material-icons\">search</span>\r\n\r\n <input type=\"text\" class=\"cc-search-input\" [value]=\"value\" [placeholder]=\"placeholder\" [disabled]=\"disabled\"\r\n (input)=\"onInputChange($event)\" (blur)=\"onBlur()\" (focus)=\"onFocus()\" />\r\n\r\n <button *ngIf=\"clearable && value && !disabled\" type=\"button\" class=\"cc-clear-btn\" (click)=\"onClear()\"\r\n [attr.aria-label]=\"clearAriaLabel\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n </div>\r\n</div>", styles: [".cc-search-wrapper{display:flex;flex-direction:column;gap:var(--cc-search-label-gap, .5rem);width:100%;font-family:var(--cc-search-font-family, inherit)}.cc-search-label{font-size:var(--cc-search-label-font-size, .875rem);font-weight:var(--cc-search-label-font-weight, 500);color:var(--cc-search-label-color, #202124);margin:0;line-height:1.4}.cc-search-field{display:flex;align-items:center;width:100%;box-sizing:border-box;background-color:var(--cc-search-bg, #FEFEFE);border:var(--cc-search-border-width, 1px) solid var(--cc-search-border-color, #BDC1C6);border-radius:var(--cc-search-border-radius, .4375rem);padding:var(--cc-search-padding, .5rem .75rem);min-height:var(--cc-search-height, 2.5rem);transition:border-color .2s,box-shadow .2s}.cc-search-field.focused{border-color:var(--cc-search-focus-border-color, #1A73E8)}.cc-search-field.disabled{background-color:var(--cc-search-disabled-bg, #F1F3F4);cursor:not-allowed}.cc-search-field.disabled .cc-search-input{cursor:not-allowed;color:var(--cc-search-disabled-color, #80868B)}.cc-search-field.disabled .cc-search-icon,.cc-search-field.disabled .cc-clear-btn{color:var(--cc-search-disabled-color, #80868B)}.cc-search-icon{margin-right:.5rem;color:var(--cc-search-icon-color, #5F6368);display:flex;align-items:center}.cc-search-input{flex:1;border:none;background:none;outline:none;font-family:inherit;font-size:var(--cc-search-font-size, .875rem);font-weight:var(--cc-search-font-weight, 400);color:var(--cc-search-color, #202124);padding:0;margin:0;width:100%}.cc-search-input::placeholder{color:var(--cc-search-placeholder-color, #80868B)}.cc-clear-btn{background:none;border:none;cursor:pointer;padding:0;margin-left:.5rem;display:flex;align-items:center;color:var(--cc-search-icon-color, #5F6368)}.cc-clear-btn:focus{outline:none}\n"] }]
|
|
591
2520
|
}], propDecorators: { config: [{
|
|
592
2521
|
type: Input
|
|
593
|
-
}],
|
|
2522
|
+
}], labels: [{
|
|
594
2523
|
type: Input
|
|
595
|
-
}],
|
|
596
|
-
type:
|
|
597
|
-
}],
|
|
598
|
-
type:
|
|
599
|
-
}],
|
|
2524
|
+
}], placeholder: [{
|
|
2525
|
+
type: Input
|
|
2526
|
+
}], label: [{
|
|
2527
|
+
type: Input
|
|
2528
|
+
}], disabled: [{
|
|
2529
|
+
type: Input
|
|
2530
|
+
}], debounceMs: [{
|
|
2531
|
+
type: Input
|
|
2532
|
+
}], clearable: [{
|
|
2533
|
+
type: Input
|
|
2534
|
+
}], value: [{
|
|
2535
|
+
type: Input
|
|
2536
|
+
}], width: [{
|
|
2537
|
+
type: Input
|
|
2538
|
+
}], height: [{
|
|
2539
|
+
type: Input
|
|
2540
|
+
}], borderRadius: [{
|
|
2541
|
+
type: Input
|
|
2542
|
+
}], fontSize: [{
|
|
2543
|
+
type: Input
|
|
2544
|
+
}], gap: [{
|
|
2545
|
+
type: Input
|
|
2546
|
+
}], fontFamily: [{
|
|
2547
|
+
type: Input
|
|
2548
|
+
}], labelColor: [{
|
|
2549
|
+
type: Input
|
|
2550
|
+
}], labelFontSize: [{
|
|
2551
|
+
type: Input
|
|
2552
|
+
}], labelFontWeight: [{
|
|
2553
|
+
type: Input
|
|
2554
|
+
}], backgroundColor: [{
|
|
2555
|
+
type: Input
|
|
2556
|
+
}], borderColor: [{
|
|
2557
|
+
type: Input
|
|
2558
|
+
}], borderWidth: [{
|
|
2559
|
+
type: Input
|
|
2560
|
+
}], border: [{
|
|
2561
|
+
type: Input
|
|
2562
|
+
}], padding: [{
|
|
2563
|
+
type: Input
|
|
2564
|
+
}], fontWeight: [{
|
|
2565
|
+
type: Input
|
|
2566
|
+
}], color: [{
|
|
2567
|
+
type: Input
|
|
2568
|
+
}], textColor: [{
|
|
2569
|
+
type: Input
|
|
2570
|
+
}], iconColor: [{
|
|
2571
|
+
type: Input
|
|
2572
|
+
}], placeholderColor: [{
|
|
2573
|
+
type: Input
|
|
2574
|
+
}], focusBorderColor: [{
|
|
2575
|
+
type: Input
|
|
2576
|
+
}], disabledBackgroundColor: [{
|
|
2577
|
+
type: Input
|
|
2578
|
+
}], disabledColor: [{
|
|
2579
|
+
type: Input
|
|
2580
|
+
}], boxShadow: [{
|
|
2581
|
+
type: Input
|
|
2582
|
+
}], search: [{
|
|
600
2583
|
type: Output
|
|
601
|
-
}],
|
|
2584
|
+
}], clear: [{
|
|
602
2585
|
type: Output
|
|
603
|
-
}], handleEscape: [{
|
|
604
|
-
type: HostListener,
|
|
605
|
-
args: ['document:keydown.escape', ['$event']]
|
|
606
2586
|
}] } });
|
|
607
2587
|
|
|
608
|
-
class ConfirmationModalModule {
|
|
609
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
610
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, declarations: [ConfirmationModalComponent], imports: [CommonModule,
|
|
611
|
-
MatIconModule, // For material icons support
|
|
612
|
-
FormsModule // For ngModel in user examples (although mostly projected content, user might need it)
|
|
613
|
-
], exports: [ConfirmationModalComponent] });
|
|
614
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, imports: [CommonModule,
|
|
615
|
-
MatIconModule, // For material icons support
|
|
616
|
-
FormsModule // For ngModel in user examples (although mostly projected content, user might need it)
|
|
617
|
-
] });
|
|
618
|
-
}
|
|
619
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalModule, decorators: [{
|
|
620
|
-
type: NgModule,
|
|
621
|
-
args: [{
|
|
622
|
-
declarations: [
|
|
623
|
-
ConfirmationModalComponent
|
|
624
|
-
],
|
|
625
|
-
imports: [
|
|
626
|
-
CommonModule,
|
|
627
|
-
MatIconModule, // For material icons support
|
|
628
|
-
FormsModule // For ngModel in user examples (although mostly projected content, user might need it)
|
|
629
|
-
],
|
|
630
|
-
exports: [
|
|
631
|
-
ConfirmationModalComponent
|
|
632
|
-
]
|
|
633
|
-
}]
|
|
634
|
-
}] });
|
|
635
|
-
|
|
636
2588
|
class FilterSidebarComponent {
|
|
637
2589
|
router;
|
|
638
2590
|
route;
|
|
@@ -641,13 +2593,16 @@ class FilterSidebarComponent {
|
|
|
641
2593
|
filterChange = new EventEmitter();
|
|
642
2594
|
filterApply = new EventEmitter();
|
|
643
2595
|
filterClear = new EventEmitter();
|
|
644
|
-
tabChange = new EventEmitter();
|
|
645
2596
|
showCodeSnippet = new EventEmitter();
|
|
2597
|
+
close = new EventEmitter();
|
|
646
2598
|
filters = {};
|
|
647
|
-
selectedTabId = null;
|
|
648
2599
|
// ControlValueAccessor callbacks
|
|
649
2600
|
onChange = () => { };
|
|
650
2601
|
onTouched = () => { };
|
|
2602
|
+
isCollapsed = false;
|
|
2603
|
+
toggleCollapse() {
|
|
2604
|
+
this.isCollapsed = !this.isCollapsed;
|
|
2605
|
+
}
|
|
651
2606
|
constructor(router, route) {
|
|
652
2607
|
this.router = router;
|
|
653
2608
|
this.route = route;
|
|
@@ -656,22 +2611,22 @@ class FilterSidebarComponent {
|
|
|
656
2611
|
if (this.initialFilters) {
|
|
657
2612
|
this.filters = { ...this.initialFilters };
|
|
658
2613
|
}
|
|
659
|
-
// Initialize from URL query params
|
|
660
|
-
this.
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}
|
|
2614
|
+
// Initialize from URL query params if persistent
|
|
2615
|
+
if (this.config.settings?.persistent !== false) {
|
|
2616
|
+
this.route.queryParams.subscribe(params => {
|
|
2617
|
+
if (Object.keys(params).length > 0) {
|
|
2618
|
+
// Start with existing filters to preserve defaults not in URL
|
|
2619
|
+
const newFilters = { ...this.filters };
|
|
2620
|
+
Object.keys(params).forEach(key => {
|
|
2621
|
+
// Try to parse arrays or numbers if possible, otherwise string
|
|
2622
|
+
// This is a naive implementation, ideally config should dictate type
|
|
2623
|
+
const val = params[key];
|
|
2624
|
+
// If comma separated and looked like array? For now keep simple
|
|
2625
|
+
newFilters[key] = val;
|
|
2626
|
+
});
|
|
2627
|
+
this.filters = newFilters;
|
|
2628
|
+
}
|
|
2629
|
+
});
|
|
675
2630
|
}
|
|
676
2631
|
}
|
|
677
2632
|
// ControlValueAccessor Implementation
|
|
@@ -690,42 +2645,18 @@ class FilterSidebarComponent {
|
|
|
690
2645
|
this.onTouched = fn;
|
|
691
2646
|
}
|
|
692
2647
|
// Component Logic
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
if (isMulti) {
|
|
699
|
-
this.toggleFilterValue(key, value);
|
|
700
|
-
}
|
|
701
|
-
else {
|
|
702
|
-
this.filters[key] = value;
|
|
703
|
-
}
|
|
704
|
-
// Notify Generic Change
|
|
705
|
-
this.notifyChanges(key, this.filters[key]);
|
|
706
|
-
}
|
|
707
|
-
toggleFilterValue(key, value) {
|
|
708
|
-
const currentValues = this.filters[key] || [];
|
|
709
|
-
if (Array.isArray(currentValues)) {
|
|
710
|
-
const index = currentValues.indexOf(value);
|
|
711
|
-
if (index > -1) {
|
|
712
|
-
// Remove value
|
|
713
|
-
this.filters[key] = currentValues.filter((v) => v !== value);
|
|
714
|
-
}
|
|
715
|
-
else {
|
|
716
|
-
// Add value
|
|
717
|
-
this.filters[key] = [...currentValues, value];
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
else {
|
|
721
|
-
// Initialize array if undefined
|
|
722
|
-
this.filters[key] = [value];
|
|
723
|
-
}
|
|
2648
|
+
onValueChange(key, value) {
|
|
2649
|
+
if (!key)
|
|
2650
|
+
return;
|
|
2651
|
+
this.filters[key] = value;
|
|
2652
|
+
this.notifyChanges(key, value);
|
|
724
2653
|
}
|
|
725
2654
|
notifyChanges(key, value) {
|
|
726
2655
|
this.onChange(this.filters);
|
|
727
|
-
// Update URL
|
|
728
|
-
this.
|
|
2656
|
+
// Update URL if persistent
|
|
2657
|
+
if (this.config.settings?.persistent !== false) {
|
|
2658
|
+
this.updateUrl();
|
|
2659
|
+
}
|
|
729
2660
|
this.filterChange.emit({
|
|
730
2661
|
key,
|
|
731
2662
|
value,
|
|
@@ -736,8 +2667,8 @@ class FilterSidebarComponent {
|
|
|
736
2667
|
this.router.navigate([], {
|
|
737
2668
|
relativeTo: this.route,
|
|
738
2669
|
queryParams: this.filters,
|
|
739
|
-
queryParamsHandling: 'merge',
|
|
740
|
-
replaceUrl: true
|
|
2670
|
+
queryParamsHandling: 'merge',
|
|
2671
|
+
replaceUrl: true
|
|
741
2672
|
});
|
|
742
2673
|
}
|
|
743
2674
|
applyFilters() {
|
|
@@ -746,41 +2677,49 @@ class FilterSidebarComponent {
|
|
|
746
2677
|
clearFilters() {
|
|
747
2678
|
this.filters = {};
|
|
748
2679
|
this.onChange(this.filters);
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
// For this task, we will just navigate with empty paramsObject for the keys in `filters`
|
|
756
|
-
// or just clear all if that's the intention.
|
|
757
|
-
// Let's try to clear only the keys we know about from the config if possible,
|
|
758
|
-
// but since `filters` is dynamic, let's clear the keys present in the current state before clearing.
|
|
759
|
-
// A safer approach for "Clear All" in a filter sidebar is often to strip query params.
|
|
760
|
-
this.router.navigate([], {
|
|
761
|
-
relativeTo: this.route,
|
|
762
|
-
queryParams: {}, // Clear all query params
|
|
763
|
-
// queryParamsHandling: 'merge' // attributes to merge would need to be null to remove
|
|
764
|
-
});
|
|
2680
|
+
if (this.config.settings?.persistent !== false) {
|
|
2681
|
+
this.router.navigate([], {
|
|
2682
|
+
relativeTo: this.route,
|
|
2683
|
+
queryParams: {},
|
|
2684
|
+
});
|
|
2685
|
+
}
|
|
765
2686
|
this.filterClear.emit();
|
|
766
2687
|
}
|
|
767
|
-
|
|
768
|
-
|
|
2688
|
+
onClose() {
|
|
2689
|
+
this.close.emit();
|
|
769
2690
|
}
|
|
770
2691
|
onShowCodeSnippet() {
|
|
771
2692
|
this.showCodeSnippet.emit();
|
|
772
2693
|
}
|
|
773
|
-
|
|
774
|
-
|
|
2694
|
+
get sidebarStyles() {
|
|
2695
|
+
const styles = {};
|
|
2696
|
+
if (this.config?.styles) {
|
|
2697
|
+
if (this.config.styles.width)
|
|
2698
|
+
styles['--cc-filter-sidebar-width'] = this.config.styles.width;
|
|
2699
|
+
if (this.config.styles.padding)
|
|
2700
|
+
styles['--cc-filter-sidebar-padding'] = this.config.styles.padding;
|
|
2701
|
+
if (this.config.styles.gap)
|
|
2702
|
+
styles['--cc-filter-sidebar-gap'] = this.config.styles.gap;
|
|
2703
|
+
if (this.config.styles.backgroundColor)
|
|
2704
|
+
styles['--cc-filter-sidebar-bg'] = this.config.styles.backgroundColor;
|
|
2705
|
+
if (this.config.styles.headerHeight)
|
|
2706
|
+
styles['--cc-filter-header-height'] = this.config.styles.headerHeight;
|
|
2707
|
+
if (this.config.styles.borderRadius)
|
|
2708
|
+
styles['--cc-filter-sidebar-border-radius'] = this.config.styles.borderRadius;
|
|
2709
|
+
}
|
|
2710
|
+
return styles;
|
|
2711
|
+
}
|
|
2712
|
+
trackByFn(index, item) {
|
|
2713
|
+
return item.key || index;
|
|
775
2714
|
}
|
|
776
2715
|
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 });
|
|
777
|
-
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",
|
|
2716
|
+
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", showCodeSnippet: "showCodeSnippet", close: "close" }, providers: [
|
|
778
2717
|
{
|
|
779
2718
|
provide: NG_VALUE_ACCESSOR,
|
|
780
2719
|
useExisting: forwardRef(() => FilterSidebarComponent),
|
|
781
2720
|
multi: true
|
|
782
2721
|
}
|
|
783
|
-
], 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" }] });
|
|
2722
|
+
], ngImport: i0, template: "<div class=\"cc-filter-sidebar\" [ngStyle]=\"sidebarStyles\" [class.collapsed]=\"isCollapsed\">\r\n\r\n <!-- Header -->\r\n <div class=\"cc-filter-header\" *ngIf=\"config.header?.visible !== false\">\r\n <div class=\"cc-header-content\">\r\n <span class=\"cc-header-title\" *ngIf=\"config.header?.title\">\r\n <span *ngIf=\"config.header?.icon\" [class]=\"config.header?.icon\" class=\"cc-header-icon material-icons\">\r\n <!-- {{config.header?.icon }} -->\r\n </span>\r\n {{ config.header?.title }}\r\n </span>\r\n <ng-content select=\"[header-actions]\"></ng-content>\r\n </div>\r\n <button type=\"button\" *ngIf=\"config.settings?.collapsible\" (click)=\"toggleCollapse()\" class=\"cc-icon-btn\"\r\n [attr.aria-label]=\"isCollapsed ? config.labels?.expandAriaLabel : config.labels?.collapseAriaLabel\">\r\n <span class=\"material-icons\">{{ isCollapsed ? 'menu_open' : 'menu' }}</span>\r\n </button>\r\n <button type=\"button\" *ngIf=\"config.header?.showClose && !isCollapsed\" (click)=\"onClose()\"\r\n class=\"cc-icon-btn cc-close-btn\" [attr.aria-label]=\"config.labels?.closeAriaLabel\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n <!-- Code snippet debug (optional) -->\r\n <button type=\"button\" *ngIf=\"config.settings?.showCodeSnippet\" (click)=\"onShowCodeSnippet()\" class=\"cc-icon-btn\"\r\n [attr.aria-label]=\"config.labels?.codeSnippetAriaLabel\">\r\n <span class=\"material-icons\">code</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Content (Scrollable) -->\r\n <div class=\"cc-filter-content\" [class.hidden]=\"isCollapsed\">\r\n <ng-container *ngFor=\"let item of config.items; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: item }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-filter-footer\" *ngIf=\"config.footer?.visible !== false && !isCollapsed\">\r\n <lib-button variant=\"outline\" color=\"warn\" class=\"cc-btn-clear\"\r\n *ngIf=\"config.footer?.clearButton?.visible !== false\" (click)=\"clearFilters()\">\r\n {{ config.footer?.clearButton?.label }}\r\n </lib-button>\r\n <lib-button variant=\"primary\" color=\"warn\" class=\"cc-btn-apply\"\r\n *ngIf=\"config.footer?.applyButton?.visible !== false\" [disabled]=\"config.footer?.applyButton?.disabled\"\r\n (click)=\"applyFilters()\">\r\n {{ config.footer?.applyButton?.label }}\r\n </lib-button>\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive Template for Items -->\r\n<ng-template #itemTemplate let-item=\"item\">\r\n <div class=\"cc-filter-item\" [ngClass]=\"['type-' + item.type]\"\r\n [style.display]=\"item.visible === false ? 'none' : 'block'\" [ngStyle]=\"item.styles\">\r\n\r\n <ng-container [ngSwitch]=\"item.type\">\r\n\r\n <!-- Input -->\r\n <lib-input *ngSwitchCase=\"'input'\" [config]=\"item.inputConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (valueChange)=\"onValueChange(item.key, $event)\">\r\n </lib-input>\r\n\r\n <!-- Dropdown -->\r\n <lib-dropdown *ngSwitchCase=\"'dropdown'\" [config]=\"item.dropdownConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (selectionChange)=\"onValueChange(item.key, $event)\">\r\n </lib-dropdown>\r\n\r\n <!-- Checkbox -->\r\n <lib-checkbox *ngSwitchCase=\"'checkbox'\" [config]=\"item.checkboxConfig\" [label]=\"item.label\"\r\n [checked]=\"!!filters[item.key]\" (checkedChange)=\"onValueChange(item.key, $event)\">\r\n </lib-checkbox>\r\n\r\n <!-- Radio -->\r\n <lib-radio *ngSwitchCase=\"'radio'\" [config]=\"item.radioConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (selectionChange)=\"onValueChange(item.key, $event)\">\r\n </lib-radio>\r\n\r\n <!-- Toggle -->\r\n <lib-toggle *ngSwitchCase=\"'toggle'\" [config]=\"item.toggleConfig\" [label]=\"item.label\"\r\n [checked]=\"filters[item.key]\" (toggleChange)=\"onValueChange(item.key, $event)\">\r\n </lib-toggle>\r\n\r\n <!-- Datepicker -->\r\n <lib-datepicker *ngSwitchCase=\"'datepicker'\" [config]=\"item.datepickerConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (dateChange)=\"onValueChange(item.key, $event)\">\r\n </lib-datepicker>\r\n\r\n <!-- Search -->\r\n <lib-search *ngSwitchCase=\"'active-search'\" [config]=\"item.searchConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (search)=\"onValueChange(item.key, $event)\">\r\n </lib-search>\r\n\r\n <!-- Group / Accordion -->\r\n <div *ngSwitchCase=\"'group'\" class=\"cc-accordion-item\" [class.expanded]=\"item.expanded\">\r\n <button type=\"button\" class=\"cc-accordion-header\" (click)=\"item.expanded = !item.expanded\">\r\n <span class=\"cc-accordion-title\">{{ item.label }}</span>\r\n <span class=\"material-icons cc-accordion-icon\">{{ item.expanded ? 'expand_less' : 'expand_more'\r\n }}</span>\r\n </button>\r\n\r\n <div class=\"cc-accordion-body\" *ngIf=\"item.expanded\">\r\n <ng-container *ngFor=\"let child of item.children; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: child }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Custom Divider -->\r\n <div *ngSwitchCase=\"'divider'\" class=\"cc-filter-divider\"></div>\r\n\r\n </ng-container>\r\n </div>\r\n</ng-template>", styles: [":host{display:block;height:100%;--cc-filter-sidebar-width: 100%;--cc-filter-sidebar-padding: 1.5rem;--cc-filter-sidebar-gap: 1.5rem;--cc-filter-sidebar-bg: #FEFEFE;--cc-filter-sidebar-border-radius: 0;--cc-filter-header-height: 3rem;--cc-filter-header-title-size: 1.125rem;--cc-filter-header-title-weight: 500;--cc-filter-header-title-color: #202124;--cc-filter-footer-padding: 1rem 0 0 0;--cc-filter-footer-gap: 1rem}.cc-filter-sidebar{display:flex;flex-direction:column;height:100%;width:var(--cc-filter-sidebar-width, 280px);background-color:var(--cc-filter-sidebar-bg, #FEFEFE);padding:var(--cc-filter-sidebar-padding, 1.5rem);box-sizing:border-box;overflow:hidden;border-radius:var(--cc-filter-sidebar-border-radius, 0);transition:width .3s ease,padding .3s ease}.cc-filter-sidebar.collapsed{width:60px!important;padding:1.5rem .5rem}.cc-filter-sidebar.collapsed .cc-filter-header{justify-content:center;margin-bottom:0}.cc-filter-sidebar.collapsed .cc-filter-header .cc-header-content,.cc-filter-sidebar.collapsed .cc-filter-header .cc-close-btn,.cc-filter-sidebar.collapsed .cc-filter-content{display:none}.cc-filter-header{display:flex;align-items:center;justify-content:space-between;min-height:var(--cc-filter-header-height, 3rem);margin-bottom:1rem;flex-shrink:0}.cc-filter-header .cc-header-content{display:flex;align-items:center;gap:.5rem;flex:1}.cc-filter-header .cc-header-title{font-size:var(--cc-filter-header-title-size, 1.125rem);font-weight:var(--cc-filter-header-title-weight, 500);color:var(--cc-filter-header-title-color, #202124);display:flex;align-items:center;gap:.5rem}.cc-filter-content{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:var(--cc-filter-sidebar-gap, 1.5rem);padding-right:.25rem}.cc-filter-content::-webkit-scrollbar{width:6px}.cc-filter-content::-webkit-scrollbar-thumb{background-color:#e0e0e0;border-radius:3px}.cc-accordion-item{border-bottom:1px solid #E0E0E0}.cc-accordion-item:last-child{border-bottom:none}.cc-accordion-item .cc-accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 0;background:none;border:none;cursor:pointer;text-align:left;outline:none}.cc-accordion-item .cc-accordion-header .cc-accordion-title{font-size:.875rem;font-weight:500;color:#202124}.cc-accordion-item .cc-accordion-header .cc-accordion-icon{color:#5f6368;transition:transform .2s}.cc-accordion-item .cc-accordion-body{padding:0 0 1rem;display:flex;flex-direction:column;gap:1rem;animation:slideDown .2s ease-out}@keyframes slideDown{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}.cc-group-content{display:flex;flex-direction:column;gap:1rem}.cc-filter-divider{height:1px;background-color:#e0e0e0;margin:.5rem 0}.cc-filter-footer{display:flex;gap:var(--cc-filter-footer-gap, 1rem);padding:var(--cc-filter-footer-padding, 1rem 0 0 0);margin-top:auto;flex-shrink:0}.cc-filter-footer button{flex:1}.cc-icon-btn{background:none;border:none;cursor:pointer;color:#5f6368;padding:.5rem;border-radius:50%;display:flex;align-items:center;justify-content:center}.cc-icon-btn:hover{background-color:#0000000a}.cc-close-btn{margin-right:-.5rem}\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.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { 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: InputComponent, selector: "lib-input", inputs: ["config", "labels", "type", "label", "placeholder", "disabled", "required", "readonly", "clearable", "maxLength", "minLength", "min", "max", "pattern", "errorMessage", "helperText", "rows", "prefixIcon", "suffixIcon", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["valueChange", "inputBlur", "inputFocus"] }, { kind: "component", type: DropdownComponent, selector: "lib-dropdown", inputs: ["config", "labels", "options", "placeholder", "label", "multiple", "searchable", "clearable", "disabled", "required", "errorMessage", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["selectionChange"] }, { kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["config", "label", "options", "disabled", "required", "labelPosition", "color", "layout", "labels", "gap", "labelColor", "checkedColor", "uncheckedColor", "fontSize", "fontWeight", "fontFamily", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight", "disabledColor", "errorColor", "size", "borderRadius", "labelFontSize", "labelFontWeight"], outputs: ["selectionChange"] }, { kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: DatepickerComponent, selector: "lib-datepicker", inputs: ["config", "labels", "label", "placeholder", "disabled", "required", "minDate", "maxDate", "isRange", "startView", "value", "startDate", "endDate", "errorMessage", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["dateChange"] }, { kind: "component", type: SearchComponent, selector: "lib-search", inputs: ["config", "labels", "placeholder", "label", "disabled", "debounceMs", "clearable", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "border", "padding", "fontWeight", "color", "textColor", "iconColor", "placeholderColor", "focusBorderColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["search", "clear"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }] });
|
|
784
2723
|
}
|
|
785
2724
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarComponent, decorators: [{
|
|
786
2725
|
type: Component,
|
|
@@ -790,7 +2729,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
790
2729
|
useExisting: forwardRef(() => FilterSidebarComponent),
|
|
791
2730
|
multi: true
|
|
792
2731
|
}
|
|
793
|
-
], 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"] }]
|
|
2732
|
+
], template: "<div class=\"cc-filter-sidebar\" [ngStyle]=\"sidebarStyles\" [class.collapsed]=\"isCollapsed\">\r\n\r\n <!-- Header -->\r\n <div class=\"cc-filter-header\" *ngIf=\"config.header?.visible !== false\">\r\n <div class=\"cc-header-content\">\r\n <span class=\"cc-header-title\" *ngIf=\"config.header?.title\">\r\n <span *ngIf=\"config.header?.icon\" [class]=\"config.header?.icon\" class=\"cc-header-icon material-icons\">\r\n <!-- {{config.header?.icon }} -->\r\n </span>\r\n {{ config.header?.title }}\r\n </span>\r\n <ng-content select=\"[header-actions]\"></ng-content>\r\n </div>\r\n <button type=\"button\" *ngIf=\"config.settings?.collapsible\" (click)=\"toggleCollapse()\" class=\"cc-icon-btn\"\r\n [attr.aria-label]=\"isCollapsed ? config.labels?.expandAriaLabel : config.labels?.collapseAriaLabel\">\r\n <span class=\"material-icons\">{{ isCollapsed ? 'menu_open' : 'menu' }}</span>\r\n </button>\r\n <button type=\"button\" *ngIf=\"config.header?.showClose && !isCollapsed\" (click)=\"onClose()\"\r\n class=\"cc-icon-btn cc-close-btn\" [attr.aria-label]=\"config.labels?.closeAriaLabel\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n <!-- Code snippet debug (optional) -->\r\n <button type=\"button\" *ngIf=\"config.settings?.showCodeSnippet\" (click)=\"onShowCodeSnippet()\" class=\"cc-icon-btn\"\r\n [attr.aria-label]=\"config.labels?.codeSnippetAriaLabel\">\r\n <span class=\"material-icons\">code</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Content (Scrollable) -->\r\n <div class=\"cc-filter-content\" [class.hidden]=\"isCollapsed\">\r\n <ng-container *ngFor=\"let item of config.items; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: item }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-filter-footer\" *ngIf=\"config.footer?.visible !== false && !isCollapsed\">\r\n <lib-button variant=\"outline\" color=\"warn\" class=\"cc-btn-clear\"\r\n *ngIf=\"config.footer?.clearButton?.visible !== false\" (click)=\"clearFilters()\">\r\n {{ config.footer?.clearButton?.label }}\r\n </lib-button>\r\n <lib-button variant=\"primary\" color=\"warn\" class=\"cc-btn-apply\"\r\n *ngIf=\"config.footer?.applyButton?.visible !== false\" [disabled]=\"config.footer?.applyButton?.disabled\"\r\n (click)=\"applyFilters()\">\r\n {{ config.footer?.applyButton?.label }}\r\n </lib-button>\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive Template for Items -->\r\n<ng-template #itemTemplate let-item=\"item\">\r\n <div class=\"cc-filter-item\" [ngClass]=\"['type-' + item.type]\"\r\n [style.display]=\"item.visible === false ? 'none' : 'block'\" [ngStyle]=\"item.styles\">\r\n\r\n <ng-container [ngSwitch]=\"item.type\">\r\n\r\n <!-- Input -->\r\n <lib-input *ngSwitchCase=\"'input'\" [config]=\"item.inputConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (valueChange)=\"onValueChange(item.key, $event)\">\r\n </lib-input>\r\n\r\n <!-- Dropdown -->\r\n <lib-dropdown *ngSwitchCase=\"'dropdown'\" [config]=\"item.dropdownConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (selectionChange)=\"onValueChange(item.key, $event)\">\r\n </lib-dropdown>\r\n\r\n <!-- Checkbox -->\r\n <lib-checkbox *ngSwitchCase=\"'checkbox'\" [config]=\"item.checkboxConfig\" [label]=\"item.label\"\r\n [checked]=\"!!filters[item.key]\" (checkedChange)=\"onValueChange(item.key, $event)\">\r\n </lib-checkbox>\r\n\r\n <!-- Radio -->\r\n <lib-radio *ngSwitchCase=\"'radio'\" [config]=\"item.radioConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (selectionChange)=\"onValueChange(item.key, $event)\">\r\n </lib-radio>\r\n\r\n <!-- Toggle -->\r\n <lib-toggle *ngSwitchCase=\"'toggle'\" [config]=\"item.toggleConfig\" [label]=\"item.label\"\r\n [checked]=\"filters[item.key]\" (toggleChange)=\"onValueChange(item.key, $event)\">\r\n </lib-toggle>\r\n\r\n <!-- Datepicker -->\r\n <lib-datepicker *ngSwitchCase=\"'datepicker'\" [config]=\"item.datepickerConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (dateChange)=\"onValueChange(item.key, $event)\">\r\n </lib-datepicker>\r\n\r\n <!-- Search -->\r\n <lib-search *ngSwitchCase=\"'active-search'\" [config]=\"item.searchConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (search)=\"onValueChange(item.key, $event)\">\r\n </lib-search>\r\n\r\n <!-- Group / Accordion -->\r\n <div *ngSwitchCase=\"'group'\" class=\"cc-accordion-item\" [class.expanded]=\"item.expanded\">\r\n <button type=\"button\" class=\"cc-accordion-header\" (click)=\"item.expanded = !item.expanded\">\r\n <span class=\"cc-accordion-title\">{{ item.label }}</span>\r\n <span class=\"material-icons cc-accordion-icon\">{{ item.expanded ? 'expand_less' : 'expand_more'\r\n }}</span>\r\n </button>\r\n\r\n <div class=\"cc-accordion-body\" *ngIf=\"item.expanded\">\r\n <ng-container *ngFor=\"let child of item.children; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: child }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Custom Divider -->\r\n <div *ngSwitchCase=\"'divider'\" class=\"cc-filter-divider\"></div>\r\n\r\n </ng-container>\r\n </div>\r\n</ng-template>", styles: [":host{display:block;height:100%;--cc-filter-sidebar-width: 100%;--cc-filter-sidebar-padding: 1.5rem;--cc-filter-sidebar-gap: 1.5rem;--cc-filter-sidebar-bg: #FEFEFE;--cc-filter-sidebar-border-radius: 0;--cc-filter-header-height: 3rem;--cc-filter-header-title-size: 1.125rem;--cc-filter-header-title-weight: 500;--cc-filter-header-title-color: #202124;--cc-filter-footer-padding: 1rem 0 0 0;--cc-filter-footer-gap: 1rem}.cc-filter-sidebar{display:flex;flex-direction:column;height:100%;width:var(--cc-filter-sidebar-width, 280px);background-color:var(--cc-filter-sidebar-bg, #FEFEFE);padding:var(--cc-filter-sidebar-padding, 1.5rem);box-sizing:border-box;overflow:hidden;border-radius:var(--cc-filter-sidebar-border-radius, 0);transition:width .3s ease,padding .3s ease}.cc-filter-sidebar.collapsed{width:60px!important;padding:1.5rem .5rem}.cc-filter-sidebar.collapsed .cc-filter-header{justify-content:center;margin-bottom:0}.cc-filter-sidebar.collapsed .cc-filter-header .cc-header-content,.cc-filter-sidebar.collapsed .cc-filter-header .cc-close-btn,.cc-filter-sidebar.collapsed .cc-filter-content{display:none}.cc-filter-header{display:flex;align-items:center;justify-content:space-between;min-height:var(--cc-filter-header-height, 3rem);margin-bottom:1rem;flex-shrink:0}.cc-filter-header .cc-header-content{display:flex;align-items:center;gap:.5rem;flex:1}.cc-filter-header .cc-header-title{font-size:var(--cc-filter-header-title-size, 1.125rem);font-weight:var(--cc-filter-header-title-weight, 500);color:var(--cc-filter-header-title-color, #202124);display:flex;align-items:center;gap:.5rem}.cc-filter-content{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:var(--cc-filter-sidebar-gap, 1.5rem);padding-right:.25rem}.cc-filter-content::-webkit-scrollbar{width:6px}.cc-filter-content::-webkit-scrollbar-thumb{background-color:#e0e0e0;border-radius:3px}.cc-accordion-item{border-bottom:1px solid #E0E0E0}.cc-accordion-item:last-child{border-bottom:none}.cc-accordion-item .cc-accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 0;background:none;border:none;cursor:pointer;text-align:left;outline:none}.cc-accordion-item .cc-accordion-header .cc-accordion-title{font-size:.875rem;font-weight:500;color:#202124}.cc-accordion-item .cc-accordion-header .cc-accordion-icon{color:#5f6368;transition:transform .2s}.cc-accordion-item .cc-accordion-body{padding:0 0 1rem;display:flex;flex-direction:column;gap:1rem;animation:slideDown .2s ease-out}@keyframes slideDown{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}.cc-group-content{display:flex;flex-direction:column;gap:1rem}.cc-filter-divider{height:1px;background-color:#e0e0e0;margin:.5rem 0}.cc-filter-footer{display:flex;gap:var(--cc-filter-footer-gap, 1rem);padding:var(--cc-filter-footer-padding, 1rem 0 0 0);margin-top:auto;flex-shrink:0}.cc-filter-footer button{flex:1}.cc-icon-btn{background:none;border:none;cursor:pointer;color:#5f6368;padding:.5rem;border-radius:50%;display:flex;align-items:center;justify-content:center}.cc-icon-btn:hover{background-color:#0000000a}.cc-close-btn{margin-right:-.5rem}\n"] }]
|
|
794
2733
|
}], ctorParameters: () => [{ type: i1$1.Router }, { type: i1$1.ActivatedRoute }], propDecorators: { config: [{
|
|
795
2734
|
type: Input
|
|
796
2735
|
}], initialFilters: [{
|
|
@@ -801,22 +2740,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
801
2740
|
type: Output
|
|
802
2741
|
}], filterClear: [{
|
|
803
2742
|
type: Output
|
|
804
|
-
}], tabChange: [{
|
|
805
|
-
type: Output
|
|
806
2743
|
}], showCodeSnippet: [{
|
|
807
2744
|
type: Output
|
|
2745
|
+
}], close: [{
|
|
2746
|
+
type: Output
|
|
808
2747
|
}] } });
|
|
809
2748
|
|
|
2749
|
+
class FormComponentsModule {
|
|
2750
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2751
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: FormComponentsModule, declarations: [InputComponent,
|
|
2752
|
+
DropdownComponent,
|
|
2753
|
+
CheckboxComponent,
|
|
2754
|
+
RadioComponent,
|
|
2755
|
+
ToggleComponent,
|
|
2756
|
+
DatepickerComponent,
|
|
2757
|
+
SearchComponent,
|
|
2758
|
+
ClickOutsideDirective], imports: [CommonModule,
|
|
2759
|
+
ReactiveFormsModule,
|
|
2760
|
+
FormsModule,
|
|
2761
|
+
ScrollingModule], exports: [InputComponent,
|
|
2762
|
+
DropdownComponent,
|
|
2763
|
+
CheckboxComponent,
|
|
2764
|
+
RadioComponent,
|
|
2765
|
+
ToggleComponent,
|
|
2766
|
+
DatepickerComponent,
|
|
2767
|
+
SearchComponent] });
|
|
2768
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormComponentsModule, imports: [CommonModule,
|
|
2769
|
+
ReactiveFormsModule,
|
|
2770
|
+
FormsModule,
|
|
2771
|
+
ScrollingModule] });
|
|
2772
|
+
}
|
|
2773
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormComponentsModule, decorators: [{
|
|
2774
|
+
type: NgModule,
|
|
2775
|
+
args: [{
|
|
2776
|
+
declarations: [
|
|
2777
|
+
InputComponent,
|
|
2778
|
+
DropdownComponent,
|
|
2779
|
+
CheckboxComponent,
|
|
2780
|
+
RadioComponent,
|
|
2781
|
+
ToggleComponent,
|
|
2782
|
+
DatepickerComponent,
|
|
2783
|
+
SearchComponent,
|
|
2784
|
+
ClickOutsideDirective
|
|
2785
|
+
],
|
|
2786
|
+
imports: [
|
|
2787
|
+
CommonModule,
|
|
2788
|
+
ReactiveFormsModule,
|
|
2789
|
+
FormsModule,
|
|
2790
|
+
ScrollingModule
|
|
2791
|
+
],
|
|
2792
|
+
exports: [
|
|
2793
|
+
InputComponent,
|
|
2794
|
+
DropdownComponent,
|
|
2795
|
+
CheckboxComponent,
|
|
2796
|
+
RadioComponent,
|
|
2797
|
+
ToggleComponent,
|
|
2798
|
+
DatepickerComponent,
|
|
2799
|
+
SearchComponent
|
|
2800
|
+
]
|
|
2801
|
+
}]
|
|
2802
|
+
}] });
|
|
2803
|
+
|
|
810
2804
|
class FilterSidebarModule {
|
|
811
2805
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
812
2806
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarModule, declarations: [FilterSidebarComponent], imports: [CommonModule,
|
|
813
2807
|
FormsModule,
|
|
814
2808
|
ReactiveFormsModule,
|
|
815
|
-
|
|
2809
|
+
FormComponentsModule,
|
|
2810
|
+
ButtonModule], exports: [FilterSidebarComponent] });
|
|
816
2811
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarModule, imports: [CommonModule,
|
|
817
2812
|
FormsModule,
|
|
818
2813
|
ReactiveFormsModule,
|
|
819
|
-
|
|
2814
|
+
FormComponentsModule,
|
|
2815
|
+
ButtonModule] });
|
|
820
2816
|
}
|
|
821
2817
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarModule, decorators: [{
|
|
822
2818
|
type: NgModule,
|
|
@@ -828,7 +2824,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
828
2824
|
CommonModule,
|
|
829
2825
|
FormsModule,
|
|
830
2826
|
ReactiveFormsModule,
|
|
831
|
-
|
|
2827
|
+
FormComponentsModule,
|
|
2828
|
+
ButtonModule
|
|
832
2829
|
],
|
|
833
2830
|
exports: [
|
|
834
2831
|
FilterSidebarComponent
|
|
@@ -942,12 +2939,11 @@ class ConfigurableFormComponent {
|
|
|
942
2939
|
jsonConfig;
|
|
943
2940
|
data = {};
|
|
944
2941
|
baseApiUrl = '';
|
|
945
|
-
formSubmit = new EventEmitter();
|
|
946
|
-
formCancel = new EventEmitter();
|
|
947
2942
|
optionsLoad = new EventEmitter();
|
|
948
2943
|
form;
|
|
949
2944
|
processedConfig;
|
|
950
2945
|
fieldVisibilityMap = new Map();
|
|
2946
|
+
passwordFieldState = new Map();
|
|
951
2947
|
constructor(fb, snackBar, http) {
|
|
952
2948
|
this.fb = fb;
|
|
953
2949
|
this.snackBar = snackBar;
|
|
@@ -1210,14 +3206,13 @@ class ConfigurableFormComponent {
|
|
|
1210
3206
|
const formArray = this.getFormArray(sectionName);
|
|
1211
3207
|
formArray.removeAt(index);
|
|
1212
3208
|
}
|
|
1213
|
-
|
|
3209
|
+
validate() {
|
|
1214
3210
|
if (this.form.invalid) {
|
|
1215
3211
|
this.form.markAllAsTouched();
|
|
1216
3212
|
this.scrollToFirstInvalidControl();
|
|
1217
|
-
|
|
1218
|
-
return;
|
|
3213
|
+
return false;
|
|
1219
3214
|
}
|
|
1220
|
-
|
|
3215
|
+
return true;
|
|
1221
3216
|
}
|
|
1222
3217
|
scrollToFirstInvalidControl() {
|
|
1223
3218
|
const firstInvalidControl = document.querySelector('.is-invalid');
|
|
@@ -1437,9 +3432,6 @@ class ConfigurableFormComponent {
|
|
|
1437
3432
|
toggleSection(section) {
|
|
1438
3433
|
section.collapsed = !section.collapsed;
|
|
1439
3434
|
}
|
|
1440
|
-
onCancel() {
|
|
1441
|
-
this.formCancel.emit();
|
|
1442
|
-
}
|
|
1443
3435
|
// Helper method to find field by name
|
|
1444
3436
|
findFieldByName(name) {
|
|
1445
3437
|
for (const section of this.processedConfig.sections) {
|
|
@@ -1454,13 +3446,19 @@ class ConfigurableFormComponent {
|
|
|
1454
3446
|
get sections() {
|
|
1455
3447
|
return this.processedConfig?.sections || [];
|
|
1456
3448
|
}
|
|
1457
|
-
|
|
1458
|
-
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"] }] });
|
|
3449
|
+
togglePassword(fieldName) {
|
|
3450
|
+
this.passwordFieldState.set(fieldName, !this.passwordFieldState.get(fieldName));
|
|
3451
|
+
}
|
|
3452
|
+
isPasswordVisible(fieldName) {
|
|
3453
|
+
return this.passwordFieldState.get(fieldName) || false;
|
|
3454
|
+
}
|
|
3455
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormComponent, deps: [{ token: i1$2.FormBuilder }, { token: i2$2.MatSnackBar }, { token: i3.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
3456
|
+
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: { optionsLoad: "optionsLoad" }, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\" 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</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 / URL (Password removed) -->\r\n <div *ngIf=\"['text', 'email', 'number', 'tel', 'url'].includes(field.type || '')\" 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\" [name]=\"field.name\"\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 <!-- Password Field (Separated) -->\r\n <div *ngIf=\"field.type === 'password'\" 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]=\"isPasswordVisible(field.name) ? 'text' : 'password'\" [formControlName]=\"field.name\"\r\n [placeholder]=\"field.placeholder || ''\" [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 <mat-icon class=\"password-toggle-icon\" (click)=\"togglePassword(field.name)\">\r\n {{ isPasswordVisible(field.name) ? 'visibility' : 'visibility_off' }}\r\n </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-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 .password-toggle-icon{pointer-events:auto;cursor:pointer}.configurable-form-container .input-suffix .password-toggle-icon:hover{color:var(--cf-text-primary, #111827)}.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}@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 .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.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i7.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i7.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i8.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: i10.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: i10.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
|
|
1459
3457
|
}
|
|
1460
3458
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormComponent, decorators: [{
|
|
1461
3459
|
type: Component,
|
|
1462
|
-
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"] }]
|
|
1463
|
-
}], ctorParameters: () => [{ type: i1$2.FormBuilder }, { type: i2$
|
|
3460
|
+
args: [{ selector: 'lib-configurable-form', standalone: true, imports: [CommonModule, ReactiveFormsModule, MaterialModule], template: "<form [formGroup]=\"form\" 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</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 / URL (Password removed) -->\r\n <div *ngIf=\"['text', 'email', 'number', 'tel', 'url'].includes(field.type || '')\" 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\" [name]=\"field.name\"\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 <!-- Password Field (Separated) -->\r\n <div *ngIf=\"field.type === 'password'\" 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]=\"isPasswordVisible(field.name) ? 'text' : 'password'\" [formControlName]=\"field.name\"\r\n [placeholder]=\"field.placeholder || ''\" [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 <mat-icon class=\"password-toggle-icon\" (click)=\"togglePassword(field.name)\">\r\n {{ isPasswordVisible(field.name) ? 'visibility' : 'visibility_off' }}\r\n </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-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 .password-toggle-icon{pointer-events:auto;cursor:pointer}.configurable-form-container .input-suffix .password-toggle-icon:hover{color:var(--cf-text-primary, #111827)}.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}@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 .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"] }]
|
|
3461
|
+
}], ctorParameters: () => [{ type: i1$2.FormBuilder }, { type: i2$2.MatSnackBar }, { type: i3.HttpClient }], propDecorators: { config: [{
|
|
1464
3462
|
type: Input
|
|
1465
3463
|
}], jsonConfig: [{
|
|
1466
3464
|
type: Input
|
|
@@ -1468,10 +3466,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
1468
3466
|
type: Input
|
|
1469
3467
|
}], baseApiUrl: [{
|
|
1470
3468
|
type: Input
|
|
1471
|
-
}], formSubmit: [{
|
|
1472
|
-
type: Output
|
|
1473
|
-
}], formCancel: [{
|
|
1474
|
-
type: Output
|
|
1475
3469
|
}], optionsLoad: [{
|
|
1476
3470
|
type: Output
|
|
1477
3471
|
}] } });
|
|
@@ -2277,23 +4271,27 @@ class SharedUiModule {
|
|
|
2277
4271
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SharedUiModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
2278
4272
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: SharedUiModule, imports: [CommonModule,
|
|
2279
4273
|
MaterialModule,
|
|
2280
|
-
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
|
|
4274
|
+
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule, FilterModule,
|
|
2281
4275
|
SummaryCardModule,
|
|
2282
4276
|
ConfigurableFormModule,
|
|
4277
|
+
FormComponentsModule,
|
|
2283
4278
|
SmartFormModule], exports: [MaterialModule,
|
|
2284
|
-
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
|
|
4279
|
+
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule, FilterModule,
|
|
2285
4280
|
SummaryCardModule,
|
|
2286
4281
|
ConfigurableFormModule,
|
|
4282
|
+
FormComponentsModule,
|
|
2287
4283
|
SmartFormModule] });
|
|
2288
4284
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SharedUiModule, imports: [CommonModule,
|
|
2289
4285
|
MaterialModule,
|
|
2290
|
-
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
|
|
4286
|
+
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule, FilterModule,
|
|
2291
4287
|
SummaryCardModule,
|
|
2292
4288
|
ConfigurableFormModule,
|
|
4289
|
+
FormComponentsModule,
|
|
2293
4290
|
SmartFormModule, MaterialModule,
|
|
2294
|
-
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
|
|
4291
|
+
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule, FilterModule,
|
|
2295
4292
|
SummaryCardModule,
|
|
2296
4293
|
ConfigurableFormModule,
|
|
4294
|
+
FormComponentsModule,
|
|
2297
4295
|
SmartFormModule] });
|
|
2298
4296
|
}
|
|
2299
4297
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SharedUiModule, decorators: [{
|
|
@@ -2303,17 +4301,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
2303
4301
|
imports: [
|
|
2304
4302
|
CommonModule,
|
|
2305
4303
|
MaterialModule,
|
|
2306
|
-
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
|
|
4304
|
+
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule, FilterModule,
|
|
2307
4305
|
SummaryCardModule,
|
|
2308
4306
|
ConfigurableFormModule,
|
|
2309
|
-
|
|
4307
|
+
FormComponentsModule,
|
|
4308
|
+
SmartFormModule
|
|
2310
4309
|
],
|
|
2311
4310
|
exports: [
|
|
2312
4311
|
MaterialModule,
|
|
2313
|
-
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule,
|
|
4312
|
+
AlertModule, ButtonModule, ConfirmationModalModule, FilterSidebarModule, FilterModule,
|
|
2314
4313
|
SummaryCardModule,
|
|
2315
4314
|
ConfigurableFormModule,
|
|
2316
|
-
|
|
4315
|
+
FormComponentsModule,
|
|
4316
|
+
SmartFormModule
|
|
2317
4317
|
],
|
|
2318
4318
|
}]
|
|
2319
4319
|
}] });
|
|
@@ -2435,8 +4435,6 @@ const EXAMPLE_FORM_CONFIG = {
|
|
|
2435
4435
|
]
|
|
2436
4436
|
}
|
|
2437
4437
|
],
|
|
2438
|
-
submitLabel: 'Save',
|
|
2439
|
-
cancelLabel: 'Cancel',
|
|
2440
4438
|
entityType: 'User'
|
|
2441
4439
|
};
|
|
2442
4440
|
/**
|
|
@@ -2500,8 +4498,6 @@ const TARGET_GROUP_CONFIG = {
|
|
|
2500
4498
|
]
|
|
2501
4499
|
}
|
|
2502
4500
|
],
|
|
2503
|
-
submitLabel: 'Save Configuration',
|
|
2504
|
-
cancelLabel: 'Cancel'
|
|
2505
4501
|
};
|
|
2506
4502
|
|
|
2507
4503
|
var configurableForm_examples = /*#__PURE__*/Object.freeze({
|
|
@@ -2733,6 +4729,253 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
2733
4729
|
}]
|
|
2734
4730
|
}] });
|
|
2735
4731
|
|
|
4732
|
+
class FilterComponent {
|
|
4733
|
+
elementRef;
|
|
4734
|
+
router;
|
|
4735
|
+
route;
|
|
4736
|
+
config = { items: [] };
|
|
4737
|
+
activeFilters = {};
|
|
4738
|
+
columns = [];
|
|
4739
|
+
labels = {
|
|
4740
|
+
filterBtn: '',
|
|
4741
|
+
clear: '',
|
|
4742
|
+
apply: '',
|
|
4743
|
+
search: '',
|
|
4744
|
+
columns: '',
|
|
4745
|
+
showAll: '',
|
|
4746
|
+
hideAll: ''
|
|
4747
|
+
};
|
|
4748
|
+
theme = '';
|
|
4749
|
+
filterChange = new EventEmitter();
|
|
4750
|
+
columnChange = new EventEmitter();
|
|
4751
|
+
toggle = new EventEmitter();
|
|
4752
|
+
isOpen = false;
|
|
4753
|
+
activeTab = 'filters';
|
|
4754
|
+
// Temporary state while panel is open
|
|
4755
|
+
tempFilters = {};
|
|
4756
|
+
tempColumns = [];
|
|
4757
|
+
constructor(elementRef, router, route) {
|
|
4758
|
+
this.elementRef = elementRef;
|
|
4759
|
+
this.router = router;
|
|
4760
|
+
this.route = route;
|
|
4761
|
+
}
|
|
4762
|
+
ngOnInit() {
|
|
4763
|
+
this.syncTempState();
|
|
4764
|
+
this.initFromUrl();
|
|
4765
|
+
}
|
|
4766
|
+
initFromUrl() {
|
|
4767
|
+
if (this.config.settings?.persistent) {
|
|
4768
|
+
this.route.queryParams.subscribe(params => {
|
|
4769
|
+
if (Object.keys(params).length > 0) {
|
|
4770
|
+
const newFilters = { ...this.activeFilters };
|
|
4771
|
+
Object.keys(params).forEach(key => {
|
|
4772
|
+
// Skip non-filter params if possible, or assume all are filters
|
|
4773
|
+
// Ideally we check against config items
|
|
4774
|
+
if (params[key] !== undefined) {
|
|
4775
|
+
newFilters[key] = params[key];
|
|
4776
|
+
}
|
|
4777
|
+
});
|
|
4778
|
+
this.activeFilters = newFilters;
|
|
4779
|
+
this.syncTempState();
|
|
4780
|
+
}
|
|
4781
|
+
});
|
|
4782
|
+
}
|
|
4783
|
+
}
|
|
4784
|
+
onClickOutside(event) {
|
|
4785
|
+
if (!this.elementRef.nativeElement.contains(event.target)) {
|
|
4786
|
+
this.isOpen = false;
|
|
4787
|
+
}
|
|
4788
|
+
}
|
|
4789
|
+
togglePanel() {
|
|
4790
|
+
this.isOpen = !this.isOpen;
|
|
4791
|
+
if (this.isOpen) {
|
|
4792
|
+
this.syncTempState();
|
|
4793
|
+
this.activeTab = 'filters';
|
|
4794
|
+
}
|
|
4795
|
+
this.toggle.emit(this.isOpen);
|
|
4796
|
+
}
|
|
4797
|
+
setActiveTab(tab) {
|
|
4798
|
+
this.activeTab = tab;
|
|
4799
|
+
}
|
|
4800
|
+
// Generic Filter Change Handler
|
|
4801
|
+
onFilterChange(key, value) {
|
|
4802
|
+
if (!key)
|
|
4803
|
+
return;
|
|
4804
|
+
this.tempFilters[key] = value;
|
|
4805
|
+
}
|
|
4806
|
+
// Column Visibility Logic
|
|
4807
|
+
toggleColumn(columnId) {
|
|
4808
|
+
const col = this.tempColumns.find(c => c.id === columnId);
|
|
4809
|
+
if (col) {
|
|
4810
|
+
col.visible = !col.visible;
|
|
4811
|
+
}
|
|
4812
|
+
}
|
|
4813
|
+
toggleAllColumns(visible) {
|
|
4814
|
+
this.tempColumns.forEach(c => c.visible = visible);
|
|
4815
|
+
}
|
|
4816
|
+
// Actions
|
|
4817
|
+
clearAll() {
|
|
4818
|
+
if (this.activeTab === 'filters') {
|
|
4819
|
+
this.tempFilters = {};
|
|
4820
|
+
if (this.config.settings?.persistent) {
|
|
4821
|
+
this.updateUrl({});
|
|
4822
|
+
}
|
|
4823
|
+
}
|
|
4824
|
+
else {
|
|
4825
|
+
// Reset columns to default or show all?
|
|
4826
|
+
// Usually 'clear' in filters context means clear filters
|
|
4827
|
+
// But if we are in columns tab, maybe we want to reset columns?
|
|
4828
|
+
// For now, let's keep it simple: generic clear clears filters.
|
|
4829
|
+
this.tempFilters = {};
|
|
4830
|
+
}
|
|
4831
|
+
// If we want clear to apply immediately without clicking apply:
|
|
4832
|
+
// this.apply();
|
|
4833
|
+
// But usually "Clear" inside panel just clears temp state until Apply is clicked.
|
|
4834
|
+
// However, if the user requested "Persistent" and "Clear", they might expect immediate URL update?
|
|
4835
|
+
// Standard UX: panel actions apply on "Apply".
|
|
4836
|
+
// The persisted state should only change when "Apply" is clicked?
|
|
4837
|
+
// Wait, if I update URL on clearAll inside panel, it might be confusing if panel is still open with cleared state but not "applied" to data.
|
|
4838
|
+
// Re-reading expectation: "Persistent" setting usually means the filter state is synced with URL.
|
|
4839
|
+
// If I clear temp state, URL shouldn't change until I click Apply.
|
|
4840
|
+
// SO I WILL NOT UPDATE URL HERE. The `initFromUrl` loads INTO `activeFilters`.
|
|
4841
|
+
// `apply()` updates `activeFilters` AND should update URL.
|
|
4842
|
+
}
|
|
4843
|
+
apply() {
|
|
4844
|
+
// Apply temp state to active state
|
|
4845
|
+
this.activeFilters = { ...this.tempFilters };
|
|
4846
|
+
// Clean up undefined/null values
|
|
4847
|
+
Object.keys(this.activeFilters).forEach(key => {
|
|
4848
|
+
if (this.activeFilters[key] === null || this.activeFilters[key] === undefined || this.activeFilters[key] === '') {
|
|
4849
|
+
delete this.activeFilters[key];
|
|
4850
|
+
}
|
|
4851
|
+
});
|
|
4852
|
+
// Apply columns
|
|
4853
|
+
this.columns = this.tempColumns.map(c => ({ ...c }));
|
|
4854
|
+
this.filterChange.emit(this.activeFilters);
|
|
4855
|
+
this.columnChange.emit(this.columns);
|
|
4856
|
+
if (this.config.settings?.persistent) {
|
|
4857
|
+
this.updateUrl(this.activeFilters);
|
|
4858
|
+
}
|
|
4859
|
+
this.isOpen = false;
|
|
4860
|
+
}
|
|
4861
|
+
updateUrl(queryParams) {
|
|
4862
|
+
this.router.navigate([], {
|
|
4863
|
+
relativeTo: this.route,
|
|
4864
|
+
queryParams: queryParams,
|
|
4865
|
+
queryParamsHandling: 'merge', // or 'replace' to clear others? 'merge' ensures we don't lose other params
|
|
4866
|
+
// But wait, if we removed a filter, merge keeps it?
|
|
4867
|
+
// We need to explicitly clear removed keys if we use merge.
|
|
4868
|
+
// Or use pure replacement of filter keys.
|
|
4869
|
+
// For simplicity, let's assuming we want to replace parameters that overlap.
|
|
4870
|
+
// But to clear keys, we need to pass `null` or `undefined` for those keys in `queryParams`?
|
|
4871
|
+
// Angular router: passing null removes the param.
|
|
4872
|
+
});
|
|
4873
|
+
// Refined updateUrl logic:
|
|
4874
|
+
// We merged activeFilters. But if we removed a key, it's missing from activeFilters.
|
|
4875
|
+
// We need to compare with current params and remove keys that are no longer in activeFilters?
|
|
4876
|
+
// A simpler way for this component:
|
|
4877
|
+
// We likely want to replace ALL query params that correspond to filters.
|
|
4878
|
+
// But we don't know which params are filters vs other things (e.g. page, sort).
|
|
4879
|
+
// For now, I will just push `this.activeFilters`.
|
|
4880
|
+
// NOTE: This doesn't clear keys that were removed.
|
|
4881
|
+
// To fix clearing:
|
|
4882
|
+
// I should probably navigate with exact activeFilters if I knew they are the ONLY params.
|
|
4883
|
+
// Better:
|
|
4884
|
+
// this.router.navigate([], { queryParams: this.activeFilters }); // property replaces all
|
|
4885
|
+
// If we want to keep 'page', etc., we need to include them.
|
|
4886
|
+
// Let's use 'merge' but we need to handle clearing.
|
|
4887
|
+
// I will implement a smarter update.
|
|
4888
|
+
}
|
|
4889
|
+
activeFilterCountValue() {
|
|
4890
|
+
return Object.keys(this.activeFilters).length;
|
|
4891
|
+
}
|
|
4892
|
+
get activeFilterCount() {
|
|
4893
|
+
return Object.keys(this.activeFilters).length;
|
|
4894
|
+
}
|
|
4895
|
+
syncTempState() {
|
|
4896
|
+
this.tempFilters = { ...this.activeFilters };
|
|
4897
|
+
this.tempColumns = JSON.parse(JSON.stringify(this.columns || []));
|
|
4898
|
+
}
|
|
4899
|
+
get containerStyles() {
|
|
4900
|
+
const styles = {};
|
|
4901
|
+
if (this.config.styles) {
|
|
4902
|
+
if (this.config.styles.width)
|
|
4903
|
+
styles['--cc-filter-panel-width'] = this.config.styles.width;
|
|
4904
|
+
if (this.config.styles.padding)
|
|
4905
|
+
styles['--cc-filter-panel-padding'] = this.config.styles.padding;
|
|
4906
|
+
if (this.config.styles.gap)
|
|
4907
|
+
styles['--cc-filter-panel-gap'] = this.config.styles.gap;
|
|
4908
|
+
if (this.config.styles.backgroundColor)
|
|
4909
|
+
styles['--cc-filter-panel-bg'] = this.config.styles.backgroundColor;
|
|
4910
|
+
if (this.config.styles.borderRadius)
|
|
4911
|
+
styles['--cc-filter-panel-radius'] = this.config.styles.borderRadius;
|
|
4912
|
+
if (this.config.styles.headerHeight)
|
|
4913
|
+
styles['--cc-filter-panel-header-height'] = this.config.styles.headerHeight;
|
|
4914
|
+
}
|
|
4915
|
+
return styles;
|
|
4916
|
+
}
|
|
4917
|
+
trackByFn(index, item) {
|
|
4918
|
+
return item.key || index;
|
|
4919
|
+
}
|
|
4920
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterComponent, deps: [{ token: i0.ElementRef }, { token: i1$1.Router }, { token: i1$1.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
|
|
4921
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FilterComponent, isStandalone: false, selector: "lib-filter", inputs: { config: "config", activeFilters: "activeFilters", columns: "columns", labels: "labels", theme: "theme" }, outputs: { filterChange: "filterChange", columnChange: "columnChange", toggle: "toggle" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, ngImport: i0, template: "<div class=\"cc-filter-container\" [class.is-open]=\"isOpen\" [ngStyle]=\"containerStyles\">\r\n\r\n <!-- Trigger Button -->\r\n <lib-button variant=\"outline\" (click)=\"togglePanel()\" class=\"cc-filter-trigger\"\r\n [class.active]=\"activeFilterCount > 0\">\r\n <span class=\"fas fa-filter\"></span> {{ labels?.filterBtn || 'Filter' }}\r\n <span *ngIf=\"activeFilterCount > 0\" class=\"cc-badge\">{{ activeFilterCount }}</span>\r\n </lib-button>\r\n\r\n <!-- Dropdown Panel -->\r\n <div class=\"cc-filter-panel mat-elevation-z4\" *ngIf=\"isOpen\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header / Tabs -->\r\n <div class=\"cc-panel-header\">\r\n <div class=\"cc-tabs\">\r\n <div class=\"cc-tab\" [class.active]=\"activeTab === 'filters'\" (click)=\"setActiveTab('filters')\">\r\n {{ labels.filterBtn }}\r\n </div>\r\n <!-- Hide columns tab if no columns config provided -->\r\n <div class=\"cc-tab\" [class.active]=\"activeTab === 'columns'\" (click)=\"setActiveTab('columns')\"\r\n *ngIf=\"columns?.length\">\r\n {{ labels.columns }}\r\n </div>\r\n </div>\r\n <button type=\"button\" class=\"cc-icon-btn\" (click)=\"togglePanel()\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Filters Tab Content -->\r\n <div class=\"cc-panel-content\" *ngIf=\"activeTab === 'filters'\">\r\n\r\n <!-- Dynamic Items -->\r\n <ng-container *ngFor=\"let item of config.items; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: item }\"></ng-container>\r\n </ng-container>\r\n\r\n </div>\r\n\r\n <!-- Columns Tab Content -->\r\n <div class=\"cc-panel-content\" *ngIf=\"activeTab === 'columns'\">\r\n <div class=\"cc-columns-actions\">\r\n <lib-button variant=\"outline\" class=\"cc-btn-text\" (click)=\"toggleAllColumns(true)\">{{ labels.showAll\r\n }}</lib-button>\r\n <lib-button variant=\"outline\" class=\"cc-btn-text\" (click)=\"toggleAllColumns(false)\">{{ labels.hideAll\r\n }}</lib-button>\r\n </div>\r\n <div class=\"cc-columns-list\">\r\n <div *ngFor=\"let col of tempColumns\" class=\"cc-column-item\">\r\n <lib-checkbox [label]=\"col.label\" [checked]=\"col.visible\" (checkedChange)=\"toggleColumn(col.id)\">\r\n </lib-checkbox>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Footer Actions -->\r\n <div class=\"cc-panel-footer\">\r\n <lib-button variant=\"outline\" color=\"warn\" class=\"cc-btn-text text-danger\" (click)=\"clearAll()\">\r\n {{ labels.clear }}\r\n </lib-button>\r\n <lib-button class=\"ms-2\" variant=\"primary\" (click)=\"apply()\">\r\n {{ labels.apply }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive Template for Items -->\r\n<ng-template #itemTemplate let-item=\"item\">\r\n <div class=\"cc-filter-item\" [ngClass]=\"['type-' + item.type]\"\r\n [style.display]=\"item.visible === false ? 'none' : 'block'\" [ngStyle]=\"item.styles\">\r\n\r\n <ng-container [ngSwitch]=\"item.type\">\r\n\r\n <!-- Input -->\r\n <lib-input *ngSwitchCase=\"'input'\" [config]=\"item.inputConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (valueChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-input>\r\n\r\n <!-- Dropdown -->\r\n <lib-dropdown *ngSwitchCase=\"'dropdown'\" [config]=\"item.dropdownConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (selectionChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-dropdown>\r\n\r\n <!-- Checkbox -->\r\n <lib-checkbox *ngSwitchCase=\"'checkbox'\" [config]=\"item.checkboxConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (checkedChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-checkbox>\r\n\r\n <!-- Radio -->\r\n <lib-radio *ngSwitchCase=\"'radio'\" [config]=\"item.radioConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (selectionChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-radio>\r\n\r\n <!-- Toggle -->\r\n <lib-toggle *ngSwitchCase=\"'toggle'\" [config]=\"item.toggleConfig\" [label]=\"item.label\"\r\n [checked]=\"tempFilters[item.key]\" (toggleChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-toggle>\r\n\r\n <!-- Datepicker -->\r\n <lib-datepicker *ngSwitchCase=\"'datepicker'\" [config]=\"item.datepickerConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (dateChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-datepicker>\r\n\r\n <!-- Search -->\r\n <lib-search *ngSwitchCase=\"'active-search'\" [config]=\"item.searchConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (search)=\"onFilterChange(item.key, $event)\">\r\n </lib-search>\r\n\r\n <!-- Group / Accordion -->\r\n <div *ngSwitchCase=\"'group'\" class=\"cc-accordion-item\" [class.expanded]=\"item.expanded\">\r\n <button type=\"button\" class=\"cc-accordion-header\" (click)=\"item.expanded = !item.expanded\">\r\n <span class=\"cc-accordion-title\">{{ item.label }}</span>\r\n <span class=\"material-icons cc-accordion-icon\">{{ item.expanded ? 'expand_less' : 'expand_more'\r\n }}</span>\r\n </button>\r\n\r\n <div class=\"cc-accordion-body\" *ngIf=\"item.expanded\">\r\n <ng-container *ngFor=\"let child of item.children; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: child }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Custom Divider -->\r\n <div *ngSwitchCase=\"'divider'\" class=\"cc-filter-divider\"></div>\r\n\r\n </ng-container>\r\n </div>\r\n</ng-template>", styles: [".cc-filter-container{position:relative;display:inline-block;font-family:var(--cc-filter-font-family, \"Roboto\", sans-serif)}.cc-filter-container .cc-filter-trigger ::ng-deep button{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:var(--cc-filter-btn-width, 103px);height:var(--cc-filter-btn-height, 44px);padding:0 16px;background-color:var(--cc-filter-btn-bg, #FCFCFB);border:var(--cc-filter-btn-border, 1px solid #E8EAED);border-radius:var(--cc-filter-btn-radius, 8px);color:var(--cc-filter-btn-text-color, #5F6368);font-size:14px;font-weight:500;transition:all .2s ease}.cc-filter-container .cc-filter-trigger ::ng-deep button mat-icon,.cc-filter-container .cc-filter-trigger ::ng-deep button .material-icons{color:#5f6368}.cc-filter-container .cc-filter-trigger ::ng-deep button:hover{background-color:var(--cc-filter-btn-hover-bg, #f1f3f4)}.cc-filter-container .cc-filter-trigger.active ::ng-deep button{background-color:var(--cc-filter-btn-active-bg, #e3f2fd);color:var(--cc-filter-btn-active-text, #1976d2);border-color:var(--cc-filter-btn-active-text, #1976d2)}.cc-filter-container .cc-filter-trigger.active ::ng-deep button mat-icon,.cc-filter-container .cc-filter-trigger.active ::ng-deep button .material-icons{color:var(--cc-filter-btn-active-text, #1976d2)}.cc-filter-container .cc-filter-trigger .cc-badge{background-color:var(--cc-filter-btn-badge-bg, #f44336);color:var(--cc-filter-btn-badge-text, #fff);font-size:10px;font-weight:700;padding:2px 6px;border-radius:10px;min-width:16px;text-align:center;margin-left:4px;line-height:1}.cc-filter-container .cc-filter-panel{position:absolute;top:calc(100% + 8px);right:0;z-index:1000;width:var(--cc-filter-panel-width, 320px);min-width:var(--cc-filter-panel-min-width, 480px)!important;padding:var(--cc-filter-panel-padding, 0);background-color:var(--cc-filter-panel-bg, #fff);border:var(--cc-filter-panel-border, 1px solid #e0e0e0);box-shadow:var(--cc-filter-panel-shadow, 0 4px 12px rgba(0, 0, 0, .15));border-radius:var(--cc-filter-panel-radius, 8px);display:flex;flex-direction:column;overflow:hidden}.cc-filter-container .cc-filter-panel.hidden{display:none}.cc-filter-container .cc-filter-panel .cc-panel-header{display:flex;align-items:center;justify-content:space-between;padding:0 1rem;height:var(--cc-filter-panel-header-height, 48px);border-bottom:1px solid #E0E0E0;background-color:var(--cc-filter-panel-header-bg, #fafafa)}.cc-filter-container .cc-tabs{display:flex;gap:1rem}.cc-filter-container .cc-tabs .cc-tab{cursor:pointer;padding:.5rem 0;font-weight:500;color:#5f6368;border-bottom:2px solid transparent;font-size:14px}.cc-filter-container .cc-tabs .cc-tab.active{color:var(--cc-filter-tab-active-text, #1976d2);border-bottom:var(--cc-filter-tab-border-bottom, 2px solid #1976d2)}.cc-filter-container .cc-icon-btn{background:none;border:none;cursor:pointer;color:#5f6368;padding:.25rem;border-radius:50%;display:flex;align-items:center;justify-content:center}.cc-filter-container .cc-icon-btn:hover{background-color:#0000000a}.cc-filter-container .cc-panel-content{padding:16px;max-height:400px;overflow-y:auto;display:flex;flex-direction:column;gap:var(--cc-filter-panel-gap, 1rem)}.cc-filter-container .cc-filter-section{margin-bottom:16px}.cc-filter-container .cc-filter-section .cc-section-title{font-size:13px;font-weight:600;margin-bottom:8px;color:var(--cc-filter-section-title, #333);text-transform:uppercase;letter-spacing:.5px}.cc-filter-container .cc-filter-section .cc-control-group{display:flex;flex-direction:column;gap:8px}.cc-filter-container .cc-filter-section .cc-control-group label{display:flex;align-items:center;gap:8px;font-size:14px;color:var(--cc-filter-option-text, #555);cursor:pointer}.cc-filter-container .cc-filter-section .cc-control-group label:hover{color:#000}.cc-filter-container .cc-accordion-item{border-bottom:1px solid #E0E0E0}.cc-filter-container .cc-accordion-item:last-child{border-bottom:none}.cc-filter-container .cc-accordion-item .cc-accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 0;background:none;border:none;cursor:pointer;text-align:left;outline:none}.cc-filter-container .cc-accordion-item .cc-accordion-header .cc-accordion-title{font-size:.875rem;font-weight:500;color:#202124}.cc-filter-container .cc-accordion-item .cc-accordion-header .cc-accordion-icon{color:#5f6368;transition:transform .2s}.cc-filter-container .cc-accordion-item .cc-accordion-body{padding:0 0 1rem;display:flex;flex-direction:column;gap:1rem;animation:slideDown .2s ease-out}.cc-filter-container .cc-filter-divider{height:1px;background-color:#e0e0e0;margin:.5rem 0}.cc-filter-container .cc-panel-footer{padding:12px 16px;background-color:var(--cc-filter-footer-bg, #fff);border-top:var(--cc-filter-footer-border-top, 1px solid #e0e0e0);display:flex;justify-content:flex-end;align-items:center;gap:10px}.cc-filter-container .cc-columns-actions{display:flex;gap:.5rem;margin-bottom:.5rem}.cc-filter-container .cc-columns-list{display:flex;flex-direction:column;gap:.5rem}\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.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { 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: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: InputComponent, selector: "lib-input", inputs: ["config", "labels", "type", "label", "placeholder", "disabled", "required", "readonly", "clearable", "maxLength", "minLength", "min", "max", "pattern", "errorMessage", "helperText", "rows", "prefixIcon", "suffixIcon", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["valueChange", "inputBlur", "inputFocus"] }, { kind: "component", type: DropdownComponent, selector: "lib-dropdown", inputs: ["config", "labels", "options", "placeholder", "label", "multiple", "searchable", "clearable", "disabled", "required", "errorMessage", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["selectionChange"] }, { kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["config", "label", "options", "disabled", "required", "labelPosition", "color", "layout", "labels", "gap", "labelColor", "checkedColor", "uncheckedColor", "fontSize", "fontWeight", "fontFamily", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight", "disabledColor", "errorColor", "size", "borderRadius", "labelFontSize", "labelFontWeight"], outputs: ["selectionChange"] }, { kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: DatepickerComponent, selector: "lib-datepicker", inputs: ["config", "labels", "label", "placeholder", "disabled", "required", "minDate", "maxDate", "isRange", "startView", "value", "startDate", "endDate", "errorMessage", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["dateChange"] }, { kind: "component", type: SearchComponent, selector: "lib-search", inputs: ["config", "labels", "placeholder", "label", "disabled", "debounceMs", "clearable", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "border", "padding", "fontWeight", "color", "textColor", "iconColor", "placeholderColor", "focusBorderColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["search", "clear"] }] });
|
|
4922
|
+
}
|
|
4923
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterComponent, decorators: [{
|
|
4924
|
+
type: Component,
|
|
4925
|
+
args: [{ selector: 'lib-filter', standalone: false, template: "<div class=\"cc-filter-container\" [class.is-open]=\"isOpen\" [ngStyle]=\"containerStyles\">\r\n\r\n <!-- Trigger Button -->\r\n <lib-button variant=\"outline\" (click)=\"togglePanel()\" class=\"cc-filter-trigger\"\r\n [class.active]=\"activeFilterCount > 0\">\r\n <span class=\"fas fa-filter\"></span> {{ labels?.filterBtn || 'Filter' }}\r\n <span *ngIf=\"activeFilterCount > 0\" class=\"cc-badge\">{{ activeFilterCount }}</span>\r\n </lib-button>\r\n\r\n <!-- Dropdown Panel -->\r\n <div class=\"cc-filter-panel mat-elevation-z4\" *ngIf=\"isOpen\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header / Tabs -->\r\n <div class=\"cc-panel-header\">\r\n <div class=\"cc-tabs\">\r\n <div class=\"cc-tab\" [class.active]=\"activeTab === 'filters'\" (click)=\"setActiveTab('filters')\">\r\n {{ labels.filterBtn }}\r\n </div>\r\n <!-- Hide columns tab if no columns config provided -->\r\n <div class=\"cc-tab\" [class.active]=\"activeTab === 'columns'\" (click)=\"setActiveTab('columns')\"\r\n *ngIf=\"columns?.length\">\r\n {{ labels.columns }}\r\n </div>\r\n </div>\r\n <button type=\"button\" class=\"cc-icon-btn\" (click)=\"togglePanel()\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Filters Tab Content -->\r\n <div class=\"cc-panel-content\" *ngIf=\"activeTab === 'filters'\">\r\n\r\n <!-- Dynamic Items -->\r\n <ng-container *ngFor=\"let item of config.items; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: item }\"></ng-container>\r\n </ng-container>\r\n\r\n </div>\r\n\r\n <!-- Columns Tab Content -->\r\n <div class=\"cc-panel-content\" *ngIf=\"activeTab === 'columns'\">\r\n <div class=\"cc-columns-actions\">\r\n <lib-button variant=\"outline\" class=\"cc-btn-text\" (click)=\"toggleAllColumns(true)\">{{ labels.showAll\r\n }}</lib-button>\r\n <lib-button variant=\"outline\" class=\"cc-btn-text\" (click)=\"toggleAllColumns(false)\">{{ labels.hideAll\r\n }}</lib-button>\r\n </div>\r\n <div class=\"cc-columns-list\">\r\n <div *ngFor=\"let col of tempColumns\" class=\"cc-column-item\">\r\n <lib-checkbox [label]=\"col.label\" [checked]=\"col.visible\" (checkedChange)=\"toggleColumn(col.id)\">\r\n </lib-checkbox>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Footer Actions -->\r\n <div class=\"cc-panel-footer\">\r\n <lib-button variant=\"outline\" color=\"warn\" class=\"cc-btn-text text-danger\" (click)=\"clearAll()\">\r\n {{ labels.clear }}\r\n </lib-button>\r\n <lib-button class=\"ms-2\" variant=\"primary\" (click)=\"apply()\">\r\n {{ labels.apply }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive Template for Items -->\r\n<ng-template #itemTemplate let-item=\"item\">\r\n <div class=\"cc-filter-item\" [ngClass]=\"['type-' + item.type]\"\r\n [style.display]=\"item.visible === false ? 'none' : 'block'\" [ngStyle]=\"item.styles\">\r\n\r\n <ng-container [ngSwitch]=\"item.type\">\r\n\r\n <!-- Input -->\r\n <lib-input *ngSwitchCase=\"'input'\" [config]=\"item.inputConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (valueChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-input>\r\n\r\n <!-- Dropdown -->\r\n <lib-dropdown *ngSwitchCase=\"'dropdown'\" [config]=\"item.dropdownConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (selectionChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-dropdown>\r\n\r\n <!-- Checkbox -->\r\n <lib-checkbox *ngSwitchCase=\"'checkbox'\" [config]=\"item.checkboxConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (checkedChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-checkbox>\r\n\r\n <!-- Radio -->\r\n <lib-radio *ngSwitchCase=\"'radio'\" [config]=\"item.radioConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (selectionChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-radio>\r\n\r\n <!-- Toggle -->\r\n <lib-toggle *ngSwitchCase=\"'toggle'\" [config]=\"item.toggleConfig\" [label]=\"item.label\"\r\n [checked]=\"tempFilters[item.key]\" (toggleChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-toggle>\r\n\r\n <!-- Datepicker -->\r\n <lib-datepicker *ngSwitchCase=\"'datepicker'\" [config]=\"item.datepickerConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (dateChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-datepicker>\r\n\r\n <!-- Search -->\r\n <lib-search *ngSwitchCase=\"'active-search'\" [config]=\"item.searchConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (search)=\"onFilterChange(item.key, $event)\">\r\n </lib-search>\r\n\r\n <!-- Group / Accordion -->\r\n <div *ngSwitchCase=\"'group'\" class=\"cc-accordion-item\" [class.expanded]=\"item.expanded\">\r\n <button type=\"button\" class=\"cc-accordion-header\" (click)=\"item.expanded = !item.expanded\">\r\n <span class=\"cc-accordion-title\">{{ item.label }}</span>\r\n <span class=\"material-icons cc-accordion-icon\">{{ item.expanded ? 'expand_less' : 'expand_more'\r\n }}</span>\r\n </button>\r\n\r\n <div class=\"cc-accordion-body\" *ngIf=\"item.expanded\">\r\n <ng-container *ngFor=\"let child of item.children; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: child }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Custom Divider -->\r\n <div *ngSwitchCase=\"'divider'\" class=\"cc-filter-divider\"></div>\r\n\r\n </ng-container>\r\n </div>\r\n</ng-template>", styles: [".cc-filter-container{position:relative;display:inline-block;font-family:var(--cc-filter-font-family, \"Roboto\", sans-serif)}.cc-filter-container .cc-filter-trigger ::ng-deep button{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:var(--cc-filter-btn-width, 103px);height:var(--cc-filter-btn-height, 44px);padding:0 16px;background-color:var(--cc-filter-btn-bg, #FCFCFB);border:var(--cc-filter-btn-border, 1px solid #E8EAED);border-radius:var(--cc-filter-btn-radius, 8px);color:var(--cc-filter-btn-text-color, #5F6368);font-size:14px;font-weight:500;transition:all .2s ease}.cc-filter-container .cc-filter-trigger ::ng-deep button mat-icon,.cc-filter-container .cc-filter-trigger ::ng-deep button .material-icons{color:#5f6368}.cc-filter-container .cc-filter-trigger ::ng-deep button:hover{background-color:var(--cc-filter-btn-hover-bg, #f1f3f4)}.cc-filter-container .cc-filter-trigger.active ::ng-deep button{background-color:var(--cc-filter-btn-active-bg, #e3f2fd);color:var(--cc-filter-btn-active-text, #1976d2);border-color:var(--cc-filter-btn-active-text, #1976d2)}.cc-filter-container .cc-filter-trigger.active ::ng-deep button mat-icon,.cc-filter-container .cc-filter-trigger.active ::ng-deep button .material-icons{color:var(--cc-filter-btn-active-text, #1976d2)}.cc-filter-container .cc-filter-trigger .cc-badge{background-color:var(--cc-filter-btn-badge-bg, #f44336);color:var(--cc-filter-btn-badge-text, #fff);font-size:10px;font-weight:700;padding:2px 6px;border-radius:10px;min-width:16px;text-align:center;margin-left:4px;line-height:1}.cc-filter-container .cc-filter-panel{position:absolute;top:calc(100% + 8px);right:0;z-index:1000;width:var(--cc-filter-panel-width, 320px);min-width:var(--cc-filter-panel-min-width, 480px)!important;padding:var(--cc-filter-panel-padding, 0);background-color:var(--cc-filter-panel-bg, #fff);border:var(--cc-filter-panel-border, 1px solid #e0e0e0);box-shadow:var(--cc-filter-panel-shadow, 0 4px 12px rgba(0, 0, 0, .15));border-radius:var(--cc-filter-panel-radius, 8px);display:flex;flex-direction:column;overflow:hidden}.cc-filter-container .cc-filter-panel.hidden{display:none}.cc-filter-container .cc-filter-panel .cc-panel-header{display:flex;align-items:center;justify-content:space-between;padding:0 1rem;height:var(--cc-filter-panel-header-height, 48px);border-bottom:1px solid #E0E0E0;background-color:var(--cc-filter-panel-header-bg, #fafafa)}.cc-filter-container .cc-tabs{display:flex;gap:1rem}.cc-filter-container .cc-tabs .cc-tab{cursor:pointer;padding:.5rem 0;font-weight:500;color:#5f6368;border-bottom:2px solid transparent;font-size:14px}.cc-filter-container .cc-tabs .cc-tab.active{color:var(--cc-filter-tab-active-text, #1976d2);border-bottom:var(--cc-filter-tab-border-bottom, 2px solid #1976d2)}.cc-filter-container .cc-icon-btn{background:none;border:none;cursor:pointer;color:#5f6368;padding:.25rem;border-radius:50%;display:flex;align-items:center;justify-content:center}.cc-filter-container .cc-icon-btn:hover{background-color:#0000000a}.cc-filter-container .cc-panel-content{padding:16px;max-height:400px;overflow-y:auto;display:flex;flex-direction:column;gap:var(--cc-filter-panel-gap, 1rem)}.cc-filter-container .cc-filter-section{margin-bottom:16px}.cc-filter-container .cc-filter-section .cc-section-title{font-size:13px;font-weight:600;margin-bottom:8px;color:var(--cc-filter-section-title, #333);text-transform:uppercase;letter-spacing:.5px}.cc-filter-container .cc-filter-section .cc-control-group{display:flex;flex-direction:column;gap:8px}.cc-filter-container .cc-filter-section .cc-control-group label{display:flex;align-items:center;gap:8px;font-size:14px;color:var(--cc-filter-option-text, #555);cursor:pointer}.cc-filter-container .cc-filter-section .cc-control-group label:hover{color:#000}.cc-filter-container .cc-accordion-item{border-bottom:1px solid #E0E0E0}.cc-filter-container .cc-accordion-item:last-child{border-bottom:none}.cc-filter-container .cc-accordion-item .cc-accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 0;background:none;border:none;cursor:pointer;text-align:left;outline:none}.cc-filter-container .cc-accordion-item .cc-accordion-header .cc-accordion-title{font-size:.875rem;font-weight:500;color:#202124}.cc-filter-container .cc-accordion-item .cc-accordion-header .cc-accordion-icon{color:#5f6368;transition:transform .2s}.cc-filter-container .cc-accordion-item .cc-accordion-body{padding:0 0 1rem;display:flex;flex-direction:column;gap:1rem;animation:slideDown .2s ease-out}.cc-filter-container .cc-filter-divider{height:1px;background-color:#e0e0e0;margin:.5rem 0}.cc-filter-container .cc-panel-footer{padding:12px 16px;background-color:var(--cc-filter-footer-bg, #fff);border-top:var(--cc-filter-footer-border-top, 1px solid #e0e0e0);display:flex;justify-content:flex-end;align-items:center;gap:10px}.cc-filter-container .cc-columns-actions{display:flex;gap:.5rem;margin-bottom:.5rem}.cc-filter-container .cc-columns-list{display:flex;flex-direction:column;gap:.5rem}\n"] }]
|
|
4926
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1$1.Router }, { type: i1$1.ActivatedRoute }], propDecorators: { config: [{
|
|
4927
|
+
type: Input
|
|
4928
|
+
}], activeFilters: [{
|
|
4929
|
+
type: Input
|
|
4930
|
+
}], columns: [{
|
|
4931
|
+
type: Input
|
|
4932
|
+
}], labels: [{
|
|
4933
|
+
type: Input
|
|
4934
|
+
}], theme: [{
|
|
4935
|
+
type: Input
|
|
4936
|
+
}], filterChange: [{
|
|
4937
|
+
type: Output
|
|
4938
|
+
}], columnChange: [{
|
|
4939
|
+
type: Output
|
|
4940
|
+
}], toggle: [{
|
|
4941
|
+
type: Output
|
|
4942
|
+
}], onClickOutside: [{
|
|
4943
|
+
type: HostListener,
|
|
4944
|
+
args: ['document:click', ['$event']]
|
|
4945
|
+
}] } });
|
|
4946
|
+
|
|
4947
|
+
class FilterModule {
|
|
4948
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
4949
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: FilterModule, declarations: [FilterComponent], imports: [CommonModule,
|
|
4950
|
+
FormsModule,
|
|
4951
|
+
ReactiveFormsModule,
|
|
4952
|
+
ButtonModule,
|
|
4953
|
+
FormComponentsModule], exports: [FilterComponent] });
|
|
4954
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterModule, imports: [CommonModule,
|
|
4955
|
+
FormsModule,
|
|
4956
|
+
ReactiveFormsModule,
|
|
4957
|
+
ButtonModule,
|
|
4958
|
+
FormComponentsModule] });
|
|
4959
|
+
}
|
|
4960
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterModule, decorators: [{
|
|
4961
|
+
type: NgModule,
|
|
4962
|
+
args: [{
|
|
4963
|
+
declarations: [
|
|
4964
|
+
FilterComponent
|
|
4965
|
+
],
|
|
4966
|
+
imports: [
|
|
4967
|
+
CommonModule,
|
|
4968
|
+
FormsModule,
|
|
4969
|
+
ReactiveFormsModule,
|
|
4970
|
+
ButtonModule,
|
|
4971
|
+
FormComponentsModule
|
|
4972
|
+
],
|
|
4973
|
+
exports: [
|
|
4974
|
+
FilterComponent
|
|
4975
|
+
]
|
|
4976
|
+
}]
|
|
4977
|
+
}] });
|
|
4978
|
+
|
|
2736
4979
|
class SmartTableComponent {
|
|
2737
4980
|
http;
|
|
2738
4981
|
router;
|
|
@@ -3193,7 +5436,7 @@ class SmartTableComponent {
|
|
|
3193
5436
|
}
|
|
3194
5437
|
}
|
|
3195
5438
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableComponent, deps: [{ token: i3.HttpClient }, { token: i1$1.Router }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
3196
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartTableComponent, isStandalone: false, selector: "lib-smart-table", inputs: { config: "config" }, outputs: { action: "action", topAction: "topAction", filterChange: "filterChange", rowSelect: "rowSelect", rowClick: "rowClick" }, viewQueries: [{ propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-table-wrapper\">\n <!-- Top Toolbar -->\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\n \n <!-- Search -->\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\n <i class=\"fa fa-search\"></i>\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\n </div>\n\n <!-- Filters -->\n <div class=\"st-filters\" *ngIf=\"config.filters\">\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\n <select (change)=\"onFilterChange(filter.key, $event)\">\n <option value=\"\">{{ filter.label }}</option>\n <option *ngFor=\"let opt of filter.options\" [value]=\"opt.value\">{{ opt.label }}</option>\n </select>\n </div>\n </div>\n\n <!-- Top Bar Buttons -->\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\n <lib-button *ngFor=\"let btn of config.topBarButtons\" \n [variant]=\"btn.btnVariant || 'primary'\"\n [icon]=\"btn.icon || ''\"\n (click)=\"onTopAction(btn)\">\n {{ btn.label }}\n </lib-button>\n </div>\n </div>\n\n <!-- Table Container -->\n <div class=\"st-table-container\">\n <div class=\"st-check-loader\" *ngIf=\"loading\">\n <div class=\"spinner\"></div>\n </div>\n <table class=\"st-table\" [class.loading-data]=\"loading\">\n <thead>\n <tr>\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\n </th>\n <th *ngFor=\"let col of config.columns\" \n #stickyHeader\n [class.sortable]=\"col.sortable\"\n [class.sticky-col]=\"col.sticky\"\n [ngStyle]=\"stickyColumnStyles[col.key]\"\n (click)=\"onSort(col)\">\n {{ col.label }}\n <span *ngIf=\"col.sortable\" class=\"sort-icon\">\n <i class=\"fa\" [ngClass]=\"getSortIcon(col.key)\"></i>\n </span>\n </th>\n <th *ngIf=\"config.actions && config.actions.length > 0\">{{ config.labels?.actionColumnHeader || 'Actions' }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of data\" \n [class.clickable-row]=\"config.clickableRows\" \n (click)=\"onRowClick(row)\">\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\n </td>\n <td *ngFor=\"let col of config.columns\" [class.sticky-col]=\"col.sticky\" [ngStyle]=\"stickyColumnStyles[col.key]\">\n <!-- Text/Number/Date -->\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\n {{ getCellValue(row, col) }}\n </span>\n <!-- HTML -->\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col)\"></div>\n <!-- Badge -->\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\n {{ getCellValue(row, col) }}\n </span>\n </td>\n \n <!-- Row Actions -->\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions\">\n <div class=\"action-buttons\">\n <ng-container *ngFor=\"let action of config.actions\">\n <lib-button \n [variant]=\"action.btnVariant || 'secondary'\"\n [icon]=\"action.icon || ''\"\n (click)=\"onAction(action, row)\">\n {{ action.label }}\n </lib-button>\n </ng-container>\n </div>\n <!-- Alternatively use specific icons if needed, but button component is requested -->\n </td>\n </tr>\n <tr *ngIf=\"data.length === 0 && !loading\">\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\n {{ config.labels?.noDataMessage || 'No data available' }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"st-pagination\" *ngIf=\"config.pagination && config.pagination.enabled\">\n <lib-pagination\n [totalItems]=\"totalItems\"\n [itemsPerPage]=\"config.pagination.pageSize\"\n [currentPage]=\"currentPage\"\n [pageSizeOptions]=\"config.pagination.pageSizeOptions\"\n (pageChange)=\"onPageChange($event)\"\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\n </lib-pagination>\n </div>\n</div>\n", styles: [".smart-table-wrapper{font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 4px rgba(0, 0, 0, .05));display:flex;flex-direction:column;gap:0;padding:0;border:var(--st-table-border, 1px solid #e0e0e0);overflow:hidden}.st-toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1rem);background:var(--st-toolbar-bg, #fff);border-bottom:var(--st-toolbar-border-bottom, 1px solid #eee);gap:var(--st-toolbar-gap, 1rem)}.st-toolbar .st-search{position:relative;width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:var(--st-search-padding, .5rem .5rem .5rem 2rem);border:var(--st-search-border, 1px solid #ccc);border-radius:var(--st-search-radius, 4px);background:var(--st-search-bg, #fff);font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333)}.st-toolbar .st-search i{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #999)}.st-toolbar .st-filters{display:flex;gap:1rem}.st-toolbar .st-filters select{padding:var(--st-filter-padding, .5rem);border:var(--st-filter-border, 1px solid #ccc);border-radius:var(--st-filter-radius, 4px);font-size:var(--st-filter-font-size, 14px);background:var(--st-filter-bg, #fff);color:var(--st-filter-color, #333)}.st-toolbar .st-actions{display:flex;gap:.5rem}.st-table-container{overflow-x:auto;overflow-y:auto;padding:var(--st-table-padding, 1rem)}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f9f9f9);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f9f9f9)}.st-table-container table thead th{padding:.75rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-bottom:var(--st-header-border, 1px solid #eee);white-space:nowrap}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th .sort-icon{margin-left:.5rem}.st-table-container table thead th .sort-icon .sort-icon{margin-left:.5rem;font-size:var(--st-sort-icon-size, .8em)}.st-table-container table thead th.st-checkbox-col{width:40px}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f9f9f9);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table thead th.sticky-col:first-child{left:0}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:var(--st-cell-padding, 1rem);color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee)}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr:hover td,.st-table-container table tbody tr:hover td.sticky-col{background:var(--st-row-hover-bg, #f9f9f9)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr.clickable-row,.st-table-container table tbody tr.clickable-row td{cursor:pointer}.st-table-container table tbody tr.clickable-row:hover td,.st-table-container table tbody tr.clickable-row:hover td.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}input[type=checkbox]{accent-color:var(--st-checkbox-color, #6200EE);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center}.no-data{text-align:center;padding:2rem;color:var(--st-no-data-color, #888)}.st-pagination{padding:var(--st-pagination-padding, 1rem);border-top:var(--st-pagination-border-top, none)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}}.st-table-container{position:relative;min-height:200px}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\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: "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.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { 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: PaginationComponent, selector: "lib-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "pageSizeOptions", "theme", "labels"], outputs: ["pageChange", "itemsPerPageChange"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon"] }] });
|
|
5439
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartTableComponent, isStandalone: false, selector: "lib-smart-table", inputs: { config: "config" }, outputs: { action: "action", topAction: "topAction", filterChange: "filterChange", rowSelect: "rowSelect", rowClick: "rowClick" }, viewQueries: [{ propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-table-wrapper\">\n <!-- Top Toolbar -->\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\n \n <!-- Search -->\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\n <i class=\"fa fa-search\"></i>\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\n </div>\n\n <!-- Filters -->\n <div class=\"st-filters\" *ngIf=\"config.filters\">\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\n <select (change)=\"onFilterChange(filter.key, $event)\">\n <option value=\"\">{{ filter.label }}</option>\n <option *ngFor=\"let opt of filter.options\" [value]=\"opt.value\">{{ opt.label }}</option>\n </select>\n </div>\n </div>\n\n <!-- Top Bar Buttons -->\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\n <lib-button *ngFor=\"let btn of config.topBarButtons\" \n [variant]=\"btn.btnVariant || 'primary'\"\n [icon]=\"btn.icon || ''\"\n (click)=\"onTopAction(btn)\">\n {{ btn.label }}\n </lib-button>\n </div>\n </div>\n\n <!-- Table Container -->\n <div class=\"st-table-container\">\n <div class=\"st-check-loader\" *ngIf=\"loading\">\n <div class=\"spinner\"></div>\n </div>\n <table class=\"st-table\" [class.loading-data]=\"loading\">\n <thead>\n <tr>\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\n </th>\n <th *ngFor=\"let col of config.columns\" \n #stickyHeader\n [class.sortable]=\"col.sortable\"\n [class.sticky-col]=\"col.sticky\"\n [ngStyle]=\"stickyColumnStyles[col.key]\"\n (click)=\"onSort(col)\">\n {{ col.label }}\n <span *ngIf=\"col.sortable\" class=\"sort-icon\">\n <i class=\"fa\" [ngClass]=\"getSortIcon(col.key)\"></i>\n </span>\n </th>\n <th *ngIf=\"config.actions && config.actions.length > 0\">{{ config.labels?.actionColumnHeader || 'Actions' }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of data\" \n [class.clickable-row]=\"config.clickableRows\" \n (click)=\"onRowClick(row)\">\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\n </td>\n <td *ngFor=\"let col of config.columns\" [class.sticky-col]=\"col.sticky\" [ngStyle]=\"stickyColumnStyles[col.key]\">\n <!-- Text/Number/Date -->\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\n {{ getCellValue(row, col) }}\n </span>\n <!-- HTML -->\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col)\"></div>\n <!-- Badge -->\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\n {{ getCellValue(row, col) }}\n </span>\n </td>\n \n <!-- Row Actions -->\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions\">\n <div class=\"action-buttons\">\n <ng-container *ngFor=\"let action of config.actions\">\n <lib-button \n [variant]=\"action.btnVariant || 'secondary'\"\n [icon]=\"action.icon || ''\"\n (click)=\"onAction(action, row)\">\n {{ action.label }}\n </lib-button>\n </ng-container>\n </div>\n <!-- Alternatively use specific icons if needed, but button component is requested -->\n </td>\n </tr>\n <tr *ngIf=\"data.length === 0 && !loading\">\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\n {{ config.labels?.noDataMessage || 'No data available' }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"st-pagination\" *ngIf=\"config.pagination && config.pagination.enabled\">\n <lib-pagination\n [totalItems]=\"totalItems\"\n [itemsPerPage]=\"config.pagination.pageSize\"\n [currentPage]=\"currentPage\"\n [pageSizeOptions]=\"config.pagination.pageSizeOptions\"\n (pageChange)=\"onPageChange($event)\"\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\n </lib-pagination>\n </div>\n</div>\n", styles: [".smart-table-wrapper{font-family:var(--st-font-family, \"Roboto\", sans-serif);background:var(--st-table-bg, #fff);border-radius:var(--st-border-radius, 8px);box-shadow:var(--st-box-shadow, 0 2px 4px rgba(0, 0, 0, .05));display:flex;flex-direction:column;gap:0;padding:0;border:var(--st-table-border, 1px solid #e0e0e0);overflow:hidden}.st-toolbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1rem);background:var(--st-toolbar-bg, #fff);border-bottom:var(--st-toolbar-border-bottom, 1px solid #eee);gap:var(--st-toolbar-gap, 1rem)}.st-toolbar .st-search{position:relative;width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:var(--st-search-padding, .5rem .5rem .5rem 2rem);border:var(--st-search-border, 1px solid #ccc);border-radius:var(--st-search-radius, 4px);background:var(--st-search-bg, #fff);font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333)}.st-toolbar .st-search i{position:absolute;left:.75rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #999)}.st-toolbar .st-filters{display:flex;gap:1rem}.st-toolbar .st-filters select{padding:var(--st-filter-padding, .5rem);border:var(--st-filter-border, 1px solid #ccc);border-radius:var(--st-filter-radius, 4px);font-size:var(--st-filter-font-size, 14px);background:var(--st-filter-bg, #fff);color:var(--st-filter-color, #333)}.st-toolbar .st-actions{display:flex;gap:.5rem}.st-table-container{overflow-x:auto;overflow-y:auto;padding:var(--st-table-padding, 1rem)}.st-table-container::-webkit-scrollbar{width:var(--st-scrollbar-width, 8px);height:var(--st-scrollbar-height, 8px)}.st-table-container::-webkit-scrollbar-track{background:var(--st-scrollbar-track-bg, #f1f1f1);border-radius:var(--st-scrollbar-track-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb{background:var(--st-scrollbar-thumb-bg, #c1c1c1);border-radius:var(--st-scrollbar-thumb-radius, 4px)}.st-table-container::-webkit-scrollbar-thumb:hover{background:var(--st-scrollbar-thumb-hover-bg, #a8a8a8)}.st-table-container.has-sticky-header .st-table thead th{position:sticky;top:0;z-index:10;background:var(--st-header-bg, #f9f9f9);box-shadow:0 1px 2px -1px #0000001a}.st-table-container table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--st-font-size, 14px)}.st-table-container table thead{background:var(--st-header-bg, #f9f9f9)}.st-table-container table thead th{padding:.75rem 1rem;text-align:left;color:var(--st-header-color, #333);font-weight:var(--st-header-weight, 500);font-size:var(--st-header-size, 14px);text-transform:var(--st-header-transform, none);border-bottom:var(--st-header-border, 1px solid #eee);white-space:nowrap}.st-table-container table thead th.sortable{cursor:pointer}.st-table-container table thead th.sortable:hover{opacity:.8}.st-table-container table thead th .sort-icon{margin-left:.5rem}.st-table-container table thead th .sort-icon .sort-icon{margin-left:.5rem;font-size:var(--st-sort-icon-size, .8em)}.st-table-container table thead th.st-checkbox-col{width:40px}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f9f9f9);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table thead th.sticky-col:first-child{left:0}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:var(--st-cell-padding, 1rem);color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee)}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff);box-shadow:var(--st-sticky-shadow, 2px 0 5px -2px rgba(0, 0, 0, .1));border-right:var(--st-sticky-border-right, 1px solid rgba(0, 0, 0, .05))}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr:hover td,.st-table-container table tbody tr:hover td.sticky-col{background:var(--st-row-hover-bg, #f9f9f9)}.st-table-container table tbody tr.selected td,.st-table-container table tbody tr.selected td.sticky-col{background:var(--st-row-selected-bg, #f3e5f5)}.st-table-container table tbody tr.clickable-row,.st-table-container table tbody tr.clickable-row td{cursor:pointer}.st-table-container table tbody tr.clickable-row:hover td,.st-table-container table tbody tr.clickable-row:hover td.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}input[type=checkbox]{accent-color:var(--st-checkbox-color, #6200EE);width:var(--st-checkbox-size, 16px);height:var(--st-checkbox-size, 16px);cursor:pointer}.st-badge{display:inline-block;padding:var(--st-badge-padding, 4px 12px);border-radius:var(--st-badge-radius, 12px);font-size:var(--st-badge-font-size, 12px);font-weight:var(--st-badge-font-weight, 500);text-align:center;white-space:nowrap}.st-badge.badge-success{background:var(--st-badge-success-bg, #e8f5e9);color:var(--st-badge-success-color, #2e7d32)}.st-badge.badge-warning{background:var(--st-badge-warning-bg, #fff3e0);color:var(--st-badge-warning-color, #ef6c00)}.st-badge.badge-danger{background:var(--st-badge-danger-bg, #ffebee);color:var(--st-badge-danger-color, #c62828)}.st-badge.badge-info{background:var(--st-badge-info-bg, #e3f2fd);color:var(--st-badge-info-color, #1565c0)}.st-badge.badge-neutral{background:var(--st-badge-neutral-bg, #f5f5f5);color:var(--st-badge-neutral-color, #616161)}.st-row-actions .action-buttons{display:flex;gap:.5rem;align-items:center}.no-data{text-align:center;padding:2rem;color:var(--st-no-data-color, #888)}.st-pagination{padding:var(--st-pagination-padding, 1rem);border-top:var(--st-pagination-border-top, none)}@media(max-width:768px){.st-toolbar{flex-direction:column;align-items:stretch}.st-toolbar .st-search,.st-toolbar .st-filters,.st-toolbar .st-actions,.st-toolbar .st-search input{width:100%}}.st-table-container{position:relative;min-height:200px}.st-table-container .st-table.loading-data{opacity:.5;pointer-events:none}.st-table-container .st-check-loader{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center;z-index:10}.st-table-container .st-check-loader .spinner{width:40px;height:40px;border:4px solid var(--st-spinner-border-color, rgba(0, 0, 0, .1));border-left-color:var(--st-loader-color);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\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: "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.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { 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: PaginationComponent, selector: "lib-pagination", inputs: ["totalItems", "itemsPerPage", "currentPage", "pageSizeOptions", "theme", "labels"], outputs: ["pageChange", "itemsPerPageChange"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }] });
|
|
3197
5440
|
}
|
|
3198
5441
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableComponent, decorators: [{
|
|
3199
5442
|
type: Component,
|
|
@@ -3628,12 +5871,12 @@ var smartForm_examples = /*#__PURE__*/Object.freeze({
|
|
|
3628
5871
|
});
|
|
3629
5872
|
|
|
3630
5873
|
/*
|
|
3631
|
-
* Public API Surface of shared-ui
|
|
5874
|
+
* Public API Surface of commons-shared-web-ui
|
|
3632
5875
|
*/
|
|
3633
5876
|
|
|
3634
5877
|
/**
|
|
3635
5878
|
* Generated bundle index. Do not edit.
|
|
3636
5879
|
*/
|
|
3637
5880
|
|
|
3638
|
-
export { AlertComponent, AlertModule, ButtonComponent, ButtonModule, ConfigurableFormComponent, configurableForm_examples as ConfigurableFormExamples, ConfigurableFormModule, ConfirmationModalComponent, ConfirmationModalModule, DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE_SIZE_OPTIONS, ExpressionService, FilterSidebarComponent, FilterSidebarModule, MaterialModule, NAV_ORIENTATION_DEFAULT, NAV_VARIANT_DEFAULT, NavComponent, NavModule, PAGINATION_THEME_DARK, PAGINATION_THEME_DEFAULT, PaginationComponent, PaginationModule, SharedUiModule, SmartFormComponent, SmartFormController, smartForm_examples as SmartFormExamples, SmartFormModule, SmartTableComponent, SmartTableModule, SummaryCardComponent, SummaryCardModule, ValidationUtils, clearLocalStorage, clearSessionStorage, getLocalStorageItem, getSessionStorageItem, removeLocalStorageItem, removeSessionStorageItem, setLocalStorageItem, setSessionStorageItem };
|
|
5881
|
+
export { AlertComponent, AlertModule, ButtonComponent, ButtonModule, CheckboxComponent, ConfigurableFormComponent, configurableForm_examples as ConfigurableFormExamples, ConfigurableFormModule, ConfirmationModalComponent, ConfirmationModalModule, DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE_SIZE_OPTIONS, DatepickerComponent, DropdownComponent, ExpressionService, FilterComponent, FilterModule, FilterSidebarComponent, FilterSidebarModule, FormComponentsModule, InputComponent, MaterialModule, NAV_ORIENTATION_DEFAULT, NAV_VARIANT_DEFAULT, NavComponent, NavModule, PAGINATION_THEME_DARK, PAGINATION_THEME_DEFAULT, PaginationComponent, PaginationModule, RadioComponent, SearchComponent, SharedUiModule, SmartFormComponent, SmartFormController, smartForm_examples as SmartFormExamples, SmartFormModule, SmartTableComponent, SmartTableModule, SummaryCardComponent, SummaryCardModule, ToggleComponent, ValidationUtils, clearLocalStorage, clearSessionStorage, getLocalStorageItem, getSessionStorageItem, removeLocalStorageItem, removeSessionStorageItem, setLocalStorageItem, setSessionStorageItem };
|
|
3639
5882
|
//# sourceMappingURL=commons-shared-web-ui.mjs.map
|