commons-shared-web-ui 0.0.45 → 0.0.46
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.
|
@@ -678,8 +678,13 @@ class FormFieldComponent {
|
|
|
678
678
|
get effectiveMaxTime() {
|
|
679
679
|
return this.config.timeConfig?.maxTime || null;
|
|
680
680
|
}
|
|
681
|
-
// ──
|
|
681
|
+
// ── DROPDOWN state ────────────────────────────────────────────────────────
|
|
682
682
|
isMultiDropdownOpen = false;
|
|
683
|
+
isSingleDropdownOpen = false;
|
|
684
|
+
// ── Dropdown search state ─────────────────────────────────────────────────
|
|
685
|
+
searchText = '';
|
|
686
|
+
filteredOptionList = [];
|
|
687
|
+
dropdownSearch$ = new Subject();
|
|
683
688
|
isDragOver = false; // file upload drag-over state
|
|
684
689
|
fileUploadError = ''; // per-field file validation error
|
|
685
690
|
multiSaveError = ''; // error for multisave validation
|
|
@@ -770,8 +775,10 @@ class FormFieldComponent {
|
|
|
770
775
|
}
|
|
771
776
|
// Seed localOptionList from any static options already in the config
|
|
772
777
|
// (e.g. optionList defined directly in the JSON like Yes/No dropdowns).
|
|
778
|
+
// filteredOptionList mirrors localOptionList and is narrowed by search.
|
|
773
779
|
// Dynamic options loaded via API will replace this array via loadDropdownOptions.
|
|
774
780
|
this.localOptionList = [...(this.config.optionConfig?.optionList || [])];
|
|
781
|
+
this.filteredOptionList = [...this.localOptionList];
|
|
775
782
|
this.registerControl();
|
|
776
783
|
this.setupVisibility();
|
|
777
784
|
this.setupMinDateField();
|
|
@@ -783,6 +790,10 @@ class FormFieldComponent {
|
|
|
783
790
|
if (!this.config.optionConfig?.dependencies) {
|
|
784
791
|
this.loadDropdownOptions();
|
|
785
792
|
}
|
|
793
|
+
// ── Dropdown search stream (shared by single-select and multi-select) ────
|
|
794
|
+
if (this.isDropdown && this.config.optionConfig?.searchConfig?.enabled) {
|
|
795
|
+
this.initDropdownSearch();
|
|
796
|
+
}
|
|
786
797
|
if (this.isAutocomplete) {
|
|
787
798
|
this.initAutocomplete();
|
|
788
799
|
}
|
|
@@ -816,6 +827,32 @@ class FormFieldComponent {
|
|
|
816
827
|
get expandMoreLabel() {
|
|
817
828
|
return this.controller.labels?.['EXPAND_MORE'] || 'expand_more';
|
|
818
829
|
}
|
|
830
|
+
/** Getter for dropdown search placeholder label */
|
|
831
|
+
get searchPlaceholderLabel() {
|
|
832
|
+
return this.controller.labels?.['SEARCH_PLACEHOLDER'] || 'Search...';
|
|
833
|
+
}
|
|
834
|
+
/** Getter for Select All label */
|
|
835
|
+
get selectAllLabel() {
|
|
836
|
+
return this.controller.labels?.['SELECT_ALL'] || 'Select All';
|
|
837
|
+
}
|
|
838
|
+
/** Getter for No matching options label */
|
|
839
|
+
get noMatchingOptionsLabel() {
|
|
840
|
+
return this.controller.labels?.['NO_MATCHING_OPTIONS'] || 'No options match your search';
|
|
841
|
+
}
|
|
842
|
+
/** Returns the label of the currently selected option for single-select custom dropdowns */
|
|
843
|
+
get singleSelectedLabel() {
|
|
844
|
+
if (!this.config.name)
|
|
845
|
+
return '';
|
|
846
|
+
const currentValue = this.formGroup?.get(this.config.name)?.value;
|
|
847
|
+
if (currentValue === null || currentValue === undefined)
|
|
848
|
+
return '';
|
|
849
|
+
const matched = this.localOptionList.find(o => o.code === currentValue);
|
|
850
|
+
return matched?.label || '';
|
|
851
|
+
}
|
|
852
|
+
/** Whether the dropdown search feature is enabled for this field */
|
|
853
|
+
get isSearchableDropdown() {
|
|
854
|
+
return !!this.config.optionConfig?.searchConfig?.enabled;
|
|
855
|
+
}
|
|
819
856
|
initGroupField() {
|
|
820
857
|
if (this.config.sectionConfig?.allowMulti) {
|
|
821
858
|
this.groupFormArray = this.fb.array([]);
|
|
@@ -1356,6 +1393,7 @@ class FormFieldComponent {
|
|
|
1356
1393
|
else if (this.config.optionConfig) {
|
|
1357
1394
|
this._latestDependencyValues = {};
|
|
1358
1395
|
this.localOptionList = [];
|
|
1396
|
+
this.filteredOptionList = [];
|
|
1359
1397
|
if (parentChanged) {
|
|
1360
1398
|
const control = this.formGroup?.get(this.config.name);
|
|
1361
1399
|
if (control && control.value !== null && control.value !== '') {
|
|
@@ -1479,6 +1517,10 @@ class FormFieldComponent {
|
|
|
1479
1517
|
this.filteredOptions = [...this.localOptionList];
|
|
1480
1518
|
this._syncAutocompleteDisplayValue();
|
|
1481
1519
|
}
|
|
1520
|
+
// Refresh dropdown search filter list after options arrive from API
|
|
1521
|
+
if (this.isDropdown) {
|
|
1522
|
+
this.filteredOptionList = [...this.localOptionList];
|
|
1523
|
+
}
|
|
1482
1524
|
},
|
|
1483
1525
|
error: err => console.error('Failed to load dropdown options:', err)
|
|
1484
1526
|
});
|
|
@@ -1612,22 +1654,120 @@ class FormFieldComponent {
|
|
|
1612
1654
|
}
|
|
1613
1655
|
return null;
|
|
1614
1656
|
}
|
|
1615
|
-
// ──
|
|
1657
|
+
// ── DROPDOWN helpers (single + multi) ─────────────────────────────────────
|
|
1616
1658
|
toggleMultiDropdown(event) {
|
|
1617
1659
|
event.stopPropagation();
|
|
1618
1660
|
this.isMultiDropdownOpen = !this.isMultiDropdownOpen;
|
|
1661
|
+
if (this.isMultiDropdownOpen) {
|
|
1662
|
+
this.resetDropdownSearch();
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
toggleSingleDropdown(event) {
|
|
1666
|
+
event.stopPropagation();
|
|
1667
|
+
this.isSingleDropdownOpen = !this.isSingleDropdownOpen;
|
|
1668
|
+
if (this.isSingleDropdownOpen) {
|
|
1669
|
+
this.resetDropdownSearch();
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
selectSingleOption(option) {
|
|
1673
|
+
this.updateValue(option.code);
|
|
1674
|
+
this.isSingleDropdownOpen = false;
|
|
1675
|
+
this.resetDropdownSearch();
|
|
1619
1676
|
}
|
|
1620
1677
|
onDocumentClick() {
|
|
1621
1678
|
if (this.isMultiDropdownOpen) {
|
|
1622
1679
|
this.isMultiDropdownOpen = false;
|
|
1680
|
+
this.resetDropdownSearch();
|
|
1681
|
+
}
|
|
1682
|
+
if (this.isSingleDropdownOpen) {
|
|
1683
|
+
this.isSingleDropdownOpen = false;
|
|
1684
|
+
this.resetDropdownSearch();
|
|
1623
1685
|
}
|
|
1624
1686
|
}
|
|
1625
1687
|
onEscapeKey() {
|
|
1626
1688
|
this.isMultiDropdownOpen = false;
|
|
1689
|
+
this.isSingleDropdownOpen = false;
|
|
1690
|
+
this.resetDropdownSearch();
|
|
1627
1691
|
}
|
|
1628
1692
|
get multiSelectedCount() {
|
|
1629
1693
|
return Array.isArray(this.value) ? this.value.length : 0;
|
|
1630
1694
|
}
|
|
1695
|
+
// ── Dropdown search helpers ───────────────────────────────────────────────
|
|
1696
|
+
/** Initialise the RxJS search stream for dropdown filtering. */
|
|
1697
|
+
initDropdownSearch() {
|
|
1698
|
+
const searchConfig = this.config.optionConfig?.searchConfig;
|
|
1699
|
+
const debounceMs = searchConfig?.debounceTime ?? 300;
|
|
1700
|
+
this.dropdownSearch$.pipe(debounceTime(debounceMs), distinctUntilChanged(), takeUntil(this.destroy$)).subscribe(query => {
|
|
1701
|
+
this.executeDropdownSearch(query);
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
/** Execute client-side or server-side dropdown search. */
|
|
1705
|
+
executeDropdownSearch(query) {
|
|
1706
|
+
const searchConfig = this.config.optionConfig?.searchConfig;
|
|
1707
|
+
const mode = searchConfig?.mode || 'local';
|
|
1708
|
+
if (mode === 'server') {
|
|
1709
|
+
const searchKey = searchConfig?.searchKey || 'search';
|
|
1710
|
+
const minLen = searchConfig?.minSearchLength ?? 3;
|
|
1711
|
+
if (query.length >= minLen) {
|
|
1712
|
+
const params = { ...this._latestDependencyValues, [searchKey]: query };
|
|
1713
|
+
this.loadDropdownOptions(params);
|
|
1714
|
+
}
|
|
1715
|
+
else if (query.length === 0) {
|
|
1716
|
+
// Empty query — restore full list
|
|
1717
|
+
this.loadDropdownOptions(this._latestDependencyValues);
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
else {
|
|
1721
|
+
// Local filtering
|
|
1722
|
+
if (!query || query.trim().length === 0) {
|
|
1723
|
+
this.filteredOptionList = [...this.localOptionList];
|
|
1724
|
+
}
|
|
1725
|
+
else {
|
|
1726
|
+
const q = query.toLowerCase().trim();
|
|
1727
|
+
this.filteredOptionList = this.localOptionList.filter(opt => opt.label?.toLowerCase().includes(q) ||
|
|
1728
|
+
String(opt.code).toLowerCase().includes(q));
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
/** Resets the dropdown search text and filtered list. */
|
|
1733
|
+
resetDropdownSearch() {
|
|
1734
|
+
this.searchText = '';
|
|
1735
|
+
this.filteredOptionList = [...this.localOptionList];
|
|
1736
|
+
}
|
|
1737
|
+
// ── Select All helpers ────────────────────────────────────────────────────
|
|
1738
|
+
/** Returns true if every option in the current filtered list is selected. */
|
|
1739
|
+
isAllSelected() {
|
|
1740
|
+
if (!this.filteredOptionList.length)
|
|
1741
|
+
return false;
|
|
1742
|
+
const currentValue = Array.isArray(this.value) ? this.value : [];
|
|
1743
|
+
return this.filteredOptionList.every(opt => currentValue.includes(opt.code));
|
|
1744
|
+
}
|
|
1745
|
+
/** Returns true if some (but not all) filtered options are selected — for indeterminate state. */
|
|
1746
|
+
isSomeSelected() {
|
|
1747
|
+
if (!this.filteredOptionList.length)
|
|
1748
|
+
return false;
|
|
1749
|
+
const currentValue = Array.isArray(this.value) ? this.value : [];
|
|
1750
|
+
const selectedCount = this.filteredOptionList.filter(opt => currentValue.includes(opt.code)).length;
|
|
1751
|
+
return selectedCount > 0 && selectedCount < this.filteredOptionList.length;
|
|
1752
|
+
}
|
|
1753
|
+
/** Toggles selection of all filtered options. */
|
|
1754
|
+
toggleSelectAll(checked) {
|
|
1755
|
+
if (!this.config.name)
|
|
1756
|
+
return;
|
|
1757
|
+
const currentValue = Array.isArray(this.value) ? [...this.value] : [];
|
|
1758
|
+
const filteredCodes = this.filteredOptionList.map(opt => opt.code);
|
|
1759
|
+
let newValue;
|
|
1760
|
+
if (checked) {
|
|
1761
|
+
// Add all filtered codes that are not already selected
|
|
1762
|
+
const toAdd = filteredCodes.filter(code => !currentValue.includes(code));
|
|
1763
|
+
newValue = [...currentValue, ...toAdd];
|
|
1764
|
+
}
|
|
1765
|
+
else {
|
|
1766
|
+
// Remove only filtered codes from the selection
|
|
1767
|
+
newValue = currentValue.filter(code => !filteredCodes.includes(code));
|
|
1768
|
+
}
|
|
1769
|
+
this.updateValue(newValue);
|
|
1770
|
+
}
|
|
1631
1771
|
// ── Type guards ──────────────────────────────────────────────────────────
|
|
1632
1772
|
get isTextField() { return this.config.type === 'TEXT_INPUT'; }
|
|
1633
1773
|
get isNumberField() { return this.config.type === 'NUMBER_INPUT'; }
|
|
@@ -2650,11 +2790,11 @@ class FormFieldComponent {
|
|
|
2650
2790
|
}
|
|
2651
2791
|
}
|
|
2652
2792
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormFieldComponent, deps: [{ token: i1$3.FormBuilder }, { token: ExpressionService }, { token: i3.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
2653
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FormFieldComponent, isStandalone: false, selector: "lib-form-field", inputs: { config: "config", controller: "controller", formGroup: "formGroup", allowMulti: "allowMulti" }, host: { listeners: { "document:click": "onDocumentClick()", "document:keydown.escape": "onEscapeKey()" } }, viewQueries: [{ propertyName: "mediaDeviceInput", first: true, predicate: ["mediaDeviceInput"], descendants: true }, { propertyName: "libraryModalRef", first: true, predicate: ["libraryModal"], descendants: true }], ngImport: i0, template: "<div class=\"form-field mb-16px\" *ngIf=\"isVisible\" [class.has-error]=\"errorMessage\">\r\n\r\n <!-- \u2550\u2550 ROW Layout \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRow\" class=\"form-row grid-row\">\r\n <ng-container *ngFor=\"let child of config.children\">\r\n <div class=\"row-field\" [style.gridColumn]=\"'span ' + getChildColSpan(child)\" *ngIf=\"child.isEnabled !== false\">\r\n <lib-form-field [config]=\"child\" [controller]=\"controller\" [formGroup]=\"formGroup\" [allowMulti]=\"allowMulti\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 allowMulti (repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig?.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\"\r\n [class.multi-save-active]=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n\r\n <!-- Multi-Save: header row with label + top-right Add button -->\r\n <div class=\"multi-save-header d-flex justify-content-between align-items-center mb-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig?.label\">{{ config.sectionConfig!.label }}</h3>\r\n <lib-button [variant]=\"'outline'\" [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\"\r\n class=\"btn-add-multi\">\r\n {{ addMultiLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- Standard heading (non-multiSave) -->\r\n <h3 class=\"group-label\"\r\n *ngIf=\"config.sectionConfig?.label && !config.sectionConfig?.multiSaveConfig?.active\">{{\r\n config.sectionConfig!.label }}</h3>\r\n\r\n <!-- \u2500\u2500 Standard (non-multiSave) repeater: accordion instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-accordion-instance\"\r\n [class.is-expanded]=\"isGroupExpanded(i)\">\r\n\r\n <!-- Accordion header -->\r\n <div class=\"group-accordion-header\" (click)=\"toggleGroupAccordion(i)\"\r\n role=\"button\" [attr.aria-expanded]=\"isGroupExpanded(i)\">\r\n <div class=\"accordion-header-left d-flex align-items-center gap-10\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.sectionConfig!.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right d-flex align-items-center gap-6\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceList.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeGroupInstance(i)\"\r\n aria-label=\"Remove\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isGroupExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body (always mounted so form controls survive collapse) -->\r\n <div class=\"group-accordion-body\" [hidden]=\"!isGroupExpanded(i)\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"instance.rowController\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-group\" (click)=\"addGroupInstance()\">\r\n <mat-icon>add</mat-icon> {{ addLabel }} {{ config.sectionConfig!.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2500\u2500 MultiSave: card instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-instance position-relative mb-16 overflow-hidden\"\r\n [class.is-editing]=\"instance.isEditing\"\r\n [class.is-card]=\"!instance.isEditing\">\r\n\r\n <!-- Edit / new form view -->\r\n <div [hidden]=\"!instance.isEditing\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"instance.rowController\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Save / Cancel -->\r\n <div class=\"group-footer d-flex justify-content-end align-items-center gap-16 p-0-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"multiSaveError\">{{ multiSaveError }}</span>\r\n <div class=\"footer-actions d-flex gap-12\">\r\n <lib-button [variant]=\"'outline'\" (click)=\"cancelGroupInstance(i)\">Cancel</lib-button>\r\n <lib-button [variant]=\"'primary'\" (click)=\"saveGroupInstance(i)\">Save</lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Card view (saved state) -->\r\n <ng-container *ngIf=\"!instance.isEditing\">\r\n <div class=\"card-view d-flex justify-content-between align-items-center p-18px-24px\"\r\n [class.is-expanded]=\"instance.isExpanded\">\r\n <div class=\"card-content flex-1 d-flex flex-column gap-4 overflow-hidden\">\r\n <span class=\"card-title font-weight-600 overflow-hidden fs-1rem c-111827\">{{\r\n instance.fg.get(config.sectionConfig!.multiSaveConfig!.summaryField || '')?.value\r\n || '\u2014' }}</span>\r\n </div>\r\n <div class=\"card-actions d-flex align-items-center gap-16 ml-20\">\r\n <mat-icon class=\"icon-delete\" (click)=\"removeGroupInstance(i, true)\">delete_outline</mat-icon>\r\n <mat-icon class=\"icon-edit\" (click)=\"editGroupInstance(i)\">edit_outline</mat-icon>\r\n <mat-icon class=\"icon-expand\" (click)=\"toggleExpandGroupInstance(i)\">\r\n {{ instance.isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 single (non-repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig && !config.sectionConfig.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig.label\">{{ config.sectionConfig.label }}</h3>\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"groupFormGroup\" [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Text Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTextField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <textarea *ngIf=\"config.subType === 'LONG'\" class=\"field-input textarea\" [placeholder]=\"config.placeholder || ''\"\r\n [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\" rows=\"4\">\r\n </textarea>\r\n\r\n <!-- Password input with show/hide toggle -->\r\n <div *ngIf=\"config.subType === 'PASSWORD'\" class=\"password-wrapper position-relative d-flex align-items-center\">\r\n <input [type]=\"showPassword ? 'text' : 'password'\" class=\"field-input password-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <button type=\"button\"\r\n class=\"password-toggle position-absolute cursor-pointer d-flex align-items-center justify-content-center b-none border-none c-6B7280 p-0-25rem\"\r\n (click)=\"showPassword = !showPassword\" tabindex=\"-1\"\r\n [attr.aria-label]=\"showPassword ? 'Hide password' : 'Show password'\">\r\n <mat-icon class=\"eye-icon\">{{ showPassword ? 'visibility' : 'visibility_off' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input *ngIf=\"config.subType !== 'LONG' && config.subType !== 'PASSWORD'\"\r\n [type]=\"config.subType === 'EMAIL' ? 'email' : config.subType === 'PHONE' ? 'tel' : 'text'\" class=\"field-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\"\r\n [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n\r\n <!-- Suffix Action Icons (clickable) -->\r\n <div class=\"suffix-action-icons position-absolute d-flex gap-8 align-items-center\"\r\n *ngIf=\"config.suffixActionIcons?.length && !config.readonly\">\r\n <mat-icon class=\"suffix-action-icon\"\r\n *ngFor=\"let action of config.suffixActionIcons\"\r\n [style.color]=\"action.color || null\"\r\n [title]=\"action.tooltip || ''\"\r\n (click)=\"onSuffixActionClick(action.actionId)\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Number Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isNumberField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input type=\"number\" class=\"field-input\" [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\"\r\n [min]=\"config.numberConfig?.min ?? null\" [max]=\"config.numberConfig?.max ?? null\"\r\n [step]=\"config.numberConfig?.step || 1\" [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n\r\n <!-- Suffix Action Icons (clickable) -->\r\n <div class=\"suffix-action-icons position-absolute d-flex gap-8 align-items-center\"\r\n *ngIf=\"config.suffixActionIcons?.length && !config.readonly\">\r\n <mat-icon class=\"suffix-action-icon\"\r\n *ngFor=\"let action of config.suffixActionIcons\"\r\n [style.color]=\"action.color || null\"\r\n [title]=\"action.tooltip || ''\"\r\n (click)=\"onSuffixActionClick(action.actionId)\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Date Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDateField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input matInput [matDatepicker]=\"datePicker\" class=\"field-input date-input has-icon-right\"\r\n [formControlName]=\"config.name!\" [min]=\"effectiveMinDate\" [max]=\"config.dateConfig?.maxDate\"\r\n [class.is-invalid]=\"errorMessage\" [placeholder]=\"config.placeholder || ''\"\r\n [readonly]=\"config.readonly || config.dateConfig?.inputReadonly\"\r\n (click)=\"!config.readonly && datePicker.open()\">\r\n <div class=\"date-icon-wrapper position-absolute d-flex align-items-center justify-content-center\"\r\n *ngIf=\"!config.readonly\">\r\n <mat-datepicker-toggle matSuffix [for]=\"datePicker\"></mat-datepicker-toggle>\r\n </div>\r\n <mat-datepicker #datePicker></mat-datepicker>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Time Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTimeField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input type=\"time\" class=\"field-input time-input\" [formControlName]=\"config.name!\"\r\n [min]=\"effectiveMinTime\" [max]=\"effectiveMaxTime\"\r\n [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly || config.timeConfig?.inputReadonly\">\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Autocomplete \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isAutocomplete\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Hidden real control (stores the code value) -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <div class=\"autocomplete-wrapper position-relative d-flex align-items-center w-100\"\r\n [class.is-invalid]=\"errorMessage\" [class.readonly]=\"config.readonly\">\r\n <!-- Search icon -->\r\n <mat-icon class=\"ac-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n\r\n <input class=\"field-input ac-input\" [formControl]=\"autocompleteInputCtrl\" [matAutocomplete]=\"auto\"\r\n [placeholder]=\"config.placeholder || 'Search\u2026'\" [readonly]=\"!!config.readonly\" [class.is-invalid]=\"errorMessage\"\r\n (blur)=\"onAutocompleteClear()\" autocomplete=\"off\">\r\n\r\n <!-- Clear button -->\r\n <button type=\"button\"\r\n class=\"ac-clear-btn position-absolute d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none c-9CA3AF p-0-2rem\"\r\n *ngIf=\"autocompleteInputCtrl.value && !config.readonly\"\r\n (click)=\"autocompleteInputCtrl.setValue(''); updateValue(null)\" tabindex=\"-1\" aria-label=\"Clear\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n\r\n <mat-autocomplete #auto=\"matAutocomplete\" [panelWidth]=\"'auto'\">\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.label\"\r\n (onSelectionChange)=\"onAutocompleteSelected(option)\">\r\n <span class=\"ac-option-label\">{{ option.label }}</span>\r\n\r\n <!-- Dynamic display fields (image / email / phone / text) -->\r\n <div class=\"ac-display-fields d-flex flex-wrap gap-6 mt-2\" *ngIf=\"option['displayMeta']?.length\">\r\n <ng-container *ngFor=\"let field of option['displayMeta']\">\r\n\r\n <!-- Image avatar -->\r\n <span *ngIf=\"field.type === 'image' && field.value\" class=\"ac-df-item ac-df-image\">\r\n <img [src]=\"field.value\" [alt]=\"field.label || 'image'\" class=\"ac-df-avatar\">\r\n </span>\r\n\r\n <!-- Email -->\r\n <span *ngIf=\"field.type === 'email' && field.value\" class=\"ac-df-item ac-df-chip\">\r\n <mat-icon class=\"ac-df-icon\">mail_outline</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n <!-- Phone -->\r\n <span *ngIf=\"field.type === 'phone' && field.value\" class=\"ac-df-item ac-df-chip\" [class]=\"field.className\">\r\n <mat-icon class=\"ac-df-icon\">phone</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n <!-- Custom / Icon-based / Generic Text -->\r\n <span *ngIf=\"field.type !== 'image' && field.type !== 'email' && field.type !== 'phone' && field.value\" \r\n class=\"ac-df-item\" [class.ac-df-chip]=\"!!field.icon\" [class]=\"field.className\">\r\n <mat-icon class=\"ac-df-icon\" *ngIf=\"field.icon\">{{ field.icon }}</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n </ng-container>\r\n </div>\r\n </mat-option>\r\n <mat-option *ngIf=\"filteredOptions.length === 0\" disabled class=\"ac-no-results fs-0-8125rem c-6B7280\">\r\n No results found\r\n </mat-option>\r\n </mat-autocomplete>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Dropdown \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDropdown\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <select *ngIf=\"config.subType === 'SINGLE'\" class=\"field-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option [ngValue]=\"null\" disabled selected>{{ config.placeholder || 'Select' }}</option>\r\n <option *ngFor=\"let option of localOptionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <!-- MULTIPLE SELECT: custom panel with checkboxes -->\r\n <div *ngIf=\"config.subType === 'MULTIPLE'\" class=\"multi-select-wrapper\"\r\n [class.is-invalid]=\"errorMessage\">\r\n\r\n <div class=\"field-input multi-select-trigger d-flex align-items-center justify-content-between cursor-pointer\"\r\n [class.ms-open]=\"isMultiDropdownOpen\"\r\n (click)=\"toggleMultiDropdown($event)\">\r\n <span *ngIf=\"multiSelectedCount > 0\" class=\"multi-select-value fs-0-9rem\">\r\n {{ multiSelectedCount }} selected\r\n </span>\r\n <span *ngIf=\"multiSelectedCount === 0\" class=\"multi-select-placeholder\">\r\n {{ config.placeholder || selectPlaceholderLabel }}\r\n </span>\r\n <mat-icon class=\"multi-select-arrow\">\r\n {{ isMultiDropdownOpen ? expandLessLabel : expandMoreLabel }}\r\n </mat-icon>\r\n </div>\r\n\r\n <div class=\"multi-select-panel\" *ngIf=\"isMultiDropdownOpen\"\r\n (click)=\"$event.stopPropagation()\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"multi-select-option d-flex align-items-center gap-8 cursor-pointer\">\r\n <input type=\"checkbox\"\r\n [checked]=\"isChecked(option.code)\"\r\n [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <span class=\"fs-0-875rem c-111827\">{{ option.label }}</span>\r\n </label>\r\n <div *ngIf=\"!localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noOptionsAvailableLabel }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Radio \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRadio\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"radio-group\" [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of localOptionList\" class=\"radio-label\"\r\n [class.card-item]=\"config.subType === 'CARD'\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"radio\" [formControlName]=\"config.name!\" [value]=\"option.code\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Checkbox \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isCheckbox\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label && config.subType === 'LIST'\"\r\n class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div *ngIf=\"config.subType === 'BOOL'\" class=\"checkbox-single\">\r\n <label class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span>{{ config.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div *ngIf=\"config.subType === 'LIST' || config.subType === 'CARD'\" class=\"checkbox-group d-flex flex-column gap-8\"\r\n [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\"\r\n [class.card-item]=\"config.subType === 'CARD'\" [class.selected]=\"isChecked(option.code)\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Chip \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isChip\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"chip-group d-flex flex-wrap gap-8\" [class.is-invalid]=\"errorMessage\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"chip-label cursor-pointer p-6px-14px b-ffffff c-374151 b-1px-solid-D1D5DB br-20px fs-0-875rem\"\r\n [class.selected]=\"isChecked(option.code)\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\" hidden>\r\n <span>{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Switch \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isSwitch\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label class=\"switch-container d-flex justify-content-between align-items-center cursor-pointer\">\r\n <span class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label }}</span>\r\n <div class=\"switch position-relative\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span class=\"slider position-absolute cursor-pointer\"></span>\r\n </div>\r\n </label>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rich Text \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRichText\" class=\"field-wrapper component-rich-text d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rich-text-container\" [class.is-invalid]=\"errorMessage\">\r\n <quill-editor [formControlName]=\"config.name!\" class=\"rich-text-editor d-block w-100\"\r\n [placeholder]=\"config.richTextConfig?.placeholder || config.placeholder || ''\"\r\n [styles]=\"{height: config.richTextConfig?.height || '200px'}\">\r\n </quill-editor>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rating \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRating\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rating-group d-flex gap-4\" [class.is-invalid]=\"errorMessage\">\r\n <span *ngFor=\"let star of getStarArray()\" class=\"star d-inline-flex align-items-center cursor-pointer\"\r\n [class.filled]=\"isStarFilled(star)\" [class.half]=\"isStarHalf(star)\" (click)=\"onRatingChange(star, $event)\">\r\n <mat-icon>{{ isStarFilled(star) || isStarHalf(star) ? 'star' : 'star_border' }}</mat-icon>\r\n </span>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Generated Field (read-only) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGenerated\" class=\"field-wrapper d-flex flex-column gap-6\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label\r\n }}</label>\r\n <div class=\"generated-value fs-0-875rem p-0-625rem-0-875rem b-F3F4F6 b-1px-solid-E5E7EB br-8px c-6B7280\">{{ value ||\r\n '-' }}</div>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint\">{{ config.hint }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 File Upload \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isFileUpload\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Drop Zone -->\r\n <div\r\n class=\"upload-drop-zone d-flex flex-column align-items-center justify-content-center gap-8 cursor-pointer text-center p-32px-24px us-none\"\r\n [class.drag-over]=\"isDragOver\" [class.has-files]=\"value?.length\" [class.is-invalid]=\"errorMessage\"\r\n (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave($event)\" (drop)=\"onFileDrop($event)\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <!-- Icon with accent-colour pill background -->\r\n <div class=\"upload-icon-wrap mb-4\">\r\n <div class=\"dropzone-icon-pill d-flex align-items-center justify-content-center\">\r\n <mat-icon class=\"upload-cloud-icon\">cloud_upload</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <p class=\"upload-main-text font-weight-600 m-0 fs-0-9rem\">Drag & drop files here</p>\r\n <p class=\"upload-sub-text m-0 fs-0-8rem c-64748B\">or <span class=\"upload-link\">Browse files</span></p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"config.attachmentConfig?.acceptLabel\">\r\n Supported: <span class=\"upload-formats font-weight-500\">{{ config.attachmentConfig!.acceptLabel }}</span>\r\n </p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"!config.attachmentConfig?.acceptLabel && config.hint\">\r\n {{ config.hint }}\r\n </p>\r\n <span class=\"upload-size-badge fs-0-72rem\" *ngIf=\"config.attachmentConfig?.maxSizeMB\">\r\n Max {{ config.attachmentConfig!.maxSizeMB }}MB\r\n </span>\r\n\r\n <!-- Hidden native file input -->\r\n <input #fileInput type=\"file\" hidden [attr.multiple]=\"config.attachmentConfig?.multiple ? true : null\"\r\n [attr.accept]=\"config.attachmentConfig?.accept || null\" (change)=\"onFileSelected($event)\">\r\n </div>\r\n\r\n <!-- Uploaded file list -->\r\n <div class=\"uploaded-list d-flex flex-column gap-8 mt-10\" *ngIf=\"value?.length\">\r\n <div *ngFor=\"let f of value; let i = index\"\r\n class=\"uploaded-item d-flex align-items-center gap-10 p-10px-14px br-8px\"\r\n [class.uploading]=\"f.isUploading\">\r\n\r\n <!-- Uploading spinner -->\r\n <ng-container *ngIf=\"f.isUploading; else fileReady\">\r\n <div class=\"upload-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size uploading-label fs-0-72rem\">Uploading...</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Normal state once upload is done -->\r\n <ng-template #fileReady>\r\n <mat-icon class=\"file-type-icon\">{{ getFileIcon(f.type) }}</mat-icon>\r\n <img *ngIf=\"f.type?.startsWith('image') && f.dataUrl\" [src]=\"f.dataUrl\" class=\"file-thumb rounded-4\"\r\n alt=\"preview\">\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size fs-0-72rem\">{{ formatFileSize(f.size) }}</span>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Compact icon-only remove button -->\r\n <button type=\"button\" class=\"file-remove-btn d-flex align-items-center justify-content-center rounded-50\"\r\n [disabled]=\"f.isUploading\" (click)=\"!f.isUploading && removeUploadedFile(i)\"\r\n aria-label=\"Remove file\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation / file errors -->\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"fileUploadError\">{{ fileUploadError }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage && !fileUploadError\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\"\r\n *ngIf=\"config.hint && !errorMessage && !fileUploadError && !config.attachmentConfig?.acceptLabel\">\r\n {{ config.hint }}\r\n </span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Media Upload (Type 2) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isMediaUpload\" class=\"field-wrapper media-upload-wrapper d-flex flex-column gap-6 p-0 border-none b-none\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Hidden file input lives outside *ngIf \u2014 triggered via ViewChild -->\r\n <input #mediaDeviceInput type=\"file\" hidden multiple accept=\"image/*\" (change)=\"onMediaFileSelected($event)\">\r\n\r\n <!-- Two-column layout -->\r\n <div class=\"mu-layout d-grid align-items-start\">\r\n\r\n <!-- \u2500\u2500 LEFT PANEL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-left d-flex flex-column gap-20\">\r\n\r\n <!-- Header: title + max-items badge -->\r\n <div class=\"mu-header d-flex align-items-start flex-wrap gap-10\">\r\n <h3 class=\"mu-title m-0 c-111827 fs-1-35rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </h3>\r\n <span\r\n class=\"mu-badge d-inline-flex align-items-center rounded-20 color-white font-weight-600 fs-0-72rem p-4px-12px b-111827\"\r\n *ngIf=\"config.attachmentConfig?.maxFiles\">\r\n {{ controller.labels['LBL_MEDIA_MAX_PREFIX'] || 'Maximum' }}\r\n {{ config.attachmentConfig?.maxFiles }}\r\n {{ controller.labels['LBL_MEDIA_MAX_SUFFIX'] || 'Image & Videos' }}\r\n </span>\r\n </div>\r\n\r\n <!-- Description -->\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\" *ngIf=\"config.attachmentConfig?.description\">\r\n {{ config.attachmentConfig?.description }}\r\n </p>\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\"\r\n *ngIf=\"!config.attachmentConfig?.description && controller.labels['LBL_MEDIA_DESC']\">\r\n {{ controller.labels['LBL_MEDIA_DESC'] }}\r\n </p>\r\n\r\n <!-- Feature bullet list -->\r\n <ul class=\"mu-features m-0 p-0 d-flex flex-column gap-8 ls-none\"\r\n *ngIf=\"config.attachmentConfig?.features?.length || controller.labels['LBL_MEDIA_FEATURE_1']\">\r\n <ng-container *ngIf=\"config.attachmentConfig?.features?.length\">\r\n <li *ngFor=\"let f of config.attachmentConfig?.features\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ f }}\r\n </li>\r\n </ng-container>\r\n <ng-container *ngIf=\"!config.attachmentConfig?.features?.length\">\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_1']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_1'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_2']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_2'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_3']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_3'] }}\r\n </li>\r\n </ng-container>\r\n </ul>\r\n\r\n <!-- Backdrop to close dropdown on outside click -->\r\n <div class=\"media-menu-backdrop\" *ngIf=\"showMediaMenu\"\r\n (click)=\"$event.stopPropagation(); showMediaMenu = false\"></div>\r\n\r\n <!-- Add Media button + dropdown -->\r\n <div class=\"media-add-container position-relative\" (click)=\"showMediaMenu = !showMediaMenu\">\r\n <lib-button id=\"btn-add-media-{{ config.name }}\" [variant]=\"'warning'\"\r\n [icon]=\"{type: 'material', value: 'add_photo_alternate'}\">\r\n {{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}\r\n <mat-icon class=\"menu-chevron fs-18px\">add</mat-icon>\r\n </lib-button>\r\n\r\n <div class=\"media-dropdown position-absolute rounded-12 overflow-hidden b-ffffff b-1px-solid-E5E7EB\"\r\n *ngIf=\"showMediaMenu\" role=\"menu\" (click)=\"$event.stopPropagation()\">\r\n <!-- Video -->\r\n <button id=\"btn-media-video-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuVideo(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--video d-flex align-items-center justify-content-center rounded-8\"><mat-icon>videocam</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_VIDEO'] || 'Video' }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_VIDEO_DESC'] || 'Add\r\n YouTube URL'\r\n }}</span>\r\n </span>\r\n </button>\r\n <!-- Device -->\r\n <button id=\"btn-media-device-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuDevice(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--device d-flex align-items-center justify-content-center rounded-8\"><mat-icon>upload</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_DEVICE'] || 'Upload from device'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_DEVICE_DESC'] ||\r\n 'Select images from your\r\n computer' }}</span>\r\n </span>\r\n </button>\r\n <!-- Library -->\r\n <button id=\"btn-media-library-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuLibrary(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--library d-flex align-items-center justify-content-center rounded-8\"><mat-icon>photo_library</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_LIBRARY'] || 'Upload from library'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_LIBRARY_DESC'] ||\r\n 'Choose from default\r\n images' }}</span>\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- YouTube URL Input (inline below button) -->\r\n <div class=\"youtube-input-panel d-flex flex-column gap-8 p-16 rounded-10 b-FFFAF1 b-1px-solid-E5E7EB\"\r\n *ngIf=\"showYoutubeInput\">\r\n <label class=\"youtube-panel-label d-flex align-items-center gap-6 font-weight-600 fs-0-875rem c-111827\">\r\n {{ controller.labels['LBL_YOUTUBE_URL'] || 'Video URL' }}\r\n </label>\r\n <div class=\"youtube-input-row d-flex gap-8\">\r\n <input id=\"input-youtube-url-{{ config.name }}\" type=\"url\" class=\"field-input youtube-url-input\"\r\n [(ngModel)]=\"youtubeUrlInput\" [ngModelOptions]=\"{standalone: true}\"\r\n [placeholder]=\"controller.labels['PH_YOUTUBE_URL'] || 'Video URL'\" (keyup.enter)=\"addYoutubeMedia()\">\r\n <lib-button id=\"btn-add-youtube-{{ config.name }}\" [variant]=\"'secondary'\" (click)=\"addYoutubeMedia()\">\r\n {{ controller.labels['LBL_ADD'] || 'Add' }}\r\n </lib-button>\r\n </div>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"youtubeUrlError\">{{ youtubeUrlError }}</span>\r\n </div>\r\n\r\n <div\r\n class=\"media-upload-status d-flex align-items-center gap-8 mt-4 color-error rounded-8 font-weight-500 p-10px-14px b-FEF2F2 fs-0-85rem\"\r\n *ngIf=\"mediaUploadError\">\r\n <mat-icon class=\"status-icon fs-18px\">error_outline</mat-icon>\r\n <span>{{ mediaUploadError }}</span>\r\n </div>\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n </div>\r\n <!-- end left panel -->\r\n\r\n <!-- \u2500\u2500 RIGHT PANEL (carousel) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-right d-flex flex-column gap-12\">\r\n\r\n <!-- Carousel (when items exist) -->\r\n <div class=\"media-carousel-section d-flex flex-column gap-12\" *ngIf=\"mediaItems.length\">\r\n <div\r\n class=\"media-carousel-main position-relative w-100 overflow-hidden d-flex align-items-center justify-content-center br-12px b-0F172A\">\r\n <button id=\"btn-carousel-prev-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--prev position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselPrev()\" [disabled]=\"mediaCarouselIndex === 0\" aria-label=\"Previous\">\r\n <mat-icon>chevron_left</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-viewer position-absolute d-flex align-items-center justify-content-center\"\r\n *ngFor=\"let item of mediaItems; let i = index\" [hidden]=\"i !== mediaCarouselIndex\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"carousel-uploading d-flex flex-column align-items-center gap-12 c-94A3B8 fs-0-85rem\">\r\n <div class=\"carousel-spinner rounded-50 b-3px-solid-rgba-255-255-255-0-15\"></div>\r\n <span>{{ controller.labels['LBL_UPLOADING'] || 'Uploading\u2026' }}</span>\r\n </div>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'youtube'\">\r\n <iframe class=\"carousel-iframe w-100 h-100 br-12px\" [src]=\"item.url | trustedUrl\" frameborder=\"0\"\r\n allowfullscreen\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\">\r\n </iframe>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'image'\">\r\n <img class=\"carousel-image w-100 h-100 br-12px\" [src]=\"item.url\" alt=\"Media\">\r\n </ng-container>\r\n <button id=\"btn-remove-media-{{ config.name }}-{{ i }}\" type=\"button\"\r\n class=\"carousel-remove-btn position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-0-0-0-0-55\"\r\n [disabled]=\"item.isUploading\" (click)=\"removeMediaItem(i)\" aria-label=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <button id=\"btn-carousel-next-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--next position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselNext()\" [disabled]=\"mediaCarouselIndex === mediaItems.length - 1\" aria-label=\"Next\">\r\n <mat-icon>chevron_right</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-dots position-absolute d-flex gap-6\">\r\n <span *ngFor=\"let item of mediaItems; let i = index\"\r\n class=\"carousel-dot rounded-50 cursor-pointer b-rgba-255-255-255-0-45\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\"></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Thumbnail strip -->\r\n <div class=\"media-thumbnail-strip d-flex flex-wrap gap-8 pb-4px\">\r\n <div *ngFor=\"let item of mediaThumbnails; let i = index\"\r\n class=\"media-thumb rounded-8 overflow-hidden cursor-pointer d-flex align-items-center justify-content-center b-2px-solid-transparent b-E2E8F0\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"thumb-uploading d-flex align-items-center justify-content-center w-100 h-100\">\r\n <div class=\"thumb-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && item.thumbnailUrl\"\r\n [src]=\"item.thumbnailUrl\" class=\"thumb-img w-100 h-100\" alt=\"Video thumbnail\">\r\n <div *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && !item.thumbnailUrl\"\r\n class=\"thumb-yt-placeholder d-flex align-items-center justify-content-center w-100 h-100 b-1E293B c-EF4444\">\r\n <mat-icon>play_circle</mat-icon>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'image' && item.url\" [src]=\"item.url\"\r\n class=\"thumb-img w-100 h-100\" alt=\"Image thumbnail\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty right-side placeholder -->\r\n <div\r\n class=\"mu-right-empty d-flex flex-column align-items-center justify-content-center gap-10 h-100 text-center p-24 br-12px b-FFFAF1 c-94A3B8 b-2px-dashed-CBD5E1\"\r\n *ngIf=\"!mediaItems.length\" (click)=\"onMediaMenuDevice()\">\r\n <mat-icon class=\"mu-right-empty-icon fs-52px\">perm_media</mat-icon>\r\n <p>{{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}</p>\r\n </div>\r\n\r\n </div>\r\n <!-- end right panel -->\r\n\r\n </div><!-- end mu-layout -->\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Library Image Picker Modal \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <!-- Wrapper is always in DOM (hidden) so @ViewChild can move it to body -->\r\n <div #libraryModal class=\"media-library-portal-host\" [class.is-open]=\"showLibraryModal\">\r\n\r\n <!-- Backdrop -->\r\n <div class=\"media-library-overlay\" (click)=\"closeLibraryModal()\"></div>\r\n\r\n <!-- Modal card -->\r\n <div class=\"media-library-modal d-flex flex-column overflow-hidden b-ffffff br-16px\"\r\n role=\"dialog\" aria-modal=\"true\">\r\n <div class=\"library-modal-header d-flex align-items-start justify-content-between p-24px-28px bb-1px-solid-E5E7EB\">\r\n <div class=\"header-left d-flex flex-column gap-8\">\r\n <h3 class=\"library-modal-title m-0 color-dark fs-1-25rem\">\r\n {{ controller.labels['LBL_ADD_IMAGES'] || 'Add Images' }}\r\n </h3>\r\n <p class=\"library-modal-subtitle m-0 color-gray fs-0-85rem\">\r\n {{ controller.labels['LBL_LIBRARY_MODAL_DESC'] || 'Select images from your library.' }}\r\n </p>\r\n </div>\r\n <button id=\"btn-close-library-{{ config.name }}\" type=\"button\"\r\n class=\"library-close-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 border-none b-none c-9CA3AF\"\r\n (click)=\"closeLibraryModal()\" aria-label=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Loading -->\r\n <div class=\"library-loading\" *ngIf=\"libraryLoading\">\r\n <div class=\"lib-spinner rounded-50 b-3px-solid-E2E8F0\"></div>\r\n <span>{{ controller.labels['LBL_LOADING'] || 'Loading\u2026' }}</span>\r\n </div>\r\n\r\n <!-- Error -->\r\n <div class=\"library-error d-flex align-items-center gap-8 color-error b-FEF2F2 fs-0-875rem p-16px-24px\"\r\n *ngIf=\"libraryError && !libraryLoading\">\r\n <mat-icon>error_outline</mat-icon>\r\n {{ libraryError }}\r\n </div>\r\n\r\n <!-- Image grid -->\r\n <div class=\"library-grid d-grid gap-16 flex-1 p-28px b-F9FAFB\" *ngIf=\"!libraryLoading && libraryImages.length\">\r\n <div *ngFor=\"let img of libraryImages; let li = index\" id=\"lib-img-{{ config.name }}-{{ li }}\"\r\n class=\"library-grid-item position-relative rounded-12 overflow-hidden cursor-pointer bg-white b-3px-solid-transparent\"\r\n [class.selected]=\"isLibraryItemSelected(img)\" (click)=\"toggleLibraryItem(img)\">\r\n <img [src]=\"getLibraryItemUrl(img)\" class=\"library-grid-img w-100 h-100 d-block\" alt=\"Library image\">\r\n <div\r\n class=\"library-check position-absolute bg-white rounded-50 d-flex align-items-center justify-content-center c-3B82F6\"\r\n *ngIf=\"isLibraryItemSelected(img)\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n <div class=\"library-overlay-hover position-absolute b-rgba-59-130-246-0-12\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty library -->\r\n <div\r\n class=\"library-empty d-flex flex-column align-items-center justify-content-center gap-12 flex-1 c-9CA3AF fs-0-875rem p-48px-24px\"\r\n *ngIf=\"!libraryLoading && !libraryError && libraryImages.length === 0\">\r\n <mat-icon>image_not_supported</mat-icon>\r\n <span>{{ controller.labels['LBL_LIBRARY_EMPTY'] || 'No images found in library.' }}</span>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"library-modal-footer d-flex align-items-center justify-content-end bg-white p-20px-28px bt-1px-solid-E5E7EB\">\r\n <div class=\"library-footer-actions d-flex gap-12\">\r\n <lib-button id=\"btn-library-cancel-{{ config.name }}\" [variant]=\"'outline'\" (click)=\"closeLibraryModal()\">\r\n {{ controller.labels['LBL_CANCEL'] || 'Cancel' }}\r\n </lib-button>\r\n <lib-button id=\"btn-library-confirm-{{ config.name }}\" [variant]=\"'primary'\"\r\n [disabled]=\"librarySelectedIds.size === 0\" (click)=\"confirmLibrarySelection()\">\r\n {{ controller.labels['LBL_CONTINUE'] || 'Continue' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <!-- \u2550\u2550 Location Field \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isLocation\" class=\"field-wrapper location-field-wrapper d-flex flex-column gap-6 gap-12\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Field label -->\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n <p class=\"location-subtitle m-0 c-6B7280 fs-0-8125rem\" *ngIf=\"config.hint\">{{ config.hint }}</p>\r\n\r\n <!-- Three-tab bar -->\r\n <div class=\"location-tabs d-flex gap-12 mb-24\">\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'VENUE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('VENUE')\">\r\n {{ controller.labels['LBL_LOC_VENUE'] || 'Venue' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'ONLINE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('ONLINE')\">\r\n {{ controller.labels['LBL_LOC_ONLINE'] || 'Online Event' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'TBA' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('TBA')\">\r\n {{ controller.labels['LBL_LOC_TBA'] || 'To be Announced' }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- VENUE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'VENUE'\" class=\"loc-panel loc-venue-panel d-flex flex-column gap-12\">\r\n\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ADDRESS'] || 'Location address' }}\r\n </p>\r\n\r\n <!-- Added venue rows -->\r\n <div class=\"loc-venue-list d-flex flex-column gap-8\" *ngIf=\"locationVenues.length > 0\">\r\n <div *ngFor=\"let venue of locationVenues; let i = index\"\r\n class=\"loc-venue-item d-flex align-items-center gap-10 p-10px-14px br-7px b-ffffff b-1px-solid-D1D5DB\">\r\n <mat-icon class=\"loc-venue-search-icon fs-18px c-9CA3AF\">search</mat-icon>\r\n <span class=\"loc-venue-text flex-1 overflow-hidden fs-0-875rem c-111827\">{{ venue.address || venue.name ||\r\n venue.description }}</span>\r\n <button type=\"button\"\r\n class=\"loc-action-btn loc-delete-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none p-4px\"\r\n (click)=\"removeLocationVenue(i)\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Location count badge -->\r\n <p class=\"loc-count-text m-0 font-weight-600 fs-0-8125rem c-3B82F6\"\r\n *ngIf=\"locationVenues.length > 0 && config.locationConfig?.allowMulti\">\r\n {{ locationVenues.length }} {{ controller.labels['LBL_LOC_COUNT_SUFFIX'] || 'Locations Added!' }}\r\n </p>\r\n\r\n <!-- Search input (hide when max reached) -->\r\n <div class=\"loc-search-container position-relative\" *ngIf=\"!locationMaxReached\">\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n [placeholder]=\"config.locationConfig?.venuePlaceholder || (controller.labels['PH_LOC_VENUE'] || 'Type to search venue...')\"\r\n [value]=\"locationSearchText\" (input)=\"handleLocationSearchInput($event)\" (blur)=\"hideLocationSuggestions()\"\r\n autocomplete=\"off\" [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n <!-- Suggestions dropdown -->\r\n <div class=\"loc-suggestions-panel position-absolute overflow-hidden br-8px b-ffffff b-1px-solid-D1D5DB\"\r\n *ngIf=\"locationShowSuggestions && locationSuggestions.length\">\r\n <div *ngFor=\"let sug of locationSuggestions\"\r\n class=\"loc-suggestion-item d-flex align-items-center gap-10 cursor-pointer p-10px-14px\"\r\n (mousedown)=\"onLocationSuggestionSelect(sug)\">\r\n <mat-icon class=\"loc-suggestion-icon fs-18px c-E53E3E\">place</mat-icon>\r\n <span class=\"loc-suggestion-text overflow-hidden fs-0-875rem c-374151\">{{ sug.description }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Add another button -->\r\n <button type=\"button\"\r\n class=\"loc-add-btn d-inline-flex align-items-center gap-6 cursor-pointer font-weight-600 p-0 b-none border-none fs-0-875rem c-1A56DB\"\r\n *ngIf=\"locationVenues.length > 0 && !locationMaxReached && config.locationConfig?.allowMulti\">\r\n <mat-icon>add_circle_outline</mat-icon>\r\n <span>{{ controller.labels['LBL_LOC_ADD_ANOTHER'] || 'Add another Location' }}</span>\r\n </button>\r\n\r\n <!-- Map -->\r\n <div class=\"loc-map-container overflow-hidden br-10px b-1px-solid-E5E7EB\"\r\n *ngIf=\"config.locationConfig?.showMap !== false\">\r\n <ng-container *ngIf=\"config.locationConfig?.googleMapsApiKey; else simpleEmbed\">\r\n <div [id]=\"'loc-map-' + config.name\" class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\"></div>\r\n </ng-container>\r\n <ng-template #simpleEmbed>\r\n <iframe class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\" [src]=\"getLocationMapEmbedUrl() | trustedUrl\"\r\n frameborder=\"0\" allowfullscreen loading=\"lazy\">\r\n </iframe>\r\n </ng-template>\r\n </div>\r\n\r\n <!-- Map hint -->\r\n <p class=\"loc-map-hint m-0 text-center fs-0-78rem c-6B7280\">\r\n {{ controller.labels['LBL_LOC_MAP_HINT'] || 'Type the venue address. A map will appear to assist you.' }}\r\n </p>\r\n </div>\r\n\r\n <!-- ONLINE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'ONLINE'\" class=\"loc-panel loc-online-panel d-flex flex-column gap-12\">\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ONLINE_URL'] || 'Event URL' }}\r\n </p>\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">link</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n type=\"url\"\r\n [placeholder]=\"config.locationConfig?.onlinePlaceholder || (controller.labels['PH_LOC_ONLINE'] || 'https://zoom.us/j/...')\"\r\n [value]=\"locationOnlineUrl\" (input)=\"onLocationUrlChange($any($event.target).value)\"\r\n [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n </div>\r\n\r\n <!-- TBA TAB -->\r\n <div *ngIf=\"locationActiveTab === 'TBA'\"\r\n class=\"loc-panel loc-tba-panel d-flex flex-column gap-12 justify-content-center\">\r\n <div\r\n class=\"loc-tba-content d-flex flex-column align-items-center justify-content-center text-center gap-12 p-32px-24px b-F9FAFB b-1px-dashed-D1D5DB br-10px\">\r\n <mat-icon class=\"loc-tba-icon fs-40px c-9CA3AF\">schedule</mat-icon>\r\n <p class=\"loc-tba-text m-0 c-6B7280 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_TBA_DESC'] || \"This event's location is yet to be announced. Check back later\r\n for updates.\" }}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden real form control -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n</div>", styles: [".d-flex{display:flex}.d-inline-flex{display:inline-flex}.d-grid{display:grid}.d-block{display:block}.d-none{display:none}.flex-column{flex-direction:column}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.align-items-center{align-items:center}.align-items-start{align-items:flex-start}.align-items-end{align-items:flex-end}.justify-content-center{justify-content:center}.justify-content-between{justify-content:space-between}.justify-content-start{justify-content:flex-start}.justify-content-end{justify-content:flex-end}.grid-cols-12{grid-template-columns:repeat(12,1fr)}.w-100{width:100%}.h-100{height:100%}.position-relative{position:relative}.position-absolute{position:absolute}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-poppins{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)}.font-weight-400{font-weight:400}.font-weight-500{font-weight:500}.font-weight-600{font-weight:600}.text-13{font-size:13px}.text-14{font-size:14px}.text-16{font-size:16px}.color-white{color:#fff}.color-dark{color:#111827}.color-gray{color:#6b7280}.color-error{color:var(--cc-sf-error-text-color, #DC2626)}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.m-0{margin:0}.mt-4{margin-top:4px}.mt-8{margin-top:8px}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}.mb-0{margin-bottom:0}.mb-4{margin-bottom:4px}.mb-8{margin-bottom:8px}.mb-10{margin-bottom:10px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}.mb-24{margin-bottom:24px}.ml-16{margin-left:16px}.ml-20{margin-left:20px}.p-0{padding:0}.p-16{padding:16px}.p-20{padding:20px}.p-24{padding:24px}.pt-20{padding-top:20px}.pb-10{padding-bottom:10px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.gap-20{gap:20px}.rounded-4{border-radius:4px}.rounded-6{border-radius:6px}.rounded-8{border-radius:8px}.rounded-10{border-radius:10px}.rounded-12{border-radius:12px}.rounded-20{border-radius:20px}.rounded-24{border-radius:24px}.rounded-50{border-radius:50%}.cursor-pointer{cursor:pointer}.overflow-hidden{overflow:hidden}.resize-vertical{resize:vertical}.box-sizing-border{box-sizing:border-box}.border-none{border:none!important}.mb-16px{margin-bottom:var(--cc-sf-grid-gap, 16px)!important}.c-DC2626{color:var(--cc-sf-label-required-color, #DC2626)!important}.ml-0-125rem{margin-left:.125rem!important}.fs-0-875rem{font-size:.875rem!important}.c-111827{color:var(--cc-sf-label-color, #111827)!important}.br-7px{border-radius:var(--cc-sf-input-radius, 7px)!important}.c-6B7280{color:var(--cc-sf-hint-color, #6B7280)!important}.fs-0-75rem{font-size:var(--cc-sf-error-text-size, .75rem)!important}.b-none{background:none!important}.p-32px-24px{padding:32px 24px!important}.us-none{-webkit-user-select:none!important;user-select:none!important}.c-1E293B{color:var(--cc-sf-label-color, #1E293B)!important}.c-3B82F6{color:var(--cc-sf-chip-selected-bg, #3B82F6)!important}.fs-0-78rem{font-size:.78rem!important}.p-10px-14px{padding:10px 14px!important}.fs-0-85rem{font-size:.85rem!important}.fs-0-72rem{font-size:.72rem!important}.c-94A3B8{color:#94a3b8!important}.p-4px{padding:4px!important}.br-8px{border-radius:var(--cc-sf-input-radius, 8px)!important}.bc-F3F4F6{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.br-none{border-right:none!important}.bl-none{border-left:none!important}.pe-none{pointer-events:none!important}.fs-1-1rem{font-size:1.1rem!important}.c-9CA3AF{color:var(--cc-sf-hint-color, #9CA3AF)!important}.pl-2-4rem{padding-left:2.4rem!important}.fs-0-8125rem{font-size:.8125rem!important}.ls-none{list-style:none!important}.br-12px{border-radius:var(--mu-carousel-radius, 12px)!important}.b-FFFAF1{background:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.fs-18px{font-size:18px!important}.b-FEF2F2{background:var(--cc-sf-error-bg, #FEF2F2)!important}.bc-DC2626{border-color:var(--cc-sf-error-border, #DC2626)!important}.c-202124{color:var(--cc-sf-label-color, #202124)!important}.fs-18px{font-size:var(--cc-sf-label-size, 18px)!important}.mb-0-5rem{margin-bottom:.5rem!important}.pt-0-625rem{padding-top:var(--cc-sf-input-padding-y, .625rem)!important}.pb-0-625rem{padding-bottom:var(--cc-sf-input-padding-y, .625rem)!important}.pl-16px{padding-left:var(--cc-sf-input-padding-x, 16px)!important}.pr-16px{padding-right:var(--cc-sf-input-padding-x, 16px)!important}.bc-ffffff{background-color:var(--cc-sf-section-bg, #ffffff)!important}.b-1px-solid-D1D5DB{border:1px solid var(--cc-sf-input-border, #D1D5DB)!important}.fs-0-75rem{font-size:.75rem!important}.c-1F2937{color:var(--cc-sf-section-label-color, #1F2937)!important}.p-6px-14px{padding:var(--cc-sf-chip-padding, 6px 14px)!important}.b-ffffff{background:var(--loc-suggestion-bg, #ffffff)!important}.c-374151{color:var(--cc-sf-label-color, #374151)!important}.br-20px{border-radius:var(--cc-sf-chip-radius, 20px)!important}.fs-0-875rem{font-size:var(--cc-sf-btn-font-size, .875rem)!important}.bc-D1D5DB{background-color:var(--cc-sf-switch-track-off, #D1D5DB)!important}.pr-2-75rem{padding-right:2.75rem!important}.p-0-25rem{padding:.25rem!important}.p-0-625rem-0-875rem{padding:var(--cc-sf-generated-padding, .625rem .875rem)!important}.b-F3F4F6{background:var(--cc-sf-generated-bg, #F3F4F6)!important}.b-1px-solid-E5E7EB{border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.br-8px{border-radius:var(--cc-sf-uploaded-item-radius, 8px)!important}.c-6B7280{color:var(--ms-desc-color, #6B7280)!important}.mb-20px{margin-bottom:var(--cc-sf-section-gap, 20px)!important}.br-10px{border-radius:var(--cc-sf-input-radius, 10px)!important}.p-20px{padding:var(--cc-sf-section-padding, 20px)!important}.fs-1rem{font-size:1rem!important}.m-0-0-16px-0{margin:0 0 16px!important}.bb-2px-solid-E5E7EB{border-bottom:var(--cc-sf-section-label-border, 2px solid #E5E7EB)!important}.p-16px{padding:var(--cc-sf-instance-padding, 16px)!important}.b-F9FAFB{background:var(--loc-tba-bg, #F9FAFB)!important}.bb-1px-dashed-D1D5DB{border-bottom:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)!important}.c-4B5563{color:var(--cc-sf-instance-num-color, #4B5563)!important}.fs-0-8125rem{font-size:var(--cc-sf-hint-size, .8125rem)!important}.pb-0{padding-bottom:0!important}.p-18px-24px{padding:18px 24px!important}.c-111827{color:var(--ms-title-color, #111827)!important}.bt-1px-solid-E5E7EB{border-top:1px solid #E5E7EB!important}.p-4px-10px{padding:4px 10px!important}.b-FFF5F5{background:var(--cc-sf-btn-remove-bg, #FFF5F5)!important}.c-E53E3E{color:var(--loc-delete-color, #E53E3E)!important}.b-1px-solid-FED7D7{border:var(--cc-sf-btn-remove-border, 1px solid #FED7D7)!important}.br-4px{border-radius:var(--cc-sf-btn-remove-radius, 4px)!important}.p-8px-16px{padding:8px 16px!important}.b-transparent{background:var(--cc-sf-btn-add-bg, transparent)!important}.c-3B82F6{color:var(--cc-sf-input-focus-border, #3B82F6)!important}.b-1px-dashed-CBD5E1{border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1)!important}.br-6px{border-radius:var(--cc-sf-btn-add-radius, 6px)!important}.b-1-5px-dashed-CBD5E1{border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1)!important}.br-12px{border-radius:var(--cc-sf-dropzone-radius, 12px)!important}.bc-FFFAF1{background-color:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.c-94A3B8{color:var(--cc-sf-uploaded-remove-color, #94A3B8)!important}.fs-0-9rem{font-size:var(--cc-sf-input-font-size, .9rem)!important}.c-64748B{color:var(--cc-sf-dropzone-hint-color, #64748B)!important}.b-1px-solid-E2E8F0{border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0)!important}.b-2px-solid-E2E8F0{border:2px solid #E2E8F0!important}.pr-3-5rem{padding-right:3.5rem!important}.p-0-0-875rem{padding:0 .875rem!important}.bc-FFFFFF{background-color:var(--cc-sf-input-bg, #FFFFFF)!important}.b-1-5px-solid-D1D5DB{border:var(--cc-sf-input-border, 1.5px solid #D1D5DB)!important}.mb-0-75rem{margin-bottom:.75rem!important}.mt-6px{margin-top:6px!important}.pr-2-4rem{padding-right:2.4rem!important}.p-0-2rem{padding:.2rem!important}.fs-1-35rem{font-size:1.35rem!important}.p-4px-12px{padding:4px 12px!important}.b-111827{background:var(--cc-sf-label-color, #111827)!important}.b-2px-dashed-CBD5E1{border:2px dashed var(--cc-sf-dropzone-border, #CBD5E1)!important}.fs-52px{font-size:52px!important}.p-12px-16px{padding:12px 16px!important}.bb-1px-solid-F3F4F6{border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)!important}.b-0F172A{background:var(--mu-carousel-bg, #0F172A)!important}.b-3px-solid-rgba-255-255-255-0-15{border:3px solid rgba(255,255,255,.15)!important}.b-rgba-255-255-255-0-85{background:#ffffffd9!important}.b-rgba-0-0-0-0-55{background:#0000008c!important}.b-rgba-255-255-255-0-45{background:#ffffff73!important}.pb-4px{padding-bottom:4px!important}.b-2px-solid-transparent{border:2px solid transparent!important}.b-E2E8F0{background:var(--mu-thumb-bg, #E2E8F0)!important}.b-1E293B{background:#1e293b!important}.c-EF4444{color:#ef4444!important}.b-rgba-0-0-0-0-5{background:#00000080!important}.br-16px{border-radius:var(--mu-modal-radius, 16px)!important}.p-24px-28px{padding:24px 28px!important}.bb-1px-solid-E5E7EB{border-bottom:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.fs-1-25rem{font-size:1.25rem!important}.p-48px-24px{padding:48px 24px!important}.b-3px-solid-E2E8F0{border:3px solid #E2E8F0!important}.p-16px-24px{padding:16px 24px!important}.p-28px{padding:28px!important}.b-3px-solid-transparent{border:3px solid transparent!important}.b-rgba-59-130-246-0-12{background:#3b82f61f!important}.p-20px-28px{padding:20px 28px!important}.c-1A56DB{color:var(--loc-add-color, #1A56DB)!important}.b-1px-dashed-D1D5DB{border:1px dashed var(--cc-sf-input-disabled-border, #D1D5DB)!important}.fs-40px{font-size:40px!important}.c-9CA3AF{color:var(--loc-tba-icon-color, #9CA3AF)!important}.form-field{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)!important}:host{--cc-sf-input-border: #D1D5DB;--cc-sf-input-bg: #ffffff;--cc-sf-input-radius: 9px;--cc-sf-input-height: 44px;--cc-sf-label-color: #111827;--cc-sf-hint-color: #9CA3AF;--cc-sf-error-border: #EF4444;--cc-sf-error-bg: #FFF5F5;--cc-sf-accent-color: #6366F1;--cc-sf-input-focus-border: #6366F1;--cc-sf-input-hover-border: #A5B4FC;--cc-sf-input-placeholder: #C4C9D4;--cc-sf-input-disabled-bg: #F8F9FB;--cc-sf-input-disabled-border: #E5E7EB;--cc-sf-switch-track-on: #6366F1;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-thumb: #ffffff;--cc-sf-selected-color: #6366F1}.form-row{gap:var(--cc-sf-grid-gap, 16px)}.form-row.horizontal{display:flex;flex-direction:row}.form-row.horizontal>*{flex:1}.form-row:not(.horizontal){flex-direction:column}.form-row.grid-row{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.form-row.grid-row{grid-template-columns:1fr}.form-row.grid-row .row-field{grid-column:span 12!important}}.field-label{font-size:.75rem;font-weight:600;line-height:1;letter-spacing:.04em;text-transform:uppercase;color:#6b7280}.field-input,input.matInput,.mat-mdc-input-element{display:block;width:100%;height:var(--cc-sf-input-height)!important;padding:0 14px!important;font-family:inherit;font-size:.9rem;color:var(--cc-sf-label-color);background-color:var(--cc-sf-input-bg)!important;border:1.5px solid var(--cc-sf-input-border)!important;border-radius:var(--cc-sf-input-radius)!important;box-sizing:border-box;box-shadow:0 1px 2px #0000000a!important;transition:all .2s cubic-bezier(.4,0,.2,1)}.field-input::placeholder,input.matInput::placeholder,.mat-mdc-input-element::placeholder{font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder)}.field-input{opacity:var(--cc-sf-input-opacity, 1);line-height:var(--cc-sf-input-line-height, 1.5);transition:var(--cc-sf-input-transition, all .2s ease)}.field-input::placeholder{font-weight:var(--cc-sf-placeholder-weight, 400);font-size:var(--cc-sf-placeholder-size, 14px);line-height:var(--cc-sf-placeholder-line-height, 100%);color:var(--cc-sf-input-placeholder)}.field-input:hover:not(:disabled):not([readonly]){border-color:var(--cc-sf-input-hover-border)!important;box-shadow:0 1px 4px #6366f114!important}.field-input:focus{outline:none;border-color:var(--cc-sf-input-focus-border)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important;background-color:#fefeff!important}.field-input:disabled,.field-input[readonly]{background-color:var(--cc-sf-input-disabled-bg)!important;color:#9ca3af!important;cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important;box-shadow:none!important}.field-input.is-invalid{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)!important}.field-input.is-invalid:focus{box-shadow:0 0 0 3px #ef44441f,0 1px 4px #ef44441a!important}.field-input.textarea{resize:vertical;min-height:100px;height:auto;padding:12px 16px!important}input[type=time].time-input{cursor:pointer}input[type=time].time-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.7;filter:invert(30%)}input[type=time].time-input::-webkit-calendar-picker-indicator:hover{opacity:1}select.field-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}select.field-input:disabled{cursor:not-allowed}.multi-select-wrapper{position:relative}.multi-select-wrapper .multi-select-trigger{min-height:var(--cc-sf-input-height, 44px);height:auto;-webkit-user-select:none;user-select:none}.multi-select-wrapper .multi-select-trigger.ms-open{border-color:var(--cc-sf-input-focus-border, #6366F1)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important}.multi-select-wrapper .multi-select-trigger .multi-select-value{flex:1;color:var(--cc-sf-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.multi-select-wrapper .multi-select-trigger .multi-select-placeholder{flex:1;font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder, #C4C9D4)}.multi-select-wrapper .multi-select-trigger .multi-select-arrow{font-size:20px;width:20px;height:20px;line-height:20px;color:#6b7280;flex-shrink:0}.multi-select-wrapper .multi-select-panel{position:absolute;top:calc(100% + 4px);left:0;right:0;background:#fff;border:1.5px solid var(--cc-sf-input-border, #D1D5DB);border-radius:var(--cc-sf-input-radius, 9px);box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f;z-index:1050;max-height:240px;overflow-y:auto}.multi-select-wrapper .multi-select-panel::-webkit-scrollbar{width:4px}.multi-select-wrapper .multi-select-panel::-webkit-scrollbar-thumb{background:#d1d5db;border-radius:2px}.multi-select-wrapper .multi-select-option{padding:8px 12px;border-bottom:1px solid #F3F4F6;transition:background .1s}.multi-select-wrapper .multi-select-option:last-of-type{border-bottom:none}.multi-select-wrapper .multi-select-option:hover{background:#f9fafb}.multi-select-wrapper .multi-select-option input[type=checkbox]{flex-shrink:0;cursor:pointer;accent-color:var(--cc-sf-selected-color, #6366F1);width:15px;height:15px}.multi-select-wrapper .multi-select-empty{padding:12px;text-align:center}.multi-select-wrapper.is-invalid .multi-select-trigger{border-color:var(--cc-sf-error-border, #EF4444)!important;background-color:var(--cc-sf-error-bg, #FFF5F5)!important}.char-count-hint{font-style:normal;line-height:100%;letter-spacing:.02em;margin-top:.4rem}.radio-group.layout-column,.checkbox-group.layout-column{display:grid!important;grid-template-columns:repeat(12,1fr);gap:16px;width:100%}.radio-group.layout-row,.checkbox-group.layout-row{flex-direction:column!important;gap:12px;width:100%}.radio-label input,.checkbox-label input{cursor:pointer;accent-color:var(--cc-sf-chip-selected-bg, #F05A28)}.radio-label.card-item,.checkbox-label.card-item{display:flex!important;flex-direction:row-reverse!important;justify-content:space-between!important;align-items:center!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB);border-radius:12px;padding:16px 20px;box-sizing:border-box;transition:all .2s ease;background:var(--cc-sf-input-bg, #ffffff);margin-bottom:0}.radio-label.card-item input,.checkbox-label.card-item input{margin-left:16px}.radio-label.card-item.selected,.checkbox-label.card-item.selected{border-color:var(--cc-sf-selected-color);background-color:#f05a280d}.radio-label.card-item .option-content .label-text,.checkbox-label.card-item .option-content .label-text,.checkbox-single .checkbox-label{font-weight:var(--cc-sf-label-weight, 500)}.chip-label{transition:var(--cc-sf-input-transition, all .2s ease)}.chip-label:hover{background:var(--cc-sf-chip-hover-bg, #F3F4F6)}.chip-label.selected{background:var(--cc-sf-selected-color);color:var(--cc-sf-chip-selected-color, #ffffff);border-color:var(--cc-sf-selected-color)}.switch{width:50px;height:24px;display:inline-block}.switch input{opacity:0;width:0;height:0;position:absolute}.switch input:checked+.slider{background-color:var(--cc-sf-switch-track-on)!important}.switch input:checked+.slider:before{transform:translate(26px)}.switch .slider{inset:0;transition:.4s;background-color:var(--cc-sf-switch-track-off);border-radius:24px}.switch .slider:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:var(--cc-sf-switch-thumb);transition:.4s;border-radius:50%}.rating-group .star{transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star mat-icon{font-size:var(--cc-sf-star-size, 28px);width:var(--cc-sf-star-size, 28px);height:var(--cc-sf-star-size, 28px);line-height:var(--cc-sf-star-size, 28px);color:var(--cc-sf-star-empty, #D1D5DB);transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star.filled mat-icon,.rating-group .star.half mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.rating-group .star:hover mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.password-wrapper .password-toggle{right:.625rem;top:50%;transform:translateY(-50%);line-height:1;transition:color var(--cc-sf-input-transition, .2s ease)}.password-wrapper .password-toggle mat-icon.eye-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem}.password-wrapper .password-toggle:hover{color:var(--cc-sf-label-color, #374151)}.password-wrapper .password-toggle:focus{outline:none}.group-section-wrapper .group-label{font-size:var(--cc-sf-section-label-size, 1rem);font-weight:var(--cc-sf-section-label-weight, 600);color:var(--cc-sf-section-label-color, #1F2937);margin:0 0 16px;padding-left:12px;padding-top:2px;padding-bottom:2px;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);line-height:1.4}.group-section-wrapper .group-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.group-section-wrapper .group-fields.sf-grid{grid-template-columns:1fr}.group-section-wrapper .group-fields.sf-grid .sf-col{grid-column:span 12!important}}.group-section-wrapper .group-accordion-instance{border:var(--cc-sf-instance-border, 1px solid #E5E7EB);border-radius:var(--cc-sf-section-border-radius-inner, 8px);margin-bottom:8px;overflow:hidden;transition:border-color .2s ease}.group-section-wrapper .group-accordion-instance:last-of-type{margin-bottom:0}.group-section-wrapper .group-accordion-instance .group-accordion-header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px;background:var(--cc-sf-repeater-accordion-header-bg, #F9FAFB);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header:hover{background:var(--cc-sf-repeater-accordion-active-bg, #EFF6FF)}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-badge{width:22px;height:22px;border-radius:50%;background:var(--cc-sf-repeater-badge-bg, #E5E7EB);color:var(--cc-sf-repeater-badge-color, #374151);font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-title{font-size:var(--cc-sf-instance-num-size, .8125rem);font-weight:600;color:var(--cc-sf-repeater-accordion-header-color, #1F2937)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:var(--cc-sf-btn-remove-color, #E53E3E);padding:4px;border-radius:4px;line-height:1;display:flex;align-items:center;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:var(--cc-sf-instance-num-color, #4B5563)}.group-section-wrapper .group-accordion-instance .group-accordion-body{padding:var(--cc-sf-instance-padding, 16px);background:var(--cc-sf-instance-bg, #F9FAFB);border-top:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)}.group-section-wrapper .btn-add-group{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:10px 20px;margin-top:12px;background:var(--cc-sf-btn-add-bg, transparent);color:var(--cc-sf-btn-add-color, #3B82F6);border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1);border-radius:var(--cc-sf-btn-add-radius, 6px);cursor:pointer;font-family:inherit;font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.group-section-wrapper .btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.group-section-wrapper .group-instance:last-child{margin-bottom:0}.group-section-wrapper.multi-save-active{border:none;box-shadow:none;padding:0;background:transparent}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button{color:var(--ms-btn-add-color, #3B82F6);font-weight:600;font-size:.875rem;padding:8px 12px}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button:hover{color:var(--ms-btn-add-hover, #2563EB);background-color:var(--cc-sf-btn-add-hover-bg, #EFF6FF)}.group-section-wrapper.multi-save-active .group-instance.is-card{cursor:pointer;transition:all .2s ease-in-out}.group-section-wrapper.multi-save-active .group-instance.is-card:hover{box-shadow:var(--ms-card-shadow-hover, 0 8px 24px rgba(0, 0, 0, .08));border-color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-title{white-space:nowrap;text-overflow:ellipsis}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-desc{line-height:1.4;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view.is-expanded .card-content .card-desc{-webkit-line-clamp:unset;line-clamp:unset}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon{font-size:22px;width:22px;height:22px;color:var(--cc-sf-hint-color, #9CA3AF);transition:color .2s}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-delete:hover{color:var(--cc-sf-error-border, #DC2626)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-edit:hover{color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-expand{color:var(--cc-sf-input-disabled-border, #E5E7EB)}.btn-remove{transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-remove mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.btn-remove:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.btn-add-group{font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.upload-drop-zone{background-color:var(--cc-sf-dropzone-bg, #F8FAFC);border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1);border-radius:var(--cc-sf-dropzone-radius, 12px);transition:background-color .2s ease,border-color .2s ease}.upload-drop-zone:hover{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-hover-border, #93C5FD)}.upload-drop-zone.drag-over{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-over-border, #3B82F6);box-shadow:var(--cc-sf-dropzone-over-shadow, 0 0 0 4px rgba(59, 130, 246, .12))}.upload-drop-zone.is-invalid{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.upload-icon-wrap .dropzone-icon-pill{width:52px;height:52px;border-radius:50%;background:var(--cc-sf-dropzone-icon-bg, rgba(59, 130, 246, .1))}.upload-icon-wrap mat-icon.upload-cloud-icon{font-size:28px;width:28px;height:28px;line-height:28px;color:var(--cc-sf-accent-color, #3B82F6)}.upload-main-text{color:var(--cc-sf-label-color, #1E293B)}.upload-sub-text{color:var(--cc-sf-hint-color, #64748B)}.upload-link{color:var(--cc-sf-dropzone-link-color, #3B82F6);font-weight:500}.upload-formats{color:var(--cc-sf-dropzone-link-color, #3B82F6)}.upload-size-badge{display:inline-block;padding:2px 8px;border-radius:20px;background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-hint-color, #6B7280);font-weight:500}.uploaded-item{background:var(--cc-sf-uploaded-item-bg, #ffffff);border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0);border-radius:var(--cc-sf-uploaded-item-radius, 8px);transition:box-shadow .15s ease}.uploaded-item:hover{box-shadow:0 2px 6px #0000000f}.uploaded-item mat-icon.file-type-icon{font-size:20px;width:20px;height:20px;line-height:20px;flex-shrink:0;color:var(--cc-sf-hint-color, #64748B)}.uploaded-item .file-thumb{width:36px;height:36px;object-fit:cover;flex-shrink:0}.uploaded-item .file-info{min-width:0;gap:2px}.uploaded-item .file-info .file-name{white-space:nowrap;text-overflow:ellipsis}.uploaded-item .file-remove-btn{flex-shrink:0;width:32px;height:32px;background:none;border:none;cursor:pointer;color:var(--cc-sf-uploaded-remove-color, #94A3B8);padding:0;display:flex;align-items:center;justify-content:center;transition:color .15s ease,background .15s ease}.uploaded-item .file-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.uploaded-item .file-remove-btn:hover:not(:disabled){color:var(--cc-sf-uploaded-remove-hover-color, #DC2626);background:var(--cc-sf-uploaded-remove-hover-bg, #FEF2F2)}.uploaded-item .file-remove-btn:disabled{opacity:.4;cursor:not-allowed}.uploaded-item.uploading{background:var(--cc-sf-uploaded-uploading-bg, #F8FAFC);border-color:var(--cc-sf-uploaded-uploading-border, #CBD5E1);opacity:.85}.upload-spinner{width:20px;height:20px;flex-shrink:0;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}@keyframes cc-spin{to{transform:rotate(360deg)}}.uploading-label{font-style:italic}.input-group{align-items:stretch}.input-group .field-input{flex:1;width:auto}.input-prefix+.input-group .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.input-group .field-input:has(+.input-suffix){border-top-right-radius:0;border-bottom-right-radius:0}.input-group .field-input.has-icon-right{padding-right:3rem}.input-group.readonly .field-input{cursor:default}.input-prefix,.input-suffix{display:flex!important;align-items:center;white-space:nowrap;padding:0 14px;background-color:var(--cc-sf-input-disabled-bg);border:1px solid var(--cc-sf-input-border);font-size:.875rem;color:var(--cc-sf-hint-color);-webkit-user-select:none;user-select:none}.input-prefix{border-right:none;border-top-left-radius:var(--cc-sf-input-radius, 8px);border-bottom-left-radius:var(--cc-sf-input-radius, 8px)}.input-suffix{border-left:none;border-top-right-radius:var(--cc-sf-input-radius, 8px);border-bottom-right-radius:var(--cc-sf-input-radius, 8px)}.readonly-icons{right:.875rem;top:50%;transform:translateY(-50%)}.readonly-icons mat-icon.lock-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem;opacity:.5;color:var(--cc-sf-hint-color, #6B7280)}.suffix-action-icons{right:.875rem;top:50%;transform:translateY(-50%);z-index:1;pointer-events:auto}.suffix-action-icons mat-icon.suffix-action-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem;color:var(--cc-sf-hint-color, #6B7280);cursor:pointer;transition:color .2s ease,transform .15s ease}.suffix-action-icons mat-icon.suffix-action-icon:hover{color:var(--cc-sf-text-color, #202124);transform:scale(1.15)}.date-icon-wrapper{right:.5rem;top:50%;transform:translateY(-50%);pointer-events:auto}.date-icon-wrapper .mat-icon-button{width:32px;height:32px;line-height:32px}.subfields-group-wrapper .subfields-row{transition:all .2s ease}.subfields-group-wrapper .subfields-row.is-invalid .subfield-item ::ng-deep .field-input{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.subfields-group-wrapper .subfields-row .subfield-item{min-width:0}.subfields-group-wrapper .subfields-row .subfield-item ::ng-deep .field-label{font-size:.75rem!important;margin-bottom:4px!important;font-weight:500!important;color:var(--cc-sf-hint-color, #6B7280)!important}.subfields-group-wrapper .subfields-row .subfield-separator{font-weight:700}.autocomplete-wrapper .ac-input{padding-left:40px!important}.autocomplete-wrapper .ac-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1;transition:color var(--cc-sf-input-transition, .2s ease)}.autocomplete-wrapper .ac-clear-btn{right:.6rem;transition:color .15s ease,background .15s ease}.autocomplete-wrapper .ac-clear-btn mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.autocomplete-wrapper .ac-clear-btn:hover{color:var(--cc-sf-label-color, #374151);background:var(--cc-sf-input-disabled-bg, #F3F4F6)}.autocomplete-wrapper .ac-clear-btn:focus{outline:none}.autocomplete-wrapper:focus-within .ac-search-icon{color:var(--cc-sf-accent-color, #3B82F6)}.autocomplete-wrapper.is-invalid .ac-input{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)}.autocomplete-wrapper.readonly .ac-input{background-color:var(--cc-sf-input-disabled-bg);color:var(--cc-sf-input-disabled-color, #6B7280);cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.ac-no-results{font-style:italic}::ng-deep .mat-mdc-autocomplete-panel,::ng-deep .mat-autocomplete-panel{background:var(--cc-sf-input-bg, #ffffff)!important;border-radius:var(--cc-sf-input-radius, 9px)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important;box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f!important;padding:4px 0!important;min-width:200px}::ng-deep .mat-mdc-autocomplete-panel mat-option,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option,::ng-deep .mat-mdc-autocomplete-panel .mat-option,::ng-deep .mat-autocomplete-panel mat-option,::ng-deep .mat-autocomplete-panel .mat-mdc-option,::ng-deep .mat-autocomplete-panel .mat-option{background:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #111827)!important;font-size:.875rem!important;padding:10px 16px!important;min-height:40px!important;line-height:1.4!important;display:flex!important;flex-direction:column!important;align-items:flex-start!important;transition:background var(--cc-sf-input-transition, .2s ease)!important}::ng-deep .mat-mdc-autocomplete-panel mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-mdc-autocomplete-panel .mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel .mat-mdc-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel .mat-option:hover:not(.mat-option-disabled):not([disabled]){background:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}::ng-deep .mat-mdc-autocomplete-panel mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel mat-option.mdc-list-item--selected,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mdc-list-item--selected,::ng-deep .mat-mdc-autocomplete-panel .mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel .mat-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel mat-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel .mat-mdc-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel .mat-mdc-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel .mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel .mat-option.mdc-list-item--selected{background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)!important;color:var(--cc-sf-selected-color, #6366F1)!important;font-weight:600!important}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-option-label,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-option-label,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-option-label,::ng-deep .mat-autocomplete-panel mat-option .ac-option-label,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-option-label,::ng-deep .mat-autocomplete-panel .mat-option .ac-option-label{font-weight:500;color:var(--cc-sf-label-color, #111827);font-size:.875rem;display:block}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-display-fields,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-display-fields,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-display-fields,::ng-deep .mat-autocomplete-panel mat-option .ac-display-fields,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-display-fields,::ng-deep .mat-autocomplete-panel .mat-option .ac-display-fields{align-items:center;line-height:1}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-item,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-item,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-item,::ng-deep .mat-autocomplete-panel mat-option .ac-df-item,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-item,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-item{display:inline-flex;align-items:center;font-size:.72rem;color:var(--cc-sf-hint-color, #6B7280);gap:3px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-chip,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-chip,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-chip,::ng-deep .mat-autocomplete-panel mat-option .ac-df-chip,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-chip,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-chip{background:var(--cc-sf-input-disabled-bg, #F3F4F6);border-radius:4px;padding:2px 6px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-text,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-text,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-text,::ng-deep .mat-autocomplete-panel mat-option .ac-df-text,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-text,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-text{color:var(--cc-sf-hint-color, #6B7280)}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-avatar,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-avatar,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel mat-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-avatar{width:24px;height:24px;border-radius:50%;object-fit:cover;border:1px solid var(--cc-sf-input-border, #D1D5DB);vertical-align:middle}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-label,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-label,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-label,::ng-deep .mat-autocomplete-panel mat-option .ac-df-label,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-label,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-label{font-weight:600;color:var(--cc-sf-hint-color, #9CA3AF);margin-right:2px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-icon,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-icon,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-icon,::ng-deep .mat-autocomplete-panel mat-option .ac-df-icon,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-icon,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-icon{font-size:11px;width:11px;height:11px;line-height:11px;color:var(--cc-sf-hint-color, #9CA3AF);flex-shrink:0}.mu-layout{grid-template-columns:1fr 1fr;gap:32px}@media(max-width:768px){.mu-layout{grid-template-columns:1fr}}.mu-title{font-weight:700;line-height:1.3}.mu-badge{white-space:nowrap;flex-shrink:0}.mu-description{line-height:1.6}.mu-feature-item .mu-check{width:16px;height:16px;line-height:16px;flex-shrink:0}.mu-right{min-height:260px}.mu-right-empty{min-height:250px;max-width:400px;box-shadow:0 2px 10px #0000000d;transition:box-shadow .2s ease}.mu-right-empty:hover{cursor:pointer;box-shadow:0 4px 16px #0000001a}.mu-right-empty .mu-right-empty-icon{width:52px;height:52px;line-height:52px;opacity:.3}.mu-right-empty p{margin:0;font-size:.85rem}.media-add-container{display:inline-block}.media-add-container ::ng-deep button{display:flex;align-items:center;gap:6px}.media-add-container ::ng-deep button .menu-chevron{width:18px;height:18px;line-height:18px;transition:transform .2s ease}.media-dropdown{top:calc(100% + 6px);left:0;z-index:200;min-width:240px;box-shadow:var(--mu-dropdown-shadow, 0 8px 32px rgba(0, 0, 0, .12));animation:mu-fade-in .15s ease}@keyframes mu-fade-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.media-dropdown-item{transition:background .15s ease}.media-dropdown-item:last-child{border-bottom:none}.media-dropdown-item:hover{background:var(--cc-sf-dropzone-hover-bg, #F0F9FF)}.media-drop-icon{width:36px;height:36px;flex-shrink:0}.media-drop-icon mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.media-drop-icon--video{background:var(--mu-icon-video-bg, #FFF0F0);color:var(--mu-icon-video-color, #EF4444)}.media-drop-icon--device{background:var(--mu-icon-device-bg, #EFF6FF);color:var(--mu-icon-device-color, #3B82F6)}.media-drop-icon--library{background:var(--mu-icon-library-bg, #F0FDF4);color:var(--mu-icon-library-color, #22C55E)}.media-drop-text{gap:2px}.youtube-input-panel{animation:mu-fade-in .18s ease}.youtube-panel-label mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:var(--mu-icon-video-color, #EF4444)}.youtube-input-row{align-items:stretch}.media-menu-backdrop{position:fixed;inset:0;z-index:100}.media-upload-status{animation:mu-fade-in .2s ease}.media-upload-status .status-icon{width:18px;height:18px;line-height:18px}.media-carousel-main{max-width:400px;height:var(--mu-carousel-height, 250px)}.carousel-viewer{inset:0}.carousel-viewer .carousel-image{object-fit:cover}.carousel-viewer .carousel-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.carousel-nav{top:50%;transform:translateY(-50%);z-index:10;width:40px;height:40px;box-shadow:0 2px 8px #0003;transition:background .2s ease,opacity .2s ease;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.carousel-nav mat-icon{font-size:22px;width:22px;height:22px;line-height:22px;color:#1e293b}.carousel-nav:hover:not(:disabled){background:#fff}.carousel-nav:disabled{opacity:.3;cursor:not-allowed}.carousel-nav--prev{left:12px}.carousel-nav--next{right:12px}.carousel-remove-btn{top:10px;right:10px;z-index:10;width:32px;height:32px;transition:background .2s ease}.carousel-remove-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:#fff}.carousel-remove-btn:hover:not(:disabled){background:#dc2626d9}.carousel-remove-btn:disabled{opacity:.4;cursor:not-allowed}.carousel-dots{bottom:10px;left:50%;transform:translate(-50%);z-index:10}.carousel-dot{width:8px;height:8px;transition:background .2s ease,transform .2s ease}.carousel-dot.active{background:#fff;transform:scale(1.3)}.media-thumbnail-strip{max-width:400px;overflow-x:auto}.media-thumbnail-strip::-webkit-scrollbar{height:4px}.media-thumbnail-strip::-webkit-scrollbar-thumb{background:var(--cc-sf-input-disabled-border, #D1D5DB);border-radius:2px}.media-thumb{flex-shrink:0;width:72px;height:52px;transition:border-color .2s ease,transform .15s ease}.media-thumb.active{border-color:var(--mu-thumb-active-border, var(--cc-sf-accent-color, #3B82F6));transform:scale(1.04)}.media-thumb:hover:not(.active){border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.media-thumb .thumb-img{object-fit:cover}.media-thumb .thumb-yt-placeholder mat-icon{font-size:28px;width:28px;height:28px;line-height:28px}.media-thumb .thumb-uploading .thumb-spinner{width:20px;height:20px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.media-library-portal-host{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;visibility:hidden;opacity:0;pointer-events:none;transition:opacity .2s ease,visibility .2s ease}.media-library-portal-host.is-open{visibility:visible;opacity:1;pointer-events:auto}.media-library-portal-host.is-open .media-library-modal{transform:scale(1) translateY(0)}.media-library-overlay{position:absolute;inset:0;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.media-library-modal{position:relative;z-index:10000;width:90vw;max-width:900px;max-height:90vh;background:#fff;border-radius:16px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;transform:scale(.95) translateY(10px);transition:transform .3s cubic-bezier(.175,.885,.32,1.275)}.library-modal-header{flex-shrink:0}.library-modal-title{font-weight:700}.library-modal-subtitle{line-height:1.5;max-width:600px}.library-close-btn{width:32px;height:32px;transition:background .15s ease,color .15s ease}.library-close-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-close-btn:hover{background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-label-color, #374151)}.library-loading mat-icon,.library-empty mat-icon{font-size:40px;width:40px;height:40px;line-height:40px;opacity:.5}.lib-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.library-error{flex-shrink:0}.library-error mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-grid{grid-template-columns:repeat(5,1fr);max-height:50vh;overflow-y:auto}.library-grid::-webkit-scrollbar{width:8px}.library-grid::-webkit-scrollbar-track{background:#f1f1f1}.library-grid::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:10px;border:2px solid #F1F1F1}.library-grid-item{aspect-ratio:1/1;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.library-grid-item:hover{transform:translateY(-4px) scale(1.02);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.library-grid-item.selected{border-color:var(--cc-sf-accent-color, #3B82F6)}.library-grid-item.selected .library-grid-img{opacity:.7}.library-grid-item:hover .library-overlay-hover{opacity:1}.library-grid-img{object-fit:cover}.library-overlay-hover{inset:0;opacity:0;transition:opacity .15s ease}.library-check{top:6px;right:6px;width:22px;height:22px;box-shadow:0 1px 4px #00000026}.library-check mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.library-modal-footer{flex-shrink:0}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary{background-color:var(--cc-sf-accent-color, #3B82F6)!important;border-color:var(--cc-sf-accent-color, #3B82F6)!important;color:#fff!important;font-weight:600;padding-left:32px;padding-right:32px}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:hover{background-color:var(--cc-sf-btn-primary-hover-bg, #2563EB)!important}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:disabled{background-color:#93c5fd!important;cursor:not-allowed}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline{font-weight:600;padding-left:24px;padding-right:24px;border-color:#d1d5db;color:#374151}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline:hover{background-color:#f9fafb}.location-subtitle{line-height:1.5}.loc-tab-btn ::ng-deep button{width:100%}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning){background-color:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #000000)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning):hover{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.loc-venue-item{transition:box-shadow .15s ease,border-color .15s ease}.loc-venue-item:hover{box-shadow:0 2px 8px #0000000f;border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.loc-venue-search-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-venue-text{white-space:nowrap;text-overflow:ellipsis}.loc-action-btn{transition:background .15s ease,color .15s ease;flex-shrink:0}.loc-action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.loc-action-btn.loc-delete-btn{color:var(--loc-delete-color, #E53E3E)}.loc-action-btn.loc-delete-btn:hover{background:var(--cc-sf-error-bg, #FEF2F2)}.loc-action-btn.loc-edit-btn{color:var(--cc-sf-hint-color, #9CA3AF)}.loc-action-btn.loc-edit-btn:hover{color:var(--cc-sf-input-focus-border, #3B82F6);background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)}.loc-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1}.loc-suggestions-panel{top:calc(100% + 4px);left:0;right:0;z-index:300;box-shadow:0 8px 24px #0000001a;animation:mu-fade-in .15s ease;max-height:260px;overflow-y:auto}.loc-suggestion-item{transition:background .12s ease}.loc-suggestion-item:hover,.loc-suggestion-item:focus{background:var(--loc-suggestion-hover-bg, #F0F9FF)}.loc-suggestion-item:not(:last-child){border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)}.loc-suggestion-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-suggestion-text{white-space:nowrap;text-overflow:ellipsis}.loc-add-btn{transition:opacity .15s ease}.loc-add-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.loc-add-btn:hover{opacity:.8}.loc-map-container{box-shadow:0 2px 10px #0000000f}.loc-tba-panel{min-height:120px}.loc-tba-icon{width:40px;height:40px;line-height:40px;opacity:.6}.loc-tba-text{line-height:1.6;max-width:360px}.radio-label{display:flex!important}.radio-label .option-content{padding-left:10px}\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$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.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$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: i9.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i9.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: i11.QuillEditorComponent, selector: "quill-editor" }, { kind: "component", type: FormFieldComponent, selector: "lib-form-field", inputs: ["config", "controller", "formGroup", "allowMulti"] }, { kind: "pipe", type: TrustedUrlPipe, name: "trustedUrl" }] });
|
|
2793
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FormFieldComponent, isStandalone: false, selector: "lib-form-field", inputs: { config: "config", controller: "controller", formGroup: "formGroup", allowMulti: "allowMulti" }, host: { listeners: { "document:click": "onDocumentClick()", "document:keydown.escape": "onEscapeKey()" } }, viewQueries: [{ propertyName: "mediaDeviceInput", first: true, predicate: ["mediaDeviceInput"], descendants: true }, { propertyName: "libraryModalRef", first: true, predicate: ["libraryModal"], descendants: true }], ngImport: i0, template: "<div class=\"form-field mb-16px\" *ngIf=\"isVisible\" [class.has-error]=\"errorMessage\">\r\n\r\n <!-- \u2550\u2550 ROW Layout \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRow\" class=\"form-row grid-row\">\r\n <ng-container *ngFor=\"let child of config.children\">\r\n <div class=\"row-field\" [style.gridColumn]=\"'span ' + getChildColSpan(child)\" *ngIf=\"child.isEnabled !== false\">\r\n <lib-form-field [config]=\"child\" [controller]=\"controller\" [formGroup]=\"formGroup\" [allowMulti]=\"allowMulti\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 allowMulti (repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig?.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\"\r\n [class.multi-save-active]=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n\r\n <!-- Multi-Save: header row with label + top-right Add button -->\r\n <div class=\"multi-save-header d-flex justify-content-between align-items-center mb-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig?.label\">{{ config.sectionConfig!.label }}</h3>\r\n <lib-button [variant]=\"'outline'\" [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\"\r\n class=\"btn-add-multi\">\r\n {{ addMultiLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- Standard heading (non-multiSave) -->\r\n <h3 class=\"group-label\"\r\n *ngIf=\"config.sectionConfig?.label && !config.sectionConfig?.multiSaveConfig?.active\">{{\r\n config.sectionConfig!.label }}</h3>\r\n\r\n <!-- \u2500\u2500 Standard (non-multiSave) repeater: accordion instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-accordion-instance\"\r\n [class.is-expanded]=\"isGroupExpanded(i)\">\r\n\r\n <!-- Accordion header -->\r\n <div class=\"group-accordion-header\" (click)=\"toggleGroupAccordion(i)\"\r\n role=\"button\" [attr.aria-expanded]=\"isGroupExpanded(i)\">\r\n <div class=\"accordion-header-left d-flex align-items-center gap-10\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.sectionConfig!.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right d-flex align-items-center gap-6\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceList.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeGroupInstance(i)\"\r\n aria-label=\"Remove\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isGroupExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body (always mounted so form controls survive collapse) -->\r\n <div class=\"group-accordion-body\" [hidden]=\"!isGroupExpanded(i)\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"instance.rowController\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-group\" (click)=\"addGroupInstance()\">\r\n <mat-icon>add</mat-icon> {{ addLabel }} {{ config.sectionConfig!.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2500\u2500 MultiSave: card instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-instance position-relative mb-16 overflow-hidden\"\r\n [class.is-editing]=\"instance.isEditing\"\r\n [class.is-card]=\"!instance.isEditing\">\r\n\r\n <!-- Edit / new form view -->\r\n <div [hidden]=\"!instance.isEditing\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"instance.rowController\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Save / Cancel -->\r\n <div class=\"group-footer d-flex justify-content-end align-items-center gap-16 p-0-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"multiSaveError\">{{ multiSaveError }}</span>\r\n <div class=\"footer-actions d-flex gap-12\">\r\n <lib-button [variant]=\"'outline'\" (click)=\"cancelGroupInstance(i)\">Cancel</lib-button>\r\n <lib-button [variant]=\"'primary'\" (click)=\"saveGroupInstance(i)\">Save</lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Card view (saved state) -->\r\n <ng-container *ngIf=\"!instance.isEditing\">\r\n <div class=\"card-view d-flex justify-content-between align-items-center p-18px-24px\"\r\n [class.is-expanded]=\"instance.isExpanded\">\r\n <div class=\"card-content flex-1 d-flex flex-column gap-4 overflow-hidden\">\r\n <span class=\"card-title font-weight-600 overflow-hidden fs-1rem c-111827\">{{\r\n instance.fg.get(config.sectionConfig!.multiSaveConfig!.summaryField || '')?.value\r\n || '\u2014' }}</span>\r\n </div>\r\n <div class=\"card-actions d-flex align-items-center gap-16 ml-20\">\r\n <mat-icon class=\"icon-delete\" (click)=\"removeGroupInstance(i, true)\">delete_outline</mat-icon>\r\n <mat-icon class=\"icon-edit\" (click)=\"editGroupInstance(i)\">edit_outline</mat-icon>\r\n <mat-icon class=\"icon-expand\" (click)=\"toggleExpandGroupInstance(i)\">\r\n {{ instance.isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 single (non-repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig && !config.sectionConfig.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig.label\">{{ config.sectionConfig.label }}</h3>\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"groupFormGroup\" [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Text Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTextField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <textarea *ngIf=\"config.subType === 'LONG'\" class=\"field-input textarea\" [placeholder]=\"config.placeholder || ''\"\r\n [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\" rows=\"4\">\r\n </textarea>\r\n\r\n <!-- Password input with show/hide toggle -->\r\n <div *ngIf=\"config.subType === 'PASSWORD'\" class=\"password-wrapper position-relative d-flex align-items-center\">\r\n <input [type]=\"showPassword ? 'text' : 'password'\" class=\"field-input password-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <button type=\"button\"\r\n class=\"password-toggle position-absolute cursor-pointer d-flex align-items-center justify-content-center b-none border-none c-6B7280 p-0-25rem\"\r\n (click)=\"showPassword = !showPassword\" tabindex=\"-1\"\r\n [attr.aria-label]=\"showPassword ? 'Hide password' : 'Show password'\">\r\n <mat-icon class=\"eye-icon\">{{ showPassword ? 'visibility' : 'visibility_off' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input *ngIf=\"config.subType !== 'LONG' && config.subType !== 'PASSWORD'\"\r\n [type]=\"config.subType === 'EMAIL' ? 'email' : config.subType === 'PHONE' ? 'tel' : 'text'\" class=\"field-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\"\r\n [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n\r\n <!-- Suffix Action Icons (clickable) -->\r\n <div class=\"suffix-action-icons position-absolute d-flex gap-8 align-items-center\"\r\n *ngIf=\"config.suffixActionIcons?.length && !config.readonly\">\r\n <mat-icon class=\"suffix-action-icon\"\r\n *ngFor=\"let action of config.suffixActionIcons\"\r\n [style.color]=\"action.color || null\"\r\n [title]=\"action.tooltip || ''\"\r\n (click)=\"onSuffixActionClick(action.actionId)\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Number Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isNumberField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input type=\"number\" class=\"field-input\" [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\"\r\n [min]=\"config.numberConfig?.min ?? null\" [max]=\"config.numberConfig?.max ?? null\"\r\n [step]=\"config.numberConfig?.step || 1\" [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n\r\n <!-- Suffix Action Icons (clickable) -->\r\n <div class=\"suffix-action-icons position-absolute d-flex gap-8 align-items-center\"\r\n *ngIf=\"config.suffixActionIcons?.length && !config.readonly\">\r\n <mat-icon class=\"suffix-action-icon\"\r\n *ngFor=\"let action of config.suffixActionIcons\"\r\n [style.color]=\"action.color || null\"\r\n [title]=\"action.tooltip || ''\"\r\n (click)=\"onSuffixActionClick(action.actionId)\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Date Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDateField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input matInput [matDatepicker]=\"datePicker\" class=\"field-input date-input has-icon-right\"\r\n [formControlName]=\"config.name!\" [min]=\"effectiveMinDate\" [max]=\"config.dateConfig?.maxDate\"\r\n [class.is-invalid]=\"errorMessage\" [placeholder]=\"config.placeholder || ''\"\r\n [readonly]=\"config.readonly || config.dateConfig?.inputReadonly\"\r\n (click)=\"!config.readonly && datePicker.open()\">\r\n <div class=\"date-icon-wrapper position-absolute d-flex align-items-center justify-content-center\"\r\n *ngIf=\"!config.readonly\">\r\n <mat-datepicker-toggle matSuffix [for]=\"datePicker\"></mat-datepicker-toggle>\r\n </div>\r\n <mat-datepicker #datePicker></mat-datepicker>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Time Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTimeField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input type=\"time\" class=\"field-input time-input\" [formControlName]=\"config.name!\"\r\n [min]=\"effectiveMinTime\" [max]=\"effectiveMaxTime\"\r\n [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly || config.timeConfig?.inputReadonly\">\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Autocomplete \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isAutocomplete\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Hidden real control (stores the code value) -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <div class=\"autocomplete-wrapper position-relative d-flex align-items-center w-100\"\r\n [class.is-invalid]=\"errorMessage\" [class.readonly]=\"config.readonly\">\r\n <!-- Search icon -->\r\n <mat-icon class=\"ac-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n\r\n <input class=\"field-input ac-input\" [formControl]=\"autocompleteInputCtrl\" [matAutocomplete]=\"auto\"\r\n [placeholder]=\"config.placeholder || 'Search\u2026'\" [readonly]=\"!!config.readonly\" [class.is-invalid]=\"errorMessage\"\r\n (blur)=\"onAutocompleteClear()\" autocomplete=\"off\">\r\n\r\n <!-- Clear button -->\r\n <button type=\"button\"\r\n class=\"ac-clear-btn position-absolute d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none c-9CA3AF p-0-2rem\"\r\n *ngIf=\"autocompleteInputCtrl.value && !config.readonly\"\r\n (click)=\"autocompleteInputCtrl.setValue(''); updateValue(null)\" tabindex=\"-1\" aria-label=\"Clear\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n\r\n <mat-autocomplete #auto=\"matAutocomplete\" [panelWidth]=\"'auto'\">\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.label\"\r\n (onSelectionChange)=\"onAutocompleteSelected(option)\">\r\n <span class=\"ac-option-label\">{{ option.label }}</span>\r\n\r\n <!-- Dynamic display fields (image / email / phone / text) -->\r\n <div class=\"ac-display-fields d-flex flex-wrap gap-6 mt-2\" *ngIf=\"option['displayMeta']?.length\">\r\n <ng-container *ngFor=\"let field of option['displayMeta']\">\r\n\r\n <!-- Image avatar -->\r\n <span *ngIf=\"field.type === 'image' && field.value\" class=\"ac-df-item ac-df-image\">\r\n <img [src]=\"field.value\" [alt]=\"field.label || 'image'\" class=\"ac-df-avatar\">\r\n </span>\r\n\r\n <!-- Email -->\r\n <span *ngIf=\"field.type === 'email' && field.value\" class=\"ac-df-item ac-df-chip\">\r\n <mat-icon class=\"ac-df-icon\">mail_outline</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n <!-- Phone -->\r\n <span *ngIf=\"field.type === 'phone' && field.value\" class=\"ac-df-item ac-df-chip\" [class]=\"field.className\">\r\n <mat-icon class=\"ac-df-icon\">phone</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n <!-- Custom / Icon-based / Generic Text -->\r\n <span *ngIf=\"field.type !== 'image' && field.type !== 'email' && field.type !== 'phone' && field.value\" \r\n class=\"ac-df-item\" [class.ac-df-chip]=\"!!field.icon\" [class]=\"field.className\">\r\n <mat-icon class=\"ac-df-icon\" *ngIf=\"field.icon\">{{ field.icon }}</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n </ng-container>\r\n </div>\r\n </mat-option>\r\n <mat-option *ngIf=\"filteredOptions.length === 0\" disabled class=\"ac-no-results fs-0-8125rem c-6B7280\">\r\n No results found\r\n </mat-option>\r\n </mat-autocomplete>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Dropdown \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDropdown\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- SINGLE SELECT: native select (default, non-searchable) -->\r\n <select *ngIf=\"config.subType === 'SINGLE' && !isSearchableDropdown\" class=\"field-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option [ngValue]=\"null\" disabled selected>{{ config.placeholder || selectPlaceholderLabel }}</option>\r\n <option *ngFor=\"let option of localOptionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <!-- SINGLE SELECT: custom searchable dropdown -->\r\n <div *ngIf=\"config.subType === 'SINGLE' && isSearchableDropdown\" class=\"single-select-wrapper\"\r\n [class.is-invalid]=\"errorMessage\">\r\n\r\n <div class=\"field-input single-select-trigger d-flex align-items-center justify-content-between cursor-pointer\"\r\n [class.ss-open]=\"isSingleDropdownOpen\"\r\n (click)=\"toggleSingleDropdown($event)\">\r\n <span *ngIf=\"singleSelectedLabel\" class=\"single-select-value fs-0-9rem\">\r\n {{ singleSelectedLabel }}\r\n </span>\r\n <span *ngIf=\"!singleSelectedLabel\" class=\"single-select-placeholder\">\r\n {{ config.placeholder || selectPlaceholderLabel }}\r\n </span>\r\n <mat-icon class=\"single-select-arrow\">\r\n {{ isSingleDropdownOpen ? expandLessLabel : expandMoreLabel }}\r\n </mat-icon>\r\n </div>\r\n\r\n <div class=\"single-select-panel\" *ngIf=\"isSingleDropdownOpen\"\r\n (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Search input -->\r\n <div class=\"dropdown-search-wrapper\">\r\n <mat-icon class=\"dropdown-search-icon\">search</mat-icon>\r\n <input type=\"text\" class=\"dropdown-search-input\"\r\n [placeholder]=\"searchPlaceholderLabel\"\r\n [(ngModel)]=\"searchText\" [ngModelOptions]=\"{standalone: true}\"\r\n (input)=\"dropdownSearch$.next(searchText)\"\r\n (click)=\"$event.stopPropagation()\">\r\n <mat-icon *ngIf=\"searchText\" class=\"dropdown-search-clear cursor-pointer\"\r\n (click)=\"searchText = ''; dropdownSearch$.next(''); $event.stopPropagation()\">close</mat-icon>\r\n </div>\r\n\r\n <!-- Options list -->\r\n <div class=\"single-select-options-list\">\r\n <div *ngFor=\"let option of filteredOptionList\"\r\n class=\"single-select-option d-flex align-items-center gap-8 cursor-pointer\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n (click)=\"selectSingleOption(option)\">\r\n <span class=\"fs-0-875rem c-111827\">{{ option.label }}</span>\r\n <mat-icon *ngIf=\"formGroup.get(config.name!)?.value === option.code\" class=\"single-select-check\">check</mat-icon>\r\n </div>\r\n <div *ngIf=\"!filteredOptionList?.length && localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noMatchingOptionsLabel }}\r\n </div>\r\n <div *ngIf=\"!localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noOptionsAvailableLabel }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- MULTIPLE SELECT: custom panel with checkboxes -->\r\n <div *ngIf=\"config.subType === 'MULTIPLE'\" class=\"multi-select-wrapper\"\r\n [class.is-invalid]=\"errorMessage\">\r\n\r\n <div class=\"field-input multi-select-trigger d-flex align-items-center justify-content-between cursor-pointer\"\r\n [class.ms-open]=\"isMultiDropdownOpen\"\r\n (click)=\"toggleMultiDropdown($event)\">\r\n <span *ngIf=\"multiSelectedCount > 0\" class=\"multi-select-value fs-0-9rem\">\r\n {{ multiSelectedCount }} selected\r\n </span>\r\n <span *ngIf=\"multiSelectedCount === 0\" class=\"multi-select-placeholder\">\r\n {{ config.placeholder || selectPlaceholderLabel }}\r\n </span>\r\n <mat-icon class=\"multi-select-arrow\">\r\n {{ isMultiDropdownOpen ? expandLessLabel : expandMoreLabel }}\r\n </mat-icon>\r\n </div>\r\n\r\n <div class=\"multi-select-panel\" *ngIf=\"isMultiDropdownOpen\"\r\n (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Search input (shown only when searchConfig.enabled) -->\r\n <div class=\"dropdown-search-wrapper\" *ngIf=\"isSearchableDropdown\">\r\n <mat-icon class=\"dropdown-search-icon\">search</mat-icon>\r\n <input type=\"text\" class=\"dropdown-search-input\"\r\n [placeholder]=\"searchPlaceholderLabel\"\r\n [(ngModel)]=\"searchText\" [ngModelOptions]=\"{standalone: true}\"\r\n (input)=\"dropdownSearch$.next(searchText)\"\r\n (click)=\"$event.stopPropagation()\">\r\n <mat-icon *ngIf=\"searchText\" class=\"dropdown-search-clear cursor-pointer\"\r\n (click)=\"searchText = ''; dropdownSearch$.next(''); $event.stopPropagation()\">close</mat-icon>\r\n </div>\r\n\r\n <!-- Select All checkbox (shown only when showSelectAll is true) -->\r\n <label *ngIf=\"config.optionConfig?.showSelectAll && filteredOptionList?.length\"\r\n class=\"multi-select-option multi-select-all d-flex align-items-center gap-8 cursor-pointer\">\r\n <input type=\"checkbox\"\r\n [checked]=\"isAllSelected()\"\r\n [indeterminate]=\"isSomeSelected()\"\r\n [disabled]=\"!!config.disabled\"\r\n (change)=\"toggleSelectAll($any($event.target).checked)\">\r\n <span class=\"fs-0-875rem c-111827 fw-600\">{{ selectAllLabel }}</span>\r\n </label>\r\n\r\n <!-- Options list -->\r\n <div class=\"multi-select-options-list\">\r\n <label *ngFor=\"let option of filteredOptionList\"\r\n class=\"multi-select-option d-flex align-items-center gap-8 cursor-pointer\">\r\n <input type=\"checkbox\"\r\n [checked]=\"isChecked(option.code)\"\r\n [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <span class=\"fs-0-875rem c-111827\">{{ option.label }}</span>\r\n </label>\r\n <div *ngIf=\"!filteredOptionList?.length && localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noMatchingOptionsLabel }}\r\n </div>\r\n <div *ngIf=\"!localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noOptionsAvailableLabel }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Radio \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRadio\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"radio-group\" [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of localOptionList\" class=\"radio-label\"\r\n [class.card-item]=\"config.subType === 'CARD'\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"radio\" [formControlName]=\"config.name!\" [value]=\"option.code\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Checkbox \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isCheckbox\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label && config.subType === 'LIST'\"\r\n class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div *ngIf=\"config.subType === 'BOOL'\" class=\"checkbox-single\">\r\n <label class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span>{{ config.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div *ngIf=\"config.subType === 'LIST' || config.subType === 'CARD'\" class=\"checkbox-group d-flex flex-column gap-8\"\r\n [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\"\r\n [class.card-item]=\"config.subType === 'CARD'\" [class.selected]=\"isChecked(option.code)\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Chip \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isChip\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"chip-group d-flex flex-wrap gap-8\" [class.is-invalid]=\"errorMessage\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"chip-label cursor-pointer p-6px-14px b-ffffff c-374151 b-1px-solid-D1D5DB br-20px fs-0-875rem\"\r\n [class.selected]=\"isChecked(option.code)\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\" hidden>\r\n <span>{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Switch \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isSwitch\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label class=\"switch-container d-flex justify-content-between align-items-center cursor-pointer\">\r\n <span class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label }}</span>\r\n <div class=\"switch position-relative\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span class=\"slider position-absolute cursor-pointer\"></span>\r\n </div>\r\n </label>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rich Text \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRichText\" class=\"field-wrapper component-rich-text d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rich-text-container\" [class.is-invalid]=\"errorMessage\">\r\n <quill-editor [formControlName]=\"config.name!\" class=\"rich-text-editor d-block w-100\"\r\n [placeholder]=\"config.richTextConfig?.placeholder || config.placeholder || ''\"\r\n [styles]=\"{height: config.richTextConfig?.height || '200px'}\">\r\n </quill-editor>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rating \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRating\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rating-group d-flex gap-4\" [class.is-invalid]=\"errorMessage\">\r\n <span *ngFor=\"let star of getStarArray()\" class=\"star d-inline-flex align-items-center cursor-pointer\"\r\n [class.filled]=\"isStarFilled(star)\" [class.half]=\"isStarHalf(star)\" (click)=\"onRatingChange(star, $event)\">\r\n <mat-icon>{{ isStarFilled(star) || isStarHalf(star) ? 'star' : 'star_border' }}</mat-icon>\r\n </span>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Generated Field (read-only) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGenerated\" class=\"field-wrapper d-flex flex-column gap-6\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label\r\n }}</label>\r\n <div class=\"generated-value fs-0-875rem p-0-625rem-0-875rem b-F3F4F6 b-1px-solid-E5E7EB br-8px c-6B7280\">{{ value ||\r\n '-' }}</div>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint\">{{ config.hint }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 File Upload \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isFileUpload\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Drop Zone -->\r\n <div\r\n class=\"upload-drop-zone d-flex flex-column align-items-center justify-content-center gap-8 cursor-pointer text-center p-32px-24px us-none\"\r\n [class.drag-over]=\"isDragOver\" [class.has-files]=\"value?.length\" [class.is-invalid]=\"errorMessage\"\r\n (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave($event)\" (drop)=\"onFileDrop($event)\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <!-- Icon with accent-colour pill background -->\r\n <div class=\"upload-icon-wrap mb-4\">\r\n <div class=\"dropzone-icon-pill d-flex align-items-center justify-content-center\">\r\n <mat-icon class=\"upload-cloud-icon\">cloud_upload</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <p class=\"upload-main-text font-weight-600 m-0 fs-0-9rem\">Drag & drop files here</p>\r\n <p class=\"upload-sub-text m-0 fs-0-8rem c-64748B\">or <span class=\"upload-link\">Browse files</span></p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"config.attachmentConfig?.acceptLabel\">\r\n Supported: <span class=\"upload-formats font-weight-500\">{{ config.attachmentConfig!.acceptLabel }}</span>\r\n </p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"!config.attachmentConfig?.acceptLabel && config.hint\">\r\n {{ config.hint }}\r\n </p>\r\n <span class=\"upload-size-badge fs-0-72rem\" *ngIf=\"config.attachmentConfig?.maxSizeMB\">\r\n Max {{ config.attachmentConfig!.maxSizeMB }}MB\r\n </span>\r\n\r\n <!-- Hidden native file input -->\r\n <input #fileInput type=\"file\" hidden [attr.multiple]=\"config.attachmentConfig?.multiple ? true : null\"\r\n [attr.accept]=\"config.attachmentConfig?.accept || null\" (change)=\"onFileSelected($event)\">\r\n </div>\r\n\r\n <!-- Uploaded file list -->\r\n <div class=\"uploaded-list d-flex flex-column gap-8 mt-10\" *ngIf=\"value?.length\">\r\n <div *ngFor=\"let f of value; let i = index\"\r\n class=\"uploaded-item d-flex align-items-center gap-10 p-10px-14px br-8px\"\r\n [class.uploading]=\"f.isUploading\">\r\n\r\n <!-- Uploading spinner -->\r\n <ng-container *ngIf=\"f.isUploading; else fileReady\">\r\n <div class=\"upload-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size uploading-label fs-0-72rem\">Uploading...</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Normal state once upload is done -->\r\n <ng-template #fileReady>\r\n <mat-icon class=\"file-type-icon\">{{ getFileIcon(f.type) }}</mat-icon>\r\n <img *ngIf=\"f.type?.startsWith('image') && f.dataUrl\" [src]=\"f.dataUrl\" class=\"file-thumb rounded-4\"\r\n alt=\"preview\">\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size fs-0-72rem\">{{ formatFileSize(f.size) }}</span>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Compact icon-only remove button -->\r\n <button type=\"button\" class=\"file-remove-btn d-flex align-items-center justify-content-center rounded-50\"\r\n [disabled]=\"f.isUploading\" (click)=\"!f.isUploading && removeUploadedFile(i)\"\r\n aria-label=\"Remove file\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation / file errors -->\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"fileUploadError\">{{ fileUploadError }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage && !fileUploadError\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\"\r\n *ngIf=\"config.hint && !errorMessage && !fileUploadError && !config.attachmentConfig?.acceptLabel\">\r\n {{ config.hint }}\r\n </span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Media Upload (Type 2) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isMediaUpload\" class=\"field-wrapper media-upload-wrapper d-flex flex-column gap-6 p-0 border-none b-none\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Hidden file input lives outside *ngIf \u2014 triggered via ViewChild -->\r\n <input #mediaDeviceInput type=\"file\" hidden multiple accept=\"image/*\" (change)=\"onMediaFileSelected($event)\">\r\n\r\n <!-- Two-column layout -->\r\n <div class=\"mu-layout d-grid align-items-start\">\r\n\r\n <!-- \u2500\u2500 LEFT PANEL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-left d-flex flex-column gap-20\">\r\n\r\n <!-- Header: title + max-items badge -->\r\n <div class=\"mu-header d-flex align-items-start flex-wrap gap-10\">\r\n <h3 class=\"mu-title m-0 c-111827 fs-1-35rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </h3>\r\n <span\r\n class=\"mu-badge d-inline-flex align-items-center rounded-20 color-white font-weight-600 fs-0-72rem p-4px-12px b-111827\"\r\n *ngIf=\"config.attachmentConfig?.maxFiles\">\r\n {{ controller.labels['LBL_MEDIA_MAX_PREFIX'] || 'Maximum' }}\r\n {{ config.attachmentConfig?.maxFiles }}\r\n {{ controller.labels['LBL_MEDIA_MAX_SUFFIX'] || 'Image & Videos' }}\r\n </span>\r\n </div>\r\n\r\n <!-- Description -->\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\" *ngIf=\"config.attachmentConfig?.description\">\r\n {{ config.attachmentConfig?.description }}\r\n </p>\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\"\r\n *ngIf=\"!config.attachmentConfig?.description && controller.labels['LBL_MEDIA_DESC']\">\r\n {{ controller.labels['LBL_MEDIA_DESC'] }}\r\n </p>\r\n\r\n <!-- Feature bullet list -->\r\n <ul class=\"mu-features m-0 p-0 d-flex flex-column gap-8 ls-none\"\r\n *ngIf=\"config.attachmentConfig?.features?.length || controller.labels['LBL_MEDIA_FEATURE_1']\">\r\n <ng-container *ngIf=\"config.attachmentConfig?.features?.length\">\r\n <li *ngFor=\"let f of config.attachmentConfig?.features\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ f }}\r\n </li>\r\n </ng-container>\r\n <ng-container *ngIf=\"!config.attachmentConfig?.features?.length\">\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_1']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_1'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_2']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_2'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_3']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_3'] }}\r\n </li>\r\n </ng-container>\r\n </ul>\r\n\r\n <!-- Backdrop to close dropdown on outside click -->\r\n <div class=\"media-menu-backdrop\" *ngIf=\"showMediaMenu\"\r\n (click)=\"$event.stopPropagation(); showMediaMenu = false\"></div>\r\n\r\n <!-- Add Media button + dropdown -->\r\n <div class=\"media-add-container position-relative\" (click)=\"showMediaMenu = !showMediaMenu\">\r\n <lib-button id=\"btn-add-media-{{ config.name }}\" [variant]=\"'warning'\"\r\n [icon]=\"{type: 'material', value: 'add_photo_alternate'}\">\r\n {{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}\r\n <mat-icon class=\"menu-chevron fs-18px\">add</mat-icon>\r\n </lib-button>\r\n\r\n <div class=\"media-dropdown position-absolute rounded-12 overflow-hidden b-ffffff b-1px-solid-E5E7EB\"\r\n *ngIf=\"showMediaMenu\" role=\"menu\" (click)=\"$event.stopPropagation()\">\r\n <!-- Video -->\r\n <button id=\"btn-media-video-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuVideo(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--video d-flex align-items-center justify-content-center rounded-8\"><mat-icon>videocam</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_VIDEO'] || 'Video' }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_VIDEO_DESC'] || 'Add\r\n YouTube URL'\r\n }}</span>\r\n </span>\r\n </button>\r\n <!-- Device -->\r\n <button id=\"btn-media-device-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuDevice(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--device d-flex align-items-center justify-content-center rounded-8\"><mat-icon>upload</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_DEVICE'] || 'Upload from device'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_DEVICE_DESC'] ||\r\n 'Select images from your\r\n computer' }}</span>\r\n </span>\r\n </button>\r\n <!-- Library -->\r\n <button id=\"btn-media-library-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuLibrary(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--library d-flex align-items-center justify-content-center rounded-8\"><mat-icon>photo_library</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_LIBRARY'] || 'Upload from library'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_LIBRARY_DESC'] ||\r\n 'Choose from default\r\n images' }}</span>\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- YouTube URL Input (inline below button) -->\r\n <div class=\"youtube-input-panel d-flex flex-column gap-8 p-16 rounded-10 b-FFFAF1 b-1px-solid-E5E7EB\"\r\n *ngIf=\"showYoutubeInput\">\r\n <label class=\"youtube-panel-label d-flex align-items-center gap-6 font-weight-600 fs-0-875rem c-111827\">\r\n {{ controller.labels['LBL_YOUTUBE_URL'] || 'Video URL' }}\r\n </label>\r\n <div class=\"youtube-input-row d-flex gap-8\">\r\n <input id=\"input-youtube-url-{{ config.name }}\" type=\"url\" class=\"field-input youtube-url-input\"\r\n [(ngModel)]=\"youtubeUrlInput\" [ngModelOptions]=\"{standalone: true}\"\r\n [placeholder]=\"controller.labels['PH_YOUTUBE_URL'] || 'Video URL'\" (keyup.enter)=\"addYoutubeMedia()\">\r\n <lib-button id=\"btn-add-youtube-{{ config.name }}\" [variant]=\"'secondary'\" (click)=\"addYoutubeMedia()\">\r\n {{ controller.labels['LBL_ADD'] || 'Add' }}\r\n </lib-button>\r\n </div>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"youtubeUrlError\">{{ youtubeUrlError }}</span>\r\n </div>\r\n\r\n <div\r\n class=\"media-upload-status d-flex align-items-center gap-8 mt-4 color-error rounded-8 font-weight-500 p-10px-14px b-FEF2F2 fs-0-85rem\"\r\n *ngIf=\"mediaUploadError\">\r\n <mat-icon class=\"status-icon fs-18px\">error_outline</mat-icon>\r\n <span>{{ mediaUploadError }}</span>\r\n </div>\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n </div>\r\n <!-- end left panel -->\r\n\r\n <!-- \u2500\u2500 RIGHT PANEL (carousel) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-right d-flex flex-column gap-12\">\r\n\r\n <!-- Carousel (when items exist) -->\r\n <div class=\"media-carousel-section d-flex flex-column gap-12\" *ngIf=\"mediaItems.length\">\r\n <div\r\n class=\"media-carousel-main position-relative w-100 overflow-hidden d-flex align-items-center justify-content-center br-12px b-0F172A\">\r\n <button id=\"btn-carousel-prev-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--prev position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselPrev()\" [disabled]=\"mediaCarouselIndex === 0\" aria-label=\"Previous\">\r\n <mat-icon>chevron_left</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-viewer position-absolute d-flex align-items-center justify-content-center\"\r\n *ngFor=\"let item of mediaItems; let i = index\" [hidden]=\"i !== mediaCarouselIndex\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"carousel-uploading d-flex flex-column align-items-center gap-12 c-94A3B8 fs-0-85rem\">\r\n <div class=\"carousel-spinner rounded-50 b-3px-solid-rgba-255-255-255-0-15\"></div>\r\n <span>{{ controller.labels['LBL_UPLOADING'] || 'Uploading\u2026' }}</span>\r\n </div>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'youtube'\">\r\n <iframe class=\"carousel-iframe w-100 h-100 br-12px\" [src]=\"item.url | trustedUrl\" frameborder=\"0\"\r\n allowfullscreen\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\">\r\n </iframe>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'image'\">\r\n <img class=\"carousel-image w-100 h-100 br-12px\" [src]=\"item.url\" alt=\"Media\">\r\n </ng-container>\r\n <button id=\"btn-remove-media-{{ config.name }}-{{ i }}\" type=\"button\"\r\n class=\"carousel-remove-btn position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-0-0-0-0-55\"\r\n [disabled]=\"item.isUploading\" (click)=\"removeMediaItem(i)\" aria-label=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <button id=\"btn-carousel-next-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--next position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselNext()\" [disabled]=\"mediaCarouselIndex === mediaItems.length - 1\" aria-label=\"Next\">\r\n <mat-icon>chevron_right</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-dots position-absolute d-flex gap-6\">\r\n <span *ngFor=\"let item of mediaItems; let i = index\"\r\n class=\"carousel-dot rounded-50 cursor-pointer b-rgba-255-255-255-0-45\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\"></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Thumbnail strip -->\r\n <div class=\"media-thumbnail-strip d-flex flex-wrap gap-8 pb-4px\">\r\n <div *ngFor=\"let item of mediaThumbnails; let i = index\"\r\n class=\"media-thumb rounded-8 overflow-hidden cursor-pointer d-flex align-items-center justify-content-center b-2px-solid-transparent b-E2E8F0\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"thumb-uploading d-flex align-items-center justify-content-center w-100 h-100\">\r\n <div class=\"thumb-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && item.thumbnailUrl\"\r\n [src]=\"item.thumbnailUrl\" class=\"thumb-img w-100 h-100\" alt=\"Video thumbnail\">\r\n <div *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && !item.thumbnailUrl\"\r\n class=\"thumb-yt-placeholder d-flex align-items-center justify-content-center w-100 h-100 b-1E293B c-EF4444\">\r\n <mat-icon>play_circle</mat-icon>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'image' && item.url\" [src]=\"item.url\"\r\n class=\"thumb-img w-100 h-100\" alt=\"Image thumbnail\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty right-side placeholder -->\r\n <div\r\n class=\"mu-right-empty d-flex flex-column align-items-center justify-content-center gap-10 h-100 text-center p-24 br-12px b-FFFAF1 c-94A3B8 b-2px-dashed-CBD5E1\"\r\n *ngIf=\"!mediaItems.length\" (click)=\"onMediaMenuDevice()\">\r\n <mat-icon class=\"mu-right-empty-icon fs-52px\">perm_media</mat-icon>\r\n <p>{{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}</p>\r\n </div>\r\n\r\n </div>\r\n <!-- end right panel -->\r\n\r\n </div><!-- end mu-layout -->\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Library Image Picker Modal \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <!-- Wrapper is always in DOM (hidden) so @ViewChild can move it to body -->\r\n <div #libraryModal class=\"media-library-portal-host\" [class.is-open]=\"showLibraryModal\">\r\n\r\n <!-- Backdrop -->\r\n <div class=\"media-library-overlay\" (click)=\"closeLibraryModal()\"></div>\r\n\r\n <!-- Modal card -->\r\n <div class=\"media-library-modal d-flex flex-column overflow-hidden b-ffffff br-16px\"\r\n role=\"dialog\" aria-modal=\"true\">\r\n <div class=\"library-modal-header d-flex align-items-start justify-content-between p-24px-28px bb-1px-solid-E5E7EB\">\r\n <div class=\"header-left d-flex flex-column gap-8\">\r\n <h3 class=\"library-modal-title m-0 color-dark fs-1-25rem\">\r\n {{ controller.labels['LBL_ADD_IMAGES'] || 'Add Images' }}\r\n </h3>\r\n <p class=\"library-modal-subtitle m-0 color-gray fs-0-85rem\">\r\n {{ controller.labels['LBL_LIBRARY_MODAL_DESC'] || 'Select images from your library.' }}\r\n </p>\r\n </div>\r\n <button id=\"btn-close-library-{{ config.name }}\" type=\"button\"\r\n class=\"library-close-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 border-none b-none c-9CA3AF\"\r\n (click)=\"closeLibraryModal()\" aria-label=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Loading -->\r\n <div class=\"library-loading\" *ngIf=\"libraryLoading\">\r\n <div class=\"lib-spinner rounded-50 b-3px-solid-E2E8F0\"></div>\r\n <span>{{ controller.labels['LBL_LOADING'] || 'Loading\u2026' }}</span>\r\n </div>\r\n\r\n <!-- Error -->\r\n <div class=\"library-error d-flex align-items-center gap-8 color-error b-FEF2F2 fs-0-875rem p-16px-24px\"\r\n *ngIf=\"libraryError && !libraryLoading\">\r\n <mat-icon>error_outline</mat-icon>\r\n {{ libraryError }}\r\n </div>\r\n\r\n <!-- Image grid -->\r\n <div class=\"library-grid d-grid gap-16 flex-1 p-28px b-F9FAFB\" *ngIf=\"!libraryLoading && libraryImages.length\">\r\n <div *ngFor=\"let img of libraryImages; let li = index\" id=\"lib-img-{{ config.name }}-{{ li }}\"\r\n class=\"library-grid-item position-relative rounded-12 overflow-hidden cursor-pointer bg-white b-3px-solid-transparent\"\r\n [class.selected]=\"isLibraryItemSelected(img)\" (click)=\"toggleLibraryItem(img)\">\r\n <img [src]=\"getLibraryItemUrl(img)\" class=\"library-grid-img w-100 h-100 d-block\" alt=\"Library image\">\r\n <div\r\n class=\"library-check position-absolute bg-white rounded-50 d-flex align-items-center justify-content-center c-3B82F6\"\r\n *ngIf=\"isLibraryItemSelected(img)\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n <div class=\"library-overlay-hover position-absolute b-rgba-59-130-246-0-12\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty library -->\r\n <div\r\n class=\"library-empty d-flex flex-column align-items-center justify-content-center gap-12 flex-1 c-9CA3AF fs-0-875rem p-48px-24px\"\r\n *ngIf=\"!libraryLoading && !libraryError && libraryImages.length === 0\">\r\n <mat-icon>image_not_supported</mat-icon>\r\n <span>{{ controller.labels['LBL_LIBRARY_EMPTY'] || 'No images found in library.' }}</span>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"library-modal-footer d-flex align-items-center justify-content-end bg-white p-20px-28px bt-1px-solid-E5E7EB\">\r\n <div class=\"library-footer-actions d-flex gap-12\">\r\n <lib-button id=\"btn-library-cancel-{{ config.name }}\" [variant]=\"'outline'\" (click)=\"closeLibraryModal()\">\r\n {{ controller.labels['LBL_CANCEL'] || 'Cancel' }}\r\n </lib-button>\r\n <lib-button id=\"btn-library-confirm-{{ config.name }}\" [variant]=\"'primary'\"\r\n [disabled]=\"librarySelectedIds.size === 0\" (click)=\"confirmLibrarySelection()\">\r\n {{ controller.labels['LBL_CONTINUE'] || 'Continue' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <!-- \u2550\u2550 Location Field \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isLocation\" class=\"field-wrapper location-field-wrapper d-flex flex-column gap-6 gap-12\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Field label -->\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n <p class=\"location-subtitle m-0 c-6B7280 fs-0-8125rem\" *ngIf=\"config.hint\">{{ config.hint }}</p>\r\n\r\n <!-- Three-tab bar -->\r\n <div class=\"location-tabs d-flex gap-12 mb-24\">\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'VENUE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('VENUE')\">\r\n {{ controller.labels['LBL_LOC_VENUE'] || 'Venue' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'ONLINE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('ONLINE')\">\r\n {{ controller.labels['LBL_LOC_ONLINE'] || 'Online Event' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'TBA' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('TBA')\">\r\n {{ controller.labels['LBL_LOC_TBA'] || 'To be Announced' }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- VENUE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'VENUE'\" class=\"loc-panel loc-venue-panel d-flex flex-column gap-12\">\r\n\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ADDRESS'] || 'Location address' }}\r\n </p>\r\n\r\n <!-- Added venue rows -->\r\n <div class=\"loc-venue-list d-flex flex-column gap-8\" *ngIf=\"locationVenues.length > 0\">\r\n <div *ngFor=\"let venue of locationVenues; let i = index\"\r\n class=\"loc-venue-item d-flex align-items-center gap-10 p-10px-14px br-7px b-ffffff b-1px-solid-D1D5DB\">\r\n <mat-icon class=\"loc-venue-search-icon fs-18px c-9CA3AF\">search</mat-icon>\r\n <span class=\"loc-venue-text flex-1 overflow-hidden fs-0-875rem c-111827\">{{ venue.address || venue.name ||\r\n venue.description }}</span>\r\n <button type=\"button\"\r\n class=\"loc-action-btn loc-delete-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none p-4px\"\r\n (click)=\"removeLocationVenue(i)\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Location count badge -->\r\n <p class=\"loc-count-text m-0 font-weight-600 fs-0-8125rem c-3B82F6\"\r\n *ngIf=\"locationVenues.length > 0 && config.locationConfig?.allowMulti\">\r\n {{ locationVenues.length }} {{ controller.labels['LBL_LOC_COUNT_SUFFIX'] || 'Locations Added!' }}\r\n </p>\r\n\r\n <!-- Search input (hide when max reached) -->\r\n <div class=\"loc-search-container position-relative\" *ngIf=\"!locationMaxReached\">\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n [placeholder]=\"config.locationConfig?.venuePlaceholder || (controller.labels['PH_LOC_VENUE'] || 'Type to search venue...')\"\r\n [value]=\"locationSearchText\" (input)=\"handleLocationSearchInput($event)\" (blur)=\"hideLocationSuggestions()\"\r\n autocomplete=\"off\" [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n <!-- Suggestions dropdown -->\r\n <div class=\"loc-suggestions-panel position-absolute overflow-hidden br-8px b-ffffff b-1px-solid-D1D5DB\"\r\n *ngIf=\"locationShowSuggestions && locationSuggestions.length\">\r\n <div *ngFor=\"let sug of locationSuggestions\"\r\n class=\"loc-suggestion-item d-flex align-items-center gap-10 cursor-pointer p-10px-14px\"\r\n (mousedown)=\"onLocationSuggestionSelect(sug)\">\r\n <mat-icon class=\"loc-suggestion-icon fs-18px c-E53E3E\">place</mat-icon>\r\n <span class=\"loc-suggestion-text overflow-hidden fs-0-875rem c-374151\">{{ sug.description }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Add another button -->\r\n <button type=\"button\"\r\n class=\"loc-add-btn d-inline-flex align-items-center gap-6 cursor-pointer font-weight-600 p-0 b-none border-none fs-0-875rem c-1A56DB\"\r\n *ngIf=\"locationVenues.length > 0 && !locationMaxReached && config.locationConfig?.allowMulti\">\r\n <mat-icon>add_circle_outline</mat-icon>\r\n <span>{{ controller.labels['LBL_LOC_ADD_ANOTHER'] || 'Add another Location' }}</span>\r\n </button>\r\n\r\n <!-- Map -->\r\n <div class=\"loc-map-container overflow-hidden br-10px b-1px-solid-E5E7EB\"\r\n *ngIf=\"config.locationConfig?.showMap !== false\">\r\n <ng-container *ngIf=\"config.locationConfig?.googleMapsApiKey; else simpleEmbed\">\r\n <div [id]=\"'loc-map-' + config.name\" class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\"></div>\r\n </ng-container>\r\n <ng-template #simpleEmbed>\r\n <iframe class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\" [src]=\"getLocationMapEmbedUrl() | trustedUrl\"\r\n frameborder=\"0\" allowfullscreen loading=\"lazy\">\r\n </iframe>\r\n </ng-template>\r\n </div>\r\n\r\n <!-- Map hint -->\r\n <p class=\"loc-map-hint m-0 text-center fs-0-78rem c-6B7280\">\r\n {{ controller.labels['LBL_LOC_MAP_HINT'] || 'Type the venue address. A map will appear to assist you.' }}\r\n </p>\r\n </div>\r\n\r\n <!-- ONLINE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'ONLINE'\" class=\"loc-panel loc-online-panel d-flex flex-column gap-12\">\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ONLINE_URL'] || 'Event URL' }}\r\n </p>\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">link</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n type=\"url\"\r\n [placeholder]=\"config.locationConfig?.onlinePlaceholder || (controller.labels['PH_LOC_ONLINE'] || 'https://zoom.us/j/...')\"\r\n [value]=\"locationOnlineUrl\" (input)=\"onLocationUrlChange($any($event.target).value)\"\r\n [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n </div>\r\n\r\n <!-- TBA TAB -->\r\n <div *ngIf=\"locationActiveTab === 'TBA'\"\r\n class=\"loc-panel loc-tba-panel d-flex flex-column gap-12 justify-content-center\">\r\n <div\r\n class=\"loc-tba-content d-flex flex-column align-items-center justify-content-center text-center gap-12 p-32px-24px b-F9FAFB b-1px-dashed-D1D5DB br-10px\">\r\n <mat-icon class=\"loc-tba-icon fs-40px c-9CA3AF\">schedule</mat-icon>\r\n <p class=\"loc-tba-text m-0 c-6B7280 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_TBA_DESC'] || \"This event's location is yet to be announced. Check back later\r\n for updates.\" }}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden real form control -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n</div>", styles: [".d-flex{display:flex}.d-inline-flex{display:inline-flex}.d-grid{display:grid}.d-block{display:block}.d-none{display:none}.flex-column{flex-direction:column}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.align-items-center{align-items:center}.align-items-start{align-items:flex-start}.align-items-end{align-items:flex-end}.justify-content-center{justify-content:center}.justify-content-between{justify-content:space-between}.justify-content-start{justify-content:flex-start}.justify-content-end{justify-content:flex-end}.grid-cols-12{grid-template-columns:repeat(12,1fr)}.w-100{width:100%}.h-100{height:100%}.position-relative{position:relative}.position-absolute{position:absolute}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-poppins{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)}.font-weight-400{font-weight:400}.font-weight-500{font-weight:500}.font-weight-600{font-weight:600}.text-13{font-size:13px}.text-14{font-size:14px}.text-16{font-size:16px}.color-white{color:#fff}.color-dark{color:#111827}.color-gray{color:#6b7280}.color-error{color:var(--cc-sf-error-text-color, #DC2626)}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.m-0{margin:0}.mt-4{margin-top:4px}.mt-8{margin-top:8px}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}.mb-0{margin-bottom:0}.mb-4{margin-bottom:4px}.mb-8{margin-bottom:8px}.mb-10{margin-bottom:10px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}.mb-24{margin-bottom:24px}.ml-16{margin-left:16px}.ml-20{margin-left:20px}.p-0{padding:0}.p-16{padding:16px}.p-20{padding:20px}.p-24{padding:24px}.pt-20{padding-top:20px}.pb-10{padding-bottom:10px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.gap-20{gap:20px}.rounded-4{border-radius:4px}.rounded-6{border-radius:6px}.rounded-8{border-radius:8px}.rounded-10{border-radius:10px}.rounded-12{border-radius:12px}.rounded-20{border-radius:20px}.rounded-24{border-radius:24px}.rounded-50{border-radius:50%}.cursor-pointer{cursor:pointer}.overflow-hidden{overflow:hidden}.resize-vertical{resize:vertical}.box-sizing-border{box-sizing:border-box}.border-none{border:none!important}.mb-16px{margin-bottom:var(--cc-sf-grid-gap, 16px)!important}.c-DC2626{color:var(--cc-sf-label-required-color, #DC2626)!important}.ml-0-125rem{margin-left:.125rem!important}.fs-0-875rem{font-size:.875rem!important}.c-111827{color:var(--cc-sf-label-color, #111827)!important}.br-7px{border-radius:var(--cc-sf-input-radius, 7px)!important}.c-6B7280{color:var(--cc-sf-hint-color, #6B7280)!important}.fs-0-75rem{font-size:var(--cc-sf-error-text-size, .75rem)!important}.b-none{background:none!important}.p-32px-24px{padding:32px 24px!important}.us-none{-webkit-user-select:none!important;user-select:none!important}.c-1E293B{color:var(--cc-sf-label-color, #1E293B)!important}.c-3B82F6{color:var(--cc-sf-chip-selected-bg, #3B82F6)!important}.fs-0-78rem{font-size:.78rem!important}.p-10px-14px{padding:10px 14px!important}.fs-0-85rem{font-size:.85rem!important}.fs-0-72rem{font-size:.72rem!important}.c-94A3B8{color:#94a3b8!important}.p-4px{padding:4px!important}.br-8px{border-radius:var(--cc-sf-input-radius, 8px)!important}.bc-F3F4F6{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.br-none{border-right:none!important}.bl-none{border-left:none!important}.pe-none{pointer-events:none!important}.fs-1-1rem{font-size:1.1rem!important}.c-9CA3AF{color:var(--cc-sf-hint-color, #9CA3AF)!important}.pl-2-4rem{padding-left:2.4rem!important}.fs-0-8125rem{font-size:.8125rem!important}.ls-none{list-style:none!important}.br-12px{border-radius:var(--mu-carousel-radius, 12px)!important}.b-FFFAF1{background:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.fs-18px{font-size:18px!important}.b-FEF2F2{background:var(--cc-sf-error-bg, #FEF2F2)!important}.bc-DC2626{border-color:var(--cc-sf-error-border, #DC2626)!important}.c-202124{color:var(--cc-sf-label-color, #202124)!important}.fs-18px{font-size:var(--cc-sf-label-size, 18px)!important}.mb-0-5rem{margin-bottom:.5rem!important}.pt-0-625rem{padding-top:var(--cc-sf-input-padding-y, .625rem)!important}.pb-0-625rem{padding-bottom:var(--cc-sf-input-padding-y, .625rem)!important}.pl-16px{padding-left:var(--cc-sf-input-padding-x, 16px)!important}.pr-16px{padding-right:var(--cc-sf-input-padding-x, 16px)!important}.bc-ffffff{background-color:var(--cc-sf-section-bg, #ffffff)!important}.b-1px-solid-D1D5DB{border:1px solid var(--cc-sf-input-border, #D1D5DB)!important}.fs-0-75rem{font-size:.75rem!important}.c-1F2937{color:var(--cc-sf-section-label-color, #1F2937)!important}.p-6px-14px{padding:var(--cc-sf-chip-padding, 6px 14px)!important}.b-ffffff{background:var(--loc-suggestion-bg, #ffffff)!important}.c-374151{color:var(--cc-sf-label-color, #374151)!important}.br-20px{border-radius:var(--cc-sf-chip-radius, 20px)!important}.fs-0-875rem{font-size:var(--cc-sf-btn-font-size, .875rem)!important}.bc-D1D5DB{background-color:var(--cc-sf-switch-track-off, #D1D5DB)!important}.pr-2-75rem{padding-right:2.75rem!important}.p-0-25rem{padding:.25rem!important}.p-0-625rem-0-875rem{padding:var(--cc-sf-generated-padding, .625rem .875rem)!important}.b-F3F4F6{background:var(--cc-sf-generated-bg, #F3F4F6)!important}.b-1px-solid-E5E7EB{border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.br-8px{border-radius:var(--cc-sf-uploaded-item-radius, 8px)!important}.c-6B7280{color:var(--ms-desc-color, #6B7280)!important}.mb-20px{margin-bottom:var(--cc-sf-section-gap, 20px)!important}.br-10px{border-radius:var(--cc-sf-input-radius, 10px)!important}.p-20px{padding:var(--cc-sf-section-padding, 20px)!important}.fs-1rem{font-size:1rem!important}.m-0-0-16px-0{margin:0 0 16px!important}.bb-2px-solid-E5E7EB{border-bottom:var(--cc-sf-section-label-border, 2px solid #E5E7EB)!important}.p-16px{padding:var(--cc-sf-instance-padding, 16px)!important}.b-F9FAFB{background:var(--loc-tba-bg, #F9FAFB)!important}.bb-1px-dashed-D1D5DB{border-bottom:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)!important}.c-4B5563{color:var(--cc-sf-instance-num-color, #4B5563)!important}.fs-0-8125rem{font-size:var(--cc-sf-hint-size, .8125rem)!important}.pb-0{padding-bottom:0!important}.p-18px-24px{padding:18px 24px!important}.c-111827{color:var(--ms-title-color, #111827)!important}.bt-1px-solid-E5E7EB{border-top:1px solid #E5E7EB!important}.p-4px-10px{padding:4px 10px!important}.b-FFF5F5{background:var(--cc-sf-btn-remove-bg, #FFF5F5)!important}.c-E53E3E{color:var(--loc-delete-color, #E53E3E)!important}.b-1px-solid-FED7D7{border:var(--cc-sf-btn-remove-border, 1px solid #FED7D7)!important}.br-4px{border-radius:var(--cc-sf-btn-remove-radius, 4px)!important}.p-8px-16px{padding:8px 16px!important}.b-transparent{background:var(--cc-sf-btn-add-bg, transparent)!important}.c-3B82F6{color:var(--cc-sf-input-focus-border, #3B82F6)!important}.b-1px-dashed-CBD5E1{border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1)!important}.br-6px{border-radius:var(--cc-sf-btn-add-radius, 6px)!important}.b-1-5px-dashed-CBD5E1{border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1)!important}.br-12px{border-radius:var(--cc-sf-dropzone-radius, 12px)!important}.bc-FFFAF1{background-color:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.c-94A3B8{color:var(--cc-sf-uploaded-remove-color, #94A3B8)!important}.fs-0-9rem{font-size:var(--cc-sf-input-font-size, .9rem)!important}.c-64748B{color:var(--cc-sf-dropzone-hint-color, #64748B)!important}.b-1px-solid-E2E8F0{border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0)!important}.b-2px-solid-E2E8F0{border:2px solid #E2E8F0!important}.pr-3-5rem{padding-right:3.5rem!important}.p-0-0-875rem{padding:0 .875rem!important}.bc-FFFFFF{background-color:var(--cc-sf-input-bg, #FFFFFF)!important}.b-1-5px-solid-D1D5DB{border:var(--cc-sf-input-border, 1.5px solid #D1D5DB)!important}.mb-0-75rem{margin-bottom:.75rem!important}.mt-6px{margin-top:6px!important}.pr-2-4rem{padding-right:2.4rem!important}.p-0-2rem{padding:.2rem!important}.fs-1-35rem{font-size:1.35rem!important}.p-4px-12px{padding:4px 12px!important}.b-111827{background:var(--cc-sf-label-color, #111827)!important}.b-2px-dashed-CBD5E1{border:2px dashed var(--cc-sf-dropzone-border, #CBD5E1)!important}.fs-52px{font-size:52px!important}.p-12px-16px{padding:12px 16px!important}.bb-1px-solid-F3F4F6{border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)!important}.b-0F172A{background:var(--mu-carousel-bg, #0F172A)!important}.b-3px-solid-rgba-255-255-255-0-15{border:3px solid rgba(255,255,255,.15)!important}.b-rgba-255-255-255-0-85{background:#ffffffd9!important}.b-rgba-0-0-0-0-55{background:#0000008c!important}.b-rgba-255-255-255-0-45{background:#ffffff73!important}.pb-4px{padding-bottom:4px!important}.b-2px-solid-transparent{border:2px solid transparent!important}.b-E2E8F0{background:var(--mu-thumb-bg, #E2E8F0)!important}.b-1E293B{background:#1e293b!important}.c-EF4444{color:#ef4444!important}.b-rgba-0-0-0-0-5{background:#00000080!important}.br-16px{border-radius:var(--mu-modal-radius, 16px)!important}.p-24px-28px{padding:24px 28px!important}.bb-1px-solid-E5E7EB{border-bottom:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.fs-1-25rem{font-size:1.25rem!important}.p-48px-24px{padding:48px 24px!important}.b-3px-solid-E2E8F0{border:3px solid #E2E8F0!important}.p-16px-24px{padding:16px 24px!important}.p-28px{padding:28px!important}.b-3px-solid-transparent{border:3px solid transparent!important}.b-rgba-59-130-246-0-12{background:#3b82f61f!important}.p-20px-28px{padding:20px 28px!important}.c-1A56DB{color:var(--loc-add-color, #1A56DB)!important}.b-1px-dashed-D1D5DB{border:1px dashed var(--cc-sf-input-disabled-border, #D1D5DB)!important}.fs-40px{font-size:40px!important}.c-9CA3AF{color:var(--loc-tba-icon-color, #9CA3AF)!important}.form-field{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)!important}:host{--cc-sf-input-border: #D1D5DB;--cc-sf-input-bg: #ffffff;--cc-sf-input-radius: 9px;--cc-sf-input-height: 44px;--cc-sf-label-color: #111827;--cc-sf-hint-color: #9CA3AF;--cc-sf-error-border: #EF4444;--cc-sf-error-bg: #FFF5F5;--cc-sf-accent-color: #6366F1;--cc-sf-input-focus-border: #6366F1;--cc-sf-input-hover-border: #A5B4FC;--cc-sf-input-placeholder: #C4C9D4;--cc-sf-input-disabled-bg: #F8F9FB;--cc-sf-input-disabled-border: #E5E7EB;--cc-sf-switch-track-on: #6366F1;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-thumb: #ffffff;--cc-sf-selected-color: #6366F1}.form-row{gap:var(--cc-sf-grid-gap, 16px)}.form-row.horizontal{display:flex;flex-direction:row}.form-row.horizontal>*{flex:1}.form-row:not(.horizontal){flex-direction:column}.form-row.grid-row{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media (max-width: 640px){.form-row.grid-row{grid-template-columns:1fr}.form-row.grid-row .row-field{grid-column:span 12!important}}.field-label{font-size:.75rem;font-weight:600;line-height:1;letter-spacing:.04em;text-transform:uppercase;color:#6b7280}.field-input,input.matInput,.mat-mdc-input-element{display:block;width:100%;height:var(--cc-sf-input-height)!important;padding:0 14px!important;font-family:inherit;font-size:.9rem;color:var(--cc-sf-label-color);background-color:var(--cc-sf-input-bg)!important;border:1.5px solid var(--cc-sf-input-border)!important;border-radius:var(--cc-sf-input-radius)!important;box-sizing:border-box;box-shadow:0 1px 2px #0000000a!important;transition:all .2s cubic-bezier(.4,0,.2,1)}.field-input::placeholder,input.matInput::placeholder,.mat-mdc-input-element::placeholder{font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder)}.field-input{opacity:var(--cc-sf-input-opacity, 1);line-height:var(--cc-sf-input-line-height, 1.5);transition:var(--cc-sf-input-transition, all .2s ease)}.field-input::placeholder{font-weight:var(--cc-sf-placeholder-weight, 400);font-size:var(--cc-sf-placeholder-size, 14px);line-height:var(--cc-sf-placeholder-line-height, 100%);color:var(--cc-sf-input-placeholder)}.field-input:hover:not(:disabled):not([readonly]){border-color:var(--cc-sf-input-hover-border)!important;box-shadow:0 1px 4px #6366f114!important}.field-input:focus{outline:none;border-color:var(--cc-sf-input-focus-border)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important;background-color:#fefeff!important}.field-input:disabled,.field-input[readonly]{background-color:var(--cc-sf-input-disabled-bg)!important;color:#9ca3af!important;cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important;box-shadow:none!important}.field-input.is-invalid{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)!important}.field-input.is-invalid:focus{box-shadow:0 0 0 3px #ef44441f,0 1px 4px #ef44441a!important}.field-input.textarea{resize:vertical;min-height:100px;height:auto;padding:12px 16px!important}input[type=time].time-input{cursor:pointer}input[type=time].time-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.7;filter:invert(30%)}input[type=time].time-input::-webkit-calendar-picker-indicator:hover{opacity:1}select.field-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}select.field-input:disabled{cursor:not-allowed}.dropdown-search-wrapper{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--cc-sf-input-border, #E5E7EB);background:var(--cc-sf-input-bg, #ffffff)}.dropdown-search-wrapper .dropdown-search-icon{font-size:18px;width:18px;height:18px;color:var(--cc-sf-input-placeholder, #9CA3AF);flex-shrink:0}.dropdown-search-wrapper .dropdown-search-input{flex:1;border:none;outline:none;background:transparent;font-size:.875rem;color:var(--cc-sf-label-color, #111827);font-family:inherit}.dropdown-search-wrapper .dropdown-search-input::placeholder{color:var(--cc-sf-input-placeholder, #C4C9D4)}.dropdown-search-wrapper .dropdown-search-clear{font-size:18px;width:18px;height:18px;color:var(--cc-sf-input-placeholder, #9CA3AF);flex-shrink:0;transition:color .15s}.dropdown-search-wrapper .dropdown-search-clear:hover{color:var(--cc-sf-label-color, #111827)}.multi-select-wrapper{position:relative}.multi-select-wrapper .multi-select-trigger{min-height:var(--cc-sf-input-height, 44px);height:auto;-webkit-user-select:none;user-select:none}.multi-select-wrapper .multi-select-trigger.ms-open{border-color:var(--cc-sf-input-focus-border, #6366F1)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important}.multi-select-wrapper .multi-select-trigger .multi-select-value{flex:1;color:var(--cc-sf-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.multi-select-wrapper .multi-select-trigger .multi-select-placeholder{flex:1;font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder, #C4C9D4)}.multi-select-wrapper .multi-select-trigger .multi-select-arrow{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--cc-sf-label-color, #6B7280);flex-shrink:0}.multi-select-wrapper .multi-select-panel{position:absolute;top:calc(100% + 4px);left:0;right:0;background:var(--cc-sf-input-bg, #ffffff);border:1.5px solid var(--cc-sf-input-border, #D1D5DB);border-radius:var(--cc-sf-input-radius, 9px);box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f;z-index:1050;display:flex;flex-direction:column;overflow:hidden;max-height:320px}.multi-select-wrapper .multi-select-options-list{flex:1;overflow-y:auto;max-height:240px}.multi-select-wrapper .multi-select-options-list::-webkit-scrollbar{width:4px}.multi-select-wrapper .multi-select-options-list::-webkit-scrollbar-thumb{background:var(--cc-sf-input-border, #D1D5DB);border-radius:2px}.multi-select-wrapper .multi-select-option{padding:8px 12px;border-bottom:1px solid var(--cc-sf-input-border, #F3F4F6);transition:background .1s}.multi-select-wrapper .multi-select-option:last-of-type{border-bottom:none}.multi-select-wrapper .multi-select-option:hover{background:var(--cc-sf-input-hover-bg, #F9FAFB)}.multi-select-wrapper .multi-select-option input[type=checkbox]{flex-shrink:0;cursor:pointer;accent-color:var(--cc-sf-selected-color, #6366F1);width:15px;height:15px}.multi-select-wrapper .multi-select-option.multi-select-all{border-bottom:1px solid var(--cc-sf-input-border, #E5E7EB);background:var(--cc-sf-input-bg, #FAFBFC)}.multi-select-wrapper .multi-select-empty{padding:12px;text-align:center}.multi-select-wrapper.is-invalid .multi-select-trigger{border-color:var(--cc-sf-error-border, #EF4444)!important;background-color:var(--cc-sf-error-bg, #FFF5F5)!important}.single-select-wrapper{position:relative}.single-select-wrapper .single-select-trigger{min-height:var(--cc-sf-input-height, 44px);height:auto;-webkit-user-select:none;user-select:none}.single-select-wrapper .single-select-trigger.ss-open{border-color:var(--cc-sf-input-focus-border, #6366F1)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important}.single-select-wrapper .single-select-trigger .single-select-value{flex:1;color:var(--cc-sf-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.single-select-wrapper .single-select-trigger .single-select-placeholder{flex:1;font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder, #C4C9D4)}.single-select-wrapper .single-select-trigger .single-select-arrow{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--cc-sf-label-color, #6B7280);flex-shrink:0}.single-select-wrapper .single-select-panel{position:absolute;top:calc(100% + 4px);left:0;right:0;background:var(--cc-sf-input-bg, #ffffff);border:1.5px solid var(--cc-sf-input-border, #D1D5DB);border-radius:var(--cc-sf-input-radius, 9px);box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f;z-index:1050;display:flex;flex-direction:column;overflow:hidden;max-height:320px}.single-select-wrapper .single-select-options-list{flex:1;overflow-y:auto;max-height:240px}.single-select-wrapper .single-select-options-list::-webkit-scrollbar{width:4px}.single-select-wrapper .single-select-options-list::-webkit-scrollbar-thumb{background:var(--cc-sf-input-border, #D1D5DB);border-radius:2px}.single-select-wrapper .single-select-option{padding:8px 12px;border-bottom:1px solid var(--cc-sf-input-border, #F3F4F6);transition:background .1s;justify-content:space-between}.single-select-wrapper .single-select-option:last-of-type{border-bottom:none}.single-select-wrapper .single-select-option:hover{background:var(--cc-sf-input-hover-bg, #F9FAFB)}.single-select-wrapper .single-select-option.selected{background:var(--cc-sf-input-hover-bg, #F0F5FF);color:var(--cc-sf-selected-color, #6366F1)}.single-select-wrapper .single-select-option .single-select-check{font-size:18px;width:18px;height:18px;color:var(--cc-sf-selected-color, #6366F1)}.single-select-wrapper.is-invalid .single-select-trigger{border-color:var(--cc-sf-error-border, #EF4444)!important;background-color:var(--cc-sf-error-bg, #FFF5F5)!important}.char-count-hint{font-style:normal;line-height:100%;letter-spacing:.02em;margin-top:.4rem}.radio-group.layout-column,.checkbox-group.layout-column{display:grid!important;grid-template-columns:repeat(12,1fr);gap:16px;width:100%}.radio-group.layout-row,.checkbox-group.layout-row{flex-direction:column!important;gap:12px;width:100%}.radio-label input,.checkbox-label input{cursor:pointer;accent-color:var(--cc-sf-chip-selected-bg, #F05A28)}.radio-label.card-item,.checkbox-label.card-item{display:flex!important;flex-direction:row-reverse!important;justify-content:space-between!important;align-items:center!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB);border-radius:12px;padding:16px 20px;box-sizing:border-box;transition:all .2s ease;background:var(--cc-sf-input-bg, #ffffff);margin-bottom:0}.radio-label.card-item input,.checkbox-label.card-item input{margin-left:16px}.radio-label.card-item.selected,.checkbox-label.card-item.selected{border-color:var(--cc-sf-selected-color);background-color:#f05a280d}.radio-label.card-item .option-content .label-text,.checkbox-label.card-item .option-content .label-text,.checkbox-single .checkbox-label{font-weight:var(--cc-sf-label-weight, 500)}.chip-label{transition:var(--cc-sf-input-transition, all .2s ease)}.chip-label:hover{background:var(--cc-sf-chip-hover-bg, #F3F4F6)}.chip-label.selected{background:var(--cc-sf-selected-color);color:var(--cc-sf-chip-selected-color, #ffffff);border-color:var(--cc-sf-selected-color)}.switch{width:50px;height:24px;display:inline-block}.switch input{opacity:0;width:0;height:0;position:absolute}.switch input:checked+.slider{background-color:var(--cc-sf-switch-track-on)!important}.switch input:checked+.slider:before{transform:translate(26px)}.switch .slider{inset:0;transition:.4s;background-color:var(--cc-sf-switch-track-off);border-radius:24px}.switch .slider:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:var(--cc-sf-switch-thumb);transition:.4s;border-radius:50%}.rating-group .star{transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star mat-icon{font-size:var(--cc-sf-star-size, 28px);width:var(--cc-sf-star-size, 28px);height:var(--cc-sf-star-size, 28px);line-height:var(--cc-sf-star-size, 28px);color:var(--cc-sf-star-empty, #D1D5DB);transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star.filled mat-icon,.rating-group .star.half mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.rating-group .star:hover mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.password-wrapper .password-toggle{right:.625rem;top:50%;transform:translateY(-50%);line-height:1;transition:color var(--cc-sf-input-transition, .2s ease)}.password-wrapper .password-toggle mat-icon.eye-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem}.password-wrapper .password-toggle:hover{color:var(--cc-sf-label-color, #374151)}.password-wrapper .password-toggle:focus{outline:none}.group-section-wrapper .group-label{font-size:var(--cc-sf-section-label-size, 1rem);font-weight:var(--cc-sf-section-label-weight, 600);color:var(--cc-sf-section-label-color, #1F2937);margin:0 0 16px;padding-left:12px;padding-top:2px;padding-bottom:2px;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);line-height:1.4}.group-section-wrapper .group-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media (max-width: 640px){.group-section-wrapper .group-fields.sf-grid{grid-template-columns:1fr}.group-section-wrapper .group-fields.sf-grid .sf-col{grid-column:span 12!important}}.group-section-wrapper .group-accordion-instance{border:var(--cc-sf-instance-border, 1px solid #E5E7EB);border-radius:var(--cc-sf-section-border-radius-inner, 8px);margin-bottom:8px;overflow:hidden;transition:border-color .2s ease}.group-section-wrapper .group-accordion-instance:last-of-type{margin-bottom:0}.group-section-wrapper .group-accordion-instance .group-accordion-header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px;background:var(--cc-sf-repeater-accordion-header-bg, #F9FAFB);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header:hover{background:var(--cc-sf-repeater-accordion-active-bg, #EFF6FF)}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-badge{width:22px;height:22px;border-radius:50%;background:var(--cc-sf-repeater-badge-bg, #E5E7EB);color:var(--cc-sf-repeater-badge-color, #374151);font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-title{font-size:var(--cc-sf-instance-num-size, .8125rem);font-weight:600;color:var(--cc-sf-repeater-accordion-header-color, #1F2937)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:var(--cc-sf-btn-remove-color, #E53E3E);padding:4px;border-radius:4px;line-height:1;display:flex;align-items:center;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:var(--cc-sf-instance-num-color, #4B5563)}.group-section-wrapper .group-accordion-instance .group-accordion-body{padding:var(--cc-sf-instance-padding, 16px);background:var(--cc-sf-instance-bg, #F9FAFB);border-top:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)}.group-section-wrapper .btn-add-group{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:10px 20px;margin-top:12px;background:var(--cc-sf-btn-add-bg, transparent);color:var(--cc-sf-btn-add-color, #3B82F6);border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1);border-radius:var(--cc-sf-btn-add-radius, 6px);cursor:pointer;font-family:inherit;font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.group-section-wrapper .btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.group-section-wrapper .group-instance:last-child{margin-bottom:0}.group-section-wrapper.multi-save-active{border:none;box-shadow:none;padding:0;background:transparent}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button{color:var(--ms-btn-add-color, #3B82F6);font-weight:600;font-size:.875rem;padding:8px 12px}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button:hover{color:var(--ms-btn-add-hover, #2563EB);background-color:var(--cc-sf-btn-add-hover-bg, #EFF6FF)}.group-section-wrapper.multi-save-active .group-instance.is-card{cursor:pointer;transition:all .2s ease-in-out}.group-section-wrapper.multi-save-active .group-instance.is-card:hover{box-shadow:var(--ms-card-shadow-hover, 0 8px 24px rgba(0, 0, 0, .08));border-color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-title{white-space:nowrap;text-overflow:ellipsis}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-desc{line-height:1.4;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view.is-expanded .card-content .card-desc{-webkit-line-clamp:unset;line-clamp:unset}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon{font-size:22px;width:22px;height:22px;color:var(--cc-sf-hint-color, #9CA3AF);transition:color .2s}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-delete:hover{color:var(--cc-sf-error-border, #DC2626)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-edit:hover{color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-expand{color:var(--cc-sf-input-disabled-border, #E5E7EB)}.btn-remove{transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-remove mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.btn-remove:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.btn-add-group{font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.upload-drop-zone{background-color:var(--cc-sf-dropzone-bg, #F8FAFC);border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1);border-radius:var(--cc-sf-dropzone-radius, 12px);transition:background-color .2s ease,border-color .2s ease}.upload-drop-zone:hover{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-hover-border, #93C5FD)}.upload-drop-zone.drag-over{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-over-border, #3B82F6);box-shadow:var(--cc-sf-dropzone-over-shadow, 0 0 0 4px rgba(59, 130, 246, .12))}.upload-drop-zone.is-invalid{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.upload-icon-wrap .dropzone-icon-pill{width:52px;height:52px;border-radius:50%;background:var(--cc-sf-dropzone-icon-bg, rgba(59, 130, 246, .1))}.upload-icon-wrap mat-icon.upload-cloud-icon{font-size:28px;width:28px;height:28px;line-height:28px;color:var(--cc-sf-accent-color, #3B82F6)}.upload-main-text{color:var(--cc-sf-label-color, #1E293B)}.upload-sub-text{color:var(--cc-sf-hint-color, #64748B)}.upload-link{color:var(--cc-sf-dropzone-link-color, #3B82F6);font-weight:500}.upload-formats{color:var(--cc-sf-dropzone-link-color, #3B82F6)}.upload-size-badge{display:inline-block;padding:2px 8px;border-radius:20px;background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-hint-color, #6B7280);font-weight:500}.uploaded-item{background:var(--cc-sf-uploaded-item-bg, #ffffff);border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0);border-radius:var(--cc-sf-uploaded-item-radius, 8px);transition:box-shadow .15s ease}.uploaded-item:hover{box-shadow:0 2px 6px #0000000f}.uploaded-item mat-icon.file-type-icon{font-size:20px;width:20px;height:20px;line-height:20px;flex-shrink:0;color:var(--cc-sf-hint-color, #64748B)}.uploaded-item .file-thumb{width:36px;height:36px;object-fit:cover;flex-shrink:0}.uploaded-item .file-info{min-width:0;gap:2px}.uploaded-item .file-info .file-name{white-space:nowrap;text-overflow:ellipsis}.uploaded-item .file-remove-btn{flex-shrink:0;width:32px;height:32px;background:none;border:none;cursor:pointer;color:var(--cc-sf-uploaded-remove-color, #94A3B8);padding:0;display:flex;align-items:center;justify-content:center;transition:color .15s ease,background .15s ease}.uploaded-item .file-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.uploaded-item .file-remove-btn:hover:not(:disabled){color:var(--cc-sf-uploaded-remove-hover-color, #DC2626);background:var(--cc-sf-uploaded-remove-hover-bg, #FEF2F2)}.uploaded-item .file-remove-btn:disabled{opacity:.4;cursor:not-allowed}.uploaded-item.uploading{background:var(--cc-sf-uploaded-uploading-bg, #F8FAFC);border-color:var(--cc-sf-uploaded-uploading-border, #CBD5E1);opacity:.85}.upload-spinner{width:20px;height:20px;flex-shrink:0;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}@keyframes cc-spin{to{transform:rotate(360deg)}}.uploading-label{font-style:italic}.input-group{align-items:stretch}.input-group .field-input{flex:1;width:auto}.input-prefix+.input-group .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.input-group .field-input:has(+.input-suffix){border-top-right-radius:0;border-bottom-right-radius:0}.input-group .field-input.has-icon-right{padding-right:3rem}.input-group.readonly .field-input{cursor:default}.input-prefix,.input-suffix{display:flex!important;align-items:center;white-space:nowrap;padding:0 14px;background-color:var(--cc-sf-input-disabled-bg);border:1px solid var(--cc-sf-input-border);font-size:.875rem;color:var(--cc-sf-hint-color);-webkit-user-select:none;user-select:none}.input-prefix{border-right:none;border-top-left-radius:var(--cc-sf-input-radius, 8px);border-bottom-left-radius:var(--cc-sf-input-radius, 8px)}.input-suffix{border-left:none;border-top-right-radius:var(--cc-sf-input-radius, 8px);border-bottom-right-radius:var(--cc-sf-input-radius, 8px)}.readonly-icons{right:.875rem;top:50%;transform:translateY(-50%)}.readonly-icons mat-icon.lock-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem;opacity:.5;color:var(--cc-sf-hint-color, #6B7280)}.suffix-action-icons{right:.875rem;top:50%;transform:translateY(-50%);z-index:1;pointer-events:auto}.suffix-action-icons mat-icon.suffix-action-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem;color:var(--cc-sf-hint-color, #6B7280);cursor:pointer;transition:color .2s ease,transform .15s ease}.suffix-action-icons mat-icon.suffix-action-icon:hover{color:var(--cc-sf-text-color, #202124);transform:scale(1.15)}.date-icon-wrapper{right:.5rem;top:50%;transform:translateY(-50%);pointer-events:auto}.date-icon-wrapper .mat-icon-button{width:32px;height:32px;line-height:32px}.subfields-group-wrapper .subfields-row{transition:all .2s ease}.subfields-group-wrapper .subfields-row.is-invalid .subfield-item ::ng-deep .field-input{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.subfields-group-wrapper .subfields-row .subfield-item{min-width:0}.subfields-group-wrapper .subfields-row .subfield-item ::ng-deep .field-label{font-size:.75rem!important;margin-bottom:4px!important;font-weight:500!important;color:var(--cc-sf-hint-color, #6B7280)!important}.subfields-group-wrapper .subfields-row .subfield-separator{font-weight:700}.autocomplete-wrapper .ac-input{padding-left:40px!important}.autocomplete-wrapper .ac-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1;transition:color var(--cc-sf-input-transition, .2s ease)}.autocomplete-wrapper .ac-clear-btn{right:.6rem;transition:color .15s ease,background .15s ease}.autocomplete-wrapper .ac-clear-btn mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.autocomplete-wrapper .ac-clear-btn:hover{color:var(--cc-sf-label-color, #374151);background:var(--cc-sf-input-disabled-bg, #F3F4F6)}.autocomplete-wrapper .ac-clear-btn:focus{outline:none}.autocomplete-wrapper:focus-within .ac-search-icon{color:var(--cc-sf-accent-color, #3B82F6)}.autocomplete-wrapper.is-invalid .ac-input{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)}.autocomplete-wrapper.readonly .ac-input{background-color:var(--cc-sf-input-disabled-bg);color:var(--cc-sf-input-disabled-color, #6B7280);cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.ac-no-results{font-style:italic}::ng-deep .mat-mdc-autocomplete-panel,::ng-deep .mat-autocomplete-panel{background:var(--cc-sf-input-bg, #ffffff)!important;border-radius:var(--cc-sf-input-radius, 9px)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important;box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f!important;padding:4px 0!important;min-width:200px}::ng-deep .mat-mdc-autocomplete-panel mat-option,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option,::ng-deep .mat-mdc-autocomplete-panel .mat-option,::ng-deep .mat-autocomplete-panel mat-option,::ng-deep .mat-autocomplete-panel .mat-mdc-option,::ng-deep .mat-autocomplete-panel .mat-option{background:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #111827)!important;font-size:.875rem!important;padding:10px 16px!important;min-height:40px!important;line-height:1.4!important;display:flex!important;flex-direction:column!important;align-items:flex-start!important;transition:background var(--cc-sf-input-transition, .2s ease)!important}::ng-deep .mat-mdc-autocomplete-panel mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-mdc-autocomplete-panel .mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel .mat-mdc-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel .mat-option:hover:not(.mat-option-disabled):not([disabled]){background:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}::ng-deep .mat-mdc-autocomplete-panel mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel mat-option.mdc-list-item--selected,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mdc-list-item--selected,::ng-deep .mat-mdc-autocomplete-panel .mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel .mat-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel mat-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel .mat-mdc-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel .mat-mdc-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel .mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel .mat-option.mdc-list-item--selected{background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)!important;color:var(--cc-sf-selected-color, #6366F1)!important;font-weight:600!important}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-option-label,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-option-label,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-option-label,::ng-deep .mat-autocomplete-panel mat-option .ac-option-label,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-option-label,::ng-deep .mat-autocomplete-panel .mat-option .ac-option-label{font-weight:500;color:var(--cc-sf-label-color, #111827);font-size:.875rem;display:block}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-display-fields,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-display-fields,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-display-fields,::ng-deep .mat-autocomplete-panel mat-option .ac-display-fields,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-display-fields,::ng-deep .mat-autocomplete-panel .mat-option .ac-display-fields{align-items:center;line-height:1}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-item,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-item,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-item,::ng-deep .mat-autocomplete-panel mat-option .ac-df-item,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-item,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-item{display:inline-flex;align-items:center;font-size:.72rem;color:var(--cc-sf-hint-color, #6B7280);gap:3px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-chip,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-chip,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-chip,::ng-deep .mat-autocomplete-panel mat-option .ac-df-chip,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-chip,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-chip{background:var(--cc-sf-input-disabled-bg, #F3F4F6);border-radius:4px;padding:2px 6px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-text,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-text,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-text,::ng-deep .mat-autocomplete-panel mat-option .ac-df-text,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-text,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-text{color:var(--cc-sf-hint-color, #6B7280)}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-avatar,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-avatar,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel mat-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-avatar{width:24px;height:24px;border-radius:50%;object-fit:cover;border:1px solid var(--cc-sf-input-border, #D1D5DB);vertical-align:middle}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-label,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-label,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-label,::ng-deep .mat-autocomplete-panel mat-option .ac-df-label,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-label,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-label{font-weight:600;color:var(--cc-sf-hint-color, #9CA3AF);margin-right:2px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-icon,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-icon,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-icon,::ng-deep .mat-autocomplete-panel mat-option .ac-df-icon,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-icon,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-icon{font-size:11px;width:11px;height:11px;line-height:11px;color:var(--cc-sf-hint-color, #9CA3AF);flex-shrink:0}.mu-layout{grid-template-columns:1fr 1fr;gap:32px}@media (max-width: 768px){.mu-layout{grid-template-columns:1fr}}.mu-title{font-weight:700;line-height:1.3}.mu-badge{white-space:nowrap;flex-shrink:0}.mu-description{line-height:1.6}.mu-feature-item .mu-check{width:16px;height:16px;line-height:16px;flex-shrink:0}.mu-right{min-height:260px}.mu-right-empty{min-height:250px;max-width:400px;box-shadow:0 2px 10px #0000000d;transition:box-shadow .2s ease}.mu-right-empty:hover{cursor:pointer;box-shadow:0 4px 16px #0000001a}.mu-right-empty .mu-right-empty-icon{width:52px;height:52px;line-height:52px;opacity:.3}.mu-right-empty p{margin:0;font-size:.85rem}.media-add-container{display:inline-block}.media-add-container ::ng-deep button{display:flex;align-items:center;gap:6px}.media-add-container ::ng-deep button .menu-chevron{width:18px;height:18px;line-height:18px;transition:transform .2s ease}.media-dropdown{top:calc(100% + 6px);left:0;z-index:200;min-width:240px;box-shadow:var(--mu-dropdown-shadow, 0 8px 32px rgba(0, 0, 0, .12));animation:mu-fade-in .15s ease}@keyframes mu-fade-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.media-dropdown-item{transition:background .15s ease}.media-dropdown-item:last-child{border-bottom:none}.media-dropdown-item:hover{background:var(--cc-sf-dropzone-hover-bg, #F0F9FF)}.media-drop-icon{width:36px;height:36px;flex-shrink:0}.media-drop-icon mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.media-drop-icon--video{background:var(--mu-icon-video-bg, #FFF0F0);color:var(--mu-icon-video-color, #EF4444)}.media-drop-icon--device{background:var(--mu-icon-device-bg, #EFF6FF);color:var(--mu-icon-device-color, #3B82F6)}.media-drop-icon--library{background:var(--mu-icon-library-bg, #F0FDF4);color:var(--mu-icon-library-color, #22C55E)}.media-drop-text{gap:2px}.youtube-input-panel{animation:mu-fade-in .18s ease}.youtube-panel-label mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:var(--mu-icon-video-color, #EF4444)}.youtube-input-row{align-items:stretch}.media-menu-backdrop{position:fixed;inset:0;z-index:100}.media-upload-status{animation:mu-fade-in .2s ease}.media-upload-status .status-icon{width:18px;height:18px;line-height:18px}.media-carousel-main{max-width:400px;height:var(--mu-carousel-height, 250px)}.carousel-viewer{inset:0}.carousel-viewer .carousel-image{object-fit:cover}.carousel-viewer .carousel-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.carousel-nav{top:50%;transform:translateY(-50%);z-index:10;width:40px;height:40px;box-shadow:0 2px 8px #0003;transition:background .2s ease,opacity .2s ease;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.carousel-nav mat-icon{font-size:22px;width:22px;height:22px;line-height:22px;color:#1e293b}.carousel-nav:hover:not(:disabled){background:#fff}.carousel-nav:disabled{opacity:.3;cursor:not-allowed}.carousel-nav--prev{left:12px}.carousel-nav--next{right:12px}.carousel-remove-btn{top:10px;right:10px;z-index:10;width:32px;height:32px;transition:background .2s ease}.carousel-remove-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:#fff}.carousel-remove-btn:hover:not(:disabled){background:#dc2626d9}.carousel-remove-btn:disabled{opacity:.4;cursor:not-allowed}.carousel-dots{bottom:10px;left:50%;transform:translate(-50%);z-index:10}.carousel-dot{width:8px;height:8px;transition:background .2s ease,transform .2s ease}.carousel-dot.active{background:#fff;transform:scale(1.3)}.media-thumbnail-strip{max-width:400px;overflow-x:auto}.media-thumbnail-strip::-webkit-scrollbar{height:4px}.media-thumbnail-strip::-webkit-scrollbar-thumb{background:var(--cc-sf-input-disabled-border, #D1D5DB);border-radius:2px}.media-thumb{flex-shrink:0;width:72px;height:52px;transition:border-color .2s ease,transform .15s ease}.media-thumb.active{border-color:var(--mu-thumb-active-border, var(--cc-sf-accent-color, #3B82F6));transform:scale(1.04)}.media-thumb:hover:not(.active){border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.media-thumb .thumb-img{object-fit:cover}.media-thumb .thumb-yt-placeholder mat-icon{font-size:28px;width:28px;height:28px;line-height:28px}.media-thumb .thumb-uploading .thumb-spinner{width:20px;height:20px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.media-library-portal-host{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;visibility:hidden;opacity:0;pointer-events:none;transition:opacity .2s ease,visibility .2s ease}.media-library-portal-host.is-open{visibility:visible;opacity:1;pointer-events:auto}.media-library-portal-host.is-open .media-library-modal{transform:scale(1) translateY(0)}.media-library-overlay{position:absolute;inset:0;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.media-library-modal{position:relative;z-index:10000;width:90vw;max-width:900px;max-height:90vh;background:#fff;border-radius:16px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;transform:scale(.95) translateY(10px);transition:transform .3s cubic-bezier(.175,.885,.32,1.275)}.library-modal-header{flex-shrink:0}.library-modal-title{font-weight:700}.library-modal-subtitle{line-height:1.5;max-width:600px}.library-close-btn{width:32px;height:32px;transition:background .15s ease,color .15s ease}.library-close-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-close-btn:hover{background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-label-color, #374151)}.library-loading mat-icon,.library-empty mat-icon{font-size:40px;width:40px;height:40px;line-height:40px;opacity:.5}.lib-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.library-error{flex-shrink:0}.library-error mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-grid{grid-template-columns:repeat(5,1fr);max-height:50vh;overflow-y:auto}.library-grid::-webkit-scrollbar{width:8px}.library-grid::-webkit-scrollbar-track{background:#f1f1f1}.library-grid::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:10px;border:2px solid #F1F1F1}.library-grid-item{aspect-ratio:1/1;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.library-grid-item:hover{transform:translateY(-4px) scale(1.02);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.library-grid-item.selected{border-color:var(--cc-sf-accent-color, #3B82F6)}.library-grid-item.selected .library-grid-img{opacity:.7}.library-grid-item:hover .library-overlay-hover{opacity:1}.library-grid-img{object-fit:cover}.library-overlay-hover{inset:0;opacity:0;transition:opacity .15s ease}.library-check{top:6px;right:6px;width:22px;height:22px;box-shadow:0 1px 4px #00000026}.library-check mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.library-modal-footer{flex-shrink:0}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary{background-color:var(--cc-sf-accent-color, #3B82F6)!important;border-color:var(--cc-sf-accent-color, #3B82F6)!important;color:#fff!important;font-weight:600;padding-left:32px;padding-right:32px}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:hover{background-color:var(--cc-sf-btn-primary-hover-bg, #2563EB)!important}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:disabled{background-color:#93c5fd!important;cursor:not-allowed}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline{font-weight:600;padding-left:24px;padding-right:24px;border-color:#d1d5db;color:#374151}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline:hover{background-color:#f9fafb}.location-subtitle{line-height:1.5}.loc-tab-btn ::ng-deep button{width:100%}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning){background-color:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #000000)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning):hover{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.loc-venue-item{transition:box-shadow .15s ease,border-color .15s ease}.loc-venue-item:hover{box-shadow:0 2px 8px #0000000f;border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.loc-venue-search-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-venue-text{white-space:nowrap;text-overflow:ellipsis}.loc-action-btn{transition:background .15s ease,color .15s ease;flex-shrink:0}.loc-action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.loc-action-btn.loc-delete-btn{color:var(--loc-delete-color, #E53E3E)}.loc-action-btn.loc-delete-btn:hover{background:var(--cc-sf-error-bg, #FEF2F2)}.loc-action-btn.loc-edit-btn{color:var(--cc-sf-hint-color, #9CA3AF)}.loc-action-btn.loc-edit-btn:hover{color:var(--cc-sf-input-focus-border, #3B82F6);background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)}.loc-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1}.loc-suggestions-panel{top:calc(100% + 4px);left:0;right:0;z-index:300;box-shadow:0 8px 24px #0000001a;animation:mu-fade-in .15s ease;max-height:260px;overflow-y:auto}.loc-suggestion-item{transition:background .12s ease}.loc-suggestion-item:hover,.loc-suggestion-item:focus{background:var(--loc-suggestion-hover-bg, #F0F9FF)}.loc-suggestion-item:not(:last-child){border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)}.loc-suggestion-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-suggestion-text{white-space:nowrap;text-overflow:ellipsis}.loc-add-btn{transition:opacity .15s ease}.loc-add-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.loc-add-btn:hover{opacity:.8}.loc-map-container{box-shadow:0 2px 10px #0000000f}.loc-tba-panel{min-height:120px}.loc-tba-icon{width:40px;height:40px;line-height:40px;opacity:.6}.loc-tba-text{line-height:1.6;max-width:360px}.radio-label{display:flex!important}.radio-label .option-content{padding-left:10px}\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$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.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$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { 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: i9.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i9.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: i11.QuillEditorComponent, selector: "quill-editor" }, { kind: "component", type: FormFieldComponent, selector: "lib-form-field", inputs: ["config", "controller", "formGroup", "allowMulti"] }, { kind: "pipe", type: TrustedUrlPipe, name: "trustedUrl" }] });
|
|
2654
2794
|
}
|
|
2655
2795
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormFieldComponent, decorators: [{
|
|
2656
2796
|
type: Component,
|
|
2657
|
-
args: [{ selector: 'lib-form-field', standalone: false, template: "<div class=\"form-field mb-16px\" *ngIf=\"isVisible\" [class.has-error]=\"errorMessage\">\r\n\r\n <!-- \u2550\u2550 ROW Layout \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRow\" class=\"form-row grid-row\">\r\n <ng-container *ngFor=\"let child of config.children\">\r\n <div class=\"row-field\" [style.gridColumn]=\"'span ' + getChildColSpan(child)\" *ngIf=\"child.isEnabled !== false\">\r\n <lib-form-field [config]=\"child\" [controller]=\"controller\" [formGroup]=\"formGroup\" [allowMulti]=\"allowMulti\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 allowMulti (repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig?.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\"\r\n [class.multi-save-active]=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n\r\n <!-- Multi-Save: header row with label + top-right Add button -->\r\n <div class=\"multi-save-header d-flex justify-content-between align-items-center mb-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig?.label\">{{ config.sectionConfig!.label }}</h3>\r\n <lib-button [variant]=\"'outline'\" [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\"\r\n class=\"btn-add-multi\">\r\n {{ addMultiLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- Standard heading (non-multiSave) -->\r\n <h3 class=\"group-label\"\r\n *ngIf=\"config.sectionConfig?.label && !config.sectionConfig?.multiSaveConfig?.active\">{{\r\n config.sectionConfig!.label }}</h3>\r\n\r\n <!-- \u2500\u2500 Standard (non-multiSave) repeater: accordion instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-accordion-instance\"\r\n [class.is-expanded]=\"isGroupExpanded(i)\">\r\n\r\n <!-- Accordion header -->\r\n <div class=\"group-accordion-header\" (click)=\"toggleGroupAccordion(i)\"\r\n role=\"button\" [attr.aria-expanded]=\"isGroupExpanded(i)\">\r\n <div class=\"accordion-header-left d-flex align-items-center gap-10\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.sectionConfig!.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right d-flex align-items-center gap-6\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceList.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeGroupInstance(i)\"\r\n aria-label=\"Remove\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isGroupExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body (always mounted so form controls survive collapse) -->\r\n <div class=\"group-accordion-body\" [hidden]=\"!isGroupExpanded(i)\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"instance.rowController\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-group\" (click)=\"addGroupInstance()\">\r\n <mat-icon>add</mat-icon> {{ addLabel }} {{ config.sectionConfig!.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2500\u2500 MultiSave: card instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-instance position-relative mb-16 overflow-hidden\"\r\n [class.is-editing]=\"instance.isEditing\"\r\n [class.is-card]=\"!instance.isEditing\">\r\n\r\n <!-- Edit / new form view -->\r\n <div [hidden]=\"!instance.isEditing\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"instance.rowController\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Save / Cancel -->\r\n <div class=\"group-footer d-flex justify-content-end align-items-center gap-16 p-0-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"multiSaveError\">{{ multiSaveError }}</span>\r\n <div class=\"footer-actions d-flex gap-12\">\r\n <lib-button [variant]=\"'outline'\" (click)=\"cancelGroupInstance(i)\">Cancel</lib-button>\r\n <lib-button [variant]=\"'primary'\" (click)=\"saveGroupInstance(i)\">Save</lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Card view (saved state) -->\r\n <ng-container *ngIf=\"!instance.isEditing\">\r\n <div class=\"card-view d-flex justify-content-between align-items-center p-18px-24px\"\r\n [class.is-expanded]=\"instance.isExpanded\">\r\n <div class=\"card-content flex-1 d-flex flex-column gap-4 overflow-hidden\">\r\n <span class=\"card-title font-weight-600 overflow-hidden fs-1rem c-111827\">{{\r\n instance.fg.get(config.sectionConfig!.multiSaveConfig!.summaryField || '')?.value\r\n || '\u2014' }}</span>\r\n </div>\r\n <div class=\"card-actions d-flex align-items-center gap-16 ml-20\">\r\n <mat-icon class=\"icon-delete\" (click)=\"removeGroupInstance(i, true)\">delete_outline</mat-icon>\r\n <mat-icon class=\"icon-edit\" (click)=\"editGroupInstance(i)\">edit_outline</mat-icon>\r\n <mat-icon class=\"icon-expand\" (click)=\"toggleExpandGroupInstance(i)\">\r\n {{ instance.isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 single (non-repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig && !config.sectionConfig.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig.label\">{{ config.sectionConfig.label }}</h3>\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"groupFormGroup\" [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Text Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTextField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <textarea *ngIf=\"config.subType === 'LONG'\" class=\"field-input textarea\" [placeholder]=\"config.placeholder || ''\"\r\n [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\" rows=\"4\">\r\n </textarea>\r\n\r\n <!-- Password input with show/hide toggle -->\r\n <div *ngIf=\"config.subType === 'PASSWORD'\" class=\"password-wrapper position-relative d-flex align-items-center\">\r\n <input [type]=\"showPassword ? 'text' : 'password'\" class=\"field-input password-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <button type=\"button\"\r\n class=\"password-toggle position-absolute cursor-pointer d-flex align-items-center justify-content-center b-none border-none c-6B7280 p-0-25rem\"\r\n (click)=\"showPassword = !showPassword\" tabindex=\"-1\"\r\n [attr.aria-label]=\"showPassword ? 'Hide password' : 'Show password'\">\r\n <mat-icon class=\"eye-icon\">{{ showPassword ? 'visibility' : 'visibility_off' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input *ngIf=\"config.subType !== 'LONG' && config.subType !== 'PASSWORD'\"\r\n [type]=\"config.subType === 'EMAIL' ? 'email' : config.subType === 'PHONE' ? 'tel' : 'text'\" class=\"field-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\"\r\n [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n\r\n <!-- Suffix Action Icons (clickable) -->\r\n <div class=\"suffix-action-icons position-absolute d-flex gap-8 align-items-center\"\r\n *ngIf=\"config.suffixActionIcons?.length && !config.readonly\">\r\n <mat-icon class=\"suffix-action-icon\"\r\n *ngFor=\"let action of config.suffixActionIcons\"\r\n [style.color]=\"action.color || null\"\r\n [title]=\"action.tooltip || ''\"\r\n (click)=\"onSuffixActionClick(action.actionId)\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Number Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isNumberField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input type=\"number\" class=\"field-input\" [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\"\r\n [min]=\"config.numberConfig?.min ?? null\" [max]=\"config.numberConfig?.max ?? null\"\r\n [step]=\"config.numberConfig?.step || 1\" [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n\r\n <!-- Suffix Action Icons (clickable) -->\r\n <div class=\"suffix-action-icons position-absolute d-flex gap-8 align-items-center\"\r\n *ngIf=\"config.suffixActionIcons?.length && !config.readonly\">\r\n <mat-icon class=\"suffix-action-icon\"\r\n *ngFor=\"let action of config.suffixActionIcons\"\r\n [style.color]=\"action.color || null\"\r\n [title]=\"action.tooltip || ''\"\r\n (click)=\"onSuffixActionClick(action.actionId)\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Date Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDateField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input matInput [matDatepicker]=\"datePicker\" class=\"field-input date-input has-icon-right\"\r\n [formControlName]=\"config.name!\" [min]=\"effectiveMinDate\" [max]=\"config.dateConfig?.maxDate\"\r\n [class.is-invalid]=\"errorMessage\" [placeholder]=\"config.placeholder || ''\"\r\n [readonly]=\"config.readonly || config.dateConfig?.inputReadonly\"\r\n (click)=\"!config.readonly && datePicker.open()\">\r\n <div class=\"date-icon-wrapper position-absolute d-flex align-items-center justify-content-center\"\r\n *ngIf=\"!config.readonly\">\r\n <mat-datepicker-toggle matSuffix [for]=\"datePicker\"></mat-datepicker-toggle>\r\n </div>\r\n <mat-datepicker #datePicker></mat-datepicker>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Time Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTimeField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input type=\"time\" class=\"field-input time-input\" [formControlName]=\"config.name!\"\r\n [min]=\"effectiveMinTime\" [max]=\"effectiveMaxTime\"\r\n [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly || config.timeConfig?.inputReadonly\">\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Autocomplete \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isAutocomplete\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Hidden real control (stores the code value) -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <div class=\"autocomplete-wrapper position-relative d-flex align-items-center w-100\"\r\n [class.is-invalid]=\"errorMessage\" [class.readonly]=\"config.readonly\">\r\n <!-- Search icon -->\r\n <mat-icon class=\"ac-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n\r\n <input class=\"field-input ac-input\" [formControl]=\"autocompleteInputCtrl\" [matAutocomplete]=\"auto\"\r\n [placeholder]=\"config.placeholder || 'Search\u2026'\" [readonly]=\"!!config.readonly\" [class.is-invalid]=\"errorMessage\"\r\n (blur)=\"onAutocompleteClear()\" autocomplete=\"off\">\r\n\r\n <!-- Clear button -->\r\n <button type=\"button\"\r\n class=\"ac-clear-btn position-absolute d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none c-9CA3AF p-0-2rem\"\r\n *ngIf=\"autocompleteInputCtrl.value && !config.readonly\"\r\n (click)=\"autocompleteInputCtrl.setValue(''); updateValue(null)\" tabindex=\"-1\" aria-label=\"Clear\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n\r\n <mat-autocomplete #auto=\"matAutocomplete\" [panelWidth]=\"'auto'\">\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.label\"\r\n (onSelectionChange)=\"onAutocompleteSelected(option)\">\r\n <span class=\"ac-option-label\">{{ option.label }}</span>\r\n\r\n <!-- Dynamic display fields (image / email / phone / text) -->\r\n <div class=\"ac-display-fields d-flex flex-wrap gap-6 mt-2\" *ngIf=\"option['displayMeta']?.length\">\r\n <ng-container *ngFor=\"let field of option['displayMeta']\">\r\n\r\n <!-- Image avatar -->\r\n <span *ngIf=\"field.type === 'image' && field.value\" class=\"ac-df-item ac-df-image\">\r\n <img [src]=\"field.value\" [alt]=\"field.label || 'image'\" class=\"ac-df-avatar\">\r\n </span>\r\n\r\n <!-- Email -->\r\n <span *ngIf=\"field.type === 'email' && field.value\" class=\"ac-df-item ac-df-chip\">\r\n <mat-icon class=\"ac-df-icon\">mail_outline</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n <!-- Phone -->\r\n <span *ngIf=\"field.type === 'phone' && field.value\" class=\"ac-df-item ac-df-chip\" [class]=\"field.className\">\r\n <mat-icon class=\"ac-df-icon\">phone</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n <!-- Custom / Icon-based / Generic Text -->\r\n <span *ngIf=\"field.type !== 'image' && field.type !== 'email' && field.type !== 'phone' && field.value\" \r\n class=\"ac-df-item\" [class.ac-df-chip]=\"!!field.icon\" [class]=\"field.className\">\r\n <mat-icon class=\"ac-df-icon\" *ngIf=\"field.icon\">{{ field.icon }}</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n </ng-container>\r\n </div>\r\n </mat-option>\r\n <mat-option *ngIf=\"filteredOptions.length === 0\" disabled class=\"ac-no-results fs-0-8125rem c-6B7280\">\r\n No results found\r\n </mat-option>\r\n </mat-autocomplete>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Dropdown \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDropdown\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <select *ngIf=\"config.subType === 'SINGLE'\" class=\"field-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option [ngValue]=\"null\" disabled selected>{{ config.placeholder || 'Select' }}</option>\r\n <option *ngFor=\"let option of localOptionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <!-- MULTIPLE SELECT: custom panel with checkboxes -->\r\n <div *ngIf=\"config.subType === 'MULTIPLE'\" class=\"multi-select-wrapper\"\r\n [class.is-invalid]=\"errorMessage\">\r\n\r\n <div class=\"field-input multi-select-trigger d-flex align-items-center justify-content-between cursor-pointer\"\r\n [class.ms-open]=\"isMultiDropdownOpen\"\r\n (click)=\"toggleMultiDropdown($event)\">\r\n <span *ngIf=\"multiSelectedCount > 0\" class=\"multi-select-value fs-0-9rem\">\r\n {{ multiSelectedCount }} selected\r\n </span>\r\n <span *ngIf=\"multiSelectedCount === 0\" class=\"multi-select-placeholder\">\r\n {{ config.placeholder || selectPlaceholderLabel }}\r\n </span>\r\n <mat-icon class=\"multi-select-arrow\">\r\n {{ isMultiDropdownOpen ? expandLessLabel : expandMoreLabel }}\r\n </mat-icon>\r\n </div>\r\n\r\n <div class=\"multi-select-panel\" *ngIf=\"isMultiDropdownOpen\"\r\n (click)=\"$event.stopPropagation()\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"multi-select-option d-flex align-items-center gap-8 cursor-pointer\">\r\n <input type=\"checkbox\"\r\n [checked]=\"isChecked(option.code)\"\r\n [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <span class=\"fs-0-875rem c-111827\">{{ option.label }}</span>\r\n </label>\r\n <div *ngIf=\"!localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noOptionsAvailableLabel }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Radio \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRadio\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"radio-group\" [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of localOptionList\" class=\"radio-label\"\r\n [class.card-item]=\"config.subType === 'CARD'\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"radio\" [formControlName]=\"config.name!\" [value]=\"option.code\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Checkbox \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isCheckbox\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label && config.subType === 'LIST'\"\r\n class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div *ngIf=\"config.subType === 'BOOL'\" class=\"checkbox-single\">\r\n <label class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span>{{ config.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div *ngIf=\"config.subType === 'LIST' || config.subType === 'CARD'\" class=\"checkbox-group d-flex flex-column gap-8\"\r\n [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\"\r\n [class.card-item]=\"config.subType === 'CARD'\" [class.selected]=\"isChecked(option.code)\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Chip \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isChip\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"chip-group d-flex flex-wrap gap-8\" [class.is-invalid]=\"errorMessage\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"chip-label cursor-pointer p-6px-14px b-ffffff c-374151 b-1px-solid-D1D5DB br-20px fs-0-875rem\"\r\n [class.selected]=\"isChecked(option.code)\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\" hidden>\r\n <span>{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Switch \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isSwitch\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label class=\"switch-container d-flex justify-content-between align-items-center cursor-pointer\">\r\n <span class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label }}</span>\r\n <div class=\"switch position-relative\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span class=\"slider position-absolute cursor-pointer\"></span>\r\n </div>\r\n </label>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rich Text \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRichText\" class=\"field-wrapper component-rich-text d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rich-text-container\" [class.is-invalid]=\"errorMessage\">\r\n <quill-editor [formControlName]=\"config.name!\" class=\"rich-text-editor d-block w-100\"\r\n [placeholder]=\"config.richTextConfig?.placeholder || config.placeholder || ''\"\r\n [styles]=\"{height: config.richTextConfig?.height || '200px'}\">\r\n </quill-editor>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rating \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRating\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rating-group d-flex gap-4\" [class.is-invalid]=\"errorMessage\">\r\n <span *ngFor=\"let star of getStarArray()\" class=\"star d-inline-flex align-items-center cursor-pointer\"\r\n [class.filled]=\"isStarFilled(star)\" [class.half]=\"isStarHalf(star)\" (click)=\"onRatingChange(star, $event)\">\r\n <mat-icon>{{ isStarFilled(star) || isStarHalf(star) ? 'star' : 'star_border' }}</mat-icon>\r\n </span>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Generated Field (read-only) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGenerated\" class=\"field-wrapper d-flex flex-column gap-6\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label\r\n }}</label>\r\n <div class=\"generated-value fs-0-875rem p-0-625rem-0-875rem b-F3F4F6 b-1px-solid-E5E7EB br-8px c-6B7280\">{{ value ||\r\n '-' }}</div>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint\">{{ config.hint }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 File Upload \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isFileUpload\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Drop Zone -->\r\n <div\r\n class=\"upload-drop-zone d-flex flex-column align-items-center justify-content-center gap-8 cursor-pointer text-center p-32px-24px us-none\"\r\n [class.drag-over]=\"isDragOver\" [class.has-files]=\"value?.length\" [class.is-invalid]=\"errorMessage\"\r\n (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave($event)\" (drop)=\"onFileDrop($event)\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <!-- Icon with accent-colour pill background -->\r\n <div class=\"upload-icon-wrap mb-4\">\r\n <div class=\"dropzone-icon-pill d-flex align-items-center justify-content-center\">\r\n <mat-icon class=\"upload-cloud-icon\">cloud_upload</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <p class=\"upload-main-text font-weight-600 m-0 fs-0-9rem\">Drag & drop files here</p>\r\n <p class=\"upload-sub-text m-0 fs-0-8rem c-64748B\">or <span class=\"upload-link\">Browse files</span></p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"config.attachmentConfig?.acceptLabel\">\r\n Supported: <span class=\"upload-formats font-weight-500\">{{ config.attachmentConfig!.acceptLabel }}</span>\r\n </p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"!config.attachmentConfig?.acceptLabel && config.hint\">\r\n {{ config.hint }}\r\n </p>\r\n <span class=\"upload-size-badge fs-0-72rem\" *ngIf=\"config.attachmentConfig?.maxSizeMB\">\r\n Max {{ config.attachmentConfig!.maxSizeMB }}MB\r\n </span>\r\n\r\n <!-- Hidden native file input -->\r\n <input #fileInput type=\"file\" hidden [attr.multiple]=\"config.attachmentConfig?.multiple ? true : null\"\r\n [attr.accept]=\"config.attachmentConfig?.accept || null\" (change)=\"onFileSelected($event)\">\r\n </div>\r\n\r\n <!-- Uploaded file list -->\r\n <div class=\"uploaded-list d-flex flex-column gap-8 mt-10\" *ngIf=\"value?.length\">\r\n <div *ngFor=\"let f of value; let i = index\"\r\n class=\"uploaded-item d-flex align-items-center gap-10 p-10px-14px br-8px\"\r\n [class.uploading]=\"f.isUploading\">\r\n\r\n <!-- Uploading spinner -->\r\n <ng-container *ngIf=\"f.isUploading; else fileReady\">\r\n <div class=\"upload-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size uploading-label fs-0-72rem\">Uploading...</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Normal state once upload is done -->\r\n <ng-template #fileReady>\r\n <mat-icon class=\"file-type-icon\">{{ getFileIcon(f.type) }}</mat-icon>\r\n <img *ngIf=\"f.type?.startsWith('image') && f.dataUrl\" [src]=\"f.dataUrl\" class=\"file-thumb rounded-4\"\r\n alt=\"preview\">\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size fs-0-72rem\">{{ formatFileSize(f.size) }}</span>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Compact icon-only remove button -->\r\n <button type=\"button\" class=\"file-remove-btn d-flex align-items-center justify-content-center rounded-50\"\r\n [disabled]=\"f.isUploading\" (click)=\"!f.isUploading && removeUploadedFile(i)\"\r\n aria-label=\"Remove file\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation / file errors -->\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"fileUploadError\">{{ fileUploadError }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage && !fileUploadError\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\"\r\n *ngIf=\"config.hint && !errorMessage && !fileUploadError && !config.attachmentConfig?.acceptLabel\">\r\n {{ config.hint }}\r\n </span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Media Upload (Type 2) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isMediaUpload\" class=\"field-wrapper media-upload-wrapper d-flex flex-column gap-6 p-0 border-none b-none\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Hidden file input lives outside *ngIf \u2014 triggered via ViewChild -->\r\n <input #mediaDeviceInput type=\"file\" hidden multiple accept=\"image/*\" (change)=\"onMediaFileSelected($event)\">\r\n\r\n <!-- Two-column layout -->\r\n <div class=\"mu-layout d-grid align-items-start\">\r\n\r\n <!-- \u2500\u2500 LEFT PANEL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-left d-flex flex-column gap-20\">\r\n\r\n <!-- Header: title + max-items badge -->\r\n <div class=\"mu-header d-flex align-items-start flex-wrap gap-10\">\r\n <h3 class=\"mu-title m-0 c-111827 fs-1-35rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </h3>\r\n <span\r\n class=\"mu-badge d-inline-flex align-items-center rounded-20 color-white font-weight-600 fs-0-72rem p-4px-12px b-111827\"\r\n *ngIf=\"config.attachmentConfig?.maxFiles\">\r\n {{ controller.labels['LBL_MEDIA_MAX_PREFIX'] || 'Maximum' }}\r\n {{ config.attachmentConfig?.maxFiles }}\r\n {{ controller.labels['LBL_MEDIA_MAX_SUFFIX'] || 'Image & Videos' }}\r\n </span>\r\n </div>\r\n\r\n <!-- Description -->\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\" *ngIf=\"config.attachmentConfig?.description\">\r\n {{ config.attachmentConfig?.description }}\r\n </p>\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\"\r\n *ngIf=\"!config.attachmentConfig?.description && controller.labels['LBL_MEDIA_DESC']\">\r\n {{ controller.labels['LBL_MEDIA_DESC'] }}\r\n </p>\r\n\r\n <!-- Feature bullet list -->\r\n <ul class=\"mu-features m-0 p-0 d-flex flex-column gap-8 ls-none\"\r\n *ngIf=\"config.attachmentConfig?.features?.length || controller.labels['LBL_MEDIA_FEATURE_1']\">\r\n <ng-container *ngIf=\"config.attachmentConfig?.features?.length\">\r\n <li *ngFor=\"let f of config.attachmentConfig?.features\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ f }}\r\n </li>\r\n </ng-container>\r\n <ng-container *ngIf=\"!config.attachmentConfig?.features?.length\">\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_1']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_1'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_2']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_2'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_3']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_3'] }}\r\n </li>\r\n </ng-container>\r\n </ul>\r\n\r\n <!-- Backdrop to close dropdown on outside click -->\r\n <div class=\"media-menu-backdrop\" *ngIf=\"showMediaMenu\"\r\n (click)=\"$event.stopPropagation(); showMediaMenu = false\"></div>\r\n\r\n <!-- Add Media button + dropdown -->\r\n <div class=\"media-add-container position-relative\" (click)=\"showMediaMenu = !showMediaMenu\">\r\n <lib-button id=\"btn-add-media-{{ config.name }}\" [variant]=\"'warning'\"\r\n [icon]=\"{type: 'material', value: 'add_photo_alternate'}\">\r\n {{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}\r\n <mat-icon class=\"menu-chevron fs-18px\">add</mat-icon>\r\n </lib-button>\r\n\r\n <div class=\"media-dropdown position-absolute rounded-12 overflow-hidden b-ffffff b-1px-solid-E5E7EB\"\r\n *ngIf=\"showMediaMenu\" role=\"menu\" (click)=\"$event.stopPropagation()\">\r\n <!-- Video -->\r\n <button id=\"btn-media-video-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuVideo(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--video d-flex align-items-center justify-content-center rounded-8\"><mat-icon>videocam</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_VIDEO'] || 'Video' }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_VIDEO_DESC'] || 'Add\r\n YouTube URL'\r\n }}</span>\r\n </span>\r\n </button>\r\n <!-- Device -->\r\n <button id=\"btn-media-device-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuDevice(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--device d-flex align-items-center justify-content-center rounded-8\"><mat-icon>upload</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_DEVICE'] || 'Upload from device'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_DEVICE_DESC'] ||\r\n 'Select images from your\r\n computer' }}</span>\r\n </span>\r\n </button>\r\n <!-- Library -->\r\n <button id=\"btn-media-library-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuLibrary(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--library d-flex align-items-center justify-content-center rounded-8\"><mat-icon>photo_library</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_LIBRARY'] || 'Upload from library'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_LIBRARY_DESC'] ||\r\n 'Choose from default\r\n images' }}</span>\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- YouTube URL Input (inline below button) -->\r\n <div class=\"youtube-input-panel d-flex flex-column gap-8 p-16 rounded-10 b-FFFAF1 b-1px-solid-E5E7EB\"\r\n *ngIf=\"showYoutubeInput\">\r\n <label class=\"youtube-panel-label d-flex align-items-center gap-6 font-weight-600 fs-0-875rem c-111827\">\r\n {{ controller.labels['LBL_YOUTUBE_URL'] || 'Video URL' }}\r\n </label>\r\n <div class=\"youtube-input-row d-flex gap-8\">\r\n <input id=\"input-youtube-url-{{ config.name }}\" type=\"url\" class=\"field-input youtube-url-input\"\r\n [(ngModel)]=\"youtubeUrlInput\" [ngModelOptions]=\"{standalone: true}\"\r\n [placeholder]=\"controller.labels['PH_YOUTUBE_URL'] || 'Video URL'\" (keyup.enter)=\"addYoutubeMedia()\">\r\n <lib-button id=\"btn-add-youtube-{{ config.name }}\" [variant]=\"'secondary'\" (click)=\"addYoutubeMedia()\">\r\n {{ controller.labels['LBL_ADD'] || 'Add' }}\r\n </lib-button>\r\n </div>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"youtubeUrlError\">{{ youtubeUrlError }}</span>\r\n </div>\r\n\r\n <div\r\n class=\"media-upload-status d-flex align-items-center gap-8 mt-4 color-error rounded-8 font-weight-500 p-10px-14px b-FEF2F2 fs-0-85rem\"\r\n *ngIf=\"mediaUploadError\">\r\n <mat-icon class=\"status-icon fs-18px\">error_outline</mat-icon>\r\n <span>{{ mediaUploadError }}</span>\r\n </div>\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n </div>\r\n <!-- end left panel -->\r\n\r\n <!-- \u2500\u2500 RIGHT PANEL (carousel) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-right d-flex flex-column gap-12\">\r\n\r\n <!-- Carousel (when items exist) -->\r\n <div class=\"media-carousel-section d-flex flex-column gap-12\" *ngIf=\"mediaItems.length\">\r\n <div\r\n class=\"media-carousel-main position-relative w-100 overflow-hidden d-flex align-items-center justify-content-center br-12px b-0F172A\">\r\n <button id=\"btn-carousel-prev-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--prev position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselPrev()\" [disabled]=\"mediaCarouselIndex === 0\" aria-label=\"Previous\">\r\n <mat-icon>chevron_left</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-viewer position-absolute d-flex align-items-center justify-content-center\"\r\n *ngFor=\"let item of mediaItems; let i = index\" [hidden]=\"i !== mediaCarouselIndex\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"carousel-uploading d-flex flex-column align-items-center gap-12 c-94A3B8 fs-0-85rem\">\r\n <div class=\"carousel-spinner rounded-50 b-3px-solid-rgba-255-255-255-0-15\"></div>\r\n <span>{{ controller.labels['LBL_UPLOADING'] || 'Uploading\u2026' }}</span>\r\n </div>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'youtube'\">\r\n <iframe class=\"carousel-iframe w-100 h-100 br-12px\" [src]=\"item.url | trustedUrl\" frameborder=\"0\"\r\n allowfullscreen\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\">\r\n </iframe>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'image'\">\r\n <img class=\"carousel-image w-100 h-100 br-12px\" [src]=\"item.url\" alt=\"Media\">\r\n </ng-container>\r\n <button id=\"btn-remove-media-{{ config.name }}-{{ i }}\" type=\"button\"\r\n class=\"carousel-remove-btn position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-0-0-0-0-55\"\r\n [disabled]=\"item.isUploading\" (click)=\"removeMediaItem(i)\" aria-label=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <button id=\"btn-carousel-next-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--next position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselNext()\" [disabled]=\"mediaCarouselIndex === mediaItems.length - 1\" aria-label=\"Next\">\r\n <mat-icon>chevron_right</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-dots position-absolute d-flex gap-6\">\r\n <span *ngFor=\"let item of mediaItems; let i = index\"\r\n class=\"carousel-dot rounded-50 cursor-pointer b-rgba-255-255-255-0-45\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\"></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Thumbnail strip -->\r\n <div class=\"media-thumbnail-strip d-flex flex-wrap gap-8 pb-4px\">\r\n <div *ngFor=\"let item of mediaThumbnails; let i = index\"\r\n class=\"media-thumb rounded-8 overflow-hidden cursor-pointer d-flex align-items-center justify-content-center b-2px-solid-transparent b-E2E8F0\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"thumb-uploading d-flex align-items-center justify-content-center w-100 h-100\">\r\n <div class=\"thumb-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && item.thumbnailUrl\"\r\n [src]=\"item.thumbnailUrl\" class=\"thumb-img w-100 h-100\" alt=\"Video thumbnail\">\r\n <div *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && !item.thumbnailUrl\"\r\n class=\"thumb-yt-placeholder d-flex align-items-center justify-content-center w-100 h-100 b-1E293B c-EF4444\">\r\n <mat-icon>play_circle</mat-icon>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'image' && item.url\" [src]=\"item.url\"\r\n class=\"thumb-img w-100 h-100\" alt=\"Image thumbnail\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty right-side placeholder -->\r\n <div\r\n class=\"mu-right-empty d-flex flex-column align-items-center justify-content-center gap-10 h-100 text-center p-24 br-12px b-FFFAF1 c-94A3B8 b-2px-dashed-CBD5E1\"\r\n *ngIf=\"!mediaItems.length\" (click)=\"onMediaMenuDevice()\">\r\n <mat-icon class=\"mu-right-empty-icon fs-52px\">perm_media</mat-icon>\r\n <p>{{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}</p>\r\n </div>\r\n\r\n </div>\r\n <!-- end right panel -->\r\n\r\n </div><!-- end mu-layout -->\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Library Image Picker Modal \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <!-- Wrapper is always in DOM (hidden) so @ViewChild can move it to body -->\r\n <div #libraryModal class=\"media-library-portal-host\" [class.is-open]=\"showLibraryModal\">\r\n\r\n <!-- Backdrop -->\r\n <div class=\"media-library-overlay\" (click)=\"closeLibraryModal()\"></div>\r\n\r\n <!-- Modal card -->\r\n <div class=\"media-library-modal d-flex flex-column overflow-hidden b-ffffff br-16px\"\r\n role=\"dialog\" aria-modal=\"true\">\r\n <div class=\"library-modal-header d-flex align-items-start justify-content-between p-24px-28px bb-1px-solid-E5E7EB\">\r\n <div class=\"header-left d-flex flex-column gap-8\">\r\n <h3 class=\"library-modal-title m-0 color-dark fs-1-25rem\">\r\n {{ controller.labels['LBL_ADD_IMAGES'] || 'Add Images' }}\r\n </h3>\r\n <p class=\"library-modal-subtitle m-0 color-gray fs-0-85rem\">\r\n {{ controller.labels['LBL_LIBRARY_MODAL_DESC'] || 'Select images from your library.' }}\r\n </p>\r\n </div>\r\n <button id=\"btn-close-library-{{ config.name }}\" type=\"button\"\r\n class=\"library-close-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 border-none b-none c-9CA3AF\"\r\n (click)=\"closeLibraryModal()\" aria-label=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Loading -->\r\n <div class=\"library-loading\" *ngIf=\"libraryLoading\">\r\n <div class=\"lib-spinner rounded-50 b-3px-solid-E2E8F0\"></div>\r\n <span>{{ controller.labels['LBL_LOADING'] || 'Loading\u2026' }}</span>\r\n </div>\r\n\r\n <!-- Error -->\r\n <div class=\"library-error d-flex align-items-center gap-8 color-error b-FEF2F2 fs-0-875rem p-16px-24px\"\r\n *ngIf=\"libraryError && !libraryLoading\">\r\n <mat-icon>error_outline</mat-icon>\r\n {{ libraryError }}\r\n </div>\r\n\r\n <!-- Image grid -->\r\n <div class=\"library-grid d-grid gap-16 flex-1 p-28px b-F9FAFB\" *ngIf=\"!libraryLoading && libraryImages.length\">\r\n <div *ngFor=\"let img of libraryImages; let li = index\" id=\"lib-img-{{ config.name }}-{{ li }}\"\r\n class=\"library-grid-item position-relative rounded-12 overflow-hidden cursor-pointer bg-white b-3px-solid-transparent\"\r\n [class.selected]=\"isLibraryItemSelected(img)\" (click)=\"toggleLibraryItem(img)\">\r\n <img [src]=\"getLibraryItemUrl(img)\" class=\"library-grid-img w-100 h-100 d-block\" alt=\"Library image\">\r\n <div\r\n class=\"library-check position-absolute bg-white rounded-50 d-flex align-items-center justify-content-center c-3B82F6\"\r\n *ngIf=\"isLibraryItemSelected(img)\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n <div class=\"library-overlay-hover position-absolute b-rgba-59-130-246-0-12\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty library -->\r\n <div\r\n class=\"library-empty d-flex flex-column align-items-center justify-content-center gap-12 flex-1 c-9CA3AF fs-0-875rem p-48px-24px\"\r\n *ngIf=\"!libraryLoading && !libraryError && libraryImages.length === 0\">\r\n <mat-icon>image_not_supported</mat-icon>\r\n <span>{{ controller.labels['LBL_LIBRARY_EMPTY'] || 'No images found in library.' }}</span>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"library-modal-footer d-flex align-items-center justify-content-end bg-white p-20px-28px bt-1px-solid-E5E7EB\">\r\n <div class=\"library-footer-actions d-flex gap-12\">\r\n <lib-button id=\"btn-library-cancel-{{ config.name }}\" [variant]=\"'outline'\" (click)=\"closeLibraryModal()\">\r\n {{ controller.labels['LBL_CANCEL'] || 'Cancel' }}\r\n </lib-button>\r\n <lib-button id=\"btn-library-confirm-{{ config.name }}\" [variant]=\"'primary'\"\r\n [disabled]=\"librarySelectedIds.size === 0\" (click)=\"confirmLibrarySelection()\">\r\n {{ controller.labels['LBL_CONTINUE'] || 'Continue' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <!-- \u2550\u2550 Location Field \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isLocation\" class=\"field-wrapper location-field-wrapper d-flex flex-column gap-6 gap-12\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Field label -->\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n <p class=\"location-subtitle m-0 c-6B7280 fs-0-8125rem\" *ngIf=\"config.hint\">{{ config.hint }}</p>\r\n\r\n <!-- Three-tab bar -->\r\n <div class=\"location-tabs d-flex gap-12 mb-24\">\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'VENUE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('VENUE')\">\r\n {{ controller.labels['LBL_LOC_VENUE'] || 'Venue' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'ONLINE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('ONLINE')\">\r\n {{ controller.labels['LBL_LOC_ONLINE'] || 'Online Event' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'TBA' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('TBA')\">\r\n {{ controller.labels['LBL_LOC_TBA'] || 'To be Announced' }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- VENUE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'VENUE'\" class=\"loc-panel loc-venue-panel d-flex flex-column gap-12\">\r\n\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ADDRESS'] || 'Location address' }}\r\n </p>\r\n\r\n <!-- Added venue rows -->\r\n <div class=\"loc-venue-list d-flex flex-column gap-8\" *ngIf=\"locationVenues.length > 0\">\r\n <div *ngFor=\"let venue of locationVenues; let i = index\"\r\n class=\"loc-venue-item d-flex align-items-center gap-10 p-10px-14px br-7px b-ffffff b-1px-solid-D1D5DB\">\r\n <mat-icon class=\"loc-venue-search-icon fs-18px c-9CA3AF\">search</mat-icon>\r\n <span class=\"loc-venue-text flex-1 overflow-hidden fs-0-875rem c-111827\">{{ venue.address || venue.name ||\r\n venue.description }}</span>\r\n <button type=\"button\"\r\n class=\"loc-action-btn loc-delete-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none p-4px\"\r\n (click)=\"removeLocationVenue(i)\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Location count badge -->\r\n <p class=\"loc-count-text m-0 font-weight-600 fs-0-8125rem c-3B82F6\"\r\n *ngIf=\"locationVenues.length > 0 && config.locationConfig?.allowMulti\">\r\n {{ locationVenues.length }} {{ controller.labels['LBL_LOC_COUNT_SUFFIX'] || 'Locations Added!' }}\r\n </p>\r\n\r\n <!-- Search input (hide when max reached) -->\r\n <div class=\"loc-search-container position-relative\" *ngIf=\"!locationMaxReached\">\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n [placeholder]=\"config.locationConfig?.venuePlaceholder || (controller.labels['PH_LOC_VENUE'] || 'Type to search venue...')\"\r\n [value]=\"locationSearchText\" (input)=\"handleLocationSearchInput($event)\" (blur)=\"hideLocationSuggestions()\"\r\n autocomplete=\"off\" [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n <!-- Suggestions dropdown -->\r\n <div class=\"loc-suggestions-panel position-absolute overflow-hidden br-8px b-ffffff b-1px-solid-D1D5DB\"\r\n *ngIf=\"locationShowSuggestions && locationSuggestions.length\">\r\n <div *ngFor=\"let sug of locationSuggestions\"\r\n class=\"loc-suggestion-item d-flex align-items-center gap-10 cursor-pointer p-10px-14px\"\r\n (mousedown)=\"onLocationSuggestionSelect(sug)\">\r\n <mat-icon class=\"loc-suggestion-icon fs-18px c-E53E3E\">place</mat-icon>\r\n <span class=\"loc-suggestion-text overflow-hidden fs-0-875rem c-374151\">{{ sug.description }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Add another button -->\r\n <button type=\"button\"\r\n class=\"loc-add-btn d-inline-flex align-items-center gap-6 cursor-pointer font-weight-600 p-0 b-none border-none fs-0-875rem c-1A56DB\"\r\n *ngIf=\"locationVenues.length > 0 && !locationMaxReached && config.locationConfig?.allowMulti\">\r\n <mat-icon>add_circle_outline</mat-icon>\r\n <span>{{ controller.labels['LBL_LOC_ADD_ANOTHER'] || 'Add another Location' }}</span>\r\n </button>\r\n\r\n <!-- Map -->\r\n <div class=\"loc-map-container overflow-hidden br-10px b-1px-solid-E5E7EB\"\r\n *ngIf=\"config.locationConfig?.showMap !== false\">\r\n <ng-container *ngIf=\"config.locationConfig?.googleMapsApiKey; else simpleEmbed\">\r\n <div [id]=\"'loc-map-' + config.name\" class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\"></div>\r\n </ng-container>\r\n <ng-template #simpleEmbed>\r\n <iframe class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\" [src]=\"getLocationMapEmbedUrl() | trustedUrl\"\r\n frameborder=\"0\" allowfullscreen loading=\"lazy\">\r\n </iframe>\r\n </ng-template>\r\n </div>\r\n\r\n <!-- Map hint -->\r\n <p class=\"loc-map-hint m-0 text-center fs-0-78rem c-6B7280\">\r\n {{ controller.labels['LBL_LOC_MAP_HINT'] || 'Type the venue address. A map will appear to assist you.' }}\r\n </p>\r\n </div>\r\n\r\n <!-- ONLINE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'ONLINE'\" class=\"loc-panel loc-online-panel d-flex flex-column gap-12\">\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ONLINE_URL'] || 'Event URL' }}\r\n </p>\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">link</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n type=\"url\"\r\n [placeholder]=\"config.locationConfig?.onlinePlaceholder || (controller.labels['PH_LOC_ONLINE'] || 'https://zoom.us/j/...')\"\r\n [value]=\"locationOnlineUrl\" (input)=\"onLocationUrlChange($any($event.target).value)\"\r\n [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n </div>\r\n\r\n <!-- TBA TAB -->\r\n <div *ngIf=\"locationActiveTab === 'TBA'\"\r\n class=\"loc-panel loc-tba-panel d-flex flex-column gap-12 justify-content-center\">\r\n <div\r\n class=\"loc-tba-content d-flex flex-column align-items-center justify-content-center text-center gap-12 p-32px-24px b-F9FAFB b-1px-dashed-D1D5DB br-10px\">\r\n <mat-icon class=\"loc-tba-icon fs-40px c-9CA3AF\">schedule</mat-icon>\r\n <p class=\"loc-tba-text m-0 c-6B7280 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_TBA_DESC'] || \"This event's location is yet to be announced. Check back later\r\n for updates.\" }}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden real form control -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n</div>", styles: [".d-flex{display:flex}.d-inline-flex{display:inline-flex}.d-grid{display:grid}.d-block{display:block}.d-none{display:none}.flex-column{flex-direction:column}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.align-items-center{align-items:center}.align-items-start{align-items:flex-start}.align-items-end{align-items:flex-end}.justify-content-center{justify-content:center}.justify-content-between{justify-content:space-between}.justify-content-start{justify-content:flex-start}.justify-content-end{justify-content:flex-end}.grid-cols-12{grid-template-columns:repeat(12,1fr)}.w-100{width:100%}.h-100{height:100%}.position-relative{position:relative}.position-absolute{position:absolute}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-poppins{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)}.font-weight-400{font-weight:400}.font-weight-500{font-weight:500}.font-weight-600{font-weight:600}.text-13{font-size:13px}.text-14{font-size:14px}.text-16{font-size:16px}.color-white{color:#fff}.color-dark{color:#111827}.color-gray{color:#6b7280}.color-error{color:var(--cc-sf-error-text-color, #DC2626)}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.m-0{margin:0}.mt-4{margin-top:4px}.mt-8{margin-top:8px}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}.mb-0{margin-bottom:0}.mb-4{margin-bottom:4px}.mb-8{margin-bottom:8px}.mb-10{margin-bottom:10px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}.mb-24{margin-bottom:24px}.ml-16{margin-left:16px}.ml-20{margin-left:20px}.p-0{padding:0}.p-16{padding:16px}.p-20{padding:20px}.p-24{padding:24px}.pt-20{padding-top:20px}.pb-10{padding-bottom:10px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.gap-20{gap:20px}.rounded-4{border-radius:4px}.rounded-6{border-radius:6px}.rounded-8{border-radius:8px}.rounded-10{border-radius:10px}.rounded-12{border-radius:12px}.rounded-20{border-radius:20px}.rounded-24{border-radius:24px}.rounded-50{border-radius:50%}.cursor-pointer{cursor:pointer}.overflow-hidden{overflow:hidden}.resize-vertical{resize:vertical}.box-sizing-border{box-sizing:border-box}.border-none{border:none!important}.mb-16px{margin-bottom:var(--cc-sf-grid-gap, 16px)!important}.c-DC2626{color:var(--cc-sf-label-required-color, #DC2626)!important}.ml-0-125rem{margin-left:.125rem!important}.fs-0-875rem{font-size:.875rem!important}.c-111827{color:var(--cc-sf-label-color, #111827)!important}.br-7px{border-radius:var(--cc-sf-input-radius, 7px)!important}.c-6B7280{color:var(--cc-sf-hint-color, #6B7280)!important}.fs-0-75rem{font-size:var(--cc-sf-error-text-size, .75rem)!important}.b-none{background:none!important}.p-32px-24px{padding:32px 24px!important}.us-none{-webkit-user-select:none!important;user-select:none!important}.c-1E293B{color:var(--cc-sf-label-color, #1E293B)!important}.c-3B82F6{color:var(--cc-sf-chip-selected-bg, #3B82F6)!important}.fs-0-78rem{font-size:.78rem!important}.p-10px-14px{padding:10px 14px!important}.fs-0-85rem{font-size:.85rem!important}.fs-0-72rem{font-size:.72rem!important}.c-94A3B8{color:#94a3b8!important}.p-4px{padding:4px!important}.br-8px{border-radius:var(--cc-sf-input-radius, 8px)!important}.bc-F3F4F6{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.br-none{border-right:none!important}.bl-none{border-left:none!important}.pe-none{pointer-events:none!important}.fs-1-1rem{font-size:1.1rem!important}.c-9CA3AF{color:var(--cc-sf-hint-color, #9CA3AF)!important}.pl-2-4rem{padding-left:2.4rem!important}.fs-0-8125rem{font-size:.8125rem!important}.ls-none{list-style:none!important}.br-12px{border-radius:var(--mu-carousel-radius, 12px)!important}.b-FFFAF1{background:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.fs-18px{font-size:18px!important}.b-FEF2F2{background:var(--cc-sf-error-bg, #FEF2F2)!important}.bc-DC2626{border-color:var(--cc-sf-error-border, #DC2626)!important}.c-202124{color:var(--cc-sf-label-color, #202124)!important}.fs-18px{font-size:var(--cc-sf-label-size, 18px)!important}.mb-0-5rem{margin-bottom:.5rem!important}.pt-0-625rem{padding-top:var(--cc-sf-input-padding-y, .625rem)!important}.pb-0-625rem{padding-bottom:var(--cc-sf-input-padding-y, .625rem)!important}.pl-16px{padding-left:var(--cc-sf-input-padding-x, 16px)!important}.pr-16px{padding-right:var(--cc-sf-input-padding-x, 16px)!important}.bc-ffffff{background-color:var(--cc-sf-section-bg, #ffffff)!important}.b-1px-solid-D1D5DB{border:1px solid var(--cc-sf-input-border, #D1D5DB)!important}.fs-0-75rem{font-size:.75rem!important}.c-1F2937{color:var(--cc-sf-section-label-color, #1F2937)!important}.p-6px-14px{padding:var(--cc-sf-chip-padding, 6px 14px)!important}.b-ffffff{background:var(--loc-suggestion-bg, #ffffff)!important}.c-374151{color:var(--cc-sf-label-color, #374151)!important}.br-20px{border-radius:var(--cc-sf-chip-radius, 20px)!important}.fs-0-875rem{font-size:var(--cc-sf-btn-font-size, .875rem)!important}.bc-D1D5DB{background-color:var(--cc-sf-switch-track-off, #D1D5DB)!important}.pr-2-75rem{padding-right:2.75rem!important}.p-0-25rem{padding:.25rem!important}.p-0-625rem-0-875rem{padding:var(--cc-sf-generated-padding, .625rem .875rem)!important}.b-F3F4F6{background:var(--cc-sf-generated-bg, #F3F4F6)!important}.b-1px-solid-E5E7EB{border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.br-8px{border-radius:var(--cc-sf-uploaded-item-radius, 8px)!important}.c-6B7280{color:var(--ms-desc-color, #6B7280)!important}.mb-20px{margin-bottom:var(--cc-sf-section-gap, 20px)!important}.br-10px{border-radius:var(--cc-sf-input-radius, 10px)!important}.p-20px{padding:var(--cc-sf-section-padding, 20px)!important}.fs-1rem{font-size:1rem!important}.m-0-0-16px-0{margin:0 0 16px!important}.bb-2px-solid-E5E7EB{border-bottom:var(--cc-sf-section-label-border, 2px solid #E5E7EB)!important}.p-16px{padding:var(--cc-sf-instance-padding, 16px)!important}.b-F9FAFB{background:var(--loc-tba-bg, #F9FAFB)!important}.bb-1px-dashed-D1D5DB{border-bottom:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)!important}.c-4B5563{color:var(--cc-sf-instance-num-color, #4B5563)!important}.fs-0-8125rem{font-size:var(--cc-sf-hint-size, .8125rem)!important}.pb-0{padding-bottom:0!important}.p-18px-24px{padding:18px 24px!important}.c-111827{color:var(--ms-title-color, #111827)!important}.bt-1px-solid-E5E7EB{border-top:1px solid #E5E7EB!important}.p-4px-10px{padding:4px 10px!important}.b-FFF5F5{background:var(--cc-sf-btn-remove-bg, #FFF5F5)!important}.c-E53E3E{color:var(--loc-delete-color, #E53E3E)!important}.b-1px-solid-FED7D7{border:var(--cc-sf-btn-remove-border, 1px solid #FED7D7)!important}.br-4px{border-radius:var(--cc-sf-btn-remove-radius, 4px)!important}.p-8px-16px{padding:8px 16px!important}.b-transparent{background:var(--cc-sf-btn-add-bg, transparent)!important}.c-3B82F6{color:var(--cc-sf-input-focus-border, #3B82F6)!important}.b-1px-dashed-CBD5E1{border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1)!important}.br-6px{border-radius:var(--cc-sf-btn-add-radius, 6px)!important}.b-1-5px-dashed-CBD5E1{border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1)!important}.br-12px{border-radius:var(--cc-sf-dropzone-radius, 12px)!important}.bc-FFFAF1{background-color:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.c-94A3B8{color:var(--cc-sf-uploaded-remove-color, #94A3B8)!important}.fs-0-9rem{font-size:var(--cc-sf-input-font-size, .9rem)!important}.c-64748B{color:var(--cc-sf-dropzone-hint-color, #64748B)!important}.b-1px-solid-E2E8F0{border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0)!important}.b-2px-solid-E2E8F0{border:2px solid #E2E8F0!important}.pr-3-5rem{padding-right:3.5rem!important}.p-0-0-875rem{padding:0 .875rem!important}.bc-FFFFFF{background-color:var(--cc-sf-input-bg, #FFFFFF)!important}.b-1-5px-solid-D1D5DB{border:var(--cc-sf-input-border, 1.5px solid #D1D5DB)!important}.mb-0-75rem{margin-bottom:.75rem!important}.mt-6px{margin-top:6px!important}.pr-2-4rem{padding-right:2.4rem!important}.p-0-2rem{padding:.2rem!important}.fs-1-35rem{font-size:1.35rem!important}.p-4px-12px{padding:4px 12px!important}.b-111827{background:var(--cc-sf-label-color, #111827)!important}.b-2px-dashed-CBD5E1{border:2px dashed var(--cc-sf-dropzone-border, #CBD5E1)!important}.fs-52px{font-size:52px!important}.p-12px-16px{padding:12px 16px!important}.bb-1px-solid-F3F4F6{border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)!important}.b-0F172A{background:var(--mu-carousel-bg, #0F172A)!important}.b-3px-solid-rgba-255-255-255-0-15{border:3px solid rgba(255,255,255,.15)!important}.b-rgba-255-255-255-0-85{background:#ffffffd9!important}.b-rgba-0-0-0-0-55{background:#0000008c!important}.b-rgba-255-255-255-0-45{background:#ffffff73!important}.pb-4px{padding-bottom:4px!important}.b-2px-solid-transparent{border:2px solid transparent!important}.b-E2E8F0{background:var(--mu-thumb-bg, #E2E8F0)!important}.b-1E293B{background:#1e293b!important}.c-EF4444{color:#ef4444!important}.b-rgba-0-0-0-0-5{background:#00000080!important}.br-16px{border-radius:var(--mu-modal-radius, 16px)!important}.p-24px-28px{padding:24px 28px!important}.bb-1px-solid-E5E7EB{border-bottom:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.fs-1-25rem{font-size:1.25rem!important}.p-48px-24px{padding:48px 24px!important}.b-3px-solid-E2E8F0{border:3px solid #E2E8F0!important}.p-16px-24px{padding:16px 24px!important}.p-28px{padding:28px!important}.b-3px-solid-transparent{border:3px solid transparent!important}.b-rgba-59-130-246-0-12{background:#3b82f61f!important}.p-20px-28px{padding:20px 28px!important}.c-1A56DB{color:var(--loc-add-color, #1A56DB)!important}.b-1px-dashed-D1D5DB{border:1px dashed var(--cc-sf-input-disabled-border, #D1D5DB)!important}.fs-40px{font-size:40px!important}.c-9CA3AF{color:var(--loc-tba-icon-color, #9CA3AF)!important}.form-field{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)!important}:host{--cc-sf-input-border: #D1D5DB;--cc-sf-input-bg: #ffffff;--cc-sf-input-radius: 9px;--cc-sf-input-height: 44px;--cc-sf-label-color: #111827;--cc-sf-hint-color: #9CA3AF;--cc-sf-error-border: #EF4444;--cc-sf-error-bg: #FFF5F5;--cc-sf-accent-color: #6366F1;--cc-sf-input-focus-border: #6366F1;--cc-sf-input-hover-border: #A5B4FC;--cc-sf-input-placeholder: #C4C9D4;--cc-sf-input-disabled-bg: #F8F9FB;--cc-sf-input-disabled-border: #E5E7EB;--cc-sf-switch-track-on: #6366F1;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-thumb: #ffffff;--cc-sf-selected-color: #6366F1}.form-row{gap:var(--cc-sf-grid-gap, 16px)}.form-row.horizontal{display:flex;flex-direction:row}.form-row.horizontal>*{flex:1}.form-row:not(.horizontal){flex-direction:column}.form-row.grid-row{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.form-row.grid-row{grid-template-columns:1fr}.form-row.grid-row .row-field{grid-column:span 12!important}}.field-label{font-size:.75rem;font-weight:600;line-height:1;letter-spacing:.04em;text-transform:uppercase;color:#6b7280}.field-input,input.matInput,.mat-mdc-input-element{display:block;width:100%;height:var(--cc-sf-input-height)!important;padding:0 14px!important;font-family:inherit;font-size:.9rem;color:var(--cc-sf-label-color);background-color:var(--cc-sf-input-bg)!important;border:1.5px solid var(--cc-sf-input-border)!important;border-radius:var(--cc-sf-input-radius)!important;box-sizing:border-box;box-shadow:0 1px 2px #0000000a!important;transition:all .2s cubic-bezier(.4,0,.2,1)}.field-input::placeholder,input.matInput::placeholder,.mat-mdc-input-element::placeholder{font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder)}.field-input{opacity:var(--cc-sf-input-opacity, 1);line-height:var(--cc-sf-input-line-height, 1.5);transition:var(--cc-sf-input-transition, all .2s ease)}.field-input::placeholder{font-weight:var(--cc-sf-placeholder-weight, 400);font-size:var(--cc-sf-placeholder-size, 14px);line-height:var(--cc-sf-placeholder-line-height, 100%);color:var(--cc-sf-input-placeholder)}.field-input:hover:not(:disabled):not([readonly]){border-color:var(--cc-sf-input-hover-border)!important;box-shadow:0 1px 4px #6366f114!important}.field-input:focus{outline:none;border-color:var(--cc-sf-input-focus-border)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important;background-color:#fefeff!important}.field-input:disabled,.field-input[readonly]{background-color:var(--cc-sf-input-disabled-bg)!important;color:#9ca3af!important;cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important;box-shadow:none!important}.field-input.is-invalid{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)!important}.field-input.is-invalid:focus{box-shadow:0 0 0 3px #ef44441f,0 1px 4px #ef44441a!important}.field-input.textarea{resize:vertical;min-height:100px;height:auto;padding:12px 16px!important}input[type=time].time-input{cursor:pointer}input[type=time].time-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.7;filter:invert(30%)}input[type=time].time-input::-webkit-calendar-picker-indicator:hover{opacity:1}select.field-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}select.field-input:disabled{cursor:not-allowed}.multi-select-wrapper{position:relative}.multi-select-wrapper .multi-select-trigger{min-height:var(--cc-sf-input-height, 44px);height:auto;-webkit-user-select:none;user-select:none}.multi-select-wrapper .multi-select-trigger.ms-open{border-color:var(--cc-sf-input-focus-border, #6366F1)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important}.multi-select-wrapper .multi-select-trigger .multi-select-value{flex:1;color:var(--cc-sf-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.multi-select-wrapper .multi-select-trigger .multi-select-placeholder{flex:1;font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder, #C4C9D4)}.multi-select-wrapper .multi-select-trigger .multi-select-arrow{font-size:20px;width:20px;height:20px;line-height:20px;color:#6b7280;flex-shrink:0}.multi-select-wrapper .multi-select-panel{position:absolute;top:calc(100% + 4px);left:0;right:0;background:#fff;border:1.5px solid var(--cc-sf-input-border, #D1D5DB);border-radius:var(--cc-sf-input-radius, 9px);box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f;z-index:1050;max-height:240px;overflow-y:auto}.multi-select-wrapper .multi-select-panel::-webkit-scrollbar{width:4px}.multi-select-wrapper .multi-select-panel::-webkit-scrollbar-thumb{background:#d1d5db;border-radius:2px}.multi-select-wrapper .multi-select-option{padding:8px 12px;border-bottom:1px solid #F3F4F6;transition:background .1s}.multi-select-wrapper .multi-select-option:last-of-type{border-bottom:none}.multi-select-wrapper .multi-select-option:hover{background:#f9fafb}.multi-select-wrapper .multi-select-option input[type=checkbox]{flex-shrink:0;cursor:pointer;accent-color:var(--cc-sf-selected-color, #6366F1);width:15px;height:15px}.multi-select-wrapper .multi-select-empty{padding:12px;text-align:center}.multi-select-wrapper.is-invalid .multi-select-trigger{border-color:var(--cc-sf-error-border, #EF4444)!important;background-color:var(--cc-sf-error-bg, #FFF5F5)!important}.char-count-hint{font-style:normal;line-height:100%;letter-spacing:.02em;margin-top:.4rem}.radio-group.layout-column,.checkbox-group.layout-column{display:grid!important;grid-template-columns:repeat(12,1fr);gap:16px;width:100%}.radio-group.layout-row,.checkbox-group.layout-row{flex-direction:column!important;gap:12px;width:100%}.radio-label input,.checkbox-label input{cursor:pointer;accent-color:var(--cc-sf-chip-selected-bg, #F05A28)}.radio-label.card-item,.checkbox-label.card-item{display:flex!important;flex-direction:row-reverse!important;justify-content:space-between!important;align-items:center!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB);border-radius:12px;padding:16px 20px;box-sizing:border-box;transition:all .2s ease;background:var(--cc-sf-input-bg, #ffffff);margin-bottom:0}.radio-label.card-item input,.checkbox-label.card-item input{margin-left:16px}.radio-label.card-item.selected,.checkbox-label.card-item.selected{border-color:var(--cc-sf-selected-color);background-color:#f05a280d}.radio-label.card-item .option-content .label-text,.checkbox-label.card-item .option-content .label-text,.checkbox-single .checkbox-label{font-weight:var(--cc-sf-label-weight, 500)}.chip-label{transition:var(--cc-sf-input-transition, all .2s ease)}.chip-label:hover{background:var(--cc-sf-chip-hover-bg, #F3F4F6)}.chip-label.selected{background:var(--cc-sf-selected-color);color:var(--cc-sf-chip-selected-color, #ffffff);border-color:var(--cc-sf-selected-color)}.switch{width:50px;height:24px;display:inline-block}.switch input{opacity:0;width:0;height:0;position:absolute}.switch input:checked+.slider{background-color:var(--cc-sf-switch-track-on)!important}.switch input:checked+.slider:before{transform:translate(26px)}.switch .slider{inset:0;transition:.4s;background-color:var(--cc-sf-switch-track-off);border-radius:24px}.switch .slider:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:var(--cc-sf-switch-thumb);transition:.4s;border-radius:50%}.rating-group .star{transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star mat-icon{font-size:var(--cc-sf-star-size, 28px);width:var(--cc-sf-star-size, 28px);height:var(--cc-sf-star-size, 28px);line-height:var(--cc-sf-star-size, 28px);color:var(--cc-sf-star-empty, #D1D5DB);transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star.filled mat-icon,.rating-group .star.half mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.rating-group .star:hover mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.password-wrapper .password-toggle{right:.625rem;top:50%;transform:translateY(-50%);line-height:1;transition:color var(--cc-sf-input-transition, .2s ease)}.password-wrapper .password-toggle mat-icon.eye-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem}.password-wrapper .password-toggle:hover{color:var(--cc-sf-label-color, #374151)}.password-wrapper .password-toggle:focus{outline:none}.group-section-wrapper .group-label{font-size:var(--cc-sf-section-label-size, 1rem);font-weight:var(--cc-sf-section-label-weight, 600);color:var(--cc-sf-section-label-color, #1F2937);margin:0 0 16px;padding-left:12px;padding-top:2px;padding-bottom:2px;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);line-height:1.4}.group-section-wrapper .group-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media(max-width:640px){.group-section-wrapper .group-fields.sf-grid{grid-template-columns:1fr}.group-section-wrapper .group-fields.sf-grid .sf-col{grid-column:span 12!important}}.group-section-wrapper .group-accordion-instance{border:var(--cc-sf-instance-border, 1px solid #E5E7EB);border-radius:var(--cc-sf-section-border-radius-inner, 8px);margin-bottom:8px;overflow:hidden;transition:border-color .2s ease}.group-section-wrapper .group-accordion-instance:last-of-type{margin-bottom:0}.group-section-wrapper .group-accordion-instance .group-accordion-header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px;background:var(--cc-sf-repeater-accordion-header-bg, #F9FAFB);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header:hover{background:var(--cc-sf-repeater-accordion-active-bg, #EFF6FF)}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-badge{width:22px;height:22px;border-radius:50%;background:var(--cc-sf-repeater-badge-bg, #E5E7EB);color:var(--cc-sf-repeater-badge-color, #374151);font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-title{font-size:var(--cc-sf-instance-num-size, .8125rem);font-weight:600;color:var(--cc-sf-repeater-accordion-header-color, #1F2937)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:var(--cc-sf-btn-remove-color, #E53E3E);padding:4px;border-radius:4px;line-height:1;display:flex;align-items:center;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:var(--cc-sf-instance-num-color, #4B5563)}.group-section-wrapper .group-accordion-instance .group-accordion-body{padding:var(--cc-sf-instance-padding, 16px);background:var(--cc-sf-instance-bg, #F9FAFB);border-top:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)}.group-section-wrapper .btn-add-group{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:10px 20px;margin-top:12px;background:var(--cc-sf-btn-add-bg, transparent);color:var(--cc-sf-btn-add-color, #3B82F6);border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1);border-radius:var(--cc-sf-btn-add-radius, 6px);cursor:pointer;font-family:inherit;font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.group-section-wrapper .btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.group-section-wrapper .group-instance:last-child{margin-bottom:0}.group-section-wrapper.multi-save-active{border:none;box-shadow:none;padding:0;background:transparent}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button{color:var(--ms-btn-add-color, #3B82F6);font-weight:600;font-size:.875rem;padding:8px 12px}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button:hover{color:var(--ms-btn-add-hover, #2563EB);background-color:var(--cc-sf-btn-add-hover-bg, #EFF6FF)}.group-section-wrapper.multi-save-active .group-instance.is-card{cursor:pointer;transition:all .2s ease-in-out}.group-section-wrapper.multi-save-active .group-instance.is-card:hover{box-shadow:var(--ms-card-shadow-hover, 0 8px 24px rgba(0, 0, 0, .08));border-color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-title{white-space:nowrap;text-overflow:ellipsis}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-desc{line-height:1.4;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view.is-expanded .card-content .card-desc{-webkit-line-clamp:unset;line-clamp:unset}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon{font-size:22px;width:22px;height:22px;color:var(--cc-sf-hint-color, #9CA3AF);transition:color .2s}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-delete:hover{color:var(--cc-sf-error-border, #DC2626)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-edit:hover{color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-expand{color:var(--cc-sf-input-disabled-border, #E5E7EB)}.btn-remove{transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-remove mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.btn-remove:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.btn-add-group{font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.upload-drop-zone{background-color:var(--cc-sf-dropzone-bg, #F8FAFC);border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1);border-radius:var(--cc-sf-dropzone-radius, 12px);transition:background-color .2s ease,border-color .2s ease}.upload-drop-zone:hover{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-hover-border, #93C5FD)}.upload-drop-zone.drag-over{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-over-border, #3B82F6);box-shadow:var(--cc-sf-dropzone-over-shadow, 0 0 0 4px rgba(59, 130, 246, .12))}.upload-drop-zone.is-invalid{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.upload-icon-wrap .dropzone-icon-pill{width:52px;height:52px;border-radius:50%;background:var(--cc-sf-dropzone-icon-bg, rgba(59, 130, 246, .1))}.upload-icon-wrap mat-icon.upload-cloud-icon{font-size:28px;width:28px;height:28px;line-height:28px;color:var(--cc-sf-accent-color, #3B82F6)}.upload-main-text{color:var(--cc-sf-label-color, #1E293B)}.upload-sub-text{color:var(--cc-sf-hint-color, #64748B)}.upload-link{color:var(--cc-sf-dropzone-link-color, #3B82F6);font-weight:500}.upload-formats{color:var(--cc-sf-dropzone-link-color, #3B82F6)}.upload-size-badge{display:inline-block;padding:2px 8px;border-radius:20px;background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-hint-color, #6B7280);font-weight:500}.uploaded-item{background:var(--cc-sf-uploaded-item-bg, #ffffff);border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0);border-radius:var(--cc-sf-uploaded-item-radius, 8px);transition:box-shadow .15s ease}.uploaded-item:hover{box-shadow:0 2px 6px #0000000f}.uploaded-item mat-icon.file-type-icon{font-size:20px;width:20px;height:20px;line-height:20px;flex-shrink:0;color:var(--cc-sf-hint-color, #64748B)}.uploaded-item .file-thumb{width:36px;height:36px;object-fit:cover;flex-shrink:0}.uploaded-item .file-info{min-width:0;gap:2px}.uploaded-item .file-info .file-name{white-space:nowrap;text-overflow:ellipsis}.uploaded-item .file-remove-btn{flex-shrink:0;width:32px;height:32px;background:none;border:none;cursor:pointer;color:var(--cc-sf-uploaded-remove-color, #94A3B8);padding:0;display:flex;align-items:center;justify-content:center;transition:color .15s ease,background .15s ease}.uploaded-item .file-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.uploaded-item .file-remove-btn:hover:not(:disabled){color:var(--cc-sf-uploaded-remove-hover-color, #DC2626);background:var(--cc-sf-uploaded-remove-hover-bg, #FEF2F2)}.uploaded-item .file-remove-btn:disabled{opacity:.4;cursor:not-allowed}.uploaded-item.uploading{background:var(--cc-sf-uploaded-uploading-bg, #F8FAFC);border-color:var(--cc-sf-uploaded-uploading-border, #CBD5E1);opacity:.85}.upload-spinner{width:20px;height:20px;flex-shrink:0;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}@keyframes cc-spin{to{transform:rotate(360deg)}}.uploading-label{font-style:italic}.input-group{align-items:stretch}.input-group .field-input{flex:1;width:auto}.input-prefix+.input-group .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.input-group .field-input:has(+.input-suffix){border-top-right-radius:0;border-bottom-right-radius:0}.input-group .field-input.has-icon-right{padding-right:3rem}.input-group.readonly .field-input{cursor:default}.input-prefix,.input-suffix{display:flex!important;align-items:center;white-space:nowrap;padding:0 14px;background-color:var(--cc-sf-input-disabled-bg);border:1px solid var(--cc-sf-input-border);font-size:.875rem;color:var(--cc-sf-hint-color);-webkit-user-select:none;user-select:none}.input-prefix{border-right:none;border-top-left-radius:var(--cc-sf-input-radius, 8px);border-bottom-left-radius:var(--cc-sf-input-radius, 8px)}.input-suffix{border-left:none;border-top-right-radius:var(--cc-sf-input-radius, 8px);border-bottom-right-radius:var(--cc-sf-input-radius, 8px)}.readonly-icons{right:.875rem;top:50%;transform:translateY(-50%)}.readonly-icons mat-icon.lock-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem;opacity:.5;color:var(--cc-sf-hint-color, #6B7280)}.suffix-action-icons{right:.875rem;top:50%;transform:translateY(-50%);z-index:1;pointer-events:auto}.suffix-action-icons mat-icon.suffix-action-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem;color:var(--cc-sf-hint-color, #6B7280);cursor:pointer;transition:color .2s ease,transform .15s ease}.suffix-action-icons mat-icon.suffix-action-icon:hover{color:var(--cc-sf-text-color, #202124);transform:scale(1.15)}.date-icon-wrapper{right:.5rem;top:50%;transform:translateY(-50%);pointer-events:auto}.date-icon-wrapper .mat-icon-button{width:32px;height:32px;line-height:32px}.subfields-group-wrapper .subfields-row{transition:all .2s ease}.subfields-group-wrapper .subfields-row.is-invalid .subfield-item ::ng-deep .field-input{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.subfields-group-wrapper .subfields-row .subfield-item{min-width:0}.subfields-group-wrapper .subfields-row .subfield-item ::ng-deep .field-label{font-size:.75rem!important;margin-bottom:4px!important;font-weight:500!important;color:var(--cc-sf-hint-color, #6B7280)!important}.subfields-group-wrapper .subfields-row .subfield-separator{font-weight:700}.autocomplete-wrapper .ac-input{padding-left:40px!important}.autocomplete-wrapper .ac-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1;transition:color var(--cc-sf-input-transition, .2s ease)}.autocomplete-wrapper .ac-clear-btn{right:.6rem;transition:color .15s ease,background .15s ease}.autocomplete-wrapper .ac-clear-btn mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.autocomplete-wrapper .ac-clear-btn:hover{color:var(--cc-sf-label-color, #374151);background:var(--cc-sf-input-disabled-bg, #F3F4F6)}.autocomplete-wrapper .ac-clear-btn:focus{outline:none}.autocomplete-wrapper:focus-within .ac-search-icon{color:var(--cc-sf-accent-color, #3B82F6)}.autocomplete-wrapper.is-invalid .ac-input{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)}.autocomplete-wrapper.readonly .ac-input{background-color:var(--cc-sf-input-disabled-bg);color:var(--cc-sf-input-disabled-color, #6B7280);cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.ac-no-results{font-style:italic}::ng-deep .mat-mdc-autocomplete-panel,::ng-deep .mat-autocomplete-panel{background:var(--cc-sf-input-bg, #ffffff)!important;border-radius:var(--cc-sf-input-radius, 9px)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important;box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f!important;padding:4px 0!important;min-width:200px}::ng-deep .mat-mdc-autocomplete-panel mat-option,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option,::ng-deep .mat-mdc-autocomplete-panel .mat-option,::ng-deep .mat-autocomplete-panel mat-option,::ng-deep .mat-autocomplete-panel .mat-mdc-option,::ng-deep .mat-autocomplete-panel .mat-option{background:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #111827)!important;font-size:.875rem!important;padding:10px 16px!important;min-height:40px!important;line-height:1.4!important;display:flex!important;flex-direction:column!important;align-items:flex-start!important;transition:background var(--cc-sf-input-transition, .2s ease)!important}::ng-deep .mat-mdc-autocomplete-panel mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-mdc-autocomplete-panel .mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel .mat-mdc-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel .mat-option:hover:not(.mat-option-disabled):not([disabled]){background:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}::ng-deep .mat-mdc-autocomplete-panel mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel mat-option.mdc-list-item--selected,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mdc-list-item--selected,::ng-deep .mat-mdc-autocomplete-panel .mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel .mat-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel mat-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel .mat-mdc-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel .mat-mdc-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel .mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel .mat-option.mdc-list-item--selected{background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)!important;color:var(--cc-sf-selected-color, #6366F1)!important;font-weight:600!important}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-option-label,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-option-label,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-option-label,::ng-deep .mat-autocomplete-panel mat-option .ac-option-label,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-option-label,::ng-deep .mat-autocomplete-panel .mat-option .ac-option-label{font-weight:500;color:var(--cc-sf-label-color, #111827);font-size:.875rem;display:block}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-display-fields,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-display-fields,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-display-fields,::ng-deep .mat-autocomplete-panel mat-option .ac-display-fields,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-display-fields,::ng-deep .mat-autocomplete-panel .mat-option .ac-display-fields{align-items:center;line-height:1}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-item,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-item,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-item,::ng-deep .mat-autocomplete-panel mat-option .ac-df-item,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-item,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-item{display:inline-flex;align-items:center;font-size:.72rem;color:var(--cc-sf-hint-color, #6B7280);gap:3px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-chip,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-chip,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-chip,::ng-deep .mat-autocomplete-panel mat-option .ac-df-chip,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-chip,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-chip{background:var(--cc-sf-input-disabled-bg, #F3F4F6);border-radius:4px;padding:2px 6px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-text,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-text,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-text,::ng-deep .mat-autocomplete-panel mat-option .ac-df-text,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-text,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-text{color:var(--cc-sf-hint-color, #6B7280)}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-avatar,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-avatar,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel mat-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-avatar{width:24px;height:24px;border-radius:50%;object-fit:cover;border:1px solid var(--cc-sf-input-border, #D1D5DB);vertical-align:middle}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-label,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-label,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-label,::ng-deep .mat-autocomplete-panel mat-option .ac-df-label,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-label,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-label{font-weight:600;color:var(--cc-sf-hint-color, #9CA3AF);margin-right:2px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-icon,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-icon,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-icon,::ng-deep .mat-autocomplete-panel mat-option .ac-df-icon,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-icon,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-icon{font-size:11px;width:11px;height:11px;line-height:11px;color:var(--cc-sf-hint-color, #9CA3AF);flex-shrink:0}.mu-layout{grid-template-columns:1fr 1fr;gap:32px}@media(max-width:768px){.mu-layout{grid-template-columns:1fr}}.mu-title{font-weight:700;line-height:1.3}.mu-badge{white-space:nowrap;flex-shrink:0}.mu-description{line-height:1.6}.mu-feature-item .mu-check{width:16px;height:16px;line-height:16px;flex-shrink:0}.mu-right{min-height:260px}.mu-right-empty{min-height:250px;max-width:400px;box-shadow:0 2px 10px #0000000d;transition:box-shadow .2s ease}.mu-right-empty:hover{cursor:pointer;box-shadow:0 4px 16px #0000001a}.mu-right-empty .mu-right-empty-icon{width:52px;height:52px;line-height:52px;opacity:.3}.mu-right-empty p{margin:0;font-size:.85rem}.media-add-container{display:inline-block}.media-add-container ::ng-deep button{display:flex;align-items:center;gap:6px}.media-add-container ::ng-deep button .menu-chevron{width:18px;height:18px;line-height:18px;transition:transform .2s ease}.media-dropdown{top:calc(100% + 6px);left:0;z-index:200;min-width:240px;box-shadow:var(--mu-dropdown-shadow, 0 8px 32px rgba(0, 0, 0, .12));animation:mu-fade-in .15s ease}@keyframes mu-fade-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.media-dropdown-item{transition:background .15s ease}.media-dropdown-item:last-child{border-bottom:none}.media-dropdown-item:hover{background:var(--cc-sf-dropzone-hover-bg, #F0F9FF)}.media-drop-icon{width:36px;height:36px;flex-shrink:0}.media-drop-icon mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.media-drop-icon--video{background:var(--mu-icon-video-bg, #FFF0F0);color:var(--mu-icon-video-color, #EF4444)}.media-drop-icon--device{background:var(--mu-icon-device-bg, #EFF6FF);color:var(--mu-icon-device-color, #3B82F6)}.media-drop-icon--library{background:var(--mu-icon-library-bg, #F0FDF4);color:var(--mu-icon-library-color, #22C55E)}.media-drop-text{gap:2px}.youtube-input-panel{animation:mu-fade-in .18s ease}.youtube-panel-label mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:var(--mu-icon-video-color, #EF4444)}.youtube-input-row{align-items:stretch}.media-menu-backdrop{position:fixed;inset:0;z-index:100}.media-upload-status{animation:mu-fade-in .2s ease}.media-upload-status .status-icon{width:18px;height:18px;line-height:18px}.media-carousel-main{max-width:400px;height:var(--mu-carousel-height, 250px)}.carousel-viewer{inset:0}.carousel-viewer .carousel-image{object-fit:cover}.carousel-viewer .carousel-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.carousel-nav{top:50%;transform:translateY(-50%);z-index:10;width:40px;height:40px;box-shadow:0 2px 8px #0003;transition:background .2s ease,opacity .2s ease;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.carousel-nav mat-icon{font-size:22px;width:22px;height:22px;line-height:22px;color:#1e293b}.carousel-nav:hover:not(:disabled){background:#fff}.carousel-nav:disabled{opacity:.3;cursor:not-allowed}.carousel-nav--prev{left:12px}.carousel-nav--next{right:12px}.carousel-remove-btn{top:10px;right:10px;z-index:10;width:32px;height:32px;transition:background .2s ease}.carousel-remove-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:#fff}.carousel-remove-btn:hover:not(:disabled){background:#dc2626d9}.carousel-remove-btn:disabled{opacity:.4;cursor:not-allowed}.carousel-dots{bottom:10px;left:50%;transform:translate(-50%);z-index:10}.carousel-dot{width:8px;height:8px;transition:background .2s ease,transform .2s ease}.carousel-dot.active{background:#fff;transform:scale(1.3)}.media-thumbnail-strip{max-width:400px;overflow-x:auto}.media-thumbnail-strip::-webkit-scrollbar{height:4px}.media-thumbnail-strip::-webkit-scrollbar-thumb{background:var(--cc-sf-input-disabled-border, #D1D5DB);border-radius:2px}.media-thumb{flex-shrink:0;width:72px;height:52px;transition:border-color .2s ease,transform .15s ease}.media-thumb.active{border-color:var(--mu-thumb-active-border, var(--cc-sf-accent-color, #3B82F6));transform:scale(1.04)}.media-thumb:hover:not(.active){border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.media-thumb .thumb-img{object-fit:cover}.media-thumb .thumb-yt-placeholder mat-icon{font-size:28px;width:28px;height:28px;line-height:28px}.media-thumb .thumb-uploading .thumb-spinner{width:20px;height:20px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.media-library-portal-host{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;visibility:hidden;opacity:0;pointer-events:none;transition:opacity .2s ease,visibility .2s ease}.media-library-portal-host.is-open{visibility:visible;opacity:1;pointer-events:auto}.media-library-portal-host.is-open .media-library-modal{transform:scale(1) translateY(0)}.media-library-overlay{position:absolute;inset:0;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.media-library-modal{position:relative;z-index:10000;width:90vw;max-width:900px;max-height:90vh;background:#fff;border-radius:16px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;transform:scale(.95) translateY(10px);transition:transform .3s cubic-bezier(.175,.885,.32,1.275)}.library-modal-header{flex-shrink:0}.library-modal-title{font-weight:700}.library-modal-subtitle{line-height:1.5;max-width:600px}.library-close-btn{width:32px;height:32px;transition:background .15s ease,color .15s ease}.library-close-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-close-btn:hover{background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-label-color, #374151)}.library-loading mat-icon,.library-empty mat-icon{font-size:40px;width:40px;height:40px;line-height:40px;opacity:.5}.lib-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.library-error{flex-shrink:0}.library-error mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-grid{grid-template-columns:repeat(5,1fr);max-height:50vh;overflow-y:auto}.library-grid::-webkit-scrollbar{width:8px}.library-grid::-webkit-scrollbar-track{background:#f1f1f1}.library-grid::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:10px;border:2px solid #F1F1F1}.library-grid-item{aspect-ratio:1/1;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.library-grid-item:hover{transform:translateY(-4px) scale(1.02);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.library-grid-item.selected{border-color:var(--cc-sf-accent-color, #3B82F6)}.library-grid-item.selected .library-grid-img{opacity:.7}.library-grid-item:hover .library-overlay-hover{opacity:1}.library-grid-img{object-fit:cover}.library-overlay-hover{inset:0;opacity:0;transition:opacity .15s ease}.library-check{top:6px;right:6px;width:22px;height:22px;box-shadow:0 1px 4px #00000026}.library-check mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.library-modal-footer{flex-shrink:0}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary{background-color:var(--cc-sf-accent-color, #3B82F6)!important;border-color:var(--cc-sf-accent-color, #3B82F6)!important;color:#fff!important;font-weight:600;padding-left:32px;padding-right:32px}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:hover{background-color:var(--cc-sf-btn-primary-hover-bg, #2563EB)!important}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:disabled{background-color:#93c5fd!important;cursor:not-allowed}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline{font-weight:600;padding-left:24px;padding-right:24px;border-color:#d1d5db;color:#374151}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline:hover{background-color:#f9fafb}.location-subtitle{line-height:1.5}.loc-tab-btn ::ng-deep button{width:100%}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning){background-color:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #000000)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning):hover{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.loc-venue-item{transition:box-shadow .15s ease,border-color .15s ease}.loc-venue-item:hover{box-shadow:0 2px 8px #0000000f;border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.loc-venue-search-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-venue-text{white-space:nowrap;text-overflow:ellipsis}.loc-action-btn{transition:background .15s ease,color .15s ease;flex-shrink:0}.loc-action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.loc-action-btn.loc-delete-btn{color:var(--loc-delete-color, #E53E3E)}.loc-action-btn.loc-delete-btn:hover{background:var(--cc-sf-error-bg, #FEF2F2)}.loc-action-btn.loc-edit-btn{color:var(--cc-sf-hint-color, #9CA3AF)}.loc-action-btn.loc-edit-btn:hover{color:var(--cc-sf-input-focus-border, #3B82F6);background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)}.loc-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1}.loc-suggestions-panel{top:calc(100% + 4px);left:0;right:0;z-index:300;box-shadow:0 8px 24px #0000001a;animation:mu-fade-in .15s ease;max-height:260px;overflow-y:auto}.loc-suggestion-item{transition:background .12s ease}.loc-suggestion-item:hover,.loc-suggestion-item:focus{background:var(--loc-suggestion-hover-bg, #F0F9FF)}.loc-suggestion-item:not(:last-child){border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)}.loc-suggestion-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-suggestion-text{white-space:nowrap;text-overflow:ellipsis}.loc-add-btn{transition:opacity .15s ease}.loc-add-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.loc-add-btn:hover{opacity:.8}.loc-map-container{box-shadow:0 2px 10px #0000000f}.loc-tba-panel{min-height:120px}.loc-tba-icon{width:40px;height:40px;line-height:40px;opacity:.6}.loc-tba-text{line-height:1.6;max-width:360px}.radio-label{display:flex!important}.radio-label .option-content{padding-left:10px}\n"] }]
|
|
2797
|
+
args: [{ selector: 'lib-form-field', standalone: false, template: "<div class=\"form-field mb-16px\" *ngIf=\"isVisible\" [class.has-error]=\"errorMessage\">\r\n\r\n <!-- \u2550\u2550 ROW Layout \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRow\" class=\"form-row grid-row\">\r\n <ng-container *ngFor=\"let child of config.children\">\r\n <div class=\"row-field\" [style.gridColumn]=\"'span ' + getChildColSpan(child)\" *ngIf=\"child.isEnabled !== false\">\r\n <lib-form-field [config]=\"child\" [controller]=\"controller\" [formGroup]=\"formGroup\" [allowMulti]=\"allowMulti\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 allowMulti (repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig?.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\"\r\n [class.multi-save-active]=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n\r\n <!-- Multi-Save: header row with label + top-right Add button -->\r\n <div class=\"multi-save-header d-flex justify-content-between align-items-center mb-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig?.label\">{{ config.sectionConfig!.label }}</h3>\r\n <lib-button [variant]=\"'outline'\" [icon]=\"{type: 'material', value: 'add'}\" (click)=\"addGroupInstance()\"\r\n class=\"btn-add-multi\">\r\n {{ addMultiLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- Standard heading (non-multiSave) -->\r\n <h3 class=\"group-label\"\r\n *ngIf=\"config.sectionConfig?.label && !config.sectionConfig?.multiSaveConfig?.active\">{{\r\n config.sectionConfig!.label }}</h3>\r\n\r\n <!-- \u2500\u2500 Standard (non-multiSave) repeater: accordion instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"!config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-accordion-instance\"\r\n [class.is-expanded]=\"isGroupExpanded(i)\">\r\n\r\n <!-- Accordion header -->\r\n <div class=\"group-accordion-header\" (click)=\"toggleGroupAccordion(i)\"\r\n role=\"button\" [attr.aria-expanded]=\"isGroupExpanded(i)\">\r\n <div class=\"accordion-header-left d-flex align-items-center gap-10\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.sectionConfig!.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right d-flex align-items-center gap-6\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceList.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeGroupInstance(i)\"\r\n aria-label=\"Remove\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isGroupExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body (always mounted so form controls survive collapse) -->\r\n <div class=\"group-accordion-body\" [hidden]=\"!isGroupExpanded(i)\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"instance.rowController\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-group\" (click)=\"addGroupInstance()\">\r\n <mat-icon>add</mat-icon> {{ addLabel }} {{ config.sectionConfig!.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2500\u2500 MultiSave: card instances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <ng-container *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <div *ngFor=\"let instance of instanceList; trackBy: trackByInstanceId; let i = index\"\r\n class=\"group-instance position-relative mb-16 overflow-hidden\"\r\n [class.is-editing]=\"instance.isEditing\"\r\n [class.is-card]=\"!instance.isEditing\">\r\n\r\n <!-- Edit / new form view -->\r\n <div [hidden]=\"!instance.isEditing\">\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig!.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"instance.rowController\" [formGroup]=\"instance.fg\"\r\n [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Save / Cancel -->\r\n <div class=\"group-footer d-flex justify-content-end align-items-center gap-16 p-0-24\"\r\n *ngIf=\"config.sectionConfig?.multiSaveConfig?.active\">\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"multiSaveError\">{{ multiSaveError }}</span>\r\n <div class=\"footer-actions d-flex gap-12\">\r\n <lib-button [variant]=\"'outline'\" (click)=\"cancelGroupInstance(i)\">Cancel</lib-button>\r\n <lib-button [variant]=\"'primary'\" (click)=\"saveGroupInstance(i)\">Save</lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Card view (saved state) -->\r\n <ng-container *ngIf=\"!instance.isEditing\">\r\n <div class=\"card-view d-flex justify-content-between align-items-center p-18px-24px\"\r\n [class.is-expanded]=\"instance.isExpanded\">\r\n <div class=\"card-content flex-1 d-flex flex-column gap-4 overflow-hidden\">\r\n <span class=\"card-title font-weight-600 overflow-hidden fs-1rem c-111827\">{{\r\n instance.fg.get(config.sectionConfig!.multiSaveConfig!.summaryField || '')?.value\r\n || '\u2014' }}</span>\r\n </div>\r\n <div class=\"card-actions d-flex align-items-center gap-16 ml-20\">\r\n <mat-icon class=\"icon-delete\" (click)=\"removeGroupInstance(i, true)\">delete_outline</mat-icon>\r\n <mat-icon class=\"icon-edit\" (click)=\"editGroupInstance(i)\">edit_outline</mat-icon>\r\n <mat-icon class=\"icon-expand\" (click)=\"toggleExpandGroupInstance(i)\">\r\n {{ instance.isExpanded ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- \u2550\u2550 GROUP \u2014 single (non-repeater) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGroup && config.sectionConfig && !config.sectionConfig.allowMulti\"\r\n class=\"group-section-wrapper mb-20px\">\r\n <h3 class=\"group-label\" *ngIf=\"config.sectionConfig.label\">{{ config.sectionConfig.label }}</h3>\r\n <div class=\"group-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.sectionConfig.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\" *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"groupFormGroup\" [allowMulti]=\"false\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Text Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTextField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <textarea *ngIf=\"config.subType === 'LONG'\" class=\"field-input textarea\" [placeholder]=\"config.placeholder || ''\"\r\n [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\" rows=\"4\">\r\n </textarea>\r\n\r\n <!-- Password input with show/hide toggle -->\r\n <div *ngIf=\"config.subType === 'PASSWORD'\" class=\"password-wrapper position-relative d-flex align-items-center\">\r\n <input [type]=\"showPassword ? 'text' : 'password'\" class=\"field-input password-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <button type=\"button\"\r\n class=\"password-toggle position-absolute cursor-pointer d-flex align-items-center justify-content-center b-none border-none c-6B7280 p-0-25rem\"\r\n (click)=\"showPassword = !showPassword\" tabindex=\"-1\"\r\n [attr.aria-label]=\"showPassword ? 'Hide password' : 'Show password'\">\r\n <mat-icon class=\"eye-icon\">{{ showPassword ? 'visibility' : 'visibility_off' }}</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input *ngIf=\"config.subType !== 'LONG' && config.subType !== 'PASSWORD'\"\r\n [type]=\"config.subType === 'EMAIL' ? 'email' : config.subType === 'PHONE' ? 'tel' : 'text'\" class=\"field-input\"\r\n [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\"\r\n [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n\r\n <!-- Suffix Action Icons (clickable) -->\r\n <div class=\"suffix-action-icons position-absolute d-flex gap-8 align-items-center\"\r\n *ngIf=\"config.suffixActionIcons?.length && !config.readonly\">\r\n <mat-icon class=\"suffix-action-icon\"\r\n *ngFor=\"let action of config.suffixActionIcons\"\r\n [style.color]=\"action.color || null\"\r\n [title]=\"action.tooltip || ''\"\r\n (click)=\"onSuffixActionClick(action.actionId)\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Number Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isNumberField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <span class=\"input-prefix br-none\" *ngIf=\"config.prefix\">{{ config.prefix }}</span>\r\n\r\n <input type=\"number\" class=\"field-input\" [placeholder]=\"config.placeholder || ''\" [formControlName]=\"config.name!\"\r\n [min]=\"config.numberConfig?.min ?? null\" [max]=\"config.numberConfig?.max ?? null\"\r\n [step]=\"config.numberConfig?.step || 1\" [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly\">\r\n\r\n <span class=\"input-suffix d-flex align-items-center font-weight-500\" *ngIf=\"config.suffix\">{{ config.suffix\r\n }}</span>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n\r\n <!-- Suffix Action Icons (clickable) -->\r\n <div class=\"suffix-action-icons position-absolute d-flex gap-8 align-items-center\"\r\n *ngIf=\"config.suffixActionIcons?.length && !config.readonly\">\r\n <mat-icon class=\"suffix-action-icon\"\r\n *ngFor=\"let action of config.suffixActionIcons\"\r\n [style.color]=\"action.color || null\"\r\n [title]=\"action.tooltip || ''\"\r\n (click)=\"onSuffixActionClick(action.actionId)\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Date Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDateField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input matInput [matDatepicker]=\"datePicker\" class=\"field-input date-input has-icon-right\"\r\n [formControlName]=\"config.name!\" [min]=\"effectiveMinDate\" [max]=\"config.dateConfig?.maxDate\"\r\n [class.is-invalid]=\"errorMessage\" [placeholder]=\"config.placeholder || ''\"\r\n [readonly]=\"config.readonly || config.dateConfig?.inputReadonly\"\r\n (click)=\"!config.readonly && datePicker.open()\">\r\n <div class=\"date-icon-wrapper position-absolute d-flex align-items-center justify-content-center\"\r\n *ngIf=\"!config.readonly\">\r\n <mat-datepicker-toggle matSuffix [for]=\"datePicker\"></mat-datepicker-toggle>\r\n </div>\r\n <mat-datepicker #datePicker></mat-datepicker>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Time Input \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isTimeField\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"input-group position-relative d-flex w-100\" [class.readonly]=\"config.readonly\">\r\n <input type=\"time\" class=\"field-input time-input\" [formControlName]=\"config.name!\"\r\n [min]=\"effectiveMinTime\" [max]=\"effectiveMaxTime\"\r\n [class.is-invalid]=\"errorMessage\" [readonly]=\"config.readonly || config.timeConfig?.inputReadonly\">\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Autocomplete \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isAutocomplete\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Hidden real control (stores the code value) -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <div class=\"autocomplete-wrapper position-relative d-flex align-items-center w-100\"\r\n [class.is-invalid]=\"errorMessage\" [class.readonly]=\"config.readonly\">\r\n <!-- Search icon -->\r\n <mat-icon class=\"ac-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n\r\n <input class=\"field-input ac-input\" [formControl]=\"autocompleteInputCtrl\" [matAutocomplete]=\"auto\"\r\n [placeholder]=\"config.placeholder || 'Search\u2026'\" [readonly]=\"!!config.readonly\" [class.is-invalid]=\"errorMessage\"\r\n (blur)=\"onAutocompleteClear()\" autocomplete=\"off\">\r\n\r\n <!-- Clear button -->\r\n <button type=\"button\"\r\n class=\"ac-clear-btn position-absolute d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none c-9CA3AF p-0-2rem\"\r\n *ngIf=\"autocompleteInputCtrl.value && !config.readonly\"\r\n (click)=\"autocompleteInputCtrl.setValue(''); updateValue(null)\" tabindex=\"-1\" aria-label=\"Clear\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n\r\n <mat-autocomplete #auto=\"matAutocomplete\" [panelWidth]=\"'auto'\">\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.label\"\r\n (onSelectionChange)=\"onAutocompleteSelected(option)\">\r\n <span class=\"ac-option-label\">{{ option.label }}</span>\r\n\r\n <!-- Dynamic display fields (image / email / phone / text) -->\r\n <div class=\"ac-display-fields d-flex flex-wrap gap-6 mt-2\" *ngIf=\"option['displayMeta']?.length\">\r\n <ng-container *ngFor=\"let field of option['displayMeta']\">\r\n\r\n <!-- Image avatar -->\r\n <span *ngIf=\"field.type === 'image' && field.value\" class=\"ac-df-item ac-df-image\">\r\n <img [src]=\"field.value\" [alt]=\"field.label || 'image'\" class=\"ac-df-avatar\">\r\n </span>\r\n\r\n <!-- Email -->\r\n <span *ngIf=\"field.type === 'email' && field.value\" class=\"ac-df-item ac-df-chip\">\r\n <mat-icon class=\"ac-df-icon\">mail_outline</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n <!-- Phone -->\r\n <span *ngIf=\"field.type === 'phone' && field.value\" class=\"ac-df-item ac-df-chip\" [class]=\"field.className\">\r\n <mat-icon class=\"ac-df-icon\">phone</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n <!-- Custom / Icon-based / Generic Text -->\r\n <span *ngIf=\"field.type !== 'image' && field.type !== 'email' && field.type !== 'phone' && field.value\" \r\n class=\"ac-df-item\" [class.ac-df-chip]=\"!!field.icon\" [class]=\"field.className\">\r\n <mat-icon class=\"ac-df-icon\" *ngIf=\"field.icon\">{{ field.icon }}</mat-icon>\r\n <span *ngIf=\"field.label\" class=\"ac-df-label\">{{ field.label }}</span>\r\n {{ field.value }}\r\n </span>\r\n\r\n </ng-container>\r\n </div>\r\n </mat-option>\r\n <mat-option *ngIf=\"filteredOptions.length === 0\" disabled class=\"ac-no-results fs-0-8125rem c-6B7280\">\r\n No results found\r\n </mat-option>\r\n </mat-autocomplete>\r\n\r\n <div class=\"readonly-icons position-absolute d-flex gap-8 pe-none\" *ngIf=\"config.readonly\">\r\n <mat-icon class=\"lock-icon\">lock</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Dropdown \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isDropdown\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- SINGLE SELECT: native select (default, non-searchable) -->\r\n <select *ngIf=\"config.subType === 'SINGLE' && !isSearchableDropdown\" class=\"field-input\" [formControlName]=\"config.name!\"\r\n [class.is-invalid]=\"errorMessage\">\r\n <option [ngValue]=\"null\" disabled selected>{{ config.placeholder || selectPlaceholderLabel }}</option>\r\n <option *ngFor=\"let option of localOptionList\" [value]=\"option.code\">\r\n {{ option.label }}\r\n </option>\r\n </select>\r\n\r\n <!-- SINGLE SELECT: custom searchable dropdown -->\r\n <div *ngIf=\"config.subType === 'SINGLE' && isSearchableDropdown\" class=\"single-select-wrapper\"\r\n [class.is-invalid]=\"errorMessage\">\r\n\r\n <div class=\"field-input single-select-trigger d-flex align-items-center justify-content-between cursor-pointer\"\r\n [class.ss-open]=\"isSingleDropdownOpen\"\r\n (click)=\"toggleSingleDropdown($event)\">\r\n <span *ngIf=\"singleSelectedLabel\" class=\"single-select-value fs-0-9rem\">\r\n {{ singleSelectedLabel }}\r\n </span>\r\n <span *ngIf=\"!singleSelectedLabel\" class=\"single-select-placeholder\">\r\n {{ config.placeholder || selectPlaceholderLabel }}\r\n </span>\r\n <mat-icon class=\"single-select-arrow\">\r\n {{ isSingleDropdownOpen ? expandLessLabel : expandMoreLabel }}\r\n </mat-icon>\r\n </div>\r\n\r\n <div class=\"single-select-panel\" *ngIf=\"isSingleDropdownOpen\"\r\n (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Search input -->\r\n <div class=\"dropdown-search-wrapper\">\r\n <mat-icon class=\"dropdown-search-icon\">search</mat-icon>\r\n <input type=\"text\" class=\"dropdown-search-input\"\r\n [placeholder]=\"searchPlaceholderLabel\"\r\n [(ngModel)]=\"searchText\" [ngModelOptions]=\"{standalone: true}\"\r\n (input)=\"dropdownSearch$.next(searchText)\"\r\n (click)=\"$event.stopPropagation()\">\r\n <mat-icon *ngIf=\"searchText\" class=\"dropdown-search-clear cursor-pointer\"\r\n (click)=\"searchText = ''; dropdownSearch$.next(''); $event.stopPropagation()\">close</mat-icon>\r\n </div>\r\n\r\n <!-- Options list -->\r\n <div class=\"single-select-options-list\">\r\n <div *ngFor=\"let option of filteredOptionList\"\r\n class=\"single-select-option d-flex align-items-center gap-8 cursor-pointer\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n (click)=\"selectSingleOption(option)\">\r\n <span class=\"fs-0-875rem c-111827\">{{ option.label }}</span>\r\n <mat-icon *ngIf=\"formGroup.get(config.name!)?.value === option.code\" class=\"single-select-check\">check</mat-icon>\r\n </div>\r\n <div *ngIf=\"!filteredOptionList?.length && localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noMatchingOptionsLabel }}\r\n </div>\r\n <div *ngIf=\"!localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noOptionsAvailableLabel }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- MULTIPLE SELECT: custom panel with checkboxes -->\r\n <div *ngIf=\"config.subType === 'MULTIPLE'\" class=\"multi-select-wrapper\"\r\n [class.is-invalid]=\"errorMessage\">\r\n\r\n <div class=\"field-input multi-select-trigger d-flex align-items-center justify-content-between cursor-pointer\"\r\n [class.ms-open]=\"isMultiDropdownOpen\"\r\n (click)=\"toggleMultiDropdown($event)\">\r\n <span *ngIf=\"multiSelectedCount > 0\" class=\"multi-select-value fs-0-9rem\">\r\n {{ multiSelectedCount }} selected\r\n </span>\r\n <span *ngIf=\"multiSelectedCount === 0\" class=\"multi-select-placeholder\">\r\n {{ config.placeholder || selectPlaceholderLabel }}\r\n </span>\r\n <mat-icon class=\"multi-select-arrow\">\r\n {{ isMultiDropdownOpen ? expandLessLabel : expandMoreLabel }}\r\n </mat-icon>\r\n </div>\r\n\r\n <div class=\"multi-select-panel\" *ngIf=\"isMultiDropdownOpen\"\r\n (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Search input (shown only when searchConfig.enabled) -->\r\n <div class=\"dropdown-search-wrapper\" *ngIf=\"isSearchableDropdown\">\r\n <mat-icon class=\"dropdown-search-icon\">search</mat-icon>\r\n <input type=\"text\" class=\"dropdown-search-input\"\r\n [placeholder]=\"searchPlaceholderLabel\"\r\n [(ngModel)]=\"searchText\" [ngModelOptions]=\"{standalone: true}\"\r\n (input)=\"dropdownSearch$.next(searchText)\"\r\n (click)=\"$event.stopPropagation()\">\r\n <mat-icon *ngIf=\"searchText\" class=\"dropdown-search-clear cursor-pointer\"\r\n (click)=\"searchText = ''; dropdownSearch$.next(''); $event.stopPropagation()\">close</mat-icon>\r\n </div>\r\n\r\n <!-- Select All checkbox (shown only when showSelectAll is true) -->\r\n <label *ngIf=\"config.optionConfig?.showSelectAll && filteredOptionList?.length\"\r\n class=\"multi-select-option multi-select-all d-flex align-items-center gap-8 cursor-pointer\">\r\n <input type=\"checkbox\"\r\n [checked]=\"isAllSelected()\"\r\n [indeterminate]=\"isSomeSelected()\"\r\n [disabled]=\"!!config.disabled\"\r\n (change)=\"toggleSelectAll($any($event.target).checked)\">\r\n <span class=\"fs-0-875rem c-111827 fw-600\">{{ selectAllLabel }}</span>\r\n </label>\r\n\r\n <!-- Options list -->\r\n <div class=\"multi-select-options-list\">\r\n <label *ngFor=\"let option of filteredOptionList\"\r\n class=\"multi-select-option d-flex align-items-center gap-8 cursor-pointer\">\r\n <input type=\"checkbox\"\r\n [checked]=\"isChecked(option.code)\"\r\n [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <span class=\"fs-0-875rem c-111827\">{{ option.label }}</span>\r\n </label>\r\n <div *ngIf=\"!filteredOptionList?.length && localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noMatchingOptionsLabel }}\r\n </div>\r\n <div *ngIf=\"!localOptionList?.length\"\r\n class=\"multi-select-empty fs-0-875rem c-6B7280\">\r\n {{ noOptionsAvailableLabel }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Radio \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRadio\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"radio-group\" [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of localOptionList\" class=\"radio-label\"\r\n [class.card-item]=\"config.subType === 'CARD'\"\r\n [class.selected]=\"formGroup.get(config.name!)?.value === option.code\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"radio\" [formControlName]=\"config.name!\" [value]=\"option.code\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Checkbox \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isCheckbox\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label && config.subType === 'LIST'\"\r\n class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div *ngIf=\"config.subType === 'BOOL'\" class=\"checkbox-single\">\r\n <label class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span>{{ config.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <div *ngIf=\"config.subType === 'LIST' || config.subType === 'CARD'\" class=\"checkbox-group d-flex flex-column gap-8\"\r\n [class.is-invalid]=\"errorMessage\"\r\n [class]=\"config.optionConfig?.layout ? 'layout-' + config.optionConfig!.layout.toLowerCase() : ''\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"checkbox-label d-flex align-items-center gap-8 cursor-pointer fs-0-875rem c-111827\"\r\n [class.card-item]=\"config.subType === 'CARD'\" [class.selected]=\"isChecked(option.code)\"\r\n [style.gridColumn]=\"config.optionConfig?.layout?.toUpperCase() === 'COLUMN' ? 'span ' + getOptionColSpan(option) : null\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\">\r\n <div class=\"option-content d-flex flex-column gap-4 flex-1 text-left\">\r\n <span class=\"label-text text-16 c-1F2937\">{{ option.label }}</span>\r\n <span class=\"option-hint text-13 color-gray\" *ngIf=\"option.hint\">{{ option.hint }}</span>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Chip \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isChip\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"chip-group d-flex flex-wrap gap-8\" [class.is-invalid]=\"errorMessage\">\r\n <label *ngFor=\"let option of localOptionList\"\r\n class=\"chip-label cursor-pointer p-6px-14px b-ffffff c-374151 b-1px-solid-D1D5DB br-20px fs-0-875rem\"\r\n [class.selected]=\"isChecked(option.code)\">\r\n <input type=\"checkbox\" [checked]=\"isChecked(option.code)\" [disabled]=\"!!config.disabled\"\r\n (change)=\"onCheckboxListChange(option.code, $any($event.target).checked)\" hidden>\r\n <span>{{ option.label }}</span>\r\n </label>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Switch \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isSwitch\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label class=\"switch-container d-flex justify-content-between align-items-center cursor-pointer\">\r\n <span class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label }}</span>\r\n <div class=\"switch position-relative\">\r\n <input type=\"checkbox\" [formControlName]=\"config.name!\" [class.is-invalid]=\"errorMessage\">\r\n <span class=\"slider position-absolute cursor-pointer\"></span>\r\n </div>\r\n </label>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rich Text \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRichText\" class=\"field-wrapper component-rich-text d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rich-text-container\" [class.is-invalid]=\"errorMessage\">\r\n <quill-editor [formControlName]=\"config.name!\" class=\"rich-text-editor d-block w-100\"\r\n [placeholder]=\"config.richTextConfig?.placeholder || config.placeholder || ''\"\r\n [styles]=\"{height: config.richTextConfig?.height || '200px'}\">\r\n </quill-editor>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <div class=\"char-count-hint font-poppins font-weight-400 text-14 text-right c-6B7280\" *ngIf=\"showCharCount\">\r\n {{ remainingCharacters }} characters remaining\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Rating \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isRating\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <div class=\"rating-group d-flex gap-4\" [class.is-invalid]=\"errorMessage\">\r\n <span *ngFor=\"let star of getStarArray()\" class=\"star d-inline-flex align-items-center cursor-pointer\"\r\n [class.filled]=\"isStarFilled(star)\" [class.half]=\"isStarHalf(star)\" (click)=\"onRatingChange(star, $event)\">\r\n <mat-icon>{{ isStarFilled(star) || isStarHalf(star) ? 'star' : 'star_border' }}</mat-icon>\r\n </span>\r\n </div>\r\n\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Generated Field (read-only) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isGenerated\" class=\"field-wrapper d-flex flex-column gap-6\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">{{ config.label\r\n }}</label>\r\n <div class=\"generated-value fs-0-875rem p-0-625rem-0-875rem b-F3F4F6 b-1px-solid-E5E7EB br-8px c-6B7280\">{{ value ||\r\n '-' }}</div>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint\">{{ config.hint }}</span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 File Upload \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isFileUpload\" class=\"field-wrapper d-flex flex-column gap-6\" [formGroup]=\"formGroup\">\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n\r\n <!-- Drop Zone -->\r\n <div\r\n class=\"upload-drop-zone d-flex flex-column align-items-center justify-content-center gap-8 cursor-pointer text-center p-32px-24px us-none\"\r\n [class.drag-over]=\"isDragOver\" [class.has-files]=\"value?.length\" [class.is-invalid]=\"errorMessage\"\r\n (dragover)=\"onDragOver($event)\" (dragleave)=\"onDragLeave($event)\" (drop)=\"onFileDrop($event)\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <!-- Icon with accent-colour pill background -->\r\n <div class=\"upload-icon-wrap mb-4\">\r\n <div class=\"dropzone-icon-pill d-flex align-items-center justify-content-center\">\r\n <mat-icon class=\"upload-cloud-icon\">cloud_upload</mat-icon>\r\n </div>\r\n </div>\r\n\r\n <p class=\"upload-main-text font-weight-600 m-0 fs-0-9rem\">Drag & drop files here</p>\r\n <p class=\"upload-sub-text m-0 fs-0-8rem c-64748B\">or <span class=\"upload-link\">Browse files</span></p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"config.attachmentConfig?.acceptLabel\">\r\n Supported: <span class=\"upload-formats font-weight-500\">{{ config.attachmentConfig!.acceptLabel }}</span>\r\n </p>\r\n <p class=\"upload-hint-text m-0 fs-0-78rem c-64748B\" *ngIf=\"!config.attachmentConfig?.acceptLabel && config.hint\">\r\n {{ config.hint }}\r\n </p>\r\n <span class=\"upload-size-badge fs-0-72rem\" *ngIf=\"config.attachmentConfig?.maxSizeMB\">\r\n Max {{ config.attachmentConfig!.maxSizeMB }}MB\r\n </span>\r\n\r\n <!-- Hidden native file input -->\r\n <input #fileInput type=\"file\" hidden [attr.multiple]=\"config.attachmentConfig?.multiple ? true : null\"\r\n [attr.accept]=\"config.attachmentConfig?.accept || null\" (change)=\"onFileSelected($event)\">\r\n </div>\r\n\r\n <!-- Uploaded file list -->\r\n <div class=\"uploaded-list d-flex flex-column gap-8 mt-10\" *ngIf=\"value?.length\">\r\n <div *ngFor=\"let f of value; let i = index\"\r\n class=\"uploaded-item d-flex align-items-center gap-10 p-10px-14px br-8px\"\r\n [class.uploading]=\"f.isUploading\">\r\n\r\n <!-- Uploading spinner -->\r\n <ng-container *ngIf=\"f.isUploading; else fileReady\">\r\n <div class=\"upload-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size uploading-label fs-0-72rem\">Uploading...</span>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Normal state once upload is done -->\r\n <ng-template #fileReady>\r\n <mat-icon class=\"file-type-icon\">{{ getFileIcon(f.type) }}</mat-icon>\r\n <img *ngIf=\"f.type?.startsWith('image') && f.dataUrl\" [src]=\"f.dataUrl\" class=\"file-thumb rounded-4\"\r\n alt=\"preview\">\r\n <div class=\"file-info flex-1 d-flex flex-column\">\r\n <span class=\"file-name font-weight-500 overflow-hidden fs-0-85rem\" [title]=\"f.name\">{{ f.name }}</span>\r\n <span class=\"file-size fs-0-72rem\">{{ formatFileSize(f.size) }}</span>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- Compact icon-only remove button -->\r\n <button type=\"button\" class=\"file-remove-btn d-flex align-items-center justify-content-center rounded-50\"\r\n [disabled]=\"f.isUploading\" (click)=\"!f.isUploading && removeUploadedFile(i)\"\r\n aria-label=\"Remove file\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation / file errors -->\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"fileUploadError\">{{ fileUploadError }}</span>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage && !fileUploadError\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\"\r\n *ngIf=\"config.hint && !errorMessage && !fileUploadError && !config.attachmentConfig?.acceptLabel\">\r\n {{ config.hint }}\r\n </span>\r\n </div>\r\n\r\n <!-- \u2550\u2550 Media Upload (Type 2) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isMediaUpload\" class=\"field-wrapper media-upload-wrapper d-flex flex-column gap-6 p-0 border-none b-none\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Hidden file input lives outside *ngIf \u2014 triggered via ViewChild -->\r\n <input #mediaDeviceInput type=\"file\" hidden multiple accept=\"image/*\" (change)=\"onMediaFileSelected($event)\">\r\n\r\n <!-- Two-column layout -->\r\n <div class=\"mu-layout d-grid align-items-start\">\r\n\r\n <!-- \u2500\u2500 LEFT PANEL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-left d-flex flex-column gap-20\">\r\n\r\n <!-- Header: title + max-items badge -->\r\n <div class=\"mu-header d-flex align-items-start flex-wrap gap-10\">\r\n <h3 class=\"mu-title m-0 c-111827 fs-1-35rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </h3>\r\n <span\r\n class=\"mu-badge d-inline-flex align-items-center rounded-20 color-white font-weight-600 fs-0-72rem p-4px-12px b-111827\"\r\n *ngIf=\"config.attachmentConfig?.maxFiles\">\r\n {{ controller.labels['LBL_MEDIA_MAX_PREFIX'] || 'Maximum' }}\r\n {{ config.attachmentConfig?.maxFiles }}\r\n {{ controller.labels['LBL_MEDIA_MAX_SUFFIX'] || 'Image & Videos' }}\r\n </span>\r\n </div>\r\n\r\n <!-- Description -->\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\" *ngIf=\"config.attachmentConfig?.description\">\r\n {{ config.attachmentConfig?.description }}\r\n </p>\r\n <p class=\"mu-description m-0 fs-0-875rem c-6B7280\"\r\n *ngIf=\"!config.attachmentConfig?.description && controller.labels['LBL_MEDIA_DESC']\">\r\n {{ controller.labels['LBL_MEDIA_DESC'] }}\r\n </p>\r\n\r\n <!-- Feature bullet list -->\r\n <ul class=\"mu-features m-0 p-0 d-flex flex-column gap-8 ls-none\"\r\n *ngIf=\"config.attachmentConfig?.features?.length || controller.labels['LBL_MEDIA_FEATURE_1']\">\r\n <ng-container *ngIf=\"config.attachmentConfig?.features?.length\">\r\n <li *ngFor=\"let f of config.attachmentConfig?.features\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ f }}\r\n </li>\r\n </ng-container>\r\n <ng-container *ngIf=\"!config.attachmentConfig?.features?.length\">\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_1']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_1'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_2']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_2'] }}\r\n </li>\r\n <li *ngIf=\"controller.labels['LBL_MEDIA_FEATURE_3']\"\r\n class=\"mu-feature-item d-flex align-items-center gap-8 fs-0-875rem c-374151\">\r\n <mat-icon class=\"mu-check text-16 c-3B82F6\">check</mat-icon>{{ controller.labels['LBL_MEDIA_FEATURE_3'] }}\r\n </li>\r\n </ng-container>\r\n </ul>\r\n\r\n <!-- Backdrop to close dropdown on outside click -->\r\n <div class=\"media-menu-backdrop\" *ngIf=\"showMediaMenu\"\r\n (click)=\"$event.stopPropagation(); showMediaMenu = false\"></div>\r\n\r\n <!-- Add Media button + dropdown -->\r\n <div class=\"media-add-container position-relative\" (click)=\"showMediaMenu = !showMediaMenu\">\r\n <lib-button id=\"btn-add-media-{{ config.name }}\" [variant]=\"'warning'\"\r\n [icon]=\"{type: 'material', value: 'add_photo_alternate'}\">\r\n {{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}\r\n <mat-icon class=\"menu-chevron fs-18px\">add</mat-icon>\r\n </lib-button>\r\n\r\n <div class=\"media-dropdown position-absolute rounded-12 overflow-hidden b-ffffff b-1px-solid-E5E7EB\"\r\n *ngIf=\"showMediaMenu\" role=\"menu\" (click)=\"$event.stopPropagation()\">\r\n <!-- Video -->\r\n <button id=\"btn-media-video-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuVideo(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--video d-flex align-items-center justify-content-center rounded-8\"><mat-icon>videocam</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_VIDEO'] || 'Video' }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_VIDEO_DESC'] || 'Add\r\n YouTube URL'\r\n }}</span>\r\n </span>\r\n </button>\r\n <!-- Device -->\r\n <button id=\"btn-media-device-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuDevice(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--device d-flex align-items-center justify-content-center rounded-8\"><mat-icon>upload</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_DEVICE'] || 'Upload from device'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_DEVICE_DESC'] ||\r\n 'Select images from your\r\n computer' }}</span>\r\n </span>\r\n </button>\r\n <!-- Library -->\r\n <button id=\"btn-media-library-{{ config.name }}\" type=\"button\"\r\n class=\"media-dropdown-item d-flex align-items-center gap-12 w-100 cursor-pointer text-left b-none border-none p-12px-16px bb-1px-solid-F3F4F6\"\r\n (click)=\"onMediaMenuLibrary(); showMediaMenu = false\" role=\"menuitem\">\r\n <span\r\n class=\"media-drop-icon media-drop-icon--library d-flex align-items-center justify-content-center rounded-8\"><mat-icon>photo_library</mat-icon></span>\r\n <span class=\"media-drop-text d-flex flex-column flex-1\">\r\n <span class=\"media-drop-label font-weight-600 fs-0-875rem c-111827\">{{\r\n controller.labels['LBL_MEDIA_LIBRARY'] || 'Upload from library'\r\n }}</span>\r\n <span class=\"media-drop-desc c-6B7280 fs-0-75rem\">{{ controller.labels['LBL_MEDIA_LIBRARY_DESC'] ||\r\n 'Choose from default\r\n images' }}</span>\r\n </span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- YouTube URL Input (inline below button) -->\r\n <div class=\"youtube-input-panel d-flex flex-column gap-8 p-16 rounded-10 b-FFFAF1 b-1px-solid-E5E7EB\"\r\n *ngIf=\"showYoutubeInput\">\r\n <label class=\"youtube-panel-label d-flex align-items-center gap-6 font-weight-600 fs-0-875rem c-111827\">\r\n {{ controller.labels['LBL_YOUTUBE_URL'] || 'Video URL' }}\r\n </label>\r\n <div class=\"youtube-input-row d-flex gap-8\">\r\n <input id=\"input-youtube-url-{{ config.name }}\" type=\"url\" class=\"field-input youtube-url-input\"\r\n [(ngModel)]=\"youtubeUrlInput\" [ngModelOptions]=\"{standalone: true}\"\r\n [placeholder]=\"controller.labels['PH_YOUTUBE_URL'] || 'Video URL'\" (keyup.enter)=\"addYoutubeMedia()\">\r\n <lib-button id=\"btn-add-youtube-{{ config.name }}\" [variant]=\"'secondary'\" (click)=\"addYoutubeMedia()\">\r\n {{ controller.labels['LBL_ADD'] || 'Add' }}\r\n </lib-button>\r\n </div>\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"youtubeUrlError\">{{ youtubeUrlError }}</span>\r\n </div>\r\n\r\n <div\r\n class=\"media-upload-status d-flex align-items-center gap-8 mt-4 color-error rounded-8 font-weight-500 p-10px-14px b-FEF2F2 fs-0-85rem\"\r\n *ngIf=\"mediaUploadError\">\r\n <mat-icon class=\"status-icon fs-18px\">error_outline</mat-icon>\r\n <span>{{ mediaUploadError }}</span>\r\n </div>\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n <span class=\"field-hint c-6B7280 fs-0-75rem\" *ngIf=\"config.hint && !errorMessage\">{{ config.hint }}</span>\r\n </div>\r\n <!-- end left panel -->\r\n\r\n <!-- \u2500\u2500 RIGHT PANEL (carousel) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"mu-right d-flex flex-column gap-12\">\r\n\r\n <!-- Carousel (when items exist) -->\r\n <div class=\"media-carousel-section d-flex flex-column gap-12\" *ngIf=\"mediaItems.length\">\r\n <div\r\n class=\"media-carousel-main position-relative w-100 overflow-hidden d-flex align-items-center justify-content-center br-12px b-0F172A\">\r\n <button id=\"btn-carousel-prev-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--prev position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselPrev()\" [disabled]=\"mediaCarouselIndex === 0\" aria-label=\"Previous\">\r\n <mat-icon>chevron_left</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-viewer position-absolute d-flex align-items-center justify-content-center\"\r\n *ngFor=\"let item of mediaItems; let i = index\" [hidden]=\"i !== mediaCarouselIndex\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"carousel-uploading d-flex flex-column align-items-center gap-12 c-94A3B8 fs-0-85rem\">\r\n <div class=\"carousel-spinner rounded-50 b-3px-solid-rgba-255-255-255-0-15\"></div>\r\n <span>{{ controller.labels['LBL_UPLOADING'] || 'Uploading\u2026' }}</span>\r\n </div>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'youtube'\">\r\n <iframe class=\"carousel-iframe w-100 h-100 br-12px\" [src]=\"item.url | trustedUrl\" frameborder=\"0\"\r\n allowfullscreen\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\">\r\n </iframe>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.isUploading && item.mediaType === 'image'\">\r\n <img class=\"carousel-image w-100 h-100 br-12px\" [src]=\"item.url\" alt=\"Media\">\r\n </ng-container>\r\n <button id=\"btn-remove-media-{{ config.name }}-{{ i }}\" type=\"button\"\r\n class=\"carousel-remove-btn position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-0-0-0-0-55\"\r\n [disabled]=\"item.isUploading\" (click)=\"removeMediaItem(i)\" aria-label=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <button id=\"btn-carousel-next-{{ config.name }}\" type=\"button\"\r\n class=\"carousel-nav carousel-nav--next position-absolute rounded-50 cursor-pointer d-flex align-items-center justify-content-center border-none b-rgba-255-255-255-0-85\"\r\n (click)=\"mediaCarouselNext()\" [disabled]=\"mediaCarouselIndex === mediaItems.length - 1\" aria-label=\"Next\">\r\n <mat-icon>chevron_right</mat-icon>\r\n </button>\r\n\r\n <div class=\"carousel-dots position-absolute d-flex gap-6\">\r\n <span *ngFor=\"let item of mediaItems; let i = index\"\r\n class=\"carousel-dot rounded-50 cursor-pointer b-rgba-255-255-255-0-45\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\"></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Thumbnail strip -->\r\n <div class=\"media-thumbnail-strip d-flex flex-wrap gap-8 pb-4px\">\r\n <div *ngFor=\"let item of mediaThumbnails; let i = index\"\r\n class=\"media-thumb rounded-8 overflow-hidden cursor-pointer d-flex align-items-center justify-content-center b-2px-solid-transparent b-E2E8F0\"\r\n [class.active]=\"i === mediaCarouselIndex\" (click)=\"mediaGoTo(i)\">\r\n <div *ngIf=\"item.isUploading\"\r\n class=\"thumb-uploading d-flex align-items-center justify-content-center w-100 h-100\">\r\n <div class=\"thumb-spinner rounded-50 b-2px-solid-E2E8F0\"></div>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && item.thumbnailUrl\"\r\n [src]=\"item.thumbnailUrl\" class=\"thumb-img w-100 h-100\" alt=\"Video thumbnail\">\r\n <div *ngIf=\"!item.isUploading && item.mediaType === 'youtube' && !item.thumbnailUrl\"\r\n class=\"thumb-yt-placeholder d-flex align-items-center justify-content-center w-100 h-100 b-1E293B c-EF4444\">\r\n <mat-icon>play_circle</mat-icon>\r\n </div>\r\n <img *ngIf=\"!item.isUploading && item.mediaType === 'image' && item.url\" [src]=\"item.url\"\r\n class=\"thumb-img w-100 h-100\" alt=\"Image thumbnail\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty right-side placeholder -->\r\n <div\r\n class=\"mu-right-empty d-flex flex-column align-items-center justify-content-center gap-10 h-100 text-center p-24 br-12px b-FFFAF1 c-94A3B8 b-2px-dashed-CBD5E1\"\r\n *ngIf=\"!mediaItems.length\" (click)=\"onMediaMenuDevice()\">\r\n <mat-icon class=\"mu-right-empty-icon fs-52px\">perm_media</mat-icon>\r\n <p>{{ controller.labels['LBL_ADD_MEDIA'] || 'Add media' }}</p>\r\n </div>\r\n\r\n </div>\r\n <!-- end right panel -->\r\n\r\n </div><!-- end mu-layout -->\r\n </div>\r\n\r\n\r\n <!-- \u2550\u2550 Library Image Picker Modal \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <!-- Wrapper is always in DOM (hidden) so @ViewChild can move it to body -->\r\n <div #libraryModal class=\"media-library-portal-host\" [class.is-open]=\"showLibraryModal\">\r\n\r\n <!-- Backdrop -->\r\n <div class=\"media-library-overlay\" (click)=\"closeLibraryModal()\"></div>\r\n\r\n <!-- Modal card -->\r\n <div class=\"media-library-modal d-flex flex-column overflow-hidden b-ffffff br-16px\"\r\n role=\"dialog\" aria-modal=\"true\">\r\n <div class=\"library-modal-header d-flex align-items-start justify-content-between p-24px-28px bb-1px-solid-E5E7EB\">\r\n <div class=\"header-left d-flex flex-column gap-8\">\r\n <h3 class=\"library-modal-title m-0 color-dark fs-1-25rem\">\r\n {{ controller.labels['LBL_ADD_IMAGES'] || 'Add Images' }}\r\n </h3>\r\n <p class=\"library-modal-subtitle m-0 color-gray fs-0-85rem\">\r\n {{ controller.labels['LBL_LIBRARY_MODAL_DESC'] || 'Select images from your library.' }}\r\n </p>\r\n </div>\r\n <button id=\"btn-close-library-{{ config.name }}\" type=\"button\"\r\n class=\"library-close-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 border-none b-none c-9CA3AF\"\r\n (click)=\"closeLibraryModal()\" aria-label=\"Close\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <!-- Loading -->\r\n <div class=\"library-loading\" *ngIf=\"libraryLoading\">\r\n <div class=\"lib-spinner rounded-50 b-3px-solid-E2E8F0\"></div>\r\n <span>{{ controller.labels['LBL_LOADING'] || 'Loading\u2026' }}</span>\r\n </div>\r\n\r\n <!-- Error -->\r\n <div class=\"library-error d-flex align-items-center gap-8 color-error b-FEF2F2 fs-0-875rem p-16px-24px\"\r\n *ngIf=\"libraryError && !libraryLoading\">\r\n <mat-icon>error_outline</mat-icon>\r\n {{ libraryError }}\r\n </div>\r\n\r\n <!-- Image grid -->\r\n <div class=\"library-grid d-grid gap-16 flex-1 p-28px b-F9FAFB\" *ngIf=\"!libraryLoading && libraryImages.length\">\r\n <div *ngFor=\"let img of libraryImages; let li = index\" id=\"lib-img-{{ config.name }}-{{ li }}\"\r\n class=\"library-grid-item position-relative rounded-12 overflow-hidden cursor-pointer bg-white b-3px-solid-transparent\"\r\n [class.selected]=\"isLibraryItemSelected(img)\" (click)=\"toggleLibraryItem(img)\">\r\n <img [src]=\"getLibraryItemUrl(img)\" class=\"library-grid-img w-100 h-100 d-block\" alt=\"Library image\">\r\n <div\r\n class=\"library-check position-absolute bg-white rounded-50 d-flex align-items-center justify-content-center c-3B82F6\"\r\n *ngIf=\"isLibraryItemSelected(img)\">\r\n <mat-icon>check_circle</mat-icon>\r\n </div>\r\n <div class=\"library-overlay-hover position-absolute b-rgba-59-130-246-0-12\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Empty library -->\r\n <div\r\n class=\"library-empty d-flex flex-column align-items-center justify-content-center gap-12 flex-1 c-9CA3AF fs-0-875rem p-48px-24px\"\r\n *ngIf=\"!libraryLoading && !libraryError && libraryImages.length === 0\">\r\n <mat-icon>image_not_supported</mat-icon>\r\n <span>{{ controller.labels['LBL_LIBRARY_EMPTY'] || 'No images found in library.' }}</span>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"library-modal-footer d-flex align-items-center justify-content-end bg-white p-20px-28px bt-1px-solid-E5E7EB\">\r\n <div class=\"library-footer-actions d-flex gap-12\">\r\n <lib-button id=\"btn-library-cancel-{{ config.name }}\" [variant]=\"'outline'\" (click)=\"closeLibraryModal()\">\r\n {{ controller.labels['LBL_CANCEL'] || 'Cancel' }}\r\n </lib-button>\r\n <lib-button id=\"btn-library-confirm-{{ config.name }}\" [variant]=\"'primary'\"\r\n [disabled]=\"librarySelectedIds.size === 0\" (click)=\"confirmLibrarySelection()\">\r\n {{ controller.labels['LBL_CONTINUE'] || 'Continue' }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <!-- \u2550\u2550 Location Field \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div *ngIf=\"isLocation\" class=\"field-wrapper location-field-wrapper d-flex flex-column gap-6 gap-12\"\r\n [formGroup]=\"formGroup\">\r\n\r\n <!-- Field label -->\r\n <label *ngIf=\"config.label\" class=\"field-label d-block font-poppins c-202124 fs-18px mb-0-5rem\">\r\n {{ config.label }}\r\n <span class=\"required c-DC2626 ml-0-125rem\" *ngIf=\"config.required\">*</span>\r\n </label>\r\n <p class=\"location-subtitle m-0 c-6B7280 fs-0-8125rem\" *ngIf=\"config.hint\">{{ config.hint }}</p>\r\n\r\n <!-- Three-tab bar -->\r\n <div class=\"location-tabs d-flex gap-12 mb-24\">\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'VENUE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('VENUE')\">\r\n {{ controller.labels['LBL_LOC_VENUE'] || 'Venue' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'ONLINE' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('ONLINE')\">\r\n {{ controller.labels['LBL_LOC_ONLINE'] || 'Online Event' }}\r\n </lib-button>\r\n <lib-button class=\"loc-tab-btn flex-1\" [variant]=\"locationActiveTab === 'TBA' ? 'warning' : 'outline'\"\r\n (click)=\"onLocationTabChange('TBA')\">\r\n {{ controller.labels['LBL_LOC_TBA'] || 'To be Announced' }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- VENUE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'VENUE'\" class=\"loc-panel loc-venue-panel d-flex flex-column gap-12\">\r\n\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ADDRESS'] || 'Location address' }}\r\n </p>\r\n\r\n <!-- Added venue rows -->\r\n <div class=\"loc-venue-list d-flex flex-column gap-8\" *ngIf=\"locationVenues.length > 0\">\r\n <div *ngFor=\"let venue of locationVenues; let i = index\"\r\n class=\"loc-venue-item d-flex align-items-center gap-10 p-10px-14px br-7px b-ffffff b-1px-solid-D1D5DB\">\r\n <mat-icon class=\"loc-venue-search-icon fs-18px c-9CA3AF\">search</mat-icon>\r\n <span class=\"loc-venue-text flex-1 overflow-hidden fs-0-875rem c-111827\">{{ venue.address || venue.name ||\r\n venue.description }}</span>\r\n <button type=\"button\"\r\n class=\"loc-action-btn loc-delete-btn d-flex align-items-center justify-content-center cursor-pointer rounded-50 b-none border-none p-4px\"\r\n (click)=\"removeLocationVenue(i)\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Location count badge -->\r\n <p class=\"loc-count-text m-0 font-weight-600 fs-0-8125rem c-3B82F6\"\r\n *ngIf=\"locationVenues.length > 0 && config.locationConfig?.allowMulti\">\r\n {{ locationVenues.length }} {{ controller.labels['LBL_LOC_COUNT_SUFFIX'] || 'Locations Added!' }}\r\n </p>\r\n\r\n <!-- Search input (hide when max reached) -->\r\n <div class=\"loc-search-container position-relative\" *ngIf=\"!locationMaxReached\">\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">search</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n [placeholder]=\"config.locationConfig?.venuePlaceholder || (controller.labels['PH_LOC_VENUE'] || 'Type to search venue...')\"\r\n [value]=\"locationSearchText\" (input)=\"handleLocationSearchInput($event)\" (blur)=\"hideLocationSuggestions()\"\r\n autocomplete=\"off\" [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n <!-- Suggestions dropdown -->\r\n <div class=\"loc-suggestions-panel position-absolute overflow-hidden br-8px b-ffffff b-1px-solid-D1D5DB\"\r\n *ngIf=\"locationShowSuggestions && locationSuggestions.length\">\r\n <div *ngFor=\"let sug of locationSuggestions\"\r\n class=\"loc-suggestion-item d-flex align-items-center gap-10 cursor-pointer p-10px-14px\"\r\n (mousedown)=\"onLocationSuggestionSelect(sug)\">\r\n <mat-icon class=\"loc-suggestion-icon fs-18px c-E53E3E\">place</mat-icon>\r\n <span class=\"loc-suggestion-text overflow-hidden fs-0-875rem c-374151\">{{ sug.description }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Add another button -->\r\n <button type=\"button\"\r\n class=\"loc-add-btn d-inline-flex align-items-center gap-6 cursor-pointer font-weight-600 p-0 b-none border-none fs-0-875rem c-1A56DB\"\r\n *ngIf=\"locationVenues.length > 0 && !locationMaxReached && config.locationConfig?.allowMulti\">\r\n <mat-icon>add_circle_outline</mat-icon>\r\n <span>{{ controller.labels['LBL_LOC_ADD_ANOTHER'] || 'Add another Location' }}</span>\r\n </button>\r\n\r\n <!-- Map -->\r\n <div class=\"loc-map-container overflow-hidden br-10px b-1px-solid-E5E7EB\"\r\n *ngIf=\"config.locationConfig?.showMap !== false\">\r\n <ng-container *ngIf=\"config.locationConfig?.googleMapsApiKey; else simpleEmbed\">\r\n <div [id]=\"'loc-map-' + config.name\" class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\"></div>\r\n </ng-container>\r\n <ng-template #simpleEmbed>\r\n <iframe class=\"loc-map-frame w-100 d-block border-none\"\r\n [style.height]=\"config.locationConfig?.mapHeight || '300px'\" [src]=\"getLocationMapEmbedUrl() | trustedUrl\"\r\n frameborder=\"0\" allowfullscreen loading=\"lazy\">\r\n </iframe>\r\n </ng-template>\r\n </div>\r\n\r\n <!-- Map hint -->\r\n <p class=\"loc-map-hint m-0 text-center fs-0-78rem c-6B7280\">\r\n {{ controller.labels['LBL_LOC_MAP_HINT'] || 'Type the venue address. A map will appear to assist you.' }}\r\n </p>\r\n </div>\r\n\r\n <!-- ONLINE TAB -->\r\n <div *ngIf=\"locationActiveTab === 'ONLINE'\" class=\"loc-panel loc-online-panel d-flex flex-column gap-12\">\r\n <p class=\"loc-section-label m-0 font-weight-600 c-111827 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_ONLINE_URL'] || 'Event URL' }}\r\n </p>\r\n <div class=\"loc-search-wrapper position-relative d-flex align-items-center mt-4\">\r\n <mat-icon class=\"loc-search-icon position-absolute fs-1-1rem c-9CA3AF pe-none\">link</mat-icon>\r\n <input\r\n class=\"field-input loc-search-input w-100 font-poppins flex-1 fs-0-875rem c-111827 br-7px br-8px bc-F3F4F6 pl-2-4rem bc-DC2626 pt-0-625rem pb-0-625rem pl-16px pr-16px bc-ffffff b-1px-solid-D1D5DB pr-3-5rem\"\r\n type=\"url\"\r\n [placeholder]=\"config.locationConfig?.onlinePlaceholder || (controller.labels['PH_LOC_ONLINE'] || 'https://zoom.us/j/...')\"\r\n [value]=\"locationOnlineUrl\" (input)=\"onLocationUrlChange($any($event.target).value)\"\r\n [class.is-invalid]=\"errorMessage\">\r\n </div>\r\n </div>\r\n\r\n <!-- TBA TAB -->\r\n <div *ngIf=\"locationActiveTab === 'TBA'\"\r\n class=\"loc-panel loc-tba-panel d-flex flex-column gap-12 justify-content-center\">\r\n <div\r\n class=\"loc-tba-content d-flex flex-column align-items-center justify-content-center text-center gap-12 p-32px-24px b-F9FAFB b-1px-dashed-D1D5DB br-10px\">\r\n <mat-icon class=\"loc-tba-icon fs-40px c-9CA3AF\">schedule</mat-icon>\r\n <p class=\"loc-tba-text m-0 c-6B7280 fs-0-9rem\">\r\n {{ controller.labels['LBL_LOC_TBA_DESC'] || \"This event's location is yet to be announced. Check back later\r\n for updates.\" }}\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden real form control -->\r\n <input type=\"hidden\" [formControlName]=\"config.name!\">\r\n\r\n <span class=\"field-error color-error fs-0-75rem\" *ngIf=\"errorMessage\">{{ errorMessage }}</span>\r\n </div>\r\n\r\n</div>", styles: [".d-flex{display:flex}.d-inline-flex{display:inline-flex}.d-grid{display:grid}.d-block{display:block}.d-none{display:none}.flex-column{flex-direction:column}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}.align-items-center{align-items:center}.align-items-start{align-items:flex-start}.align-items-end{align-items:flex-end}.justify-content-center{justify-content:center}.justify-content-between{justify-content:space-between}.justify-content-start{justify-content:flex-start}.justify-content-end{justify-content:flex-end}.grid-cols-12{grid-template-columns:repeat(12,1fr)}.w-100{width:100%}.h-100{height:100%}.position-relative{position:relative}.position-absolute{position:absolute}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-poppins{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)}.font-weight-400{font-weight:400}.font-weight-500{font-weight:500}.font-weight-600{font-weight:600}.text-13{font-size:13px}.text-14{font-size:14px}.text-16{font-size:16px}.color-white{color:#fff}.color-dark{color:#111827}.color-gray{color:#6b7280}.color-error{color:var(--cc-sf-error-text-color, #DC2626)}.bg-white{background-color:#fff}.bg-transparent{background-color:transparent}.m-0{margin:0}.mt-4{margin-top:4px}.mt-8{margin-top:8px}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}.mb-0{margin-bottom:0}.mb-4{margin-bottom:4px}.mb-8{margin-bottom:8px}.mb-10{margin-bottom:10px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}.mb-24{margin-bottom:24px}.ml-16{margin-left:16px}.ml-20{margin-left:20px}.p-0{padding:0}.p-16{padding:16px}.p-20{padding:20px}.p-24{padding:24px}.pt-20{padding-top:20px}.pb-10{padding-bottom:10px}.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-10{gap:10px}.gap-12{gap:12px}.gap-16{gap:16px}.gap-20{gap:20px}.rounded-4{border-radius:4px}.rounded-6{border-radius:6px}.rounded-8{border-radius:8px}.rounded-10{border-radius:10px}.rounded-12{border-radius:12px}.rounded-20{border-radius:20px}.rounded-24{border-radius:24px}.rounded-50{border-radius:50%}.cursor-pointer{cursor:pointer}.overflow-hidden{overflow:hidden}.resize-vertical{resize:vertical}.box-sizing-border{box-sizing:border-box}.border-none{border:none!important}.mb-16px{margin-bottom:var(--cc-sf-grid-gap, 16px)!important}.c-DC2626{color:var(--cc-sf-label-required-color, #DC2626)!important}.ml-0-125rem{margin-left:.125rem!important}.fs-0-875rem{font-size:.875rem!important}.c-111827{color:var(--cc-sf-label-color, #111827)!important}.br-7px{border-radius:var(--cc-sf-input-radius, 7px)!important}.c-6B7280{color:var(--cc-sf-hint-color, #6B7280)!important}.fs-0-75rem{font-size:var(--cc-sf-error-text-size, .75rem)!important}.b-none{background:none!important}.p-32px-24px{padding:32px 24px!important}.us-none{-webkit-user-select:none!important;user-select:none!important}.c-1E293B{color:var(--cc-sf-label-color, #1E293B)!important}.c-3B82F6{color:var(--cc-sf-chip-selected-bg, #3B82F6)!important}.fs-0-78rem{font-size:.78rem!important}.p-10px-14px{padding:10px 14px!important}.fs-0-85rem{font-size:.85rem!important}.fs-0-72rem{font-size:.72rem!important}.c-94A3B8{color:#94a3b8!important}.p-4px{padding:4px!important}.br-8px{border-radius:var(--cc-sf-input-radius, 8px)!important}.bc-F3F4F6{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.br-none{border-right:none!important}.bl-none{border-left:none!important}.pe-none{pointer-events:none!important}.fs-1-1rem{font-size:1.1rem!important}.c-9CA3AF{color:var(--cc-sf-hint-color, #9CA3AF)!important}.pl-2-4rem{padding-left:2.4rem!important}.fs-0-8125rem{font-size:.8125rem!important}.ls-none{list-style:none!important}.br-12px{border-radius:var(--mu-carousel-radius, 12px)!important}.b-FFFAF1{background:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.fs-18px{font-size:18px!important}.b-FEF2F2{background:var(--cc-sf-error-bg, #FEF2F2)!important}.bc-DC2626{border-color:var(--cc-sf-error-border, #DC2626)!important}.c-202124{color:var(--cc-sf-label-color, #202124)!important}.fs-18px{font-size:var(--cc-sf-label-size, 18px)!important}.mb-0-5rem{margin-bottom:.5rem!important}.pt-0-625rem{padding-top:var(--cc-sf-input-padding-y, .625rem)!important}.pb-0-625rem{padding-bottom:var(--cc-sf-input-padding-y, .625rem)!important}.pl-16px{padding-left:var(--cc-sf-input-padding-x, 16px)!important}.pr-16px{padding-right:var(--cc-sf-input-padding-x, 16px)!important}.bc-ffffff{background-color:var(--cc-sf-section-bg, #ffffff)!important}.b-1px-solid-D1D5DB{border:1px solid var(--cc-sf-input-border, #D1D5DB)!important}.fs-0-75rem{font-size:.75rem!important}.c-1F2937{color:var(--cc-sf-section-label-color, #1F2937)!important}.p-6px-14px{padding:var(--cc-sf-chip-padding, 6px 14px)!important}.b-ffffff{background:var(--loc-suggestion-bg, #ffffff)!important}.c-374151{color:var(--cc-sf-label-color, #374151)!important}.br-20px{border-radius:var(--cc-sf-chip-radius, 20px)!important}.fs-0-875rem{font-size:var(--cc-sf-btn-font-size, .875rem)!important}.bc-D1D5DB{background-color:var(--cc-sf-switch-track-off, #D1D5DB)!important}.pr-2-75rem{padding-right:2.75rem!important}.p-0-25rem{padding:.25rem!important}.p-0-625rem-0-875rem{padding:var(--cc-sf-generated-padding, .625rem .875rem)!important}.b-F3F4F6{background:var(--cc-sf-generated-bg, #F3F4F6)!important}.b-1px-solid-E5E7EB{border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.br-8px{border-radius:var(--cc-sf-uploaded-item-radius, 8px)!important}.c-6B7280{color:var(--ms-desc-color, #6B7280)!important}.mb-20px{margin-bottom:var(--cc-sf-section-gap, 20px)!important}.br-10px{border-radius:var(--cc-sf-input-radius, 10px)!important}.p-20px{padding:var(--cc-sf-section-padding, 20px)!important}.fs-1rem{font-size:1rem!important}.m-0-0-16px-0{margin:0 0 16px!important}.bb-2px-solid-E5E7EB{border-bottom:var(--cc-sf-section-label-border, 2px solid #E5E7EB)!important}.p-16px{padding:var(--cc-sf-instance-padding, 16px)!important}.b-F9FAFB{background:var(--loc-tba-bg, #F9FAFB)!important}.bb-1px-dashed-D1D5DB{border-bottom:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)!important}.c-4B5563{color:var(--cc-sf-instance-num-color, #4B5563)!important}.fs-0-8125rem{font-size:var(--cc-sf-hint-size, .8125rem)!important}.pb-0{padding-bottom:0!important}.p-18px-24px{padding:18px 24px!important}.c-111827{color:var(--ms-title-color, #111827)!important}.bt-1px-solid-E5E7EB{border-top:1px solid #E5E7EB!important}.p-4px-10px{padding:4px 10px!important}.b-FFF5F5{background:var(--cc-sf-btn-remove-bg, #FFF5F5)!important}.c-E53E3E{color:var(--loc-delete-color, #E53E3E)!important}.b-1px-solid-FED7D7{border:var(--cc-sf-btn-remove-border, 1px solid #FED7D7)!important}.br-4px{border-radius:var(--cc-sf-btn-remove-radius, 4px)!important}.p-8px-16px{padding:8px 16px!important}.b-transparent{background:var(--cc-sf-btn-add-bg, transparent)!important}.c-3B82F6{color:var(--cc-sf-input-focus-border, #3B82F6)!important}.b-1px-dashed-CBD5E1{border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1)!important}.br-6px{border-radius:var(--cc-sf-btn-add-radius, 6px)!important}.b-1-5px-dashed-CBD5E1{border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1)!important}.br-12px{border-radius:var(--cc-sf-dropzone-radius, 12px)!important}.bc-FFFAF1{background-color:var(--cc-sf-dropzone-bg, #FFFAF1)!important}.c-94A3B8{color:var(--cc-sf-uploaded-remove-color, #94A3B8)!important}.fs-0-9rem{font-size:var(--cc-sf-input-font-size, .9rem)!important}.c-64748B{color:var(--cc-sf-dropzone-hint-color, #64748B)!important}.b-1px-solid-E2E8F0{border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0)!important}.b-2px-solid-E2E8F0{border:2px solid #E2E8F0!important}.pr-3-5rem{padding-right:3.5rem!important}.p-0-0-875rem{padding:0 .875rem!important}.bc-FFFFFF{background-color:var(--cc-sf-input-bg, #FFFFFF)!important}.b-1-5px-solid-D1D5DB{border:var(--cc-sf-input-border, 1.5px solid #D1D5DB)!important}.mb-0-75rem{margin-bottom:.75rem!important}.mt-6px{margin-top:6px!important}.pr-2-4rem{padding-right:2.4rem!important}.p-0-2rem{padding:.2rem!important}.fs-1-35rem{font-size:1.35rem!important}.p-4px-12px{padding:4px 12px!important}.b-111827{background:var(--cc-sf-label-color, #111827)!important}.b-2px-dashed-CBD5E1{border:2px dashed var(--cc-sf-dropzone-border, #CBD5E1)!important}.fs-52px{font-size:52px!important}.p-12px-16px{padding:12px 16px!important}.bb-1px-solid-F3F4F6{border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)!important}.b-0F172A{background:var(--mu-carousel-bg, #0F172A)!important}.b-3px-solid-rgba-255-255-255-0-15{border:3px solid rgba(255,255,255,.15)!important}.b-rgba-255-255-255-0-85{background:#ffffffd9!important}.b-rgba-0-0-0-0-55{background:#0000008c!important}.b-rgba-255-255-255-0-45{background:#ffffff73!important}.pb-4px{padding-bottom:4px!important}.b-2px-solid-transparent{border:2px solid transparent!important}.b-E2E8F0{background:var(--mu-thumb-bg, #E2E8F0)!important}.b-1E293B{background:#1e293b!important}.c-EF4444{color:#ef4444!important}.b-rgba-0-0-0-0-5{background:#00000080!important}.br-16px{border-radius:var(--mu-modal-radius, 16px)!important}.p-24px-28px{padding:24px 28px!important}.bb-1px-solid-E5E7EB{border-bottom:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important}.fs-1-25rem{font-size:1.25rem!important}.p-48px-24px{padding:48px 24px!important}.b-3px-solid-E2E8F0{border:3px solid #E2E8F0!important}.p-16px-24px{padding:16px 24px!important}.p-28px{padding:28px!important}.b-3px-solid-transparent{border:3px solid transparent!important}.b-rgba-59-130-246-0-12{background:#3b82f61f!important}.p-20px-28px{padding:20px 28px!important}.c-1A56DB{color:var(--loc-add-color, #1A56DB)!important}.b-1px-dashed-D1D5DB{border:1px dashed var(--cc-sf-input-disabled-border, #D1D5DB)!important}.fs-40px{font-size:40px!important}.c-9CA3AF{color:var(--loc-tba-icon-color, #9CA3AF)!important}.form-field{font-family:var(--cc-sf-font-family, \"Poppins\", sans-serif)!important}:host{--cc-sf-input-border: #D1D5DB;--cc-sf-input-bg: #ffffff;--cc-sf-input-radius: 9px;--cc-sf-input-height: 44px;--cc-sf-label-color: #111827;--cc-sf-hint-color: #9CA3AF;--cc-sf-error-border: #EF4444;--cc-sf-error-bg: #FFF5F5;--cc-sf-accent-color: #6366F1;--cc-sf-input-focus-border: #6366F1;--cc-sf-input-hover-border: #A5B4FC;--cc-sf-input-placeholder: #C4C9D4;--cc-sf-input-disabled-bg: #F8F9FB;--cc-sf-input-disabled-border: #E5E7EB;--cc-sf-switch-track-on: #6366F1;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-thumb: #ffffff;--cc-sf-selected-color: #6366F1}.form-row{gap:var(--cc-sf-grid-gap, 16px)}.form-row.horizontal{display:flex;flex-direction:row}.form-row.horizontal>*{flex:1}.form-row:not(.horizontal){flex-direction:column}.form-row.grid-row{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media (max-width: 640px){.form-row.grid-row{grid-template-columns:1fr}.form-row.grid-row .row-field{grid-column:span 12!important}}.field-label{font-size:.75rem;font-weight:600;line-height:1;letter-spacing:.04em;text-transform:uppercase;color:#6b7280}.field-input,input.matInput,.mat-mdc-input-element{display:block;width:100%;height:var(--cc-sf-input-height)!important;padding:0 14px!important;font-family:inherit;font-size:.9rem;color:var(--cc-sf-label-color);background-color:var(--cc-sf-input-bg)!important;border:1.5px solid var(--cc-sf-input-border)!important;border-radius:var(--cc-sf-input-radius)!important;box-sizing:border-box;box-shadow:0 1px 2px #0000000a!important;transition:all .2s cubic-bezier(.4,0,.2,1)}.field-input::placeholder,input.matInput::placeholder,.mat-mdc-input-element::placeholder{font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder)}.field-input{opacity:var(--cc-sf-input-opacity, 1);line-height:var(--cc-sf-input-line-height, 1.5);transition:var(--cc-sf-input-transition, all .2s ease)}.field-input::placeholder{font-weight:var(--cc-sf-placeholder-weight, 400);font-size:var(--cc-sf-placeholder-size, 14px);line-height:var(--cc-sf-placeholder-line-height, 100%);color:var(--cc-sf-input-placeholder)}.field-input:hover:not(:disabled):not([readonly]){border-color:var(--cc-sf-input-hover-border)!important;box-shadow:0 1px 4px #6366f114!important}.field-input:focus{outline:none;border-color:var(--cc-sf-input-focus-border)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important;background-color:#fefeff!important}.field-input:disabled,.field-input[readonly]{background-color:var(--cc-sf-input-disabled-bg)!important;color:#9ca3af!important;cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important;box-shadow:none!important}.field-input.is-invalid{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)!important}.field-input.is-invalid:focus{box-shadow:0 0 0 3px #ef44441f,0 1px 4px #ef44441a!important}.field-input.textarea{resize:vertical;min-height:100px;height:auto;padding:12px 16px!important}input[type=time].time-input{cursor:pointer}input[type=time].time-input::-webkit-calendar-picker-indicator{cursor:pointer;opacity:.7;filter:invert(30%)}input[type=time].time-input::-webkit-calendar-picker-indicator:hover{opacity:1}select.field-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}select.field-input:disabled{cursor:not-allowed}.dropdown-search-wrapper{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--cc-sf-input-border, #E5E7EB);background:var(--cc-sf-input-bg, #ffffff)}.dropdown-search-wrapper .dropdown-search-icon{font-size:18px;width:18px;height:18px;color:var(--cc-sf-input-placeholder, #9CA3AF);flex-shrink:0}.dropdown-search-wrapper .dropdown-search-input{flex:1;border:none;outline:none;background:transparent;font-size:.875rem;color:var(--cc-sf-label-color, #111827);font-family:inherit}.dropdown-search-wrapper .dropdown-search-input::placeholder{color:var(--cc-sf-input-placeholder, #C4C9D4)}.dropdown-search-wrapper .dropdown-search-clear{font-size:18px;width:18px;height:18px;color:var(--cc-sf-input-placeholder, #9CA3AF);flex-shrink:0;transition:color .15s}.dropdown-search-wrapper .dropdown-search-clear:hover{color:var(--cc-sf-label-color, #111827)}.multi-select-wrapper{position:relative}.multi-select-wrapper .multi-select-trigger{min-height:var(--cc-sf-input-height, 44px);height:auto;-webkit-user-select:none;user-select:none}.multi-select-wrapper .multi-select-trigger.ms-open{border-color:var(--cc-sf-input-focus-border, #6366F1)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important}.multi-select-wrapper .multi-select-trigger .multi-select-value{flex:1;color:var(--cc-sf-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.multi-select-wrapper .multi-select-trigger .multi-select-placeholder{flex:1;font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder, #C4C9D4)}.multi-select-wrapper .multi-select-trigger .multi-select-arrow{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--cc-sf-label-color, #6B7280);flex-shrink:0}.multi-select-wrapper .multi-select-panel{position:absolute;top:calc(100% + 4px);left:0;right:0;background:var(--cc-sf-input-bg, #ffffff);border:1.5px solid var(--cc-sf-input-border, #D1D5DB);border-radius:var(--cc-sf-input-radius, 9px);box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f;z-index:1050;display:flex;flex-direction:column;overflow:hidden;max-height:320px}.multi-select-wrapper .multi-select-options-list{flex:1;overflow-y:auto;max-height:240px}.multi-select-wrapper .multi-select-options-list::-webkit-scrollbar{width:4px}.multi-select-wrapper .multi-select-options-list::-webkit-scrollbar-thumb{background:var(--cc-sf-input-border, #D1D5DB);border-radius:2px}.multi-select-wrapper .multi-select-option{padding:8px 12px;border-bottom:1px solid var(--cc-sf-input-border, #F3F4F6);transition:background .1s}.multi-select-wrapper .multi-select-option:last-of-type{border-bottom:none}.multi-select-wrapper .multi-select-option:hover{background:var(--cc-sf-input-hover-bg, #F9FAFB)}.multi-select-wrapper .multi-select-option input[type=checkbox]{flex-shrink:0;cursor:pointer;accent-color:var(--cc-sf-selected-color, #6366F1);width:15px;height:15px}.multi-select-wrapper .multi-select-option.multi-select-all{border-bottom:1px solid var(--cc-sf-input-border, #E5E7EB);background:var(--cc-sf-input-bg, #FAFBFC)}.multi-select-wrapper .multi-select-empty{padding:12px;text-align:center}.multi-select-wrapper.is-invalid .multi-select-trigger{border-color:var(--cc-sf-error-border, #EF4444)!important;background-color:var(--cc-sf-error-bg, #FFF5F5)!important}.single-select-wrapper{position:relative}.single-select-wrapper .single-select-trigger{min-height:var(--cc-sf-input-height, 44px);height:auto;-webkit-user-select:none;user-select:none}.single-select-wrapper .single-select-trigger.ss-open{border-color:var(--cc-sf-input-focus-border, #6366F1)!important;box-shadow:0 0 0 3px #6366f124,0 1px 4px #6366f11a!important}.single-select-wrapper .single-select-trigger .single-select-value{flex:1;color:var(--cc-sf-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.single-select-wrapper .single-select-trigger .single-select-placeholder{flex:1;font-weight:400;font-size:14px;color:var(--cc-sf-input-placeholder, #C4C9D4)}.single-select-wrapper .single-select-trigger .single-select-arrow{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--cc-sf-label-color, #6B7280);flex-shrink:0}.single-select-wrapper .single-select-panel{position:absolute;top:calc(100% + 4px);left:0;right:0;background:var(--cc-sf-input-bg, #ffffff);border:1.5px solid var(--cc-sf-input-border, #D1D5DB);border-radius:var(--cc-sf-input-radius, 9px);box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f;z-index:1050;display:flex;flex-direction:column;overflow:hidden;max-height:320px}.single-select-wrapper .single-select-options-list{flex:1;overflow-y:auto;max-height:240px}.single-select-wrapper .single-select-options-list::-webkit-scrollbar{width:4px}.single-select-wrapper .single-select-options-list::-webkit-scrollbar-thumb{background:var(--cc-sf-input-border, #D1D5DB);border-radius:2px}.single-select-wrapper .single-select-option{padding:8px 12px;border-bottom:1px solid var(--cc-sf-input-border, #F3F4F6);transition:background .1s;justify-content:space-between}.single-select-wrapper .single-select-option:last-of-type{border-bottom:none}.single-select-wrapper .single-select-option:hover{background:var(--cc-sf-input-hover-bg, #F9FAFB)}.single-select-wrapper .single-select-option.selected{background:var(--cc-sf-input-hover-bg, #F0F5FF);color:var(--cc-sf-selected-color, #6366F1)}.single-select-wrapper .single-select-option .single-select-check{font-size:18px;width:18px;height:18px;color:var(--cc-sf-selected-color, #6366F1)}.single-select-wrapper.is-invalid .single-select-trigger{border-color:var(--cc-sf-error-border, #EF4444)!important;background-color:var(--cc-sf-error-bg, #FFF5F5)!important}.char-count-hint{font-style:normal;line-height:100%;letter-spacing:.02em;margin-top:.4rem}.radio-group.layout-column,.checkbox-group.layout-column{display:grid!important;grid-template-columns:repeat(12,1fr);gap:16px;width:100%}.radio-group.layout-row,.checkbox-group.layout-row{flex-direction:column!important;gap:12px;width:100%}.radio-label input,.checkbox-label input{cursor:pointer;accent-color:var(--cc-sf-chip-selected-bg, #F05A28)}.radio-label.card-item,.checkbox-label.card-item{display:flex!important;flex-direction:row-reverse!important;justify-content:space-between!important;align-items:center!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB);border-radius:12px;padding:16px 20px;box-sizing:border-box;transition:all .2s ease;background:var(--cc-sf-input-bg, #ffffff);margin-bottom:0}.radio-label.card-item input,.checkbox-label.card-item input{margin-left:16px}.radio-label.card-item.selected,.checkbox-label.card-item.selected{border-color:var(--cc-sf-selected-color);background-color:#f05a280d}.radio-label.card-item .option-content .label-text,.checkbox-label.card-item .option-content .label-text,.checkbox-single .checkbox-label{font-weight:var(--cc-sf-label-weight, 500)}.chip-label{transition:var(--cc-sf-input-transition, all .2s ease)}.chip-label:hover{background:var(--cc-sf-chip-hover-bg, #F3F4F6)}.chip-label.selected{background:var(--cc-sf-selected-color);color:var(--cc-sf-chip-selected-color, #ffffff);border-color:var(--cc-sf-selected-color)}.switch{width:50px;height:24px;display:inline-block}.switch input{opacity:0;width:0;height:0;position:absolute}.switch input:checked+.slider{background-color:var(--cc-sf-switch-track-on)!important}.switch input:checked+.slider:before{transform:translate(26px)}.switch .slider{inset:0;transition:.4s;background-color:var(--cc-sf-switch-track-off);border-radius:24px}.switch .slider:before{position:absolute;content:\"\";height:18px;width:18px;left:3px;bottom:3px;background-color:var(--cc-sf-switch-thumb);transition:.4s;border-radius:50%}.rating-group .star{transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star mat-icon{font-size:var(--cc-sf-star-size, 28px);width:var(--cc-sf-star-size, 28px);height:var(--cc-sf-star-size, 28px);line-height:var(--cc-sf-star-size, 28px);color:var(--cc-sf-star-empty, #D1D5DB);transition:var(--cc-sf-input-transition, all .2s ease)}.rating-group .star.filled mat-icon,.rating-group .star.half mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.rating-group .star:hover mat-icon{color:var(--cc-sf-star-filled, #F59E0B)}.password-wrapper .password-toggle{right:.625rem;top:50%;transform:translateY(-50%);line-height:1;transition:color var(--cc-sf-input-transition, .2s ease)}.password-wrapper .password-toggle mat-icon.eye-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem}.password-wrapper .password-toggle:hover{color:var(--cc-sf-label-color, #374151)}.password-wrapper .password-toggle:focus{outline:none}.group-section-wrapper .group-label{font-size:var(--cc-sf-section-label-size, 1rem);font-weight:var(--cc-sf-section-label-weight, 600);color:var(--cc-sf-section-label-color, #1F2937);margin:0 0 16px;padding-left:12px;padding-top:2px;padding-bottom:2px;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);line-height:1.4}.group-section-wrapper .group-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--cc-sf-grid-gap, 16px);align-items:start}@media (max-width: 640px){.group-section-wrapper .group-fields.sf-grid{grid-template-columns:1fr}.group-section-wrapper .group-fields.sf-grid .sf-col{grid-column:span 12!important}}.group-section-wrapper .group-accordion-instance{border:var(--cc-sf-instance-border, 1px solid #E5E7EB);border-radius:var(--cc-sf-section-border-radius-inner, 8px);margin-bottom:8px;overflow:hidden;transition:border-color .2s ease}.group-section-wrapper .group-accordion-instance:last-of-type{margin-bottom:0}.group-section-wrapper .group-accordion-instance .group-accordion-header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px;background:var(--cc-sf-repeater-accordion-header-bg, #F9FAFB);cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header:hover{background:var(--cc-sf-repeater-accordion-active-bg, #EFF6FF)}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-badge{width:22px;height:22px;border-radius:50%;background:var(--cc-sf-repeater-badge-bg, #E5E7EB);color:var(--cc-sf-repeater-badge-color, #374151);font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0}.group-section-wrapper .group-accordion-instance .group-accordion-header .instance-title{font-size:var(--cc-sf-instance-num-size, .8125rem);font-weight:600;color:var(--cc-sf-repeater-accordion-header-color, #1F2937)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:var(--cc-sf-btn-remove-color, #E53E3E);padding:4px;border-radius:4px;line-height:1;display:flex;align-items:center;transition:background .15s ease}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-remove-btn:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.group-section-wrapper .group-accordion-instance .group-accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:var(--cc-sf-instance-num-color, #4B5563)}.group-section-wrapper .group-accordion-instance .group-accordion-body{padding:var(--cc-sf-instance-padding, 16px);background:var(--cc-sf-instance-bg, #F9FAFB);border-top:var(--cc-sf-instance-divider, 1px dashed #D1D5DB)}.group-section-wrapper .btn-add-group{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:10px 20px;margin-top:12px;background:var(--cc-sf-btn-add-bg, transparent);color:var(--cc-sf-btn-add-color, #3B82F6);border:var(--cc-sf-btn-add-border, 1px dashed #CBD5E1);border-radius:var(--cc-sf-btn-add-radius, 6px);cursor:pointer;font-family:inherit;font-size:var(--cc-sf-btn-font-size, .875rem);font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.group-section-wrapper .btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.group-section-wrapper .btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.group-section-wrapper .group-instance:last-child{margin-bottom:0}.group-section-wrapper.multi-save-active{border:none;box-shadow:none;padding:0;background:transparent}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button{color:var(--ms-btn-add-color, #3B82F6);font-weight:600;font-size:.875rem;padding:8px 12px}.group-section-wrapper.multi-save-active .multi-save-header .btn-add-multi ::ng-deep button:hover{color:var(--ms-btn-add-hover, #2563EB);background-color:var(--cc-sf-btn-add-hover-bg, #EFF6FF)}.group-section-wrapper.multi-save-active .group-instance.is-card{cursor:pointer;transition:all .2s ease-in-out}.group-section-wrapper.multi-save-active .group-instance.is-card:hover{box-shadow:var(--ms-card-shadow-hover, 0 8px 24px rgba(0, 0, 0, .08));border-color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-title{white-space:nowrap;text-overflow:ellipsis}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-content .card-desc{line-height:1.4;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view.is-expanded .card-content .card-desc{-webkit-line-clamp:unset;line-clamp:unset}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon{font-size:22px;width:22px;height:22px;color:var(--cc-sf-hint-color, #9CA3AF);transition:color .2s}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-delete:hover{color:var(--cc-sf-error-border, #DC2626)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-edit:hover{color:var(--cc-sf-input-focus-border, #3B82F6)}.group-section-wrapper.multi-save-active .group-instance.is-card .card-view .card-actions mat-icon.icon-expand{color:var(--cc-sf-input-disabled-border, #E5E7EB)}.btn-remove{transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-remove mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.btn-remove:hover{background:var(--cc-sf-btn-remove-hover-bg, #FED7D7)}.btn-add-group{font-weight:var(--cc-sf-btn-font-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.btn-add-group mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.btn-add-group:hover{background:var(--cc-sf-btn-add-hover-bg, #EFF6FF);border-color:var(--cc-sf-btn-add-hover-border, #BFDBFE)}.upload-drop-zone{background-color:var(--cc-sf-dropzone-bg, #F8FAFC);border:var(--cc-sf-dropzone-border, 1.5px dashed #CBD5E1);border-radius:var(--cc-sf-dropzone-radius, 12px);transition:background-color .2s ease,border-color .2s ease}.upload-drop-zone:hover{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-hover-border, #93C5FD)}.upload-drop-zone.drag-over{background-color:var(--cc-sf-dropzone-hover-bg, #EFF6FF);border-color:var(--cc-sf-dropzone-over-border, #3B82F6);box-shadow:var(--cc-sf-dropzone-over-shadow, 0 0 0 4px rgba(59, 130, 246, .12))}.upload-drop-zone.is-invalid{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.upload-icon-wrap .dropzone-icon-pill{width:52px;height:52px;border-radius:50%;background:var(--cc-sf-dropzone-icon-bg, rgba(59, 130, 246, .1))}.upload-icon-wrap mat-icon.upload-cloud-icon{font-size:28px;width:28px;height:28px;line-height:28px;color:var(--cc-sf-accent-color, #3B82F6)}.upload-main-text{color:var(--cc-sf-label-color, #1E293B)}.upload-sub-text{color:var(--cc-sf-hint-color, #64748B)}.upload-link{color:var(--cc-sf-dropzone-link-color, #3B82F6);font-weight:500}.upload-formats{color:var(--cc-sf-dropzone-link-color, #3B82F6)}.upload-size-badge{display:inline-block;padding:2px 8px;border-radius:20px;background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-hint-color, #6B7280);font-weight:500}.uploaded-item{background:var(--cc-sf-uploaded-item-bg, #ffffff);border:var(--cc-sf-uploaded-item-border, 1px solid #E2E8F0);border-radius:var(--cc-sf-uploaded-item-radius, 8px);transition:box-shadow .15s ease}.uploaded-item:hover{box-shadow:0 2px 6px #0000000f}.uploaded-item mat-icon.file-type-icon{font-size:20px;width:20px;height:20px;line-height:20px;flex-shrink:0;color:var(--cc-sf-hint-color, #64748B)}.uploaded-item .file-thumb{width:36px;height:36px;object-fit:cover;flex-shrink:0}.uploaded-item .file-info{min-width:0;gap:2px}.uploaded-item .file-info .file-name{white-space:nowrap;text-overflow:ellipsis}.uploaded-item .file-remove-btn{flex-shrink:0;width:32px;height:32px;background:none;border:none;cursor:pointer;color:var(--cc-sf-uploaded-remove-color, #94A3B8);padding:0;display:flex;align-items:center;justify-content:center;transition:color .15s ease,background .15s ease}.uploaded-item .file-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.uploaded-item .file-remove-btn:hover:not(:disabled){color:var(--cc-sf-uploaded-remove-hover-color, #DC2626);background:var(--cc-sf-uploaded-remove-hover-bg, #FEF2F2)}.uploaded-item .file-remove-btn:disabled{opacity:.4;cursor:not-allowed}.uploaded-item.uploading{background:var(--cc-sf-uploaded-uploading-bg, #F8FAFC);border-color:var(--cc-sf-uploaded-uploading-border, #CBD5E1);opacity:.85}.upload-spinner{width:20px;height:20px;flex-shrink:0;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}@keyframes cc-spin{to{transform:rotate(360deg)}}.uploading-label{font-style:italic}.input-group{align-items:stretch}.input-group .field-input{flex:1;width:auto}.input-prefix+.input-group .field-input{border-top-left-radius:0;border-bottom-left-radius:0}.input-group .field-input:has(+.input-suffix){border-top-right-radius:0;border-bottom-right-radius:0}.input-group .field-input.has-icon-right{padding-right:3rem}.input-group.readonly .field-input{cursor:default}.input-prefix,.input-suffix{display:flex!important;align-items:center;white-space:nowrap;padding:0 14px;background-color:var(--cc-sf-input-disabled-bg);border:1px solid var(--cc-sf-input-border);font-size:.875rem;color:var(--cc-sf-hint-color);-webkit-user-select:none;user-select:none}.input-prefix{border-right:none;border-top-left-radius:var(--cc-sf-input-radius, 8px);border-bottom-left-radius:var(--cc-sf-input-radius, 8px)}.input-suffix{border-left:none;border-top-right-radius:var(--cc-sf-input-radius, 8px);border-bottom-right-radius:var(--cc-sf-input-radius, 8px)}.readonly-icons{right:.875rem;top:50%;transform:translateY(-50%)}.readonly-icons mat-icon.lock-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem;opacity:.5;color:var(--cc-sf-hint-color, #6B7280)}.suffix-action-icons{right:.875rem;top:50%;transform:translateY(-50%);z-index:1;pointer-events:auto}.suffix-action-icons mat-icon.suffix-action-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;line-height:1.125rem;color:var(--cc-sf-hint-color, #6B7280);cursor:pointer;transition:color .2s ease,transform .15s ease}.suffix-action-icons mat-icon.suffix-action-icon:hover{color:var(--cc-sf-text-color, #202124);transform:scale(1.15)}.date-icon-wrapper{right:.5rem;top:50%;transform:translateY(-50%);pointer-events:auto}.date-icon-wrapper .mat-icon-button{width:32px;height:32px;line-height:32px}.subfields-group-wrapper .subfields-row{transition:all .2s ease}.subfields-group-wrapper .subfields-row.is-invalid .subfield-item ::ng-deep .field-input{border-color:var(--cc-sf-error-border, #DC2626);background-color:var(--cc-sf-error-bg, #FEF2F2)}.subfields-group-wrapper .subfields-row .subfield-item{min-width:0}.subfields-group-wrapper .subfields-row .subfield-item ::ng-deep .field-label{font-size:.75rem!important;margin-bottom:4px!important;font-weight:500!important;color:var(--cc-sf-hint-color, #6B7280)!important}.subfields-group-wrapper .subfields-row .subfield-separator{font-weight:700}.autocomplete-wrapper .ac-input{padding-left:40px!important}.autocomplete-wrapper .ac-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1;transition:color var(--cc-sf-input-transition, .2s ease)}.autocomplete-wrapper .ac-clear-btn{right:.6rem;transition:color .15s ease,background .15s ease}.autocomplete-wrapper .ac-clear-btn mat-icon{font-size:1rem;width:1rem;height:1rem;line-height:1rem}.autocomplete-wrapper .ac-clear-btn:hover{color:var(--cc-sf-label-color, #374151);background:var(--cc-sf-input-disabled-bg, #F3F4F6)}.autocomplete-wrapper .ac-clear-btn:focus{outline:none}.autocomplete-wrapper:focus-within .ac-search-icon{color:var(--cc-sf-accent-color, #3B82F6)}.autocomplete-wrapper.is-invalid .ac-input{border-color:var(--cc-sf-error-border)!important;background-color:var(--cc-sf-error-bg)}.autocomplete-wrapper.readonly .ac-input{background-color:var(--cc-sf-input-disabled-bg);color:var(--cc-sf-input-disabled-color, #6B7280);cursor:not-allowed;border-color:var(--cc-sf-input-disabled-border)!important}.ac-no-results{font-style:italic}::ng-deep .mat-mdc-autocomplete-panel,::ng-deep .mat-autocomplete-panel{background:var(--cc-sf-input-bg, #ffffff)!important;border-radius:var(--cc-sf-input-radius, 9px)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)!important;box-shadow:0 8px 24px #0000001a,0 2px 6px #0000000f!important;padding:4px 0!important;min-width:200px}::ng-deep .mat-mdc-autocomplete-panel mat-option,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option,::ng-deep .mat-mdc-autocomplete-panel .mat-option,::ng-deep .mat-autocomplete-panel mat-option,::ng-deep .mat-autocomplete-panel .mat-mdc-option,::ng-deep .mat-autocomplete-panel .mat-option{background:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #111827)!important;font-size:.875rem!important;padding:10px 16px!important;min-height:40px!important;line-height:1.4!important;display:flex!important;flex-direction:column!important;align-items:flex-start!important;transition:background var(--cc-sf-input-transition, .2s ease)!important}::ng-deep .mat-mdc-autocomplete-panel mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-mdc-autocomplete-panel .mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel mat-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel .mat-mdc-option:hover:not(.mat-option-disabled):not([disabled]),::ng-deep .mat-autocomplete-panel .mat-option:hover:not(.mat-option-disabled):not([disabled]){background:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}::ng-deep .mat-mdc-autocomplete-panel mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel mat-option.mdc-list-item--selected,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option.mdc-list-item--selected,::ng-deep .mat-mdc-autocomplete-panel .mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-mdc-autocomplete-panel .mat-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel mat-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel .mat-mdc-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel .mat-mdc-option.mdc-list-item--selected,::ng-deep .mat-autocomplete-panel .mat-option.mat-selected:not(.mat-option-multiple),::ng-deep .mat-autocomplete-panel .mat-option.mdc-list-item--selected{background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)!important;color:var(--cc-sf-selected-color, #6366F1)!important;font-weight:600!important}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-option-label,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-option-label,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-option-label,::ng-deep .mat-autocomplete-panel mat-option .ac-option-label,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-option-label,::ng-deep .mat-autocomplete-panel .mat-option .ac-option-label{font-weight:500;color:var(--cc-sf-label-color, #111827);font-size:.875rem;display:block}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-display-fields,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-display-fields,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-display-fields,::ng-deep .mat-autocomplete-panel mat-option .ac-display-fields,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-display-fields,::ng-deep .mat-autocomplete-panel .mat-option .ac-display-fields{align-items:center;line-height:1}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-item,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-item,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-item,::ng-deep .mat-autocomplete-panel mat-option .ac-df-item,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-item,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-item{display:inline-flex;align-items:center;font-size:.72rem;color:var(--cc-sf-hint-color, #6B7280);gap:3px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-chip,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-chip,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-chip,::ng-deep .mat-autocomplete-panel mat-option .ac-df-chip,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-chip,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-chip{background:var(--cc-sf-input-disabled-bg, #F3F4F6);border-radius:4px;padding:2px 6px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-text,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-text,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-text,::ng-deep .mat-autocomplete-panel mat-option .ac-df-text,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-text,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-text{color:var(--cc-sf-hint-color, #6B7280)}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-avatar,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-avatar,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel mat-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-avatar,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-avatar{width:24px;height:24px;border-radius:50%;object-fit:cover;border:1px solid var(--cc-sf-input-border, #D1D5DB);vertical-align:middle}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-label,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-label,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-label,::ng-deep .mat-autocomplete-panel mat-option .ac-df-label,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-label,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-label{font-weight:600;color:var(--cc-sf-hint-color, #9CA3AF);margin-right:2px}::ng-deep .mat-mdc-autocomplete-panel mat-option .ac-df-icon,::ng-deep .mat-mdc-autocomplete-panel .mat-mdc-option .ac-df-icon,::ng-deep .mat-mdc-autocomplete-panel .mat-option .ac-df-icon,::ng-deep .mat-autocomplete-panel mat-option .ac-df-icon,::ng-deep .mat-autocomplete-panel .mat-mdc-option .ac-df-icon,::ng-deep .mat-autocomplete-panel .mat-option .ac-df-icon{font-size:11px;width:11px;height:11px;line-height:11px;color:var(--cc-sf-hint-color, #9CA3AF);flex-shrink:0}.mu-layout{grid-template-columns:1fr 1fr;gap:32px}@media (max-width: 768px){.mu-layout{grid-template-columns:1fr}}.mu-title{font-weight:700;line-height:1.3}.mu-badge{white-space:nowrap;flex-shrink:0}.mu-description{line-height:1.6}.mu-feature-item .mu-check{width:16px;height:16px;line-height:16px;flex-shrink:0}.mu-right{min-height:260px}.mu-right-empty{min-height:250px;max-width:400px;box-shadow:0 2px 10px #0000000d;transition:box-shadow .2s ease}.mu-right-empty:hover{cursor:pointer;box-shadow:0 4px 16px #0000001a}.mu-right-empty .mu-right-empty-icon{width:52px;height:52px;line-height:52px;opacity:.3}.mu-right-empty p{margin:0;font-size:.85rem}.media-add-container{display:inline-block}.media-add-container ::ng-deep button{display:flex;align-items:center;gap:6px}.media-add-container ::ng-deep button .menu-chevron{width:18px;height:18px;line-height:18px;transition:transform .2s ease}.media-dropdown{top:calc(100% + 6px);left:0;z-index:200;min-width:240px;box-shadow:var(--mu-dropdown-shadow, 0 8px 32px rgba(0, 0, 0, .12));animation:mu-fade-in .15s ease}@keyframes mu-fade-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.media-dropdown-item{transition:background .15s ease}.media-dropdown-item:last-child{border-bottom:none}.media-dropdown-item:hover{background:var(--cc-sf-dropzone-hover-bg, #F0F9FF)}.media-drop-icon{width:36px;height:36px;flex-shrink:0}.media-drop-icon mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.media-drop-icon--video{background:var(--mu-icon-video-bg, #FFF0F0);color:var(--mu-icon-video-color, #EF4444)}.media-drop-icon--device{background:var(--mu-icon-device-bg, #EFF6FF);color:var(--mu-icon-device-color, #3B82F6)}.media-drop-icon--library{background:var(--mu-icon-library-bg, #F0FDF4);color:var(--mu-icon-library-color, #22C55E)}.media-drop-text{gap:2px}.youtube-input-panel{animation:mu-fade-in .18s ease}.youtube-panel-label mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:var(--mu-icon-video-color, #EF4444)}.youtube-input-row{align-items:stretch}.media-menu-backdrop{position:fixed;inset:0;z-index:100}.media-upload-status{animation:mu-fade-in .2s ease}.media-upload-status .status-icon{width:18px;height:18px;line-height:18px}.media-carousel-main{max-width:400px;height:var(--mu-carousel-height, 250px)}.carousel-viewer{inset:0}.carousel-viewer .carousel-image{object-fit:cover}.carousel-viewer .carousel-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.carousel-nav{top:50%;transform:translateY(-50%);z-index:10;width:40px;height:40px;box-shadow:0 2px 8px #0003;transition:background .2s ease,opacity .2s ease;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.carousel-nav mat-icon{font-size:22px;width:22px;height:22px;line-height:22px;color:#1e293b}.carousel-nav:hover:not(:disabled){background:#fff}.carousel-nav:disabled{opacity:.3;cursor:not-allowed}.carousel-nav--prev{left:12px}.carousel-nav--next{right:12px}.carousel-remove-btn{top:10px;right:10px;z-index:10;width:32px;height:32px;transition:background .2s ease}.carousel-remove-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px;color:#fff}.carousel-remove-btn:hover:not(:disabled){background:#dc2626d9}.carousel-remove-btn:disabled{opacity:.4;cursor:not-allowed}.carousel-dots{bottom:10px;left:50%;transform:translate(-50%);z-index:10}.carousel-dot{width:8px;height:8px;transition:background .2s ease,transform .2s ease}.carousel-dot.active{background:#fff;transform:scale(1.3)}.media-thumbnail-strip{max-width:400px;overflow-x:auto}.media-thumbnail-strip::-webkit-scrollbar{height:4px}.media-thumbnail-strip::-webkit-scrollbar-thumb{background:var(--cc-sf-input-disabled-border, #D1D5DB);border-radius:2px}.media-thumb{flex-shrink:0;width:72px;height:52px;transition:border-color .2s ease,transform .15s ease}.media-thumb.active{border-color:var(--mu-thumb-active-border, var(--cc-sf-accent-color, #3B82F6));transform:scale(1.04)}.media-thumb:hover:not(.active){border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.media-thumb .thumb-img{object-fit:cover}.media-thumb .thumb-yt-placeholder mat-icon{font-size:28px;width:28px;height:28px;line-height:28px}.media-thumb .thumb-uploading .thumb-spinner{width:20px;height:20px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.media-library-portal-host{position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;visibility:hidden;opacity:0;pointer-events:none;transition:opacity .2s ease,visibility .2s ease}.media-library-portal-host.is-open{visibility:visible;opacity:1;pointer-events:auto}.media-library-portal-host.is-open .media-library-modal{transform:scale(1) translateY(0)}.media-library-overlay{position:absolute;inset:0;background:#00000080;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.media-library-modal{position:relative;z-index:10000;width:90vw;max-width:900px;max-height:90vh;background:#fff;border-radius:16px;box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;transform:scale(.95) translateY(10px);transition:transform .3s cubic-bezier(.175,.885,.32,1.275)}.library-modal-header{flex-shrink:0}.library-modal-title{font-weight:700}.library-modal-subtitle{line-height:1.5;max-width:600px}.library-close-btn{width:32px;height:32px;transition:background .15s ease,color .15s ease}.library-close-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-close-btn:hover{background:var(--cc-sf-input-disabled-bg, #F3F4F6);color:var(--cc-sf-label-color, #374151)}.library-loading mat-icon,.library-empty mat-icon{font-size:40px;width:40px;height:40px;line-height:40px;opacity:.5}.lib-spinner{width:36px;height:36px;border-top-color:var(--cc-sf-accent-color, #3B82F6);animation:cc-spin .7s linear infinite}.library-error{flex-shrink:0}.library-error mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.library-grid{grid-template-columns:repeat(5,1fr);max-height:50vh;overflow-y:auto}.library-grid::-webkit-scrollbar{width:8px}.library-grid::-webkit-scrollbar-track{background:#f1f1f1}.library-grid::-webkit-scrollbar-thumb{background:#c1c1c1;border-radius:10px;border:2px solid #F1F1F1}.library-grid-item{aspect-ratio:1/1;transition:all .3s cubic-bezier(.4,0,.2,1);box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -1px #0000000f}.library-grid-item:hover{transform:translateY(-4px) scale(1.02);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a}.library-grid-item.selected{border-color:var(--cc-sf-accent-color, #3B82F6)}.library-grid-item.selected .library-grid-img{opacity:.7}.library-grid-item:hover .library-overlay-hover{opacity:1}.library-grid-img{object-fit:cover}.library-overlay-hover{inset:0;opacity:0;transition:opacity .15s ease}.library-check{top:6px;right:6px;width:22px;height:22px;box-shadow:0 1px 4px #00000026}.library-check mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.library-modal-footer{flex-shrink:0}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary{background-color:var(--cc-sf-accent-color, #3B82F6)!important;border-color:var(--cc-sf-accent-color, #3B82F6)!important;color:#fff!important;font-weight:600;padding-left:32px;padding-right:32px}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:hover{background-color:var(--cc-sf-btn-primary-hover-bg, #2563EB)!important}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-primary:disabled{background-color:#93c5fd!important;cursor:not-allowed}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline{font-weight:600;padding-left:24px;padding-right:24px;border-color:#d1d5db;color:#374151}.library-modal-footer .library-footer-actions ::ng-deep .cc-btn-outline:hover{background-color:#f9fafb}.location-subtitle{line-height:1.5}.loc-tab-btn ::ng-deep button{width:100%}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning){background-color:var(--cc-sf-input-bg, #ffffff)!important;color:var(--cc-sf-label-color, #000000)!important;border:1px solid var(--cc-sf-input-disabled-border, #E5E7EB)}.loc-tab-btn ::ng-deep button:not(.cc-btn-warning):hover{background-color:var(--cc-sf-input-disabled-bg, #F3F4F6)!important}.loc-venue-item{transition:box-shadow .15s ease,border-color .15s ease}.loc-venue-item:hover{box-shadow:0 2px 8px #0000000f;border-color:var(--cc-sf-input-hover-border, #9CA3AF)}.loc-venue-search-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-venue-text{white-space:nowrap;text-overflow:ellipsis}.loc-action-btn{transition:background .15s ease,color .15s ease;flex-shrink:0}.loc-action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.loc-action-btn.loc-delete-btn{color:var(--loc-delete-color, #E53E3E)}.loc-action-btn.loc-delete-btn:hover{background:var(--cc-sf-error-bg, #FEF2F2)}.loc-action-btn.loc-edit-btn{color:var(--cc-sf-hint-color, #9CA3AF)}.loc-action-btn.loc-edit-btn:hover{color:var(--cc-sf-input-focus-border, #3B82F6);background:var(--cc-sf-dropzone-hover-bg, #EFF6FF)}.loc-search-icon{left:.75rem;width:1.1rem;height:1.1rem;line-height:1.1rem;z-index:1}.loc-suggestions-panel{top:calc(100% + 4px);left:0;right:0;z-index:300;box-shadow:0 8px 24px #0000001a;animation:mu-fade-in .15s ease;max-height:260px;overflow-y:auto}.loc-suggestion-item{transition:background .12s ease}.loc-suggestion-item:hover,.loc-suggestion-item:focus{background:var(--loc-suggestion-hover-bg, #F0F9FF)}.loc-suggestion-item:not(:last-child){border-bottom:1px solid var(--cc-sf-input-disabled-border, #F3F4F6)}.loc-suggestion-icon{width:18px;height:18px;line-height:18px;flex-shrink:0}.loc-suggestion-text{white-space:nowrap;text-overflow:ellipsis}.loc-add-btn{transition:opacity .15s ease}.loc-add-btn mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.loc-add-btn:hover{opacity:.8}.loc-map-container{box-shadow:0 2px 10px #0000000f}.loc-tba-panel{min-height:120px}.loc-tba-icon{width:40px;height:40px;line-height:40px;opacity:.6}.loc-tba-text{line-height:1.6;max-width:360px}.radio-label{display:flex!important}.radio-label .option-content{padding-left:10px}\n"] }]
|
|
2658
2798
|
}], ctorParameters: () => [{ type: i1$3.FormBuilder }, { type: ExpressionService }, { type: i3.HttpClient }], propDecorators: { config: [{
|
|
2659
2799
|
type: Input
|
|
2660
2800
|
}], controller: [{
|
|
@@ -2775,11 +2915,11 @@ class FormSectionComponent {
|
|
|
2775
2915
|
return result;
|
|
2776
2916
|
}
|
|
2777
2917
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormSectionComponent, deps: [{ token: i1$3.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
2778
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FormSectionComponent, isStandalone: false, selector: "lib-form-section", inputs: { config: "config", controller: "controller", formGroup: "formGroup" }, ngImport: i0, template: "<div class=\"form-section-container\">\r\n <h3 class=\"section-label\" *ngIf=\"config.label && !config.allowMulti\">{{ config.label }}</h3>\r\n\r\n <!-- \u2550\u2550 Repeater (allowMulti) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"config.allowMulti\">\r\n <h3 class=\"section-label\">{{ config.label }}</h3>\r\n\r\n <div *ngFor=\"let instanceGroup of instanceGroups; let i = index\"\r\n class=\"accordion-instance\"\r\n [class.is-expanded]=\"isExpanded(i)\">\r\n\r\n <!-- Accordion header (always visible) -->\r\n <div class=\"accordion-header\" (click)=\"toggleInstance(i)\" role=\"button\" [attr.aria-expanded]=\"isExpanded(i)\">\r\n <div class=\"accordion-header-left\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceGroups.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeInstance(i)\"\r\n aria-label=\"Remove instance\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body (always mounted so form controls survive collapse) -->\r\n <div class=\"accordion-body\" [hidden]=\"!isExpanded(i)\">\r\n <div class=\"section-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instanceGroup\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-section\" (click)=\"addInstance()\">\r\n <mat-icon>add</mat-icon> Add {{ config.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2550\u2550 Non-repeater (single instance) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"!config.allowMulti\">\r\n <div class=\"section-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"flatFormGroup\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n</div>\r\n", styles: ["@keyframes section-card-in{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.form-section-container{background:#fff;border:1px solid #EAECF0;border-radius:14px;padding:22px 24px 24px;margin-bottom:14px;box-shadow:0 1px 2px #0000000a,0 4px 12px #6366f10a;animation:section-card-in .3s cubic-bezier(.4,0,.2,1) both;transition:box-shadow .2s ease}.form-section-container:hover{box-shadow:0 1px 2px #0000000a,0 6px 20px #6366f114}.form-section-container:last-child{margin-bottom:0}.form-section-container .section-label{display:flex;align-items:center;gap:10px;font-size:.9375rem;font-weight:700;color:#111827;margin:0 0 20px;padding-bottom:14px;border-bottom:1px solid #F3F4F6;letter-spacing:-.01em}.form-section-container .section-label:before{content:\"\";display:inline-block;width:4px;height:18px;border-radius:4px;background:linear-gradient(180deg,#6366f1,#8b5cf6);flex-shrink:0}.form-section-container .section-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:18px 20px;align-items:start}@media(max-width:640px){.form-section-container .section-fields.sf-grid{grid-template-columns:1fr}.form-section-container .section-fields.sf-grid .sf-col{grid-column:span 12!important}}.form-section-container .accordion-instance{border:1px solid #E8EAF0;border-radius:10px;margin-bottom:10px;overflow:hidden;transition:border-color .2s ease,box-shadow .2s ease;background:#fafbff}.form-section-container .accordion-instance:last-of-type{margin-bottom:0}.form-section-container .accordion-instance.is-expanded{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f112}.form-section-container .accordion-instance .accordion-header{display:flex;justify-content:space-between;align-items:center;padding:11px 16px;background:#f8f9ff;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.form-section-container .accordion-instance .accordion-header:hover{background:#eef0ff}.form-section-container .accordion-instance .accordion-header .accordion-header-left{display:flex;align-items:center;gap:10px}.form-section-container .accordion-instance .accordion-header .instance-badge{width:24px;height:24px;border-radius:6px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.form-section-container .accordion-instance .accordion-header .instance-title{font-size:.8125rem;font-weight:600;color:#1f2937}.form-section-container .accordion-instance .accordion-header .accordion-header-right{display:flex;align-items:center;gap:6px}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:#ef4444;padding:4px 6px;border-radius:6px;line-height:1;display:flex;align-items:center;transition:background .15s ease,color .15s ease}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn:hover{background:#fee2e2;color:#dc2626}.form-section-container .accordion-instance .accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:#6b7280;transition:transform .2s ease}.form-section-container .accordion-instance .accordion-body{padding:18px 16px;background:#fff;border-top:1px solid #E8EAF0}.form-section-container .btn-add-section{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:11px 20px;margin-top:14px;background:transparent;color:#6366f1;border:1.5px dashed #C7D2FE;border-radius:8px;cursor:pointer;font-family:inherit;font-size:.8125rem;font-weight:600;transition:all .2s ease;letter-spacing:.01em}.form-section-container .btn-add-section mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .btn-add-section:hover{background:#eef2ff;border-color:#a5b4fc;border-style:solid;transform:translateY(-1px);box-shadow:0 2px 8px #6366f11f}.form-section-container .btn-add-section:active{transform:translateY(0)}\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$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FormFieldComponent, selector: "lib-form-field", inputs: ["config", "controller", "formGroup", "allowMulti"] }] });
|
|
2918
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FormSectionComponent, isStandalone: false, selector: "lib-form-section", inputs: { config: "config", controller: "controller", formGroup: "formGroup" }, ngImport: i0, template: "<div class=\"form-section-container\">\r\n <h3 class=\"section-label\" *ngIf=\"config.label && !config.allowMulti\">{{ config.label }}</h3>\r\n\r\n <!-- \u2550\u2550 Repeater (allowMulti) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"config.allowMulti\">\r\n <h3 class=\"section-label\">{{ config.label }}</h3>\r\n\r\n <div *ngFor=\"let instanceGroup of instanceGroups; let i = index\"\r\n class=\"accordion-instance\"\r\n [class.is-expanded]=\"isExpanded(i)\">\r\n\r\n <!-- Accordion header (always visible) -->\r\n <div class=\"accordion-header\" (click)=\"toggleInstance(i)\" role=\"button\" [attr.aria-expanded]=\"isExpanded(i)\">\r\n <div class=\"accordion-header-left\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceGroups.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeInstance(i)\"\r\n aria-label=\"Remove instance\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body (always mounted so form controls survive collapse) -->\r\n <div class=\"accordion-body\" [hidden]=\"!isExpanded(i)\">\r\n <div class=\"section-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instanceGroup\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-section\" (click)=\"addInstance()\">\r\n <mat-icon>add</mat-icon> Add {{ config.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2550\u2550 Non-repeater (single instance) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"!config.allowMulti\">\r\n <div class=\"section-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"flatFormGroup\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n</div>\r\n", styles: ["@keyframes section-card-in{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.form-section-container{background:#fff;border:1px solid #EAECF0;border-radius:14px;padding:22px 24px 24px;margin-bottom:14px;box-shadow:0 1px 2px #0000000a,0 4px 12px #6366f10a;animation:section-card-in .3s cubic-bezier(.4,0,.2,1) both;transition:box-shadow .2s ease}.form-section-container:hover{box-shadow:0 1px 2px #0000000a,0 6px 20px #6366f114}.form-section-container:last-child{margin-bottom:0}.form-section-container .section-label{display:flex;align-items:center;gap:10px;font-size:.9375rem;font-weight:700;color:#111827;margin:0 0 20px;padding-bottom:14px;border-bottom:1px solid #F3F4F6;letter-spacing:-.01em}.form-section-container .section-label:before{content:\"\";display:inline-block;width:4px;height:18px;border-radius:4px;background:linear-gradient(180deg,#6366f1,#8b5cf6);flex-shrink:0}.form-section-container .section-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:18px 20px;align-items:start}@media (max-width: 640px){.form-section-container .section-fields.sf-grid{grid-template-columns:1fr}.form-section-container .section-fields.sf-grid .sf-col{grid-column:span 12!important}}.form-section-container .accordion-instance{border:1px solid #E8EAF0;border-radius:10px;margin-bottom:10px;overflow:hidden;transition:border-color .2s ease,box-shadow .2s ease;background:#fafbff}.form-section-container .accordion-instance:last-of-type{margin-bottom:0}.form-section-container .accordion-instance.is-expanded{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f112}.form-section-container .accordion-instance .accordion-header{display:flex;justify-content:space-between;align-items:center;padding:11px 16px;background:#f8f9ff;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.form-section-container .accordion-instance .accordion-header:hover{background:#eef0ff}.form-section-container .accordion-instance .accordion-header .accordion-header-left{display:flex;align-items:center;gap:10px}.form-section-container .accordion-instance .accordion-header .instance-badge{width:24px;height:24px;border-radius:6px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.form-section-container .accordion-instance .accordion-header .instance-title{font-size:.8125rem;font-weight:600;color:#1f2937}.form-section-container .accordion-instance .accordion-header .accordion-header-right{display:flex;align-items:center;gap:6px}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:#ef4444;padding:4px 6px;border-radius:6px;line-height:1;display:flex;align-items:center;transition:background .15s ease,color .15s ease}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn:hover{background:#fee2e2;color:#dc2626}.form-section-container .accordion-instance .accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:#6b7280;transition:transform .2s ease}.form-section-container .accordion-instance .accordion-body{padding:18px 16px;background:#fff;border-top:1px solid #E8EAF0}.form-section-container .btn-add-section{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:11px 20px;margin-top:14px;background:transparent;color:#6366f1;border:1.5px dashed #C7D2FE;border-radius:8px;cursor:pointer;font-family:inherit;font-size:.8125rem;font-weight:600;transition:all .2s ease;letter-spacing:.01em}.form-section-container .btn-add-section mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .btn-add-section:hover{background:#eef2ff;border-color:#a5b4fc;border-style:solid;transform:translateY(-1px);box-shadow:0 2px 8px #6366f11f}.form-section-container .btn-add-section:active{transform:translateY(0)}\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$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: FormFieldComponent, selector: "lib-form-field", inputs: ["config", "controller", "formGroup", "allowMulti"] }] });
|
|
2779
2919
|
}
|
|
2780
2920
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FormSectionComponent, decorators: [{
|
|
2781
2921
|
type: Component,
|
|
2782
|
-
args: [{ selector: 'lib-form-section', standalone: false, template: "<div class=\"form-section-container\">\r\n <h3 class=\"section-label\" *ngIf=\"config.label && !config.allowMulti\">{{ config.label }}</h3>\r\n\r\n <!-- \u2550\u2550 Repeater (allowMulti) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"config.allowMulti\">\r\n <h3 class=\"section-label\">{{ config.label }}</h3>\r\n\r\n <div *ngFor=\"let instanceGroup of instanceGroups; let i = index\"\r\n class=\"accordion-instance\"\r\n [class.is-expanded]=\"isExpanded(i)\">\r\n\r\n <!-- Accordion header (always visible) -->\r\n <div class=\"accordion-header\" (click)=\"toggleInstance(i)\" role=\"button\" [attr.aria-expanded]=\"isExpanded(i)\">\r\n <div class=\"accordion-header-left\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceGroups.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeInstance(i)\"\r\n aria-label=\"Remove instance\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body (always mounted so form controls survive collapse) -->\r\n <div class=\"accordion-body\" [hidden]=\"!isExpanded(i)\">\r\n <div class=\"section-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instanceGroup\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-section\" (click)=\"addInstance()\">\r\n <mat-icon>add</mat-icon> Add {{ config.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2550\u2550 Non-repeater (single instance) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"!config.allowMulti\">\r\n <div class=\"section-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"flatFormGroup\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n</div>\r\n", styles: ["@keyframes section-card-in{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.form-section-container{background:#fff;border:1px solid #EAECF0;border-radius:14px;padding:22px 24px 24px;margin-bottom:14px;box-shadow:0 1px 2px #0000000a,0 4px 12px #6366f10a;animation:section-card-in .3s cubic-bezier(.4,0,.2,1) both;transition:box-shadow .2s ease}.form-section-container:hover{box-shadow:0 1px 2px #0000000a,0 6px 20px #6366f114}.form-section-container:last-child{margin-bottom:0}.form-section-container .section-label{display:flex;align-items:center;gap:10px;font-size:.9375rem;font-weight:700;color:#111827;margin:0 0 20px;padding-bottom:14px;border-bottom:1px solid #F3F4F6;letter-spacing:-.01em}.form-section-container .section-label:before{content:\"\";display:inline-block;width:4px;height:18px;border-radius:4px;background:linear-gradient(180deg,#6366f1,#8b5cf6);flex-shrink:0}.form-section-container .section-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:18px 20px;align-items:start}@media(max-width:640px){.form-section-container .section-fields.sf-grid{grid-template-columns:1fr}.form-section-container .section-fields.sf-grid .sf-col{grid-column:span 12!important}}.form-section-container .accordion-instance{border:1px solid #E8EAF0;border-radius:10px;margin-bottom:10px;overflow:hidden;transition:border-color .2s ease,box-shadow .2s ease;background:#fafbff}.form-section-container .accordion-instance:last-of-type{margin-bottom:0}.form-section-container .accordion-instance.is-expanded{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f112}.form-section-container .accordion-instance .accordion-header{display:flex;justify-content:space-between;align-items:center;padding:11px 16px;background:#f8f9ff;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.form-section-container .accordion-instance .accordion-header:hover{background:#eef0ff}.form-section-container .accordion-instance .accordion-header .accordion-header-left{display:flex;align-items:center;gap:10px}.form-section-container .accordion-instance .accordion-header .instance-badge{width:24px;height:24px;border-radius:6px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.form-section-container .accordion-instance .accordion-header .instance-title{font-size:.8125rem;font-weight:600;color:#1f2937}.form-section-container .accordion-instance .accordion-header .accordion-header-right{display:flex;align-items:center;gap:6px}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:#ef4444;padding:4px 6px;border-radius:6px;line-height:1;display:flex;align-items:center;transition:background .15s ease,color .15s ease}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn:hover{background:#fee2e2;color:#dc2626}.form-section-container .accordion-instance .accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:#6b7280;transition:transform .2s ease}.form-section-container .accordion-instance .accordion-body{padding:18px 16px;background:#fff;border-top:1px solid #E8EAF0}.form-section-container .btn-add-section{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:11px 20px;margin-top:14px;background:transparent;color:#6366f1;border:1.5px dashed #C7D2FE;border-radius:8px;cursor:pointer;font-family:inherit;font-size:.8125rem;font-weight:600;transition:all .2s ease;letter-spacing:.01em}.form-section-container .btn-add-section mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .btn-add-section:hover{background:#eef2ff;border-color:#a5b4fc;border-style:solid;transform:translateY(-1px);box-shadow:0 2px 8px #6366f11f}.form-section-container .btn-add-section:active{transform:translateY(0)}\n"] }]
|
|
2922
|
+
args: [{ selector: 'lib-form-section', standalone: false, template: "<div class=\"form-section-container\">\r\n <h3 class=\"section-label\" *ngIf=\"config.label && !config.allowMulti\">{{ config.label }}</h3>\r\n\r\n <!-- \u2550\u2550 Repeater (allowMulti) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"config.allowMulti\">\r\n <h3 class=\"section-label\">{{ config.label }}</h3>\r\n\r\n <div *ngFor=\"let instanceGroup of instanceGroups; let i = index\"\r\n class=\"accordion-instance\"\r\n [class.is-expanded]=\"isExpanded(i)\">\r\n\r\n <!-- Accordion header (always visible) -->\r\n <div class=\"accordion-header\" (click)=\"toggleInstance(i)\" role=\"button\" [attr.aria-expanded]=\"isExpanded(i)\">\r\n <div class=\"accordion-header-left\">\r\n <span class=\"instance-badge\">{{ i + 1 }}</span>\r\n <span class=\"instance-title\">{{ config.label }} #{{ i + 1 }}</span>\r\n </div>\r\n <div class=\"accordion-header-right\">\r\n <button type=\"button\" class=\"accordion-remove-btn\"\r\n *ngIf=\"instanceGroups.length > 1\"\r\n (click)=\"$event.stopPropagation(); removeInstance(i)\"\r\n aria-label=\"Remove instance\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n <mat-icon class=\"accordion-chevron\">\r\n {{ isExpanded(i) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\r\n </mat-icon>\r\n </div>\r\n </div>\r\n\r\n <!-- Accordion body (always mounted so form controls survive collapse) -->\r\n <div class=\"accordion-body\" [hidden]=\"!isExpanded(i)\">\r\n <div class=\"section-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"instanceGroup\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Full-width dashed Add button -->\r\n <button type=\"button\" class=\"btn-add-section\" (click)=\"addInstance()\">\r\n <mat-icon>add</mat-icon> Add {{ config.label }}\r\n </button>\r\n </ng-container>\r\n\r\n <!-- \u2550\u2550 Non-repeater (single instance) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"!config.allowMulti\">\r\n <div class=\"section-fields sf-grid\">\r\n <ng-container *ngFor=\"let field of config.children\">\r\n <div class=\"sf-col\" [style.gridColumn]=\"'span ' + (field.colSpan || 12)\"\r\n *ngIf=\"field.isEnabled !== false\">\r\n <lib-form-field [config]=\"field\" [controller]=\"controller\" [formGroup]=\"flatFormGroup\">\r\n </lib-form-field>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n</div>\r\n", styles: ["@keyframes section-card-in{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.form-section-container{background:#fff;border:1px solid #EAECF0;border-radius:14px;padding:22px 24px 24px;margin-bottom:14px;box-shadow:0 1px 2px #0000000a,0 4px 12px #6366f10a;animation:section-card-in .3s cubic-bezier(.4,0,.2,1) both;transition:box-shadow .2s ease}.form-section-container:hover{box-shadow:0 1px 2px #0000000a,0 6px 20px #6366f114}.form-section-container:last-child{margin-bottom:0}.form-section-container .section-label{display:flex;align-items:center;gap:10px;font-size:.9375rem;font-weight:700;color:#111827;margin:0 0 20px;padding-bottom:14px;border-bottom:1px solid #F3F4F6;letter-spacing:-.01em}.form-section-container .section-label:before{content:\"\";display:inline-block;width:4px;height:18px;border-radius:4px;background:linear-gradient(180deg,#6366f1,#8b5cf6);flex-shrink:0}.form-section-container .section-fields.sf-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:18px 20px;align-items:start}@media (max-width: 640px){.form-section-container .section-fields.sf-grid{grid-template-columns:1fr}.form-section-container .section-fields.sf-grid .sf-col{grid-column:span 12!important}}.form-section-container .accordion-instance{border:1px solid #E8EAF0;border-radius:10px;margin-bottom:10px;overflow:hidden;transition:border-color .2s ease,box-shadow .2s ease;background:#fafbff}.form-section-container .accordion-instance:last-of-type{margin-bottom:0}.form-section-container .accordion-instance.is-expanded{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f112}.form-section-container .accordion-instance .accordion-header{display:flex;justify-content:space-between;align-items:center;padding:11px 16px;background:#f8f9ff;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s ease}.form-section-container .accordion-instance .accordion-header:hover{background:#eef0ff}.form-section-container .accordion-instance .accordion-header .accordion-header-left{display:flex;align-items:center;gap:10px}.form-section-container .accordion-instance .accordion-header .instance-badge{width:24px;height:24px;border-radius:6px;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;font-size:.75rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}.form-section-container .accordion-instance .accordion-header .instance-title{font-size:.8125rem;font-weight:600;color:#1f2937}.form-section-container .accordion-instance .accordion-header .accordion-header-right{display:flex;align-items:center;gap:6px}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn{background:none;border:none;cursor:pointer;color:#ef4444;padding:4px 6px;border-radius:6px;line-height:1;display:flex;align-items:center;transition:background .15s ease,color .15s ease}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .accordion-instance .accordion-header .accordion-remove-btn:hover{background:#fee2e2;color:#dc2626}.form-section-container .accordion-instance .accordion-header .accordion-chevron{font-size:1.25rem;width:1.25rem;height:1.25rem;line-height:1.25rem;color:#6b7280;transition:transform .2s ease}.form-section-container .accordion-instance .accordion-body{padding:18px 16px;background:#fff;border-top:1px solid #E8EAF0}.form-section-container .btn-add-section{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;padding:11px 20px;margin-top:14px;background:transparent;color:#6366f1;border:1.5px dashed #C7D2FE;border-radius:8px;cursor:pointer;font-family:inherit;font-size:.8125rem;font-weight:600;transition:all .2s ease;letter-spacing:.01em}.form-section-container .btn-add-section mat-icon{font-size:1.1rem;width:1.1rem;height:1.1rem;line-height:1.1rem}.form-section-container .btn-add-section:hover{background:#eef2ff;border-color:#a5b4fc;border-style:solid;transform:translateY(-1px);box-shadow:0 2px 8px #6366f11f}.form-section-container .btn-add-section:active{transform:translateY(0)}\n"] }]
|
|
2783
2923
|
}], ctorParameters: () => [{ type: i1$3.FormBuilder }], propDecorators: { config: [{
|
|
2784
2924
|
type: Input
|
|
2785
2925
|
}], controller: [{
|
|
@@ -3790,11 +3930,11 @@ class SmartFormComponent {
|
|
|
3790
3930
|
return suffix.split('_').map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(' ');
|
|
3791
3931
|
}
|
|
3792
3932
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormComponent, deps: [{ token: i1$3.FormBuilder }, { token: SmartFormController }, { token: ExpressionService }, { token: i3.HttpClient }, { token: SnackbarService }, { token: i1$4.Router }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
3793
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartFormComponent, isStandalone: false, selector: "lib-smart-form", inputs: { formJson: "formJson", initialValues: "initialValues", enableDraftAutoSave: "enableDraftAutoSave", labels: "labels", mode: "mode", readOnly: "readOnly" }, outputs: { submit: "submit", draftSave: "draftSave", actionClick: "actionClick", valueChange: "valueChange", fileAdded: "fileAdded", fileUploadFinished: "fileUploadFinished", fileRemoved: "fileRemoved", suffixActionClick: "suffixActionClick", stepChange: "stepChange" }, providers: [SmartFormController], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-form-container\">\r\n\r\n <!-- \u2550\u2550 Skeleton loader \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"smart-form-skeleton\" *ngIf=\"!isFormReady\" aria-hidden=\"true\">\r\n\r\n <!-- Title + description -->\r\n <div class=\"skel-header\">\r\n <div class=\"skel-block skel-title\" style=\"--sd: 0s\"></div>\r\n <div class=\"skel-block skel-desc\" style=\"--sd: 0.07s\"></div>\r\n </div>\r\n\r\n <!-- Section 1 \u2014 two full-width fields -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.1s; width: 32%\"></div>\r\n <div class=\"skel-fields skel-fields--two\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.13s; width: 55%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.15s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.16s; width: 45%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.18s\"></div>\r\n </div>\r\n <div class=\"skel-field skel-field--full\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.2s; width: 38%\"></div>\r\n <div class=\"skel-block skel-input skel-input--textarea\" style=\"--sd: 0.22s\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Section 2 \u2014 three columns -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.25s; width: 24%\"></div>\r\n <div class=\"skel-fields skel-fields--three\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.28s; width: 60%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.30s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.31s; width: 50%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.33s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.34s; width: 65%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.36s\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Section 3 \u2014 two columns + chip row -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.38s; width: 28%\"></div>\r\n <div class=\"skel-fields skel-fields--two\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.40s; width: 48%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.42s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.43s; width: 55%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.45s\"></div>\r\n </div>\r\n </div>\r\n <div class=\"skel-chips\">\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.47s; width: 72px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.49s; width: 96px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.51s; width: 80px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.53s; width: 64px\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Action bar -->\r\n <div class=\"skel-actions\">\r\n <div class=\"skel-block skel-btn\" style=\"--sd: 0.55s; width: 88px\"></div>\r\n <div class=\"skel-block skel-btn skel-btn--primary\" style=\"--sd: 0.58s; width: 120px\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n SECTION STEPPER layout \u2014 stepper nav card + per-step form panels.\r\n Rendered when formSchema.sectionStepper === true.\r\n The nav and each step section are separate cards (no outer wrapper card).\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"formSchema && isFormReady && isSectionStepper\">\r\n\r\n <!-- Horizontal stepper nav card -->\r\n <div class=\"section-stepper-nav\" *ngIf=\"sectionSteps.length > 0\">\r\n <div class=\"section-stepper-track\">\r\n <div\r\n *ngFor=\"let step of sectionSteps; let i = index\"\r\n class=\"section-stepper-step\"\r\n [class.ss-active]=\"i === currentSectionStep\"\r\n [class.ss-completed]=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\r\n [class.ss-warning]=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\r\n [attr.data-tooltip]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\"\r\n (click)=\"goToSectionStep(i)\">\r\n\r\n <!-- Connector line \u2014 left side (hidden for first step) -->\r\n <div class=\"ss-connector ss-connector--left\" *ngIf=\"i > 0\"></div>\r\n\r\n <!-- Step badge -->\r\n <div class=\"ss-badge\">\r\n <!-- Green checkmark: visited and valid -->\r\n <svg *ngIf=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\r\n width=\"13\" height=\"13\" viewBox=\"0 0 24 24\"\r\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg>\r\n <!-- Warning: bold ! is the most visible option inside a 38px circle badge -->\r\n <span *ngIf=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\r\n class=\"ss-warning-mark\">!</span>\r\n <!-- Number: current or future step -->\r\n <span *ngIf=\"i >= currentSectionStep\">{{ i + 1 }}</span>\r\n </div>\r\n\r\n <!-- Step label (truncated; full text revealed by CSS tooltip) -->\r\n <div class=\"ss-label\" [title]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\">\r\n {{ step.sectionConfig?.label || 'Step ' + (i + 1) }}\r\n </div>\r\n\r\n <!-- Connector line \u2014 right side (hidden for last step) -->\r\n <div class=\"ss-connector ss-connector--right\" *ngIf=\"i < sectionSteps.length - 1\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Step panels \u2014 all mounted, only active one is visible (preserves form data) -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form ss-form\">\r\n <div\r\n *ngFor=\"let step of sectionSteps; let i = index\"\r\n class=\"ss-step-panel\"\r\n [style.display]=\"i === currentSectionStep ? 'block' : 'none'\">\r\n <lib-form-section\r\n [config]=\"getSectionStepConfig(step)\"\r\n [controller]=\"controller\"\r\n [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Action bar: Prev / custom action buttons / Next \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\"\r\n *ngIf=\"!readOnly && formSchema.showActions !== false && actionBarConfig?.buttons?.length\">\r\n\r\n <!-- LEFT GROUP: Previous button + left-aligned custom buttons -->\r\n <div class=\"action-group action-group--left\">\r\n <lib-button\r\n *ngIf=\"!isSectionStepFirst\"\r\n variant=\"outline\"\r\n (click)=\"navigateToPrevious()\">\r\n {{ previousLabel }}\r\n </lib-button>\r\n <ng-container *ngFor=\"let btn of getButtonsForAlignment('left')\">\r\n <lib-button\r\n *ngIf=\"!btn.showOnLastStepOnly || isSectionStepLast\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- RIGHT GROUP: right-aligned custom buttons + Next button -->\r\n <div class=\"action-group action-group--right\">\r\n <ng-container *ngFor=\"let btn of getButtonsForAlignment('right')\">\r\n <lib-button\r\n *ngIf=\"!btn.showOnLastStepOnly || isSectionStepLast\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </ng-container>\r\n <lib-button\r\n *ngIf=\"!isSectionStepLast\"\r\n variant=\"primary\"\r\n (click)=\"navigateToNext()\">\r\n {{ nextLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n Regular card wrapper \u2014 used for SECTION and STEPPER form types.\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema && isFormReady && !isSectionStepper\"\r\n [class.smart-form-wrapper--readonly]=\"readOnly\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- STEPPER type nav -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Regular SECTION form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- STEPPER type form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly && actionBarConfig?.buttons?.length\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>\r\n", styles: ["@keyframes skel-wave{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes skel-fade-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes form-reveal{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.smart-form-skeleton{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06));padding:1.5rem;display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px);animation:skel-fade-in .3s ease both}.skel-block{position:relative;overflow:hidden;border-radius:6px;background:var(--cc-sf-input-disabled-bg, #F0F2F5)}.skel-block:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,rgba(255,255,255,.75) 50%,rgba(255,255,255,.55) 55%,transparent 100%);animation:skel-wave 1.8s ease-in-out infinite;animation-delay:var(--sd, 0s)}.skel-header{display:flex;flex-direction:column;gap:10px}.skel-header .skel-title{height:26px;border-radius:8px}.skel-header .skel-desc{height:14px;border-radius:5px;opacity:.7}.skel-section{display:flex;flex-direction:column;gap:14px}.skel-section-label{height:16px;border-radius:0 5px 5px 0;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);background:var(--cc-sf-input-disabled-bg, #F0F2F5);opacity:.85}.skel-fields{display:grid;gap:var(--cc-sf-grid-gap, 16px);align-items:start}.skel-fields--two{grid-template-columns:1fr 1fr}.skel-fields--three{grid-template-columns:1fr 1fr 1fr}@media(max-width:640px){.skel-fields--two,.skel-fields--three{grid-template-columns:1fr}}.skel-field{display:flex;flex-direction:column;gap:7px}.skel-field--full{grid-column:1/-1}.skel-label{height:12px;border-radius:4px;opacity:.75}.skel-input{height:42px;border-radius:8px}.skel-input--textarea{height:80px}.skel-chips{display:flex;flex-wrap:wrap;gap:8px}.skel-chip{height:32px;border-radius:20px;opacity:.8}.skel-actions{display:flex;justify-content:flex-end;align-items:center;gap:12px;padding-top:20px;border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.skel-btn{height:40px;border-radius:8px}.skel-btn--primary{background:color-mix(in srgb,var(--cc-sf-accent-color, #3B82F6) 18%,var(--cc-sf-input-disabled-bg, #F0F2F5))}.smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);animation:form-reveal .3s ease both}.smart-form-wrapper .form-alert-feedback,.form-header{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}@keyframes ss-badge-pop{0%{transform:scale(.6);opacity:0}70%{transform:scale(1.12)}to{transform:scale(1);opacity:1}}@keyframes ss-pulse-ring{0%{box-shadow:0 0 #6366f173}70%{box-shadow:0 0 0 10px #6366f100}to{box-shadow:0 0 #6366f100}}@keyframes ss-panel-in{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes ss-connector-fill{0%{transform:scaleX(0)}to{transform:scaleX(1)}}.section-stepper-nav{position:relative;background:#fff;border-radius:16px;border:1px solid #E8EAF0;box-shadow:0 1px 3px #0000000d,0 4px 16px #6366f10f;padding:24px 28px 48px;margin-bottom:14px;overflow-x:clip;overflow-y:hidden}.section-stepper-nav:before{content:\"\";position:absolute;inset:0 0 auto;height:3px;border-radius:16px 16px 0 0;background:linear-gradient(90deg,#6366f1,#8b5cf6,#ec4899)}.section-stepper-track{display:flex;align-items:flex-start;justify-content:space-between;min-width:max-content;width:100%}.section-stepper-step{display:flex;flex-direction:column;align-items:center;position:relative;flex:1;cursor:pointer;padding:0 4px}.section-stepper-step:after{content:attr(data-tooltip);position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%) translateY(4px);white-space:nowrap;background:#1e1b4b;color:#fff;font-size:.6875rem;font-weight:500;letter-spacing:.02em;padding:5px 11px;border-radius:6px;pointer-events:none;opacity:0;transition:opacity .2s ease,transform .2s ease;z-index:200;box-shadow:0 4px 14px #0003}.section-stepper-step:hover:after{opacity:1;transform:translate(-50%) translateY(0)}.section-stepper-step .ss-badge{width:38px;height:38px;min-width:38px;border-radius:50%;background:#f1f2f6;color:#9ca3af;border:2px solid #E5E7EB;display:flex;align-items:center;justify-content:center;font-size:.8125rem;font-weight:700;position:relative;z-index:1;transition:all .3s cubic-bezier(.34,1.56,.64,1)}.section-stepper-step .ss-badge span{line-height:1;letter-spacing:-.01em}.section-stepper-step .ss-badge svg{flex-shrink:0}.section-stepper-step .ss-badge .ss-warning-mark{font-size:1.25rem;font-weight:900;line-height:1;letter-spacing:0;color:#fff}.section-stepper-step .ss-label{margin-top:9px;font-size:.6875rem;font-weight:500;color:#b0b7c3;white-space:nowrap;text-align:center;transition:color .25s ease,font-weight .25s ease;max-width:88px;overflow:hidden;text-overflow:ellipsis;letter-spacing:.01em}.section-stepper-step .ss-connector{height:2px;background:#e8eaf0;position:absolute;top:19px;z-index:0;overflow:hidden;border-radius:2px}.section-stepper-step .ss-connector--left{left:0;right:calc(50% + 19px)}.section-stepper-step .ss-connector--right{left:calc(50% + 19px);right:0}.section-stepper-step .ss-connector:after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,#6366f1,#8b5cf6);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.4,0,.2,1)}.section-stepper-step.ss-active{cursor:default}.section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;border-color:transparent;box-shadow:0 0 0 4px #6366f12e,0 4px 12px #6366f159;animation:ss-badge-pop .4s cubic-bezier(.34,1.56,.64,1) both,ss-pulse-ring 2s .4s ease-out infinite}.section-stepper-step.ss-active .ss-label{color:#4f46e5;font-weight:700}.section-stepper-step.ss-completed .ss-badge{background:linear-gradient(135deg,#10b981,#059669);color:#fff;border-color:transparent;box-shadow:0 2px 8px #10b9814d}.section-stepper-step.ss-completed .ss-label{color:#6b7280;font-weight:500}.section-stepper-step.ss-completed .ss-connector--left:after,.section-stepper-step.ss-completed .ss-connector--right:after{transform:scaleX(1)}.section-stepper-step.ss-warning .ss-badge{background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;border-color:transparent;box-shadow:0 2px 8px #f59e0b59;animation:ss-badge-pop .35s cubic-bezier(.34,1.56,.64,1) both}.section-stepper-step.ss-warning .ss-label{color:#b45309;font-weight:600}.section-stepper-step.ss-warning .ss-connector--left:after{transform:scaleX(0)}.section-stepper-step.ss-warning .ss-connector--right:after{transform:scaleX(0)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{background:#e8eaf0;color:#6366f1;border-color:#c7d2fe;transform:translateY(-2px)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-label{color:#6b7280}.ss-step-panel{animation:ss-panel-in .35s cubic-bezier(.4,0,.2,1) both}.ss-form{padding-top:0}@media(max-width:768px){.section-stepper-nav{padding:20px 16px 16px}.section-stepper-step .ss-label{font-size:.625rem;max-width:64px}.section-stepper-step .ss-badge{width:32px;height:32px;min-width:32px;font-size:.75rem}.section-stepper-step .ss-connector{top:16px}.section-stepper-step .ss-connector--left{right:calc(50% + 16px)}.section-stepper-step .ss-connector--right{left:calc(50% + 16px)}}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px)}.smart-form>*{margin-bottom:0!important}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 10px 0);margin-top:8px}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\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$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: FormSectionComponent, selector: "lib-form-section", inputs: ["config", "controller", "formGroup"] }] });
|
|
3933
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartFormComponent, isStandalone: false, selector: "lib-smart-form", inputs: { formJson: "formJson", initialValues: "initialValues", enableDraftAutoSave: "enableDraftAutoSave", labels: "labels", mode: "mode", readOnly: "readOnly" }, outputs: { submit: "submit", draftSave: "draftSave", actionClick: "actionClick", valueChange: "valueChange", fileAdded: "fileAdded", fileUploadFinished: "fileUploadFinished", fileRemoved: "fileRemoved", suffixActionClick: "suffixActionClick", stepChange: "stepChange" }, providers: [SmartFormController], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-form-container\">\r\n\r\n <!-- \u2550\u2550 Skeleton loader \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"smart-form-skeleton\" *ngIf=\"!isFormReady\" aria-hidden=\"true\">\r\n\r\n <!-- Title + description -->\r\n <div class=\"skel-header\">\r\n <div class=\"skel-block skel-title\" style=\"--sd: 0s\"></div>\r\n <div class=\"skel-block skel-desc\" style=\"--sd: 0.07s\"></div>\r\n </div>\r\n\r\n <!-- Section 1 \u2014 two full-width fields -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.1s; width: 32%\"></div>\r\n <div class=\"skel-fields skel-fields--two\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.13s; width: 55%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.15s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.16s; width: 45%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.18s\"></div>\r\n </div>\r\n <div class=\"skel-field skel-field--full\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.2s; width: 38%\"></div>\r\n <div class=\"skel-block skel-input skel-input--textarea\" style=\"--sd: 0.22s\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Section 2 \u2014 three columns -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.25s; width: 24%\"></div>\r\n <div class=\"skel-fields skel-fields--three\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.28s; width: 60%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.30s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.31s; width: 50%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.33s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.34s; width: 65%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.36s\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Section 3 \u2014 two columns + chip row -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.38s; width: 28%\"></div>\r\n <div class=\"skel-fields skel-fields--two\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.40s; width: 48%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.42s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.43s; width: 55%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.45s\"></div>\r\n </div>\r\n </div>\r\n <div class=\"skel-chips\">\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.47s; width: 72px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.49s; width: 96px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.51s; width: 80px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.53s; width: 64px\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Action bar -->\r\n <div class=\"skel-actions\">\r\n <div class=\"skel-block skel-btn\" style=\"--sd: 0.55s; width: 88px\"></div>\r\n <div class=\"skel-block skel-btn skel-btn--primary\" style=\"--sd: 0.58s; width: 120px\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n SECTION STEPPER layout \u2014 stepper nav card + per-step form panels.\r\n Rendered when formSchema.sectionStepper === true.\r\n The nav and each step section are separate cards (no outer wrapper card).\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"formSchema && isFormReady && isSectionStepper\">\r\n\r\n <!-- Horizontal stepper nav card -->\r\n <div class=\"section-stepper-nav\" *ngIf=\"sectionSteps.length > 0\">\r\n <div class=\"section-stepper-track\">\r\n <div\r\n *ngFor=\"let step of sectionSteps; let i = index\"\r\n class=\"section-stepper-step\"\r\n [class.ss-active]=\"i === currentSectionStep\"\r\n [class.ss-completed]=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\r\n [class.ss-warning]=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\r\n [attr.data-tooltip]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\"\r\n (click)=\"goToSectionStep(i)\">\r\n\r\n <!-- Connector line \u2014 left side (hidden for first step) -->\r\n <div class=\"ss-connector ss-connector--left\" *ngIf=\"i > 0\"></div>\r\n\r\n <!-- Step badge -->\r\n <div class=\"ss-badge\">\r\n <!-- Green checkmark: visited and valid -->\r\n <svg *ngIf=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\r\n width=\"13\" height=\"13\" viewBox=\"0 0 24 24\"\r\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg>\r\n <!-- Warning: bold ! is the most visible option inside a 38px circle badge -->\r\n <span *ngIf=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\r\n class=\"ss-warning-mark\">!</span>\r\n <!-- Number: current or future step -->\r\n <span *ngIf=\"i >= currentSectionStep\">{{ i + 1 }}</span>\r\n </div>\r\n\r\n <!-- Step label (truncated; full text revealed by CSS tooltip) -->\r\n <div class=\"ss-label\" [title]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\">\r\n {{ step.sectionConfig?.label || 'Step ' + (i + 1) }}\r\n </div>\r\n\r\n <!-- Connector line \u2014 right side (hidden for last step) -->\r\n <div class=\"ss-connector ss-connector--right\" *ngIf=\"i < sectionSteps.length - 1\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Step panels \u2014 all mounted, only active one is visible (preserves form data) -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form ss-form\">\r\n <div\r\n *ngFor=\"let step of sectionSteps; let i = index\"\r\n class=\"ss-step-panel\"\r\n [style.display]=\"i === currentSectionStep ? 'block' : 'none'\">\r\n <lib-form-section\r\n [config]=\"getSectionStepConfig(step)\"\r\n [controller]=\"controller\"\r\n [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Action bar: Prev / custom action buttons / Next \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\"\r\n *ngIf=\"!readOnly && formSchema.showActions !== false && actionBarConfig?.buttons?.length\">\r\n\r\n <!-- LEFT GROUP: Previous button + left-aligned custom buttons -->\r\n <div class=\"action-group action-group--left\">\r\n <lib-button\r\n *ngIf=\"!isSectionStepFirst\"\r\n variant=\"outline\"\r\n (click)=\"navigateToPrevious()\">\r\n {{ previousLabel }}\r\n </lib-button>\r\n <ng-container *ngFor=\"let btn of getButtonsForAlignment('left')\">\r\n <lib-button\r\n *ngIf=\"!btn.showOnLastStepOnly || isSectionStepLast\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- RIGHT GROUP: right-aligned custom buttons + Next button -->\r\n <div class=\"action-group action-group--right\">\r\n <ng-container *ngFor=\"let btn of getButtonsForAlignment('right')\">\r\n <lib-button\r\n *ngIf=\"!btn.showOnLastStepOnly || isSectionStepLast\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </ng-container>\r\n <lib-button\r\n *ngIf=\"!isSectionStepLast\"\r\n variant=\"primary\"\r\n (click)=\"navigateToNext()\">\r\n {{ nextLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n Regular card wrapper \u2014 used for SECTION and STEPPER form types.\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema && isFormReady && !isSectionStepper\"\r\n [class.smart-form-wrapper--readonly]=\"readOnly\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- STEPPER type nav -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Regular SECTION form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- STEPPER type form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly && actionBarConfig?.buttons?.length\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>\r\n", styles: ["@keyframes skel-wave{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes skel-fade-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes form-reveal{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.smart-form-skeleton{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06));padding:1.5rem;display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px);animation:skel-fade-in .3s ease both}.skel-block{position:relative;overflow:hidden;border-radius:6px;background:var(--cc-sf-input-disabled-bg, #F0F2F5)}.skel-block:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,rgba(255,255,255,.75) 50%,rgba(255,255,255,.55) 55%,transparent 100%);animation:skel-wave 1.8s ease-in-out infinite;animation-delay:var(--sd, 0s)}.skel-header{display:flex;flex-direction:column;gap:10px}.skel-header .skel-title{height:26px;border-radius:8px}.skel-header .skel-desc{height:14px;border-radius:5px;opacity:.7}.skel-section{display:flex;flex-direction:column;gap:14px}.skel-section-label{height:16px;border-radius:0 5px 5px 0;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);background:var(--cc-sf-input-disabled-bg, #F0F2F5);opacity:.85}.skel-fields{display:grid;gap:var(--cc-sf-grid-gap, 16px);align-items:start}.skel-fields--two{grid-template-columns:1fr 1fr}.skel-fields--three{grid-template-columns:1fr 1fr 1fr}@media (max-width: 640px){.skel-fields--two,.skel-fields--three{grid-template-columns:1fr}}.skel-field{display:flex;flex-direction:column;gap:7px}.skel-field--full{grid-column:1/-1}.skel-label{height:12px;border-radius:4px;opacity:.75}.skel-input{height:42px;border-radius:8px}.skel-input--textarea{height:80px}.skel-chips{display:flex;flex-wrap:wrap;gap:8px}.skel-chip{height:32px;border-radius:20px;opacity:.8}.skel-actions{display:flex;justify-content:flex-end;align-items:center;gap:12px;padding-top:20px;border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.skel-btn{height:40px;border-radius:8px}.skel-btn--primary{background:color-mix(in srgb,var(--cc-sf-accent-color, #3B82F6) 18%,var(--cc-sf-input-disabled-bg, #F0F2F5))}.smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);animation:form-reveal .3s ease both}.smart-form-wrapper .form-alert-feedback,.form-header{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}@keyframes ss-badge-pop{0%{transform:scale(.6);opacity:0}70%{transform:scale(1.12)}to{transform:scale(1);opacity:1}}@keyframes ss-pulse-ring{0%{box-shadow:0 0 #6366f173}70%{box-shadow:0 0 0 10px #6366f100}to{box-shadow:0 0 #6366f100}}@keyframes ss-panel-in{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes ss-connector-fill{0%{transform:scaleX(0)}to{transform:scaleX(1)}}.section-stepper-nav{position:relative;background:#fff;border-radius:16px;border:1px solid #E8EAF0;box-shadow:0 1px 3px #0000000d,0 4px 16px #6366f10f;padding:24px 28px 48px;margin-bottom:14px;overflow-x:clip;overflow-y:hidden}.section-stepper-nav:before{content:\"\";position:absolute;inset:0 0 auto;height:3px;border-radius:16px 16px 0 0;background:linear-gradient(90deg,#6366f1,#8b5cf6,#ec4899)}.section-stepper-track{display:flex;align-items:flex-start;justify-content:space-between;min-width:max-content;width:100%}.section-stepper-step{display:flex;flex-direction:column;align-items:center;position:relative;flex:1;cursor:pointer;padding:0 4px}.section-stepper-step:after{content:attr(data-tooltip);position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%) translateY(4px);white-space:nowrap;background:#1e1b4b;color:#fff;font-size:.6875rem;font-weight:500;letter-spacing:.02em;padding:5px 11px;border-radius:6px;pointer-events:none;opacity:0;transition:opacity .2s ease,transform .2s ease;z-index:200;box-shadow:0 4px 14px #0003}.section-stepper-step:hover:after{opacity:1;transform:translate(-50%) translateY(0)}.section-stepper-step .ss-badge{width:38px;height:38px;min-width:38px;border-radius:50%;background:#f1f2f6;color:#9ca3af;border:2px solid #E5E7EB;display:flex;align-items:center;justify-content:center;font-size:.8125rem;font-weight:700;position:relative;z-index:1;transition:all .3s cubic-bezier(.34,1.56,.64,1)}.section-stepper-step .ss-badge span{line-height:1;letter-spacing:-.01em}.section-stepper-step .ss-badge svg{flex-shrink:0}.section-stepper-step .ss-badge .ss-warning-mark{font-size:1.25rem;font-weight:900;line-height:1;letter-spacing:0;color:#fff}.section-stepper-step .ss-label{margin-top:9px;font-size:.6875rem;font-weight:500;color:#b0b7c3;white-space:nowrap;text-align:center;transition:color .25s ease,font-weight .25s ease;max-width:88px;overflow:hidden;text-overflow:ellipsis;letter-spacing:.01em}.section-stepper-step .ss-connector{height:2px;background:#e8eaf0;position:absolute;top:19px;z-index:0;overflow:hidden;border-radius:2px}.section-stepper-step .ss-connector--left{left:0;right:calc(50% + 19px)}.section-stepper-step .ss-connector--right{left:calc(50% + 19px);right:0}.section-stepper-step .ss-connector:after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,#6366f1,#8b5cf6);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.4,0,.2,1)}.section-stepper-step.ss-active{cursor:default}.section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;border-color:transparent;box-shadow:0 0 0 4px #6366f12e,0 4px 12px #6366f159;animation:ss-badge-pop .4s cubic-bezier(.34,1.56,.64,1) both,ss-pulse-ring 2s .4s ease-out infinite}.section-stepper-step.ss-active .ss-label{color:#4f46e5;font-weight:700}.section-stepper-step.ss-completed .ss-badge{background:linear-gradient(135deg,#10b981,#059669);color:#fff;border-color:transparent;box-shadow:0 2px 8px #10b9814d}.section-stepper-step.ss-completed .ss-label{color:#6b7280;font-weight:500}.section-stepper-step.ss-completed .ss-connector--left:after,.section-stepper-step.ss-completed .ss-connector--right:after{transform:scaleX(1)}.section-stepper-step.ss-warning .ss-badge{background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;border-color:transparent;box-shadow:0 2px 8px #f59e0b59;animation:ss-badge-pop .35s cubic-bezier(.34,1.56,.64,1) both}.section-stepper-step.ss-warning .ss-label{color:#b45309;font-weight:600}.section-stepper-step.ss-warning .ss-connector--left:after{transform:scaleX(0)}.section-stepper-step.ss-warning .ss-connector--right:after{transform:scaleX(0)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{background:#e8eaf0;color:#6366f1;border-color:#c7d2fe;transform:translateY(-2px)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-label{color:#6b7280}.ss-step-panel{animation:ss-panel-in .35s cubic-bezier(.4,0,.2,1) both}.ss-form{padding-top:0}@media (max-width: 768px){.section-stepper-nav{padding:20px 16px 16px}.section-stepper-step .ss-label{font-size:.625rem;max-width:64px}.section-stepper-step .ss-badge{width:32px;height:32px;min-width:32px;font-size:.75rem}.section-stepper-step .ss-connector{top:16px}.section-stepper-step .ss-connector--left{right:calc(50% + 16px)}.section-stepper-step .ss-connector--right{left:calc(50% + 16px)}}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px)}.smart-form>*{margin-bottom:0!important}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 10px 0);margin-top:8px}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\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$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: FormSectionComponent, selector: "lib-form-section", inputs: ["config", "controller", "formGroup"] }] });
|
|
3794
3934
|
}
|
|
3795
3935
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartFormComponent, decorators: [{
|
|
3796
3936
|
type: Component,
|
|
3797
|
-
args: [{ selector: 'lib-smart-form', providers: [SmartFormController], standalone: false, template: "<div class=\"smart-form-container\">\r\n\r\n <!-- \u2550\u2550 Skeleton loader \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"smart-form-skeleton\" *ngIf=\"!isFormReady\" aria-hidden=\"true\">\r\n\r\n <!-- Title + description -->\r\n <div class=\"skel-header\">\r\n <div class=\"skel-block skel-title\" style=\"--sd: 0s\"></div>\r\n <div class=\"skel-block skel-desc\" style=\"--sd: 0.07s\"></div>\r\n </div>\r\n\r\n <!-- Section 1 \u2014 two full-width fields -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.1s; width: 32%\"></div>\r\n <div class=\"skel-fields skel-fields--two\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.13s; width: 55%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.15s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.16s; width: 45%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.18s\"></div>\r\n </div>\r\n <div class=\"skel-field skel-field--full\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.2s; width: 38%\"></div>\r\n <div class=\"skel-block skel-input skel-input--textarea\" style=\"--sd: 0.22s\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Section 2 \u2014 three columns -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.25s; width: 24%\"></div>\r\n <div class=\"skel-fields skel-fields--three\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.28s; width: 60%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.30s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.31s; width: 50%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.33s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.34s; width: 65%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.36s\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Section 3 \u2014 two columns + chip row -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.38s; width: 28%\"></div>\r\n <div class=\"skel-fields skel-fields--two\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.40s; width: 48%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.42s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.43s; width: 55%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.45s\"></div>\r\n </div>\r\n </div>\r\n <div class=\"skel-chips\">\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.47s; width: 72px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.49s; width: 96px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.51s; width: 80px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.53s; width: 64px\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Action bar -->\r\n <div class=\"skel-actions\">\r\n <div class=\"skel-block skel-btn\" style=\"--sd: 0.55s; width: 88px\"></div>\r\n <div class=\"skel-block skel-btn skel-btn--primary\" style=\"--sd: 0.58s; width: 120px\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n SECTION STEPPER layout \u2014 stepper nav card + per-step form panels.\r\n Rendered when formSchema.sectionStepper === true.\r\n The nav and each step section are separate cards (no outer wrapper card).\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"formSchema && isFormReady && isSectionStepper\">\r\n\r\n <!-- Horizontal stepper nav card -->\r\n <div class=\"section-stepper-nav\" *ngIf=\"sectionSteps.length > 0\">\r\n <div class=\"section-stepper-track\">\r\n <div\r\n *ngFor=\"let step of sectionSteps; let i = index\"\r\n class=\"section-stepper-step\"\r\n [class.ss-active]=\"i === currentSectionStep\"\r\n [class.ss-completed]=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\r\n [class.ss-warning]=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\r\n [attr.data-tooltip]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\"\r\n (click)=\"goToSectionStep(i)\">\r\n\r\n <!-- Connector line \u2014 left side (hidden for first step) -->\r\n <div class=\"ss-connector ss-connector--left\" *ngIf=\"i > 0\"></div>\r\n\r\n <!-- Step badge -->\r\n <div class=\"ss-badge\">\r\n <!-- Green checkmark: visited and valid -->\r\n <svg *ngIf=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\r\n width=\"13\" height=\"13\" viewBox=\"0 0 24 24\"\r\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg>\r\n <!-- Warning: bold ! is the most visible option inside a 38px circle badge -->\r\n <span *ngIf=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\r\n class=\"ss-warning-mark\">!</span>\r\n <!-- Number: current or future step -->\r\n <span *ngIf=\"i >= currentSectionStep\">{{ i + 1 }}</span>\r\n </div>\r\n\r\n <!-- Step label (truncated; full text revealed by CSS tooltip) -->\r\n <div class=\"ss-label\" [title]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\">\r\n {{ step.sectionConfig?.label || 'Step ' + (i + 1) }}\r\n </div>\r\n\r\n <!-- Connector line \u2014 right side (hidden for last step) -->\r\n <div class=\"ss-connector ss-connector--right\" *ngIf=\"i < sectionSteps.length - 1\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Step panels \u2014 all mounted, only active one is visible (preserves form data) -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form ss-form\">\r\n <div\r\n *ngFor=\"let step of sectionSteps; let i = index\"\r\n class=\"ss-step-panel\"\r\n [style.display]=\"i === currentSectionStep ? 'block' : 'none'\">\r\n <lib-form-section\r\n [config]=\"getSectionStepConfig(step)\"\r\n [controller]=\"controller\"\r\n [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Action bar: Prev / custom action buttons / Next \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\"\r\n *ngIf=\"!readOnly && formSchema.showActions !== false && actionBarConfig?.buttons?.length\">\r\n\r\n <!-- LEFT GROUP: Previous button + left-aligned custom buttons -->\r\n <div class=\"action-group action-group--left\">\r\n <lib-button\r\n *ngIf=\"!isSectionStepFirst\"\r\n variant=\"outline\"\r\n (click)=\"navigateToPrevious()\">\r\n {{ previousLabel }}\r\n </lib-button>\r\n <ng-container *ngFor=\"let btn of getButtonsForAlignment('left')\">\r\n <lib-button\r\n *ngIf=\"!btn.showOnLastStepOnly || isSectionStepLast\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- RIGHT GROUP: right-aligned custom buttons + Next button -->\r\n <div class=\"action-group action-group--right\">\r\n <ng-container *ngFor=\"let btn of getButtonsForAlignment('right')\">\r\n <lib-button\r\n *ngIf=\"!btn.showOnLastStepOnly || isSectionStepLast\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </ng-container>\r\n <lib-button\r\n *ngIf=\"!isSectionStepLast\"\r\n variant=\"primary\"\r\n (click)=\"navigateToNext()\">\r\n {{ nextLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n Regular card wrapper \u2014 used for SECTION and STEPPER form types.\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema && isFormReady && !isSectionStepper\"\r\n [class.smart-form-wrapper--readonly]=\"readOnly\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- STEPPER type nav -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Regular SECTION form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- STEPPER type form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly && actionBarConfig?.buttons?.length\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>\r\n", styles: ["@keyframes skel-wave{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes skel-fade-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes form-reveal{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.smart-form-skeleton{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06));padding:1.5rem;display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px);animation:skel-fade-in .3s ease both}.skel-block{position:relative;overflow:hidden;border-radius:6px;background:var(--cc-sf-input-disabled-bg, #F0F2F5)}.skel-block:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,rgba(255,255,255,.75) 50%,rgba(255,255,255,.55) 55%,transparent 100%);animation:skel-wave 1.8s ease-in-out infinite;animation-delay:var(--sd, 0s)}.skel-header{display:flex;flex-direction:column;gap:10px}.skel-header .skel-title{height:26px;border-radius:8px}.skel-header .skel-desc{height:14px;border-radius:5px;opacity:.7}.skel-section{display:flex;flex-direction:column;gap:14px}.skel-section-label{height:16px;border-radius:0 5px 5px 0;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);background:var(--cc-sf-input-disabled-bg, #F0F2F5);opacity:.85}.skel-fields{display:grid;gap:var(--cc-sf-grid-gap, 16px);align-items:start}.skel-fields--two{grid-template-columns:1fr 1fr}.skel-fields--three{grid-template-columns:1fr 1fr 1fr}@media(max-width:640px){.skel-fields--two,.skel-fields--three{grid-template-columns:1fr}}.skel-field{display:flex;flex-direction:column;gap:7px}.skel-field--full{grid-column:1/-1}.skel-label{height:12px;border-radius:4px;opacity:.75}.skel-input{height:42px;border-radius:8px}.skel-input--textarea{height:80px}.skel-chips{display:flex;flex-wrap:wrap;gap:8px}.skel-chip{height:32px;border-radius:20px;opacity:.8}.skel-actions{display:flex;justify-content:flex-end;align-items:center;gap:12px;padding-top:20px;border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.skel-btn{height:40px;border-radius:8px}.skel-btn--primary{background:color-mix(in srgb,var(--cc-sf-accent-color, #3B82F6) 18%,var(--cc-sf-input-disabled-bg, #F0F2F5))}.smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);animation:form-reveal .3s ease both}.smart-form-wrapper .form-alert-feedback,.form-header{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}@keyframes ss-badge-pop{0%{transform:scale(.6);opacity:0}70%{transform:scale(1.12)}to{transform:scale(1);opacity:1}}@keyframes ss-pulse-ring{0%{box-shadow:0 0 #6366f173}70%{box-shadow:0 0 0 10px #6366f100}to{box-shadow:0 0 #6366f100}}@keyframes ss-panel-in{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes ss-connector-fill{0%{transform:scaleX(0)}to{transform:scaleX(1)}}.section-stepper-nav{position:relative;background:#fff;border-radius:16px;border:1px solid #E8EAF0;box-shadow:0 1px 3px #0000000d,0 4px 16px #6366f10f;padding:24px 28px 48px;margin-bottom:14px;overflow-x:clip;overflow-y:hidden}.section-stepper-nav:before{content:\"\";position:absolute;inset:0 0 auto;height:3px;border-radius:16px 16px 0 0;background:linear-gradient(90deg,#6366f1,#8b5cf6,#ec4899)}.section-stepper-track{display:flex;align-items:flex-start;justify-content:space-between;min-width:max-content;width:100%}.section-stepper-step{display:flex;flex-direction:column;align-items:center;position:relative;flex:1;cursor:pointer;padding:0 4px}.section-stepper-step:after{content:attr(data-tooltip);position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%) translateY(4px);white-space:nowrap;background:#1e1b4b;color:#fff;font-size:.6875rem;font-weight:500;letter-spacing:.02em;padding:5px 11px;border-radius:6px;pointer-events:none;opacity:0;transition:opacity .2s ease,transform .2s ease;z-index:200;box-shadow:0 4px 14px #0003}.section-stepper-step:hover:after{opacity:1;transform:translate(-50%) translateY(0)}.section-stepper-step .ss-badge{width:38px;height:38px;min-width:38px;border-radius:50%;background:#f1f2f6;color:#9ca3af;border:2px solid #E5E7EB;display:flex;align-items:center;justify-content:center;font-size:.8125rem;font-weight:700;position:relative;z-index:1;transition:all .3s cubic-bezier(.34,1.56,.64,1)}.section-stepper-step .ss-badge span{line-height:1;letter-spacing:-.01em}.section-stepper-step .ss-badge svg{flex-shrink:0}.section-stepper-step .ss-badge .ss-warning-mark{font-size:1.25rem;font-weight:900;line-height:1;letter-spacing:0;color:#fff}.section-stepper-step .ss-label{margin-top:9px;font-size:.6875rem;font-weight:500;color:#b0b7c3;white-space:nowrap;text-align:center;transition:color .25s ease,font-weight .25s ease;max-width:88px;overflow:hidden;text-overflow:ellipsis;letter-spacing:.01em}.section-stepper-step .ss-connector{height:2px;background:#e8eaf0;position:absolute;top:19px;z-index:0;overflow:hidden;border-radius:2px}.section-stepper-step .ss-connector--left{left:0;right:calc(50% + 19px)}.section-stepper-step .ss-connector--right{left:calc(50% + 19px);right:0}.section-stepper-step .ss-connector:after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,#6366f1,#8b5cf6);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.4,0,.2,1)}.section-stepper-step.ss-active{cursor:default}.section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;border-color:transparent;box-shadow:0 0 0 4px #6366f12e,0 4px 12px #6366f159;animation:ss-badge-pop .4s cubic-bezier(.34,1.56,.64,1) both,ss-pulse-ring 2s .4s ease-out infinite}.section-stepper-step.ss-active .ss-label{color:#4f46e5;font-weight:700}.section-stepper-step.ss-completed .ss-badge{background:linear-gradient(135deg,#10b981,#059669);color:#fff;border-color:transparent;box-shadow:0 2px 8px #10b9814d}.section-stepper-step.ss-completed .ss-label{color:#6b7280;font-weight:500}.section-stepper-step.ss-completed .ss-connector--left:after,.section-stepper-step.ss-completed .ss-connector--right:after{transform:scaleX(1)}.section-stepper-step.ss-warning .ss-badge{background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;border-color:transparent;box-shadow:0 2px 8px #f59e0b59;animation:ss-badge-pop .35s cubic-bezier(.34,1.56,.64,1) both}.section-stepper-step.ss-warning .ss-label{color:#b45309;font-weight:600}.section-stepper-step.ss-warning .ss-connector--left:after{transform:scaleX(0)}.section-stepper-step.ss-warning .ss-connector--right:after{transform:scaleX(0)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{background:#e8eaf0;color:#6366f1;border-color:#c7d2fe;transform:translateY(-2px)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-label{color:#6b7280}.ss-step-panel{animation:ss-panel-in .35s cubic-bezier(.4,0,.2,1) both}.ss-form{padding-top:0}@media(max-width:768px){.section-stepper-nav{padding:20px 16px 16px}.section-stepper-step .ss-label{font-size:.625rem;max-width:64px}.section-stepper-step .ss-badge{width:32px;height:32px;min-width:32px;font-size:.75rem}.section-stepper-step .ss-connector{top:16px}.section-stepper-step .ss-connector--left{right:calc(50% + 16px)}.section-stepper-step .ss-connector--right{left:calc(50% + 16px)}}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px)}.smart-form>*{margin-bottom:0!important}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 10px 0);margin-top:8px}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"] }]
|
|
3937
|
+
args: [{ selector: 'lib-smart-form', providers: [SmartFormController], standalone: false, template: "<div class=\"smart-form-container\">\r\n\r\n <!-- \u2550\u2550 Skeleton loader \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"smart-form-skeleton\" *ngIf=\"!isFormReady\" aria-hidden=\"true\">\r\n\r\n <!-- Title + description -->\r\n <div class=\"skel-header\">\r\n <div class=\"skel-block skel-title\" style=\"--sd: 0s\"></div>\r\n <div class=\"skel-block skel-desc\" style=\"--sd: 0.07s\"></div>\r\n </div>\r\n\r\n <!-- Section 1 \u2014 two full-width fields -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.1s; width: 32%\"></div>\r\n <div class=\"skel-fields skel-fields--two\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.13s; width: 55%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.15s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.16s; width: 45%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.18s\"></div>\r\n </div>\r\n <div class=\"skel-field skel-field--full\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.2s; width: 38%\"></div>\r\n <div class=\"skel-block skel-input skel-input--textarea\" style=\"--sd: 0.22s\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Section 2 \u2014 three columns -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.25s; width: 24%\"></div>\r\n <div class=\"skel-fields skel-fields--three\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.28s; width: 60%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.30s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.31s; width: 50%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.33s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.34s; width: 65%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.36s\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Section 3 \u2014 two columns + chip row -->\r\n <div class=\"skel-section\">\r\n <div class=\"skel-block skel-section-label\" style=\"--sd: 0.38s; width: 28%\"></div>\r\n <div class=\"skel-fields skel-fields--two\">\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.40s; width: 48%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.42s\"></div>\r\n </div>\r\n <div class=\"skel-field\">\r\n <div class=\"skel-block skel-label\" style=\"--sd: 0.43s; width: 55%\"></div>\r\n <div class=\"skel-block skel-input\" style=\"--sd: 0.45s\"></div>\r\n </div>\r\n </div>\r\n <div class=\"skel-chips\">\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.47s; width: 72px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.49s; width: 96px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.51s; width: 80px\"></div>\r\n <div class=\"skel-block skel-chip\" style=\"--sd: 0.53s; width: 64px\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Action bar -->\r\n <div class=\"skel-actions\">\r\n <div class=\"skel-block skel-btn\" style=\"--sd: 0.55s; width: 88px\"></div>\r\n <div class=\"skel-block skel-btn skel-btn--primary\" style=\"--sd: 0.58s; width: 120px\"></div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n SECTION STEPPER layout \u2014 stepper nav card + per-step form panels.\r\n Rendered when formSchema.sectionStepper === true.\r\n The nav and each step section are separate cards (no outer wrapper card).\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <ng-container *ngIf=\"formSchema && isFormReady && isSectionStepper\">\r\n\r\n <!-- Horizontal stepper nav card -->\r\n <div class=\"section-stepper-nav\" *ngIf=\"sectionSteps.length > 0\">\r\n <div class=\"section-stepper-track\">\r\n <div\r\n *ngFor=\"let step of sectionSteps; let i = index\"\r\n class=\"section-stepper-step\"\r\n [class.ss-active]=\"i === currentSectionStep\"\r\n [class.ss-completed]=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\r\n [class.ss-warning]=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\r\n [attr.data-tooltip]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\"\r\n (click)=\"goToSectionStep(i)\">\r\n\r\n <!-- Connector line \u2014 left side (hidden for first step) -->\r\n <div class=\"ss-connector ss-connector--left\" *ngIf=\"i > 0\"></div>\r\n\r\n <!-- Step badge -->\r\n <div class=\"ss-badge\">\r\n <!-- Green checkmark: visited and valid -->\r\n <svg *ngIf=\"i < currentSectionStep && stepValidationStates[i] !== 'warning'\"\r\n width=\"13\" height=\"13\" viewBox=\"0 0 24 24\"\r\n fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"20 6 9 17 4 12\"></polyline>\r\n </svg>\r\n <!-- Warning: bold ! is the most visible option inside a 38px circle badge -->\r\n <span *ngIf=\"i < currentSectionStep && stepValidationStates[i] === 'warning'\"\r\n class=\"ss-warning-mark\">!</span>\r\n <!-- Number: current or future step -->\r\n <span *ngIf=\"i >= currentSectionStep\">{{ i + 1 }}</span>\r\n </div>\r\n\r\n <!-- Step label (truncated; full text revealed by CSS tooltip) -->\r\n <div class=\"ss-label\" [title]=\"step.sectionConfig?.label || 'Step ' + (i + 1)\">\r\n {{ step.sectionConfig?.label || 'Step ' + (i + 1) }}\r\n </div>\r\n\r\n <!-- Connector line \u2014 right side (hidden for last step) -->\r\n <div class=\"ss-connector ss-connector--right\" *ngIf=\"i < sectionSteps.length - 1\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Step panels \u2014 all mounted, only active one is visible (preserves form data) -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form ss-form\">\r\n <div\r\n *ngFor=\"let step of sectionSteps; let i = index\"\r\n class=\"ss-step-panel\"\r\n [style.display]=\"i === currentSectionStep ? 'block' : 'none'\">\r\n <lib-form-section\r\n [config]=\"getSectionStepConfig(step)\"\r\n [controller]=\"controller\"\r\n [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Action bar: Prev / custom action buttons / Next \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\"\r\n *ngIf=\"!readOnly && formSchema.showActions !== false && actionBarConfig?.buttons?.length\">\r\n\r\n <!-- LEFT GROUP: Previous button + left-aligned custom buttons -->\r\n <div class=\"action-group action-group--left\">\r\n <lib-button\r\n *ngIf=\"!isSectionStepFirst\"\r\n variant=\"outline\"\r\n (click)=\"navigateToPrevious()\">\r\n {{ previousLabel }}\r\n </lib-button>\r\n <ng-container *ngFor=\"let btn of getButtonsForAlignment('left')\">\r\n <lib-button\r\n *ngIf=\"!btn.showOnLastStepOnly || isSectionStepLast\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- RIGHT GROUP: right-aligned custom buttons + Next button -->\r\n <div class=\"action-group action-group--right\">\r\n <ng-container *ngFor=\"let btn of getButtonsForAlignment('right')\">\r\n <lib-button\r\n *ngIf=\"!btn.showOnLastStepOnly || isSectionStepLast\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </ng-container>\r\n <lib-button\r\n *ngIf=\"!isSectionStepLast\"\r\n variant=\"primary\"\r\n (click)=\"navigateToNext()\">\r\n {{ nextLabel }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n\r\n </ng-container>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n Regular card wrapper \u2014 used for SECTION and STEPPER form types.\r\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <div class=\"smart-form-wrapper\" *ngIf=\"formSchema && isFormReady && !isSectionStepper\"\r\n [class.smart-form-wrapper--readonly]=\"readOnly\">\r\n\r\n <!-- Form Header -->\r\n <div class=\"form-header\" *ngIf=\"formSchema.showTitle !== false\">\r\n <h2 class=\"form-title\">{{ formSchema.label }}</h2>\r\n <p class=\"form-description\" *ngIf=\"formSchema.description\">{{ formSchema.description }}</p>\r\n </div>\r\n\r\n <!-- STEPPER type nav -->\r\n <div class=\"stepper-nav\" *ngIf=\"isStepper && formSchema.stepperConfig?.showStep !== false\">\r\n <div class=\"stepper-steps\" [class.horizontal]=\"formSchema.stepperConfig?.isHorizontal !== false\">\r\n <div *ngFor=\"let step of fieldList; let i = index\" class=\"stepper-step\" [class.active]=\"i === currentStep\"\r\n [class.completed]=\"i < currentStep\">\r\n <div class=\"step-number\">{{ i + 1 }}</div>\r\n <div class=\"step-label\">{{ step.sectionConfig?.label || 'Step ' + (i + 1) }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Form Content -->\r\n <form [formGroup]=\"formGroup\" class=\"smart-form\">\r\n <!-- Regular SECTION form -->\r\n <div *ngIf=\"!isStepper && formSchema.sectionConfig && formSchema.sectionConfig.isEnabled !== false\" class=\"form-section\">\r\n <lib-form-section [config]=\"formSchema.sectionConfig\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n\r\n <!-- STEPPER type form -->\r\n <div *ngIf=\"isStepper && currentStepConfig && currentStepConfig.sectionConfig?.isEnabled !== false\" class=\"form-stepper\">\r\n <lib-form-section [config]=\"currentStepConfig.sectionConfig!\" [controller]=\"controller\" [formGroup]=\"formGroup\">\r\n </lib-form-section>\r\n </div>\r\n </form>\r\n\r\n <!-- \u2500\u2500 Form Actions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"form-actions\" *ngIf=\"formSchema.showActions !== false && !readOnly && actionBarConfig?.buttons?.length\">\r\n\r\n <!-- LEFT GROUP -->\r\n <div class=\"action-group action-group--left\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('left')\"\r\n [variant]=\"$any(btn.variant) || 'outline'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n <!-- RIGHT GROUP -->\r\n <div class=\"action-group action-group--right\">\r\n <lib-button\r\n *ngFor=\"let btn of getButtonsForAlignment('right')\"\r\n [variant]=\"$any(btn.variant) || 'primary'\"\r\n [disabled]=\"isButtonDisabled(btn)\"\r\n (click)=\"handleButtonClick(btn)\">\r\n {{ getButtonLabel(btn) }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n</div>\r\n", styles: ["@keyframes skel-wave{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes skel-fade-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes form-reveal{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.smart-form-skeleton{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);box-shadow:var(--cc-sf-form-shadow, 0 1px 3px rgba(0, 0, 0, .06));padding:1.5rem;display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px);animation:skel-fade-in .3s ease both}.skel-block{position:relative;overflow:hidden;border-radius:6px;background:var(--cc-sf-input-disabled-bg, #F0F2F5)}.skel-block:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent 0%,rgba(255,255,255,.55) 45%,rgba(255,255,255,.75) 50%,rgba(255,255,255,.55) 55%,transparent 100%);animation:skel-wave 1.8s ease-in-out infinite;animation-delay:var(--sd, 0s)}.skel-header{display:flex;flex-direction:column;gap:10px}.skel-header .skel-title{height:26px;border-radius:8px}.skel-header .skel-desc{height:14px;border-radius:5px;opacity:.7}.skel-section{display:flex;flex-direction:column;gap:14px}.skel-section-label{height:16px;border-radius:0 5px 5px 0;border-left:var(--cc-sf-section-header-accent-width, 4px) solid var(--cc-sf-section-header-accent-color, #3B82F6);background:var(--cc-sf-input-disabled-bg, #F0F2F5);opacity:.85}.skel-fields{display:grid;gap:var(--cc-sf-grid-gap, 16px);align-items:start}.skel-fields--two{grid-template-columns:1fr 1fr}.skel-fields--three{grid-template-columns:1fr 1fr 1fr}@media (max-width: 640px){.skel-fields--two,.skel-fields--three{grid-template-columns:1fr}}.skel-field{display:flex;flex-direction:column;gap:7px}.skel-field--full{grid-column:1/-1}.skel-label{height:12px;border-radius:4px;opacity:.75}.skel-input{height:42px;border-radius:8px}.skel-input--textarea{height:80px}.skel-chips{display:flex;flex-wrap:wrap;gap:8px}.skel-chip{height:32px;border-radius:20px;opacity:.8}.skel-actions{display:flex;justify-content:flex-end;align-items:center;gap:12px;padding-top:20px;border-top:var(--cc-sf-actions-border, 1px solid #E5E7EB)}.skel-btn{height:40px;border-radius:8px}.skel-btn--primary{background:color-mix(in srgb,var(--cc-sf-accent-color, #3B82F6) 18%,var(--cc-sf-input-disabled-bg, #F0F2F5))}.smart-form-container{width:100%;font-family:var(--cc-sf-font-family, \"Inter\", sans-serif)}.smart-form-wrapper{background:var(--cc-sf-form-bg, #ffffff);border-radius:var(--cc-sf-form-border-radius, 12px);border:var(--cc-sf-form-border, none);animation:form-reveal .3s ease both}.smart-form-wrapper .form-alert-feedback,.form-header{margin-bottom:1rem}.form-header .form-title{font-size:var(--cc-sf-form-title-size, 1.5rem);font-weight:var(--cc-sf-form-title-weight, 700);color:var(--cc-sf-form-title-color, #111827);margin:0 0 8px;line-height:1.25}.form-header .form-description{font-size:var(--cc-sf-form-desc-size, .875rem);color:var(--cc-sf-form-desc-color, #6B7280);margin:0}@keyframes ss-badge-pop{0%{transform:scale(.6);opacity:0}70%{transform:scale(1.12)}to{transform:scale(1);opacity:1}}@keyframes ss-pulse-ring{0%{box-shadow:0 0 #6366f173}70%{box-shadow:0 0 0 10px #6366f100}to{box-shadow:0 0 #6366f100}}@keyframes ss-panel-in{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes ss-connector-fill{0%{transform:scaleX(0)}to{transform:scaleX(1)}}.section-stepper-nav{position:relative;background:#fff;border-radius:16px;border:1px solid #E8EAF0;box-shadow:0 1px 3px #0000000d,0 4px 16px #6366f10f;padding:24px 28px 48px;margin-bottom:14px;overflow-x:clip;overflow-y:hidden}.section-stepper-nav:before{content:\"\";position:absolute;inset:0 0 auto;height:3px;border-radius:16px 16px 0 0;background:linear-gradient(90deg,#6366f1,#8b5cf6,#ec4899)}.section-stepper-track{display:flex;align-items:flex-start;justify-content:space-between;min-width:max-content;width:100%}.section-stepper-step{display:flex;flex-direction:column;align-items:center;position:relative;flex:1;cursor:pointer;padding:0 4px}.section-stepper-step:after{content:attr(data-tooltip);position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%) translateY(4px);white-space:nowrap;background:#1e1b4b;color:#fff;font-size:.6875rem;font-weight:500;letter-spacing:.02em;padding:5px 11px;border-radius:6px;pointer-events:none;opacity:0;transition:opacity .2s ease,transform .2s ease;z-index:200;box-shadow:0 4px 14px #0003}.section-stepper-step:hover:after{opacity:1;transform:translate(-50%) translateY(0)}.section-stepper-step .ss-badge{width:38px;height:38px;min-width:38px;border-radius:50%;background:#f1f2f6;color:#9ca3af;border:2px solid #E5E7EB;display:flex;align-items:center;justify-content:center;font-size:.8125rem;font-weight:700;position:relative;z-index:1;transition:all .3s cubic-bezier(.34,1.56,.64,1)}.section-stepper-step .ss-badge span{line-height:1;letter-spacing:-.01em}.section-stepper-step .ss-badge svg{flex-shrink:0}.section-stepper-step .ss-badge .ss-warning-mark{font-size:1.25rem;font-weight:900;line-height:1;letter-spacing:0;color:#fff}.section-stepper-step .ss-label{margin-top:9px;font-size:.6875rem;font-weight:500;color:#b0b7c3;white-space:nowrap;text-align:center;transition:color .25s ease,font-weight .25s ease;max-width:88px;overflow:hidden;text-overflow:ellipsis;letter-spacing:.01em}.section-stepper-step .ss-connector{height:2px;background:#e8eaf0;position:absolute;top:19px;z-index:0;overflow:hidden;border-radius:2px}.section-stepper-step .ss-connector--left{left:0;right:calc(50% + 19px)}.section-stepper-step .ss-connector--right{left:calc(50% + 19px);right:0}.section-stepper-step .ss-connector:after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,#6366f1,#8b5cf6);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.4,0,.2,1)}.section-stepper-step.ss-active{cursor:default}.section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;border-color:transparent;box-shadow:0 0 0 4px #6366f12e,0 4px 12px #6366f159;animation:ss-badge-pop .4s cubic-bezier(.34,1.56,.64,1) both,ss-pulse-ring 2s .4s ease-out infinite}.section-stepper-step.ss-active .ss-label{color:#4f46e5;font-weight:700}.section-stepper-step.ss-completed .ss-badge{background:linear-gradient(135deg,#10b981,#059669);color:#fff;border-color:transparent;box-shadow:0 2px 8px #10b9814d}.section-stepper-step.ss-completed .ss-label{color:#6b7280;font-weight:500}.section-stepper-step.ss-completed .ss-connector--left:after,.section-stepper-step.ss-completed .ss-connector--right:after{transform:scaleX(1)}.section-stepper-step.ss-warning .ss-badge{background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;border-color:transparent;box-shadow:0 2px 8px #f59e0b59;animation:ss-badge-pop .35s cubic-bezier(.34,1.56,.64,1) both}.section-stepper-step.ss-warning .ss-label{color:#b45309;font-weight:600}.section-stepper-step.ss-warning .ss-connector--left:after{transform:scaleX(0)}.section-stepper-step.ss-warning .ss-connector--right:after{transform:scaleX(0)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{background:#e8eaf0;color:#6366f1;border-color:#c7d2fe;transform:translateY(-2px)}.section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-label{color:#6b7280}.ss-step-panel{animation:ss-panel-in .35s cubic-bezier(.4,0,.2,1) both}.ss-form{padding-top:0}@media (max-width: 768px){.section-stepper-nav{padding:20px 16px 16px}.section-stepper-step .ss-label{font-size:.625rem;max-width:64px}.section-stepper-step .ss-badge{width:32px;height:32px;min-width:32px;font-size:.75rem}.section-stepper-step .ss-connector{top:16px}.section-stepper-step .ss-connector--left{right:calc(50% + 16px)}.section-stepper-step .ss-connector--right{left:calc(50% + 16px)}}.stepper-nav{margin-bottom:32px}.stepper-nav .stepper-steps{display:flex;gap:16px}.stepper-nav .stepper-steps.horizontal{flex-direction:row;justify-content:space-between}.stepper-nav .stepper-steps:not(.horizontal){flex-direction:column}.stepper-nav .stepper-step{display:flex;align-items:center;gap:12px;flex:1;position:relative}.stepper-nav .stepper-step:not(:last-child):after{content:\"\";position:absolute;top:calc(var(--cc-sf-step-number-size, 40px) / 2);left:calc(100% + 8px);width:calc(100% - 40px);height:2px;background:var(--cc-sf-step-connector-color, #E5E7EB);transition:background var(--cc-sf-btn-transition, .2s ease)}.stepper-nav .stepper-step.completed:after{background:var(--cc-sf-step-connector-done, #22C55E)}.stepper-nav .stepper-step .step-number{width:var(--cc-sf-step-number-size, 40px);height:var(--cc-sf-step-number-size, 40px);min-width:var(--cc-sf-step-number-size, 40px);border-radius:50%;background:var(--cc-sf-step-number-bg, #E5E7EB);color:var(--cc-sf-step-number-color, #6B7280);display:flex;align-items:center;justify-content:center;font-size:var(--cc-sf-step-number-font-size, .875rem);font-weight:var(--cc-sf-step-number-weight, 600);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step .step-label{font-size:var(--cc-sf-step-label-size, .875rem);color:var(--cc-sf-step-label-color, #6B7280);font-weight:var(--cc-sf-step-label-weight, 500);transition:var(--cc-sf-btn-transition, all .2s ease)}.stepper-nav .stepper-step.active .step-number{background:var(--cc-sf-step-active-bg, #3B82F6);color:var(--cc-sf-step-active-color, #ffffff)}.stepper-nav .stepper-step.active .step-label{color:var(--cc-sf-step-active-label, #1D4ED8);font-weight:var(--cc-sf-step-active-label-weight, 700)}.stepper-nav .stepper-step.completed .step-number{background:var(--cc-sf-step-done-bg, #22C55E);color:var(--cc-sf-step-done-color, #ffffff)}.smart-form{display:flex;flex-direction:column;gap:var(--cc-sf-form-section-gap, 24px)}.smart-form>*{margin-bottom:0!important}.form-actions{display:flex;justify-content:space-between;align-items:center;gap:var(--cc-sf-actions-gap, 12px);padding:var(--cc-sf-actions-padding, 20px 10px 0);margin-top:8px}.form-actions .action-group{display:flex;align-items:center;gap:var(--cc-sf-actions-gap, 12px)}.form-actions .action-group--left{justify-content:flex-start}.form-actions .action-group--right{justify-content:flex-end;margin-left:auto}\n"] }]
|
|
3798
3938
|
}], ctorParameters: () => [{ type: i1$3.FormBuilder }, { type: SmartFormController }, { type: ExpressionService }, { type: i3.HttpClient }, { type: SnackbarService }, { type: i1$4.Router }, { type: i0.ChangeDetectorRef }], propDecorators: { formJson: [{
|
|
3799
3939
|
type: Input
|
|
3800
3940
|
}], initialValues: [{
|
|
@@ -7033,11 +7173,11 @@ class SelectionSectionNodeComponent {
|
|
|
7033
7173
|
return index;
|
|
7034
7174
|
}
|
|
7035
7175
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionSectionNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7036
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionSectionNodeComponent, isStandalone: false, selector: "lib-selection-section-node", inputs: { section: "section", sectionIndex: "sectionIndex", depth: "depth", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded && section.enabled) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}@media(max-width:640px){.fb-selection-section{border-radius:6px}}.fb-selection-section--disabled{opacity:.55}.fb-selection-section--disabled .fb-selection-section__body{pointer-events:none}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}@media(max-width:640px){.fb-selection-section__header{padding:8px 10px;gap:6px}}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media(max-width:640px){.fb-selection-section__expand-btn{padding:0}}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media(max-width:640px){.fb-selection-section__meta{gap:6px}}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media(max-width:640px){.fb-selection-section__label{font-size:12px}}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}@media(max-width:768px){.fb-selection-section__body{padding:4px 12px 12px 24px;gap:5px}}@media(max-width:640px){.fb-selection-section__body{padding:4px 10px 10px 20px;gap:4px}}\n"], dependencies: [{ 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: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }, { kind: "component", type: SelectionFieldNodeComponent, selector: "lib-selection-field-node", inputs: ["field", "hideToggleForOptionTypes"], outputs: ["toggleSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7176
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionSectionNodeComponent, isStandalone: false, selector: "lib-selection-section-node", inputs: { section: "section", sectionIndex: "sectionIndex", depth: "depth", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded && section.enabled) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}@media (max-width: 640px){.fb-selection-section{border-radius:6px}}.fb-selection-section--disabled{opacity:.55}.fb-selection-section--disabled .fb-selection-section__body{pointer-events:none}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}@media (max-width: 640px){.fb-selection-section__header{padding:8px 10px;gap:6px}}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media (max-width: 640px){.fb-selection-section__expand-btn{padding:0}}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media (max-width: 640px){.fb-selection-section__meta{gap:6px}}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media (max-width: 640px){.fb-selection-section__label{font-size:12px}}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}@media (max-width: 768px){.fb-selection-section__body{padding:4px 12px 12px 24px;gap:5px}}@media (max-width: 640px){.fb-selection-section__body{padding:4px 10px 10px 20px;gap:4px}}\n"], dependencies: [{ 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: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }, { kind: "component", type: SelectionFieldNodeComponent, selector: "lib-selection-field-node", inputs: ["field", "hideToggleForOptionTypes"], outputs: ["toggleSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7037
7177
|
}
|
|
7038
7178
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionSectionNodeComponent, decorators: [{
|
|
7039
7179
|
type: Component,
|
|
7040
|
-
args: [{ selector: 'lib-selection-section-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded && section.enabled) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}@media(max-width:640px){.fb-selection-section{border-radius:6px}}.fb-selection-section--disabled{opacity:.55}.fb-selection-section--disabled .fb-selection-section__body{pointer-events:none}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}@media(max-width:640px){.fb-selection-section__header{padding:8px 10px;gap:6px}}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media(max-width:640px){.fb-selection-section__expand-btn{padding:0}}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media(max-width:640px){.fb-selection-section__meta{gap:6px}}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media(max-width:640px){.fb-selection-section__label{font-size:12px}}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}@media(max-width:768px){.fb-selection-section__body{padding:4px 12px 12px 24px;gap:5px}}@media(max-width:640px){.fb-selection-section__body{padding:4px 10px 10px 20px;gap:4px}}\n"] }]
|
|
7180
|
+
args: [{ selector: 'lib-selection-section-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded && section.enabled) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}@media (max-width: 640px){.fb-selection-section{border-radius:6px}}.fb-selection-section--disabled{opacity:.55}.fb-selection-section--disabled .fb-selection-section__body{pointer-events:none}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}@media (max-width: 640px){.fb-selection-section__header{padding:8px 10px;gap:6px}}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media (max-width: 640px){.fb-selection-section__expand-btn{padding:0}}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media (max-width: 640px){.fb-selection-section__meta{gap:6px}}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media (max-width: 640px){.fb-selection-section__label{font-size:12px}}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}@media (max-width: 768px){.fb-selection-section__body{padding:4px 12px 12px 24px;gap:5px}}@media (max-width: 640px){.fb-selection-section__body{padding:4px 10px 10px 20px;gap:4px}}\n"] }]
|
|
7041
7181
|
}], propDecorators: { section: [{
|
|
7042
7182
|
type: Input,
|
|
7043
7183
|
args: [{ required: true }]
|
|
@@ -7082,11 +7222,11 @@ class GroupNodeComponent {
|
|
|
7082
7222
|
return index;
|
|
7083
7223
|
}
|
|
7084
7224
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GroupNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7085
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: GroupNodeComponent, isStandalone: false, selector: "lib-group-node", inputs: { group: "group", groupIndex: "groupIndex", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", sectionToggleEnabled: "sectionToggleEnabled", sectionToggleExpanded: "sectionToggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div class=\"fb-group-node\" [class.fb-group-node--disabled]=\"!group.enabled\">\r\n <div class=\"fb-group-node__header\">\r\n <button\r\n class=\"fb-group-node__expand-btn\"\r\n (click)=\"toggleExpanded.emit()\"\r\n [attr.aria-expanded]=\"group.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-group-node__chevron\"\r\n [class.fb-group-node__chevron--open]=\"group.expanded\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-group-node__meta\">\r\n <span class=\"fb-group-node__label\">{{ group.label }}</span>\r\n </div>\r\n\r\n <lib-toggle\r\n [checked]=\"group.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + group.label\"\r\n (toggleChange)=\"toggleEnabled.emit()\"\r\n />\r\n </div>\r\n\r\n @if (group.expanded && group.enabled) {\r\n <div class=\"fb-group-node__body\">\r\n @for (section of group.sections; track trackBySectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"section\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"0\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-group-node{border:1px solid var(--fb-fs-group-border, #e5e7eb);border-radius:var(--fb-fs-group-radius, 12px);background:var(--fb-fs-group-bg, #ffffff);overflow:hidden}@media(max-width:640px){.fb-group-node{border-radius:8px}}.fb-group-node--disabled{opacity:.6}.fb-group-node--disabled .fb-group-node__body{pointer-events:none}.fb-group-node__header{display:flex;align-items:center;gap:var(--fb-fs-header-gap, 10px);padding:var(--fb-fs-header-padding, 14px 16px);cursor:pointer;-webkit-user-select:none;user-select:none}@media(max-width:640px){.fb-group-node__header{padding:12px;gap:8px}}.fb-group-node__header:hover{background:var(--fb-fs-header-hover-bg, #f9fafb)}.fb-group-node__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media(max-width:640px){.fb-group-node__expand-btn{padding:0}}.fb-group-node__chevron{transition:transform .2s}.fb-group-node__chevron--open{transform:rotate(180deg)}.fb-group-node__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media(max-width:640px){.fb-group-node__meta{gap:6px}}.fb-group-node__label{font-size:var(--fb-fs-group-label-size, 14px);font-weight:700;color:var(--fb-fs-group-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media(max-width:640px){.fb-group-node__label{font-size:13px}}.fb-group-node__body{padding:var(--fb-fs-body-padding, 0 16px 16px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-section-gap, 12px)}@media(max-width:768px){.fb-group-node__body{padding:0 12px 12px 24px;gap:10px}}@media(max-width:640px){.fb-group-node__body{padding:0 12px 12px 20px;gap:8px}}\n"], dependencies: [{ 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: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7225
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: GroupNodeComponent, isStandalone: false, selector: "lib-group-node", inputs: { group: "group", groupIndex: "groupIndex", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", sectionToggleEnabled: "sectionToggleEnabled", sectionToggleExpanded: "sectionToggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div class=\"fb-group-node\" [class.fb-group-node--disabled]=\"!group.enabled\">\r\n <div class=\"fb-group-node__header\">\r\n <button\r\n class=\"fb-group-node__expand-btn\"\r\n (click)=\"toggleExpanded.emit()\"\r\n [attr.aria-expanded]=\"group.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-group-node__chevron\"\r\n [class.fb-group-node__chevron--open]=\"group.expanded\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-group-node__meta\">\r\n <span class=\"fb-group-node__label\">{{ group.label }}</span>\r\n </div>\r\n\r\n <lib-toggle\r\n [checked]=\"group.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + group.label\"\r\n (toggleChange)=\"toggleEnabled.emit()\"\r\n />\r\n </div>\r\n\r\n @if (group.expanded && group.enabled) {\r\n <div class=\"fb-group-node__body\">\r\n @for (section of group.sections; track trackBySectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"section\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"0\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-group-node{border:1px solid var(--fb-fs-group-border, #e5e7eb);border-radius:var(--fb-fs-group-radius, 12px);background:var(--fb-fs-group-bg, #ffffff);overflow:hidden}@media (max-width: 640px){.fb-group-node{border-radius:8px}}.fb-group-node--disabled{opacity:.6}.fb-group-node--disabled .fb-group-node__body{pointer-events:none}.fb-group-node__header{display:flex;align-items:center;gap:var(--fb-fs-header-gap, 10px);padding:var(--fb-fs-header-padding, 14px 16px);cursor:pointer;-webkit-user-select:none;user-select:none}@media (max-width: 640px){.fb-group-node__header{padding:12px;gap:8px}}.fb-group-node__header:hover{background:var(--fb-fs-header-hover-bg, #f9fafb)}.fb-group-node__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media (max-width: 640px){.fb-group-node__expand-btn{padding:0}}.fb-group-node__chevron{transition:transform .2s}.fb-group-node__chevron--open{transform:rotate(180deg)}.fb-group-node__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media (max-width: 640px){.fb-group-node__meta{gap:6px}}.fb-group-node__label{font-size:var(--fb-fs-group-label-size, 14px);font-weight:700;color:var(--fb-fs-group-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media (max-width: 640px){.fb-group-node__label{font-size:13px}}.fb-group-node__body{padding:var(--fb-fs-body-padding, 0 16px 16px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-section-gap, 12px)}@media (max-width: 768px){.fb-group-node__body{padding:0 12px 12px 24px;gap:10px}}@media (max-width: 640px){.fb-group-node__body{padding:0 12px 12px 20px;gap:8px}}\n"], dependencies: [{ 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: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7086
7226
|
}
|
|
7087
7227
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: GroupNodeComponent, decorators: [{
|
|
7088
7228
|
type: Component,
|
|
7089
|
-
args: [{ selector: 'lib-group-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-group-node\" [class.fb-group-node--disabled]=\"!group.enabled\">\r\n <div class=\"fb-group-node__header\">\r\n <button\r\n class=\"fb-group-node__expand-btn\"\r\n (click)=\"toggleExpanded.emit()\"\r\n [attr.aria-expanded]=\"group.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-group-node__chevron\"\r\n [class.fb-group-node__chevron--open]=\"group.expanded\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-group-node__meta\">\r\n <span class=\"fb-group-node__label\">{{ group.label }}</span>\r\n </div>\r\n\r\n <lib-toggle\r\n [checked]=\"group.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + group.label\"\r\n (toggleChange)=\"toggleEnabled.emit()\"\r\n />\r\n </div>\r\n\r\n @if (group.expanded && group.enabled) {\r\n <div class=\"fb-group-node__body\">\r\n @for (section of group.sections; track trackBySectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"section\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"0\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-group-node{border:1px solid var(--fb-fs-group-border, #e5e7eb);border-radius:var(--fb-fs-group-radius, 12px);background:var(--fb-fs-group-bg, #ffffff);overflow:hidden}@media(max-width:640px){.fb-group-node{border-radius:8px}}.fb-group-node--disabled{opacity:.6}.fb-group-node--disabled .fb-group-node__body{pointer-events:none}.fb-group-node__header{display:flex;align-items:center;gap:var(--fb-fs-header-gap, 10px);padding:var(--fb-fs-header-padding, 14px 16px);cursor:pointer;-webkit-user-select:none;user-select:none}@media(max-width:640px){.fb-group-node__header{padding:12px;gap:8px}}.fb-group-node__header:hover{background:var(--fb-fs-header-hover-bg, #f9fafb)}.fb-group-node__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media(max-width:640px){.fb-group-node__expand-btn{padding:0}}.fb-group-node__chevron{transition:transform .2s}.fb-group-node__chevron--open{transform:rotate(180deg)}.fb-group-node__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media(max-width:640px){.fb-group-node__meta{gap:6px}}.fb-group-node__label{font-size:var(--fb-fs-group-label-size, 14px);font-weight:700;color:var(--fb-fs-group-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media(max-width:640px){.fb-group-node__label{font-size:13px}}.fb-group-node__body{padding:var(--fb-fs-body-padding, 0 16px 16px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-section-gap, 12px)}@media(max-width:768px){.fb-group-node__body{padding:0 12px 12px 24px;gap:10px}}@media(max-width:640px){.fb-group-node__body{padding:0 12px 12px 20px;gap:8px}}\n"] }]
|
|
7229
|
+
args: [{ selector: 'lib-group-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-group-node\" [class.fb-group-node--disabled]=\"!group.enabled\">\r\n <div class=\"fb-group-node__header\">\r\n <button\r\n class=\"fb-group-node__expand-btn\"\r\n (click)=\"toggleExpanded.emit()\"\r\n [attr.aria-expanded]=\"group.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-group-node__chevron\"\r\n [class.fb-group-node__chevron--open]=\"group.expanded\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-group-node__meta\">\r\n <span class=\"fb-group-node__label\">{{ group.label }}</span>\r\n </div>\r\n\r\n <lib-toggle\r\n [checked]=\"group.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + group.label\"\r\n (toggleChange)=\"toggleEnabled.emit()\"\r\n />\r\n </div>\r\n\r\n @if (group.expanded && group.enabled) {\r\n <div class=\"fb-group-node__body\">\r\n @for (section of group.sections; track trackBySectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"section\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"0\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-group-node{border:1px solid var(--fb-fs-group-border, #e5e7eb);border-radius:var(--fb-fs-group-radius, 12px);background:var(--fb-fs-group-bg, #ffffff);overflow:hidden}@media (max-width: 640px){.fb-group-node{border-radius:8px}}.fb-group-node--disabled{opacity:.6}.fb-group-node--disabled .fb-group-node__body{pointer-events:none}.fb-group-node__header{display:flex;align-items:center;gap:var(--fb-fs-header-gap, 10px);padding:var(--fb-fs-header-padding, 14px 16px);cursor:pointer;-webkit-user-select:none;user-select:none}@media (max-width: 640px){.fb-group-node__header{padding:12px;gap:8px}}.fb-group-node__header:hover{background:var(--fb-fs-header-hover-bg, #f9fafb)}.fb-group-node__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media (max-width: 640px){.fb-group-node__expand-btn{padding:0}}.fb-group-node__chevron{transition:transform .2s}.fb-group-node__chevron--open{transform:rotate(180deg)}.fb-group-node__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media (max-width: 640px){.fb-group-node__meta{gap:6px}}.fb-group-node__label{font-size:var(--fb-fs-group-label-size, 14px);font-weight:700;color:var(--fb-fs-group-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media (max-width: 640px){.fb-group-node__label{font-size:13px}}.fb-group-node__body{padding:var(--fb-fs-body-padding, 0 16px 16px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-section-gap, 12px)}@media (max-width: 768px){.fb-group-node__body{padding:0 12px 12px 24px;gap:10px}}@media (max-width: 640px){.fb-group-node__body{padding:0 12px 12px 20px;gap:8px}}\n"] }]
|
|
7090
7230
|
}], propDecorators: { group: [{
|
|
7091
7231
|
type: Input,
|
|
7092
7232
|
args: [{ required: true }]
|
|
@@ -7168,11 +7308,11 @@ class FieldSelectionComponent {
|
|
|
7168
7308
|
}
|
|
7169
7309
|
}
|
|
7170
7310
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FieldSelectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7171
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: FieldSelectionComponent, isStandalone: false, selector: "lib-field-selection", inputs: { schema: "schema", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { schemaChange: "schemaChange" }, providers: [FieldSelectionService], usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-field-selection\">\r\n @for (group of store.groups(); track trackByGroupIndex($index); let gi = $index) {\r\n <lib-group-node\r\n [group]=\"group\"\r\n [groupIndex]=\"gi\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onToggleGroup(gi)\"\r\n (toggleExpanded)=\"onToggleGroupExpanded(gi)\"\r\n (sectionToggleEnabled)=\"onToggleSection(gi, $event)\"\r\n (sectionToggleExpanded)=\"onToggleSectionExpanded(gi, $event)\"\r\n (fieldToggle)=\"onToggleField(gi, $event.sectionPath, $event.fieldIndex)\"\r\n />\r\n }\r\n\r\n @if (store.groups().length === 0) {\r\n <div class=\"fb-field-selection__empty\">\r\n <p>No groups or fields found in the schema.</p>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-field-selection{display:flex;flex-direction:column;gap:var(--fb-fs-group-gap, 16px);padding:var(--fb-fs-padding, 16px);font-family:var(--fb-font-family, \"Inter\", sans-serif)}@media(max-width:768px){.fb-field-selection{gap:12px;padding:12px}}@media(max-width:640px){.fb-field-selection{gap:8px;padding:8px}}.fb-field-selection__empty{display:flex;align-items:center;justify-content:center;padding:48px 24px;color:var(--fb-fs-empty-color, #9ca3af);font-size:14px;text-align:center}@media(max-width:1024px){.fb-field-selection__empty{padding:32px 16px;font-size:13px}}@media(max-width:640px){.fb-field-selection__empty{padding:24px 12px;font-size:12px}}\n"], dependencies: [{ kind: "component", type: GroupNodeComponent, selector: "lib-group-node", inputs: ["group", "groupIndex", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "sectionToggleEnabled", "sectionToggleExpanded", "fieldToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7311
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: FieldSelectionComponent, isStandalone: false, selector: "lib-field-selection", inputs: { schema: "schema", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { schemaChange: "schemaChange" }, providers: [FieldSelectionService], usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-field-selection\">\r\n @for (group of store.groups(); track trackByGroupIndex($index); let gi = $index) {\r\n <lib-group-node\r\n [group]=\"group\"\r\n [groupIndex]=\"gi\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onToggleGroup(gi)\"\r\n (toggleExpanded)=\"onToggleGroupExpanded(gi)\"\r\n (sectionToggleEnabled)=\"onToggleSection(gi, $event)\"\r\n (sectionToggleExpanded)=\"onToggleSectionExpanded(gi, $event)\"\r\n (fieldToggle)=\"onToggleField(gi, $event.sectionPath, $event.fieldIndex)\"\r\n />\r\n }\r\n\r\n @if (store.groups().length === 0) {\r\n <div class=\"fb-field-selection__empty\">\r\n <p>No groups or fields found in the schema.</p>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-field-selection{display:flex;flex-direction:column;gap:var(--fb-fs-group-gap, 16px);padding:var(--fb-fs-padding, 16px);font-family:var(--fb-font-family, \"Inter\", sans-serif)}@media (max-width: 768px){.fb-field-selection{gap:12px;padding:12px}}@media (max-width: 640px){.fb-field-selection{gap:8px;padding:8px}}.fb-field-selection__empty{display:flex;align-items:center;justify-content:center;padding:48px 24px;color:var(--fb-fs-empty-color, #9ca3af);font-size:14px;text-align:center}@media (max-width: 1024px){.fb-field-selection__empty{padding:32px 16px;font-size:13px}}@media (max-width: 640px){.fb-field-selection__empty{padding:24px 12px;font-size:12px}}\n"], dependencies: [{ kind: "component", type: GroupNodeComponent, selector: "lib-group-node", inputs: ["group", "groupIndex", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "sectionToggleEnabled", "sectionToggleExpanded", "fieldToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7172
7312
|
}
|
|
7173
7313
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FieldSelectionComponent, decorators: [{
|
|
7174
7314
|
type: Component,
|
|
7175
|
-
args: [{ selector: 'lib-field-selection', standalone: false, providers: [FieldSelectionService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-field-selection\">\r\n @for (group of store.groups(); track trackByGroupIndex($index); let gi = $index) {\r\n <lib-group-node\r\n [group]=\"group\"\r\n [groupIndex]=\"gi\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onToggleGroup(gi)\"\r\n (toggleExpanded)=\"onToggleGroupExpanded(gi)\"\r\n (sectionToggleEnabled)=\"onToggleSection(gi, $event)\"\r\n (sectionToggleExpanded)=\"onToggleSectionExpanded(gi, $event)\"\r\n (fieldToggle)=\"onToggleField(gi, $event.sectionPath, $event.fieldIndex)\"\r\n />\r\n }\r\n\r\n @if (store.groups().length === 0) {\r\n <div class=\"fb-field-selection__empty\">\r\n <p>No groups or fields found in the schema.</p>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-field-selection{display:flex;flex-direction:column;gap:var(--fb-fs-group-gap, 16px);padding:var(--fb-fs-padding, 16px);font-family:var(--fb-font-family, \"Inter\", sans-serif)}@media(max-width:768px){.fb-field-selection{gap:12px;padding:12px}}@media(max-width:640px){.fb-field-selection{gap:8px;padding:8px}}.fb-field-selection__empty{display:flex;align-items:center;justify-content:center;padding:48px 24px;color:var(--fb-fs-empty-color, #9ca3af);font-size:14px;text-align:center}@media(max-width:1024px){.fb-field-selection__empty{padding:32px 16px;font-size:13px}}@media(max-width:640px){.fb-field-selection__empty{padding:24px 12px;font-size:12px}}\n"] }]
|
|
7315
|
+
args: [{ selector: 'lib-field-selection', standalone: false, providers: [FieldSelectionService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-field-selection\">\r\n @for (group of store.groups(); track trackByGroupIndex($index); let gi = $index) {\r\n <lib-group-node\r\n [group]=\"group\"\r\n [groupIndex]=\"gi\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onToggleGroup(gi)\"\r\n (toggleExpanded)=\"onToggleGroupExpanded(gi)\"\r\n (sectionToggleEnabled)=\"onToggleSection(gi, $event)\"\r\n (sectionToggleExpanded)=\"onToggleSectionExpanded(gi, $event)\"\r\n (fieldToggle)=\"onToggleField(gi, $event.sectionPath, $event.fieldIndex)\"\r\n />\r\n }\r\n\r\n @if (store.groups().length === 0) {\r\n <div class=\"fb-field-selection__empty\">\r\n <p>No groups or fields found in the schema.</p>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-field-selection{display:flex;flex-direction:column;gap:var(--fb-fs-group-gap, 16px);padding:var(--fb-fs-padding, 16px);font-family:var(--fb-font-family, \"Inter\", sans-serif)}@media (max-width: 768px){.fb-field-selection{gap:12px;padding:12px}}@media (max-width: 640px){.fb-field-selection{gap:8px;padding:8px}}.fb-field-selection__empty{display:flex;align-items:center;justify-content:center;padding:48px 24px;color:var(--fb-fs-empty-color, #9ca3af);font-size:14px;text-align:center}@media (max-width: 1024px){.fb-field-selection__empty{padding:32px 16px;font-size:13px}}@media (max-width: 640px){.fb-field-selection__empty{padding:24px 12px;font-size:12px}}\n"] }]
|
|
7176
7316
|
}], propDecorators: { schema: [{
|
|
7177
7317
|
type: Input,
|
|
7178
7318
|
args: [{ required: true }]
|
|
@@ -7746,11 +7886,11 @@ class ConfiguratorTreeComponent {
|
|
|
7746
7886
|
return a.every((v, i) => v === b[i]);
|
|
7747
7887
|
}
|
|
7748
7888
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfiguratorTreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7749
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfiguratorTreeComponent, isStandalone: false, selector: "lib-configurator-tree", inputs: { tree: "tree", selectedFieldPath: "selectedFieldPath" }, outputs: { selectField: "selectField", toggleExpanded: "toggleExpanded" }, ngImport: i0, template: "<div class=\"fb-cfg-tree\">\r\n <div class=\"fb-cfg-tree__header\">\r\n <h4 class=\"fb-cfg-tree__title\">Field Tree</h4>\r\n <p class=\"fb-cfg-tree__subtitle\">Select a field to configure</p>\r\n </div>\r\n\r\n <div class=\"fb-cfg-tree__scrollable\">\r\n @for (node of tree; track trackByNodeId($index, node)) {\r\n <ng-container *ngTemplateOutlet=\"treeNodeTpl; context: { $implicit: node, depth: 0 }\"></ng-container>\r\n }\r\n\r\n @if (tree.length === 0) {\r\n <div class=\"fb-cfg-tree__empty\">\r\n No fields to configure.\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive tree node template -->\r\n<ng-template #treeNodeTpl let-node let-depth=\"depth\">\r\n @if (node.type === 'field') {\r\n <!-- Field node (clickable leaf) -->\r\n <div\r\n class=\"fb-cfg-tree-item\"\r\n [class.fb-cfg-tree-item--active]=\"isSelected(node)\"\r\n (click)=\"onFieldSelect(node)\"\r\n [style.padding-left.px]=\"16 + depth * 16\"\r\n >\r\n <span class=\"fb-cfg-tree-item__drag\" title=\"Drag to reorder\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"9\" cy=\"5\" r=\"1\"/><circle cx=\"9\" cy=\"12\" r=\"1\"/>\r\n <circle cx=\"9\" cy=\"19\" r=\"1\"/><circle cx=\"15\" cy=\"5\" r=\"1\"/>\r\n <circle cx=\"15\" cy=\"12\" r=\"1\"/><circle cx=\"15\" cy=\"19\" r=\"1\"/>\r\n </svg>\r\n </span>\r\n <div class=\"fb-cfg-tree-item__content\">\r\n <span class=\"fb-cfg-tree-item__label\">{{ node.label }}</span>\r\n @if (node.fieldConfig?.type) {\r\n <span class=\"fb-cfg-tree-item__type\">{{ node.fieldConfig.type }}</span>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- Group or Section node (expandable) -->\r\n <div\r\n class=\"fb-cfg-tree-section\"\r\n [style.padding-left.px]=\"8 + depth * 12\"\r\n >\r\n <div class=\"fb-cfg-tree-section__header\" (click)=\"onNodeClick(node)\">\r\n <div class=\"fb-cfg-tree-section__title-group\">\r\n <span\r\n class=\"fb-cfg-tree-section__chevron\"\r\n [class.fb-cfg-tree-section__chevron--expanded]=\"node.expanded\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"9 18 15 12 9 6\"></polyline>\r\n </svg>\r\n </span>\r\n <span class=\"fb-cfg-tree-section__label\">{{ node.label }}</span>\r\n </div>\r\n </div>\r\n\r\n @if (node.expanded && node.children.length > 0) {\r\n <div class=\"fb-cfg-tree-section__children\">\r\n @for (child of node.children; track trackByNodeId($index, child)) {\r\n <ng-container *ngTemplateOutlet=\"treeNodeTpl; context: { $implicit: child, depth: depth + 1 }\"></ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;height:100%;overflow:hidden}.fb-cfg-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.fb-cfg-tree__header{padding:16px 20px;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-tree-header-bg, #ffffff);flex-shrink:0}@media(max-width:768px){.fb-cfg-tree__header{padding:12px 16px}}@media(max-width:640px){.fb-cfg-tree__header{padding:10px 12px}}.fb-cfg-tree__title{margin:0;font-size:14px;font-weight:700;color:var(--fb-fc-tree-title-color, #111827)}@media(max-width:640px){.fb-cfg-tree__title{font-size:13px}}.fb-cfg-tree__subtitle{margin:4px 0 0;font-size:11px;color:var(--fb-fc-tree-subtitle-color, #6b7280);letter-spacing:.02em}@media(max-width:640px){.fb-cfg-tree__subtitle{font-size:10px}}.fb-cfg-tree__scrollable{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:16px}@media(max-width:768px){.fb-cfg-tree__scrollable{padding:12px}}@media(max-width:640px){.fb-cfg-tree__scrollable{padding:8px}}.fb-cfg-tree__empty{padding:32px 16px;text-align:center;color:var(--fb-fc-empty-color, #9ca3af);font-size:13px}@media(max-width:640px){.fb-cfg-tree__empty{padding:24px 12px;font-size:12px}}.fb-cfg-tree-section{margin-bottom:16px}@media(max-width:768px){.fb-cfg-tree-section{margin-bottom:12px}}@media(max-width:640px){.fb-cfg-tree-section{margin-bottom:8px}}.fb-cfg-tree-section__header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px 8px;border-bottom:1px solid var(--fb-fc-section-divider, #f3f4f6);margin-bottom:8px;cursor:pointer}@media(max-width:640px){.fb-cfg-tree-section__header{padding:3px 6px 6px;margin-bottom:6px}}.fb-cfg-tree-section__header:hover{background:var(--fb-fc-section-hover, #f9fafb);border-radius:6px}.fb-cfg-tree-section__title-group{display:flex;align-items:center;gap:6px}@media(max-width:640px){.fb-cfg-tree-section__title-group{gap:4px}}.fb-cfg-tree-section__chevron{display:flex;color:var(--fb-fc-chevron-color, #9ca3af);transition:transform .2s cubic-bezier(.4,0,.2,1)}.fb-cfg-tree-section__chevron--expanded{transform:rotate(90deg)}.fb-cfg-tree-section__label{font-size:13px;font-weight:700;color:var(--fb-fc-section-label-color, #111827);text-transform:uppercase;letter-spacing:.05em}@media(max-width:640px){.fb-cfg-tree-section__label{font-size:12px;letter-spacing:.02em}}.fb-cfg-tree-section__children{display:flex;flex-direction:column;gap:8px}@media(max-width:640px){.fb-cfg-tree-section__children{gap:6px}}.fb-cfg-tree-item{display:flex;align-items:center;padding:12px;background:var(--fb-fc-item-bg, #ffffff);border:1px solid var(--fb-fc-item-border, #e5e7eb);border-radius:10px;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1)}.fb-cfg-tree-item:hover{border-color:var(--fb-fc-item-hover-border, #3b82f6);box-shadow:0 2px 8px #3b82f614}.fb-cfg-tree-item--active{border-color:var(--fb-fc-item-active-border, #3b82f6);background:var(--fb-fc-item-active-bg, #f0f7ff);box-shadow:0 0 0 1px var(--fb-fc-item-active-border, #3b82f6)}.fb-cfg-tree-item__drag{color:var(--fb-fc-drag-color, #d1d5db);cursor:grab;margin-right:8px;display:flex}.fb-cfg-tree-item__content{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fb-cfg-tree-item__label{font-size:13px;font-weight:600;color:var(--fb-fc-item-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-cfg-tree-item__type{font-size:10px;color:var(--fb-fc-item-type-color, #6b7280);text-transform:uppercase;letter-spacing:.05em;font-weight:500}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7889
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfiguratorTreeComponent, isStandalone: false, selector: "lib-configurator-tree", inputs: { tree: "tree", selectedFieldPath: "selectedFieldPath" }, outputs: { selectField: "selectField", toggleExpanded: "toggleExpanded" }, ngImport: i0, template: "<div class=\"fb-cfg-tree\">\r\n <div class=\"fb-cfg-tree__header\">\r\n <h4 class=\"fb-cfg-tree__title\">Field Tree</h4>\r\n <p class=\"fb-cfg-tree__subtitle\">Select a field to configure</p>\r\n </div>\r\n\r\n <div class=\"fb-cfg-tree__scrollable\">\r\n @for (node of tree; track trackByNodeId($index, node)) {\r\n <ng-container *ngTemplateOutlet=\"treeNodeTpl; context: { $implicit: node, depth: 0 }\"></ng-container>\r\n }\r\n\r\n @if (tree.length === 0) {\r\n <div class=\"fb-cfg-tree__empty\">\r\n No fields to configure.\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive tree node template -->\r\n<ng-template #treeNodeTpl let-node let-depth=\"depth\">\r\n @if (node.type === 'field') {\r\n <!-- Field node (clickable leaf) -->\r\n <div\r\n class=\"fb-cfg-tree-item\"\r\n [class.fb-cfg-tree-item--active]=\"isSelected(node)\"\r\n (click)=\"onFieldSelect(node)\"\r\n [style.padding-left.px]=\"16 + depth * 16\"\r\n >\r\n <span class=\"fb-cfg-tree-item__drag\" title=\"Drag to reorder\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"9\" cy=\"5\" r=\"1\"/><circle cx=\"9\" cy=\"12\" r=\"1\"/>\r\n <circle cx=\"9\" cy=\"19\" r=\"1\"/><circle cx=\"15\" cy=\"5\" r=\"1\"/>\r\n <circle cx=\"15\" cy=\"12\" r=\"1\"/><circle cx=\"15\" cy=\"19\" r=\"1\"/>\r\n </svg>\r\n </span>\r\n <div class=\"fb-cfg-tree-item__content\">\r\n <span class=\"fb-cfg-tree-item__label\">{{ node.label }}</span>\r\n @if (node.fieldConfig?.type) {\r\n <span class=\"fb-cfg-tree-item__type\">{{ node.fieldConfig.type }}</span>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- Group or Section node (expandable) -->\r\n <div\r\n class=\"fb-cfg-tree-section\"\r\n [style.padding-left.px]=\"8 + depth * 12\"\r\n >\r\n <div class=\"fb-cfg-tree-section__header\" (click)=\"onNodeClick(node)\">\r\n <div class=\"fb-cfg-tree-section__title-group\">\r\n <span\r\n class=\"fb-cfg-tree-section__chevron\"\r\n [class.fb-cfg-tree-section__chevron--expanded]=\"node.expanded\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"9 18 15 12 9 6\"></polyline>\r\n </svg>\r\n </span>\r\n <span class=\"fb-cfg-tree-section__label\">{{ node.label }}</span>\r\n </div>\r\n </div>\r\n\r\n @if (node.expanded && node.children.length > 0) {\r\n <div class=\"fb-cfg-tree-section__children\">\r\n @for (child of node.children; track trackByNodeId($index, child)) {\r\n <ng-container *ngTemplateOutlet=\"treeNodeTpl; context: { $implicit: child, depth: depth + 1 }\"></ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;height:100%;overflow:hidden}.fb-cfg-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.fb-cfg-tree__header{padding:16px 20px;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-tree-header-bg, #ffffff);flex-shrink:0}@media (max-width: 768px){.fb-cfg-tree__header{padding:12px 16px}}@media (max-width: 640px){.fb-cfg-tree__header{padding:10px 12px}}.fb-cfg-tree__title{margin:0;font-size:14px;font-weight:700;color:var(--fb-fc-tree-title-color, #111827)}@media (max-width: 640px){.fb-cfg-tree__title{font-size:13px}}.fb-cfg-tree__subtitle{margin:4px 0 0;font-size:11px;color:var(--fb-fc-tree-subtitle-color, #6b7280);letter-spacing:.02em}@media (max-width: 640px){.fb-cfg-tree__subtitle{font-size:10px}}.fb-cfg-tree__scrollable{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:16px}@media (max-width: 768px){.fb-cfg-tree__scrollable{padding:12px}}@media (max-width: 640px){.fb-cfg-tree__scrollable{padding:8px}}.fb-cfg-tree__empty{padding:32px 16px;text-align:center;color:var(--fb-fc-empty-color, #9ca3af);font-size:13px}@media (max-width: 640px){.fb-cfg-tree__empty{padding:24px 12px;font-size:12px}}.fb-cfg-tree-section{margin-bottom:16px}@media (max-width: 768px){.fb-cfg-tree-section{margin-bottom:12px}}@media (max-width: 640px){.fb-cfg-tree-section{margin-bottom:8px}}.fb-cfg-tree-section__header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px 8px;border-bottom:1px solid var(--fb-fc-section-divider, #f3f4f6);margin-bottom:8px;cursor:pointer}@media (max-width: 640px){.fb-cfg-tree-section__header{padding:3px 6px 6px;margin-bottom:6px}}.fb-cfg-tree-section__header:hover{background:var(--fb-fc-section-hover, #f9fafb);border-radius:6px}.fb-cfg-tree-section__title-group{display:flex;align-items:center;gap:6px}@media (max-width: 640px){.fb-cfg-tree-section__title-group{gap:4px}}.fb-cfg-tree-section__chevron{display:flex;color:var(--fb-fc-chevron-color, #9ca3af);transition:transform .2s cubic-bezier(.4,0,.2,1)}.fb-cfg-tree-section__chevron--expanded{transform:rotate(90deg)}.fb-cfg-tree-section__label{font-size:13px;font-weight:700;color:var(--fb-fc-section-label-color, #111827);text-transform:uppercase;letter-spacing:.05em}@media (max-width: 640px){.fb-cfg-tree-section__label{font-size:12px;letter-spacing:.02em}}.fb-cfg-tree-section__children{display:flex;flex-direction:column;gap:8px}@media (max-width: 640px){.fb-cfg-tree-section__children{gap:6px}}.fb-cfg-tree-item{display:flex;align-items:center;padding:12px;background:var(--fb-fc-item-bg, #ffffff);border:1px solid var(--fb-fc-item-border, #e5e7eb);border-radius:10px;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1)}.fb-cfg-tree-item:hover{border-color:var(--fb-fc-item-hover-border, #3b82f6);box-shadow:0 2px 8px #3b82f614}.fb-cfg-tree-item--active{border-color:var(--fb-fc-item-active-border, #3b82f6);background:var(--fb-fc-item-active-bg, #f0f7ff);box-shadow:0 0 0 1px var(--fb-fc-item-active-border, #3b82f6)}.fb-cfg-tree-item__drag{color:var(--fb-fc-drag-color, #d1d5db);cursor:grab;margin-right:8px;display:flex}.fb-cfg-tree-item__content{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fb-cfg-tree-item__label{font-size:13px;font-weight:600;color:var(--fb-fc-item-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-cfg-tree-item__type{font-size:10px;color:var(--fb-fc-item-type-color, #6b7280);text-transform:uppercase;letter-spacing:.05em;font-weight:500}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7750
7890
|
}
|
|
7751
7891
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfiguratorTreeComponent, decorators: [{
|
|
7752
7892
|
type: Component,
|
|
7753
|
-
args: [{ selector: 'lib-configurator-tree', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-cfg-tree\">\r\n <div class=\"fb-cfg-tree__header\">\r\n <h4 class=\"fb-cfg-tree__title\">Field Tree</h4>\r\n <p class=\"fb-cfg-tree__subtitle\">Select a field to configure</p>\r\n </div>\r\n\r\n <div class=\"fb-cfg-tree__scrollable\">\r\n @for (node of tree; track trackByNodeId($index, node)) {\r\n <ng-container *ngTemplateOutlet=\"treeNodeTpl; context: { $implicit: node, depth: 0 }\"></ng-container>\r\n }\r\n\r\n @if (tree.length === 0) {\r\n <div class=\"fb-cfg-tree__empty\">\r\n No fields to configure.\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive tree node template -->\r\n<ng-template #treeNodeTpl let-node let-depth=\"depth\">\r\n @if (node.type === 'field') {\r\n <!-- Field node (clickable leaf) -->\r\n <div\r\n class=\"fb-cfg-tree-item\"\r\n [class.fb-cfg-tree-item--active]=\"isSelected(node)\"\r\n (click)=\"onFieldSelect(node)\"\r\n [style.padding-left.px]=\"16 + depth * 16\"\r\n >\r\n <span class=\"fb-cfg-tree-item__drag\" title=\"Drag to reorder\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"9\" cy=\"5\" r=\"1\"/><circle cx=\"9\" cy=\"12\" r=\"1\"/>\r\n <circle cx=\"9\" cy=\"19\" r=\"1\"/><circle cx=\"15\" cy=\"5\" r=\"1\"/>\r\n <circle cx=\"15\" cy=\"12\" r=\"1\"/><circle cx=\"15\" cy=\"19\" r=\"1\"/>\r\n </svg>\r\n </span>\r\n <div class=\"fb-cfg-tree-item__content\">\r\n <span class=\"fb-cfg-tree-item__label\">{{ node.label }}</span>\r\n @if (node.fieldConfig?.type) {\r\n <span class=\"fb-cfg-tree-item__type\">{{ node.fieldConfig.type }}</span>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- Group or Section node (expandable) -->\r\n <div\r\n class=\"fb-cfg-tree-section\"\r\n [style.padding-left.px]=\"8 + depth * 12\"\r\n >\r\n <div class=\"fb-cfg-tree-section__header\" (click)=\"onNodeClick(node)\">\r\n <div class=\"fb-cfg-tree-section__title-group\">\r\n <span\r\n class=\"fb-cfg-tree-section__chevron\"\r\n [class.fb-cfg-tree-section__chevron--expanded]=\"node.expanded\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"9 18 15 12 9 6\"></polyline>\r\n </svg>\r\n </span>\r\n <span class=\"fb-cfg-tree-section__label\">{{ node.label }}</span>\r\n </div>\r\n </div>\r\n\r\n @if (node.expanded && node.children.length > 0) {\r\n <div class=\"fb-cfg-tree-section__children\">\r\n @for (child of node.children; track trackByNodeId($index, child)) {\r\n <ng-container *ngTemplateOutlet=\"treeNodeTpl; context: { $implicit: child, depth: depth + 1 }\"></ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;height:100%;overflow:hidden}.fb-cfg-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.fb-cfg-tree__header{padding:16px 20px;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-tree-header-bg, #ffffff);flex-shrink:0}@media(max-width:768px){.fb-cfg-tree__header{padding:12px 16px}}@media(max-width:640px){.fb-cfg-tree__header{padding:10px 12px}}.fb-cfg-tree__title{margin:0;font-size:14px;font-weight:700;color:var(--fb-fc-tree-title-color, #111827)}@media(max-width:640px){.fb-cfg-tree__title{font-size:13px}}.fb-cfg-tree__subtitle{margin:4px 0 0;font-size:11px;color:var(--fb-fc-tree-subtitle-color, #6b7280);letter-spacing:.02em}@media(max-width:640px){.fb-cfg-tree__subtitle{font-size:10px}}.fb-cfg-tree__scrollable{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:16px}@media(max-width:768px){.fb-cfg-tree__scrollable{padding:12px}}@media(max-width:640px){.fb-cfg-tree__scrollable{padding:8px}}.fb-cfg-tree__empty{padding:32px 16px;text-align:center;color:var(--fb-fc-empty-color, #9ca3af);font-size:13px}@media(max-width:640px){.fb-cfg-tree__empty{padding:24px 12px;font-size:12px}}.fb-cfg-tree-section{margin-bottom:16px}@media(max-width:768px){.fb-cfg-tree-section{margin-bottom:12px}}@media(max-width:640px){.fb-cfg-tree-section{margin-bottom:8px}}.fb-cfg-tree-section__header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px 8px;border-bottom:1px solid var(--fb-fc-section-divider, #f3f4f6);margin-bottom:8px;cursor:pointer}@media(max-width:640px){.fb-cfg-tree-section__header{padding:3px 6px 6px;margin-bottom:6px}}.fb-cfg-tree-section__header:hover{background:var(--fb-fc-section-hover, #f9fafb);border-radius:6px}.fb-cfg-tree-section__title-group{display:flex;align-items:center;gap:6px}@media(max-width:640px){.fb-cfg-tree-section__title-group{gap:4px}}.fb-cfg-tree-section__chevron{display:flex;color:var(--fb-fc-chevron-color, #9ca3af);transition:transform .2s cubic-bezier(.4,0,.2,1)}.fb-cfg-tree-section__chevron--expanded{transform:rotate(90deg)}.fb-cfg-tree-section__label{font-size:13px;font-weight:700;color:var(--fb-fc-section-label-color, #111827);text-transform:uppercase;letter-spacing:.05em}@media(max-width:640px){.fb-cfg-tree-section__label{font-size:12px;letter-spacing:.02em}}.fb-cfg-tree-section__children{display:flex;flex-direction:column;gap:8px}@media(max-width:640px){.fb-cfg-tree-section__children{gap:6px}}.fb-cfg-tree-item{display:flex;align-items:center;padding:12px;background:var(--fb-fc-item-bg, #ffffff);border:1px solid var(--fb-fc-item-border, #e5e7eb);border-radius:10px;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1)}.fb-cfg-tree-item:hover{border-color:var(--fb-fc-item-hover-border, #3b82f6);box-shadow:0 2px 8px #3b82f614}.fb-cfg-tree-item--active{border-color:var(--fb-fc-item-active-border, #3b82f6);background:var(--fb-fc-item-active-bg, #f0f7ff);box-shadow:0 0 0 1px var(--fb-fc-item-active-border, #3b82f6)}.fb-cfg-tree-item__drag{color:var(--fb-fc-drag-color, #d1d5db);cursor:grab;margin-right:8px;display:flex}.fb-cfg-tree-item__content{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fb-cfg-tree-item__label{font-size:13px;font-weight:600;color:var(--fb-fc-item-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-cfg-tree-item__type{font-size:10px;color:var(--fb-fc-item-type-color, #6b7280);text-transform:uppercase;letter-spacing:.05em;font-weight:500}\n"] }]
|
|
7893
|
+
args: [{ selector: 'lib-configurator-tree', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-cfg-tree\">\r\n <div class=\"fb-cfg-tree__header\">\r\n <h4 class=\"fb-cfg-tree__title\">Field Tree</h4>\r\n <p class=\"fb-cfg-tree__subtitle\">Select a field to configure</p>\r\n </div>\r\n\r\n <div class=\"fb-cfg-tree__scrollable\">\r\n @for (node of tree; track trackByNodeId($index, node)) {\r\n <ng-container *ngTemplateOutlet=\"treeNodeTpl; context: { $implicit: node, depth: 0 }\"></ng-container>\r\n }\r\n\r\n @if (tree.length === 0) {\r\n <div class=\"fb-cfg-tree__empty\">\r\n No fields to configure.\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive tree node template -->\r\n<ng-template #treeNodeTpl let-node let-depth=\"depth\">\r\n @if (node.type === 'field') {\r\n <!-- Field node (clickable leaf) -->\r\n <div\r\n class=\"fb-cfg-tree-item\"\r\n [class.fb-cfg-tree-item--active]=\"isSelected(node)\"\r\n (click)=\"onFieldSelect(node)\"\r\n [style.padding-left.px]=\"16 + depth * 16\"\r\n >\r\n <span class=\"fb-cfg-tree-item__drag\" title=\"Drag to reorder\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"9\" cy=\"5\" r=\"1\"/><circle cx=\"9\" cy=\"12\" r=\"1\"/>\r\n <circle cx=\"9\" cy=\"19\" r=\"1\"/><circle cx=\"15\" cy=\"5\" r=\"1\"/>\r\n <circle cx=\"15\" cy=\"12\" r=\"1\"/><circle cx=\"15\" cy=\"19\" r=\"1\"/>\r\n </svg>\r\n </span>\r\n <div class=\"fb-cfg-tree-item__content\">\r\n <span class=\"fb-cfg-tree-item__label\">{{ node.label }}</span>\r\n @if (node.fieldConfig?.type) {\r\n <span class=\"fb-cfg-tree-item__type\">{{ node.fieldConfig.type }}</span>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- Group or Section node (expandable) -->\r\n <div\r\n class=\"fb-cfg-tree-section\"\r\n [style.padding-left.px]=\"8 + depth * 12\"\r\n >\r\n <div class=\"fb-cfg-tree-section__header\" (click)=\"onNodeClick(node)\">\r\n <div class=\"fb-cfg-tree-section__title-group\">\r\n <span\r\n class=\"fb-cfg-tree-section__chevron\"\r\n [class.fb-cfg-tree-section__chevron--expanded]=\"node.expanded\"\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <polyline points=\"9 18 15 12 9 6\"></polyline>\r\n </svg>\r\n </span>\r\n <span class=\"fb-cfg-tree-section__label\">{{ node.label }}</span>\r\n </div>\r\n </div>\r\n\r\n @if (node.expanded && node.children.length > 0) {\r\n <div class=\"fb-cfg-tree-section__children\">\r\n @for (child of node.children; track trackByNodeId($index, child)) {\r\n <ng-container *ngTemplateOutlet=\"treeNodeTpl; context: { $implicit: child, depth: depth + 1 }\"></ng-container>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;height:100%;overflow:hidden}.fb-cfg-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.fb-cfg-tree__header{padding:16px 20px;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-tree-header-bg, #ffffff);flex-shrink:0}@media (max-width: 768px){.fb-cfg-tree__header{padding:12px 16px}}@media (max-width: 640px){.fb-cfg-tree__header{padding:10px 12px}}.fb-cfg-tree__title{margin:0;font-size:14px;font-weight:700;color:var(--fb-fc-tree-title-color, #111827)}@media (max-width: 640px){.fb-cfg-tree__title{font-size:13px}}.fb-cfg-tree__subtitle{margin:4px 0 0;font-size:11px;color:var(--fb-fc-tree-subtitle-color, #6b7280);letter-spacing:.02em}@media (max-width: 640px){.fb-cfg-tree__subtitle{font-size:10px}}.fb-cfg-tree__scrollable{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:16px}@media (max-width: 768px){.fb-cfg-tree__scrollable{padding:12px}}@media (max-width: 640px){.fb-cfg-tree__scrollable{padding:8px}}.fb-cfg-tree__empty{padding:32px 16px;text-align:center;color:var(--fb-fc-empty-color, #9ca3af);font-size:13px}@media (max-width: 640px){.fb-cfg-tree__empty{padding:24px 12px;font-size:12px}}.fb-cfg-tree-section{margin-bottom:16px}@media (max-width: 768px){.fb-cfg-tree-section{margin-bottom:12px}}@media (max-width: 640px){.fb-cfg-tree-section{margin-bottom:8px}}.fb-cfg-tree-section__header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px 8px;border-bottom:1px solid var(--fb-fc-section-divider, #f3f4f6);margin-bottom:8px;cursor:pointer}@media (max-width: 640px){.fb-cfg-tree-section__header{padding:3px 6px 6px;margin-bottom:6px}}.fb-cfg-tree-section__header:hover{background:var(--fb-fc-section-hover, #f9fafb);border-radius:6px}.fb-cfg-tree-section__title-group{display:flex;align-items:center;gap:6px}@media (max-width: 640px){.fb-cfg-tree-section__title-group{gap:4px}}.fb-cfg-tree-section__chevron{display:flex;color:var(--fb-fc-chevron-color, #9ca3af);transition:transform .2s cubic-bezier(.4,0,.2,1)}.fb-cfg-tree-section__chevron--expanded{transform:rotate(90deg)}.fb-cfg-tree-section__label{font-size:13px;font-weight:700;color:var(--fb-fc-section-label-color, #111827);text-transform:uppercase;letter-spacing:.05em}@media (max-width: 640px){.fb-cfg-tree-section__label{font-size:12px;letter-spacing:.02em}}.fb-cfg-tree-section__children{display:flex;flex-direction:column;gap:8px}@media (max-width: 640px){.fb-cfg-tree-section__children{gap:6px}}.fb-cfg-tree-item{display:flex;align-items:center;padding:12px;background:var(--fb-fc-item-bg, #ffffff);border:1px solid var(--fb-fc-item-border, #e5e7eb);border-radius:10px;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1)}.fb-cfg-tree-item:hover{border-color:var(--fb-fc-item-hover-border, #3b82f6);box-shadow:0 2px 8px #3b82f614}.fb-cfg-tree-item--active{border-color:var(--fb-fc-item-active-border, #3b82f6);background:var(--fb-fc-item-active-bg, #f0f7ff);box-shadow:0 0 0 1px var(--fb-fc-item-active-border, #3b82f6)}.fb-cfg-tree-item__drag{color:var(--fb-fc-drag-color, #d1d5db);cursor:grab;margin-right:8px;display:flex}.fb-cfg-tree-item__content{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fb-cfg-tree-item__label{font-size:13px;font-weight:600;color:var(--fb-fc-item-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-cfg-tree-item__type{font-size:10px;color:var(--fb-fc-item-type-color, #6b7280);text-transform:uppercase;letter-spacing:.05em;font-weight:500}\n"] }]
|
|
7754
7894
|
}], propDecorators: { tree: [{
|
|
7755
7895
|
type: Input
|
|
7756
7896
|
}], selectedFieldPath: [{
|
|
@@ -8148,11 +8288,11 @@ class ConfiguratorConfigPanelComponent {
|
|
|
8148
8288
|
return patch;
|
|
8149
8289
|
}
|
|
8150
8290
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfiguratorConfigPanelComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: SnackbarService }], target: i0.ɵɵFactoryTarget.Component });
|
|
8151
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfiguratorConfigPanelComponent, isStandalone: false, selector: "lib-configurator-config-panel", inputs: { selectedField: "selectedField", selectedFieldInfo: "selectedFieldInfo", builderFieldType: "builderFieldType", fieldTypeSchemaMap: "fieldTypeSchemaMap", showOptionConfig: "showOptionConfig", lockedFieldNames: "lockedFieldNames" }, outputs: { configChange: "configChange", typeChange: "typeChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 12px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 12px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .75rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}@media(min-width:600px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 14px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 14px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:768px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1024px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1440px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1920px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px 24px}@media(max-width:640px){.fb-config-panel__empty{padding:24px 16px}}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}@media(max-width:640px){.fb-config-panel__empty-icon{margin-bottom:16px}}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}@media(max-width:640px){.fb-config-panel__empty-text{font-size:14px;max-width:100%}}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:1.4rem;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}@media(max-width:768px){.fb-config-panel__header{padding:16px 24px;gap:12px}}@media(max-width:640px){.fb-config-panel__header{padding:12px 16px;gap:8px}}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap}@media(max-width:640px){.fb-config-panel__header-left{gap:8px}}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}@media(max-width:640px){.fb-config-panel__type-switcher{gap:4px}}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}@media(max-width:640px){.fb-config-panel__type-label{font-size:.7rem}}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}@media(max-width:640px){.fb-config-panel__type-select{height:32px;font-size:.75rem;min-width:140px;padding:0 28px 0 8px}}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}@media(max-width:1024px){.fb-config-panel__title{font-size:1.125rem}}@media(max-width:640px){.fb-config-panel__title{font-size:1rem}}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}@media(max-width:640px){.fb-config-panel__badge{padding:3px 8px;font-size:9px}}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;overflow-x:hidden;width:100%;min-width:0;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;padding:12px 16px}@media(min-width:600px){.fb-config-panel__form-wrapper{padding:16px 20px}}@media(min-width:768px){.fb-config-panel__form-wrapper{padding:20px 24px}}@media(min-width:1024px){.fb-config-panel__form-wrapper{padding:1rem}}@media(min-width:1440px){.fb-config-panel__form-wrapper{padding:28px 40px}}@media(min-width:1920px){.fb-config-panel__form-wrapper{padding:32px 48px}}.fb-config-panel__form-wrapper .fb-config-card{width:100%;max-width:none;margin:0;background:transparent;border:none;box-shadow:none;display:flex;flex-direction:column;min-width:0;flex:1;box-sizing:border-box}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .sf-col{min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{display:grid;grid-auto-flow:dense;gap:12px;width:100%;align-items:start}@media(max-width:599px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:12px}}@media(min-width:600px)and (max-width:767px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:14px}}@media(min-width:768px)and (max-width:1023px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:14px}}@media(min-width:1024px)and (max-width:1439px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:16px}}@media(min-width:1440px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:18px}}@media(min-width:1920px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:20px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{display:flex;flex-direction:column;min-width:0;overflow:hidden}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .form-field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep input,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep select,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep textarea{width:100%;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}@media(max-width:768px){.fb-config-panel__error{padding:16px;font-size:13px}}@media(max-width:640px){.fb-config-panel__error{padding:12px;font-size:12px}}\n"], dependencies: [{ kind: "component", type: SmartFormComponent, selector: "lib-smart-form", inputs: ["formJson", "initialValues", "enableDraftAutoSave", "labels", "mode", "readOnly"], outputs: ["submit", "draftSave", "actionClick", "valueChange", "fileAdded", "fileUploadFinished", "fileRemoved", "suffixActionClick", "stepChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8291
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfiguratorConfigPanelComponent, isStandalone: false, selector: "lib-configurator-config-panel", inputs: { selectedField: "selectedField", selectedFieldInfo: "selectedFieldInfo", builderFieldType: "builderFieldType", fieldTypeSchemaMap: "fieldTypeSchemaMap", showOptionConfig: "showOptionConfig", lockedFieldNames: "lockedFieldNames" }, outputs: { configChange: "configChange", typeChange: "typeChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 12px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 12px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .75rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}@media (min-width: 600px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 14px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 14px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media (min-width: 768px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media (min-width: 1024px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media (min-width: 1440px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media (min-width: 1920px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px 24px}@media (max-width: 640px){.fb-config-panel__empty{padding:24px 16px}}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}@media (max-width: 640px){.fb-config-panel__empty-icon{margin-bottom:16px}}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}@media (max-width: 640px){.fb-config-panel__empty-text{font-size:14px;max-width:100%}}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:1.4rem;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}@media (max-width: 768px){.fb-config-panel__header{padding:16px 24px;gap:12px}}@media (max-width: 640px){.fb-config-panel__header{padding:12px 16px;gap:8px}}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap}@media (max-width: 640px){.fb-config-panel__header-left{gap:8px}}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}@media (max-width: 640px){.fb-config-panel__type-switcher{gap:4px}}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}@media (max-width: 640px){.fb-config-panel__type-label{font-size:.7rem}}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}@media (max-width: 640px){.fb-config-panel__type-select{height:32px;font-size:.75rem;min-width:140px;padding:0 28px 0 8px}}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}@media (max-width: 1024px){.fb-config-panel__title{font-size:1.125rem}}@media (max-width: 640px){.fb-config-panel__title{font-size:1rem}}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}@media (max-width: 640px){.fb-config-panel__badge{padding:3px 8px;font-size:9px}}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;overflow-x:hidden;width:100%;min-width:0;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;padding:12px 16px}@media (min-width: 600px){.fb-config-panel__form-wrapper{padding:16px 20px}}@media (min-width: 768px){.fb-config-panel__form-wrapper{padding:20px 24px}}@media (min-width: 1024px){.fb-config-panel__form-wrapper{padding:1rem}}@media (min-width: 1440px){.fb-config-panel__form-wrapper{padding:28px 40px}}@media (min-width: 1920px){.fb-config-panel__form-wrapper{padding:32px 48px}}.fb-config-panel__form-wrapper .fb-config-card{width:100%;max-width:none;margin:0;background:transparent;border:none;box-shadow:none;display:flex;flex-direction:column;min-width:0;flex:1;box-sizing:border-box}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .sf-col{min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{display:grid;grid-auto-flow:dense;gap:12px;width:100%;align-items:start}@media (max-width: 599px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:12px}}@media (min-width: 600px) and (max-width: 767px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:14px}}@media (min-width: 768px) and (max-width: 1023px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:14px}}@media (min-width: 1024px) and (max-width: 1439px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:16px}}@media (min-width: 1440px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:18px}}@media (min-width: 1920px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:20px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{display:flex;flex-direction:column;min-width:0;overflow:hidden}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .form-field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep input,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep select,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep textarea{width:100%;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media (max-width: 768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media (max-width: 768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.7rem}}@media (max-width: 640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media (max-width: 768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media (max-width: 768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.7rem}}@media (max-width: 640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}@media (max-width: 768px){.fb-config-panel__error{padding:16px;font-size:13px}}@media (max-width: 640px){.fb-config-panel__error{padding:12px;font-size:12px}}\n"], dependencies: [{ kind: "component", type: SmartFormComponent, selector: "lib-smart-form", inputs: ["formJson", "initialValues", "enableDraftAutoSave", "labels", "mode", "readOnly"], outputs: ["submit", "draftSave", "actionClick", "valueChange", "fileAdded", "fileUploadFinished", "fileRemoved", "suffixActionClick", "stepChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8152
8292
|
}
|
|
8153
8293
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfiguratorConfigPanelComponent, decorators: [{
|
|
8154
8294
|
type: Component,
|
|
8155
|
-
args: [{ selector: 'lib-configurator-config-panel', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 12px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 12px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .75rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}@media(min-width:600px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 14px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 14px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:768px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1024px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1440px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media(min-width:1920px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px 24px}@media(max-width:640px){.fb-config-panel__empty{padding:24px 16px}}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}@media(max-width:640px){.fb-config-panel__empty-icon{margin-bottom:16px}}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}@media(max-width:640px){.fb-config-panel__empty-text{font-size:14px;max-width:100%}}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:1.4rem;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}@media(max-width:768px){.fb-config-panel__header{padding:16px 24px;gap:12px}}@media(max-width:640px){.fb-config-panel__header{padding:12px 16px;gap:8px}}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap}@media(max-width:640px){.fb-config-panel__header-left{gap:8px}}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}@media(max-width:640px){.fb-config-panel__type-switcher{gap:4px}}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}@media(max-width:640px){.fb-config-panel__type-label{font-size:.7rem}}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}@media(max-width:640px){.fb-config-panel__type-select{height:32px;font-size:.75rem;min-width:140px;padding:0 28px 0 8px}}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}@media(max-width:1024px){.fb-config-panel__title{font-size:1.125rem}}@media(max-width:640px){.fb-config-panel__title{font-size:1rem}}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}@media(max-width:640px){.fb-config-panel__badge{padding:3px 8px;font-size:9px}}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;overflow-x:hidden;width:100%;min-width:0;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;padding:12px 16px}@media(min-width:600px){.fb-config-panel__form-wrapper{padding:16px 20px}}@media(min-width:768px){.fb-config-panel__form-wrapper{padding:20px 24px}}@media(min-width:1024px){.fb-config-panel__form-wrapper{padding:1rem}}@media(min-width:1440px){.fb-config-panel__form-wrapper{padding:28px 40px}}@media(min-width:1920px){.fb-config-panel__form-wrapper{padding:32px 48px}}.fb-config-panel__form-wrapper .fb-config-card{width:100%;max-width:none;margin:0;background:transparent;border:none;box-shadow:none;display:flex;flex-direction:column;min-width:0;flex:1;box-sizing:border-box}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .sf-col{min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{display:grid;grid-auto-flow:dense;gap:12px;width:100%;align-items:start}@media(max-width:599px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:12px}}@media(min-width:600px)and (max-width:767px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:14px}}@media(min-width:768px)and (max-width:1023px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:14px}}@media(min-width:1024px)and (max-width:1439px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:16px}}@media(min-width:1440px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:18px}}@media(min-width:1920px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:20px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{display:flex;flex-direction:column;min-width:0;overflow:hidden}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .form-field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep input,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep select,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep textarea{width:100%;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media(max-width:768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.7rem}}@media(max-width:640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}@media(max-width:768px){.fb-config-panel__error{padding:16px;font-size:13px}}@media(max-width:640px){.fb-config-panel__error{padding:12px;font-size:12px}}\n"] }]
|
|
8295
|
+
args: [{ selector: 'lib-configurator-config-panel', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-config-panel\">\r\n @if (!selectedField) {\r\n <div class=\"fb-config-panel__empty\">\r\n <div class=\"fb-config-panel__empty-icon\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"21\" x2=\"9\" y2=\"9\"/>\r\n </svg>\r\n </div>\r\n <p class=\"fb-config-panel__empty-text\">\r\n Select a field from the tree panel to edit its configuration.\r\n </p>\r\n </div>\r\n } @else {\r\n <div class=\"fb-config-panel__header\">\r\n <div class=\"fb-config-panel__header-left\">\r\n <h3 class=\"fb-config-panel__title\">\r\n {{ selectedField.label || selectedField.name || 'Field Settings' }}\r\n </h3>\r\n @if (selectedField.type) {\r\n <span class=\"fb-config-panel__badge\">{{ selectedField.type }}</span>\r\n }\r\n </div>\r\n\r\n <!-- Field Type Switcher: hidden for DROPDOWN / MULTI_SELECT fields -->\r\n @if (!isDropdownType) {\r\n <div class=\"fb-config-panel__type-switcher\">\r\n <label class=\"fb-config-panel__type-label\" for=\"fb-field-type-select\">Field Type</label>\r\n <select\r\n id=\"fb-field-type-select\"\r\n class=\"fb-config-panel__type-select\"\r\n [value]=\"currentBuilderType\"\r\n (change)=\"onTypeSelectChange($event)\"\r\n >\r\n @for (opt of switchableFieldTypes; track opt.value) {\r\n <option [value]=\"opt.value\">{{ opt.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div class=\"fb-config-panel__form-wrapper\">\r\n @if (showConfigForm && configFormJson) {\r\n <div class=\"fb-config-card\">\r\n <lib-smart-form\r\n [formJson]=\"configFormJson\"\r\n [initialValues]=\"configInitialValues\"\r\n (actionClick)=\"onActionClick($event)\"\r\n />\r\n </div>\r\n } @else if (!showConfigForm) {\r\n <!-- intentionally empty \u2014 SmartForm is being recycled -->\r\n } @else {\r\n <div class=\"fb-config-panel__error\">\r\n No configuration schema available for this field type.\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-config-panel{display:flex;flex-direction:column;height:100%;background:var(--fb-fc-panel-bg, #f9fafb);overflow:hidden;--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 12px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 12px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .75rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}@media (min-width: 600px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 14px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 14px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .5rem .75rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media (min-width: 768px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media (min-width: 1024px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 16px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 16px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media (min-width: 1440px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}@media (min-width: 1920px){.fb-config-panel{--cc-sf-font-family: Inter, Segoe UI, sans-serif;--cc-sf-font-size-base: .875rem;--cc-sf-accent-color: #3B82F6;--cc-sf-selected-color: #3B82F6;--cc-sf-form-bg: transparent;--cc-sf-form-padding: 0;--cc-sf-form-border-radius: 12px;--cc-sf-form-border: none;--cc-sf-form-shadow: none;--cc-sf-form-max-width: 1200px;--cc-sf-form-section-gap: 24px;--cc-sf-form-title-size: 1.5rem;--cc-sf-form-title-weight: 700;--cc-sf-form-title-color: #111827;--cc-sf-form-desc-size: .875rem;--cc-sf-form-desc-color: #6B7280;--cc-sf-section-bg: transparent;--cc-sf-section-border: none;--cc-sf-section-radius: 10px;--cc-sf-section-padding: 18px;--cc-sf-section-shadow: none;--cc-sf-section-gap: 20px;--cc-sf-section-label-size: 1rem;--cc-sf-section-label-weight: 600;--cc-sf-section-label-color: #1F2937;--cc-sf-section-label-border: 2px solid #E5E7EB;--cc-sf-section-header-accent-width: 4px;--cc-sf-section-header-accent-color: #3B82F6;--cc-sf-section-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-bg: #F9FAFB;--cc-sf-repeater-accordion-header-color: #1F2937;--cc-sf-repeater-accordion-active-bg: #EFF6FF;--cc-sf-repeater-badge-bg: #E5E7EB;--cc-sf-repeater-badge-color: #374151;--cc-sf-section-border-radius-inner: 8px;--cc-sf-instance-bg: #F9FAFB;--cc-sf-instance-border: 1px solid #E5E7EB;--cc-sf-instance-radius: 8px;--cc-sf-instance-padding: 16px;--cc-sf-instance-divider: 1px dashed #D1D5DB;--cc-sf-instance-num-color:#4B5563;--cc-sf-instance-num-size: .8125rem;--cc-sf-grid-gap: 18px;--cc-sf-field-gap: 6px;--cc-sf-focus-ring-width: 3px;--cc-sf-focus-ring-offset: 0;--cc-sf-label-size: .8125rem;--cc-sf-label-weight: 600;--cc-sf-label-color: #111827;--cc-sf-label-required-color: #DC2626;--cc-sf-input-bg: #ffffff;--cc-sf-input-color: #111827;--cc-sf-input-placeholder: #9CA3AF;--cc-sf-input-border: 1.5px solid #D1D5DB;--cc-sf-input-radius: 8px;--cc-sf-input-padding: .625rem .875rem;--cc-sf-input-font-size: .875rem;--cc-sf-input-shadow: none;--cc-sf-input-hover-border:#9CA3AF;--cc-sf-input-focus-border:#3B82F6;--cc-sf-input-focus-shadow:0 0 0 3px rgba(59, 130, 246, .12);--cc-sf-input-transition: all .2s ease;--cc-sf-input-disabled-bg: #F3F4F6;--cc-sf-input-disabled-color: #6B7280;--cc-sf-input-disabled-border:#E5E7EB;--cc-sf-error-border: #DC2626;--cc-sf-error-bg: #FEF2F2;--cc-sf-error-focus-shadow: 0 0 0 3px rgba(220, 38, 38, .1);--cc-sf-error-text-color: #DC2626;--cc-sf-error-text-size: .75rem;--cc-sf-hint-color: #6B7280;--cc-sf-hint-size: .75rem;--cc-sf-chip-border: 1px solid #D1D5DB;--cc-sf-chip-radius: 20px;--cc-sf-chip-padding: 6px 14px;--cc-sf-chip-bg: #ffffff;--cc-sf-chip-color: #374151;--cc-sf-chip-hover-bg: #F3F4F6;--cc-sf-chip-selected-bg: #3B82F6;--cc-sf-chip-selected-color: #ffffff;--cc-sf-chip-selected-border:#3B82F6;--cc-sf-switch-track-off: #D1D5DB;--cc-sf-switch-track-on: #3B82F6;--cc-sf-switch-thumb: #ffffff;--cc-sf-star-empty: #D1D5DB;--cc-sf-star-filled: #F59E0B;--cc-sf-star-size: 28px;--cc-sf-generated-bg: #F3F4F6;--cc-sf-generated-border: 1px solid #E5E7EB;--cc-sf-generated-color: #6B7280;--cc-sf-generated-radius: 8px;--cc-sf-generated-padding: .625rem .875rem;--cc-sf-dropzone-bg: #F8FAFC;--cc-sf-dropzone-border: 1.5px dashed #CBD5E1;--cc-sf-dropzone-radius: 12px;--cc-sf-dropzone-hover-bg: #EFF6FF;--cc-sf-dropzone-hover-border: #93C5FD;--cc-sf-dropzone-over-border: #3B82F6;--cc-sf-dropzone-over-shadow: 0 0 0 4px rgba(59, 130, 246, .12);--cc-sf-dropzone-icon-color: #94A3B8;--cc-sf-dropzone-icon-bg: rgba(59, 130, 246, .1);--cc-sf-dropzone-link-color: #3B82F6;--cc-sf-dropzone-hint-color: #64748B;--cc-sf-uploaded-item-bg: #ffffff;--cc-sf-uploaded-item-border: 1px solid #E2E8F0;--cc-sf-uploaded-item-radius: 8px;--cc-sf-uploaded-remove-color: #94A3B8;--cc-sf-uploaded-remove-hover-bg: #FEF2F2;--cc-sf-uploaded-remove-hover-color: #DC2626;--cc-sf-btn-add-bg: transparent;--cc-sf-btn-add-color: #3B82F6;--cc-sf-btn-add-border: 1px dashed #CBD5E1;--cc-sf-btn-add-radius: 6px;--cc-sf-btn-add-hover-bg: #EFF6FF;--cc-sf-btn-add-hover-border: #BFDBFE;--cc-sf-btn-remove-bg: #FFF5F5;--cc-sf-btn-remove-color: #E53E3E;--cc-sf-btn-remove-border: 1px solid #FED7D7;--cc-sf-btn-remove-radius: 4px;--cc-sf-btn-remove-hover-bg: #FED7D7;--cc-sf-btn-remove-padding: .375rem .75rem;--cc-sf-btn-remove-font-size: .875rem;--cc-sf-btn-remove-font-weight: 500;--cc-sf-btn-add-padding: .625rem 1.5rem;--cc-sf-btn-add-font-size: .875rem;--cc-sf-btn-add-font-weight: 600;--cc-sf-stepper-connector-display: block;--cc-sf-instance-shadow: none;--cc-sf-instance-hover-shadow: none;--cc-sf-instance-transition: none;--cc-sf-instance-header-divider: none;--cc-sf-instance-header-pb: 0px;--cc-sf-instance-header-mb: 0px;--cc-sf-instance-num-weight: 600;--cc-sf-section-stepper-accent: #6366F1;--cc-sf-section-stepper-accent-end: #8B5CF6;--cc-sf-section-stepper-active-label: #4F46E5;--cc-sf-section-stepper-active-glow: rgba(99, 102, 241, .25);--cc-sf-step-connector-color: #E5E7EB;--cc-sf-step-connector-done: #22C55E;--cc-sf-step-number-bg: #E5E7EB;--cc-sf-step-number-color: #6B7280;--cc-sf-step-number-size: 40px;--cc-sf-step-number-font-size: .875rem;--cc-sf-step-number-weight: 600;--cc-sf-step-label-size: .875rem;--cc-sf-step-label-color: #6B7280;--cc-sf-step-label-weight: 500;--cc-sf-step-active-bg: #3B82F6;--cc-sf-step-active-color: #ffffff;--cc-sf-step-active-label: #1D4ED8;--cc-sf-step-active-label-weight: 700;--cc-sf-step-done-bg: #22C55E;--cc-sf-step-done-color: #ffffff;--cc-sf-actions-border: 1px solid #E5E7EB;--cc-sf-actions-padding: 20px 10px 0;--cc-sf-actions-gap: 12px;--cc-sf-btn-primary-bg: #3B82F6;--cc-sf-btn-primary-color: #ffffff;--cc-sf-btn-primary-radius: 8px;--cc-sf-btn-primary-padding: .625rem 1.5rem;--cc-sf-btn-primary-hover-bg: #2563EB;--cc-sf-btn-secondary-bg: #F3F4F6;--cc-sf-btn-secondary-color: #374151;--cc-sf-btn-secondary-radius: 8px;--cc-sf-btn-secondary-padding: .625rem 1.5rem;--cc-sf-btn-secondary-hover-bg: #E5E7EB;--cc-sf-btn-font-size: .875rem;--cc-sf-btn-font-weight: 600;--cc-sf-btn-transition: all .2s ease;--cc-sf-btn-disabled-opacity: .55}.fb-config-panel ::ng-deep .stepper-nav .stepper-step:not(:last-child):after{display:var(--cc-sf-stepper-connector-display)!important}.fb-config-panel ::ng-deep .section-instance{background:var(--cc-sf-instance-bg)!important;border:var(--cc-sf-instance-border)!important;border-radius:var(--cc-sf-instance-radius)!important;box-shadow:var(--cc-sf-instance-shadow);transition:var(--cc-sf-instance-transition)}.fb-config-panel ::ng-deep .section-instance:hover{box-shadow:var(--cc-sf-instance-hover-shadow)}.fb-config-panel ::ng-deep .section-instance-header{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--cc-sf-instance-header-pb);margin-bottom:var(--cc-sf-instance-header-mb);border-bottom:var(--cc-sf-instance-header-divider)}.fb-config-panel ::ng-deep .section-instance-num{font-size:var(--cc-sf-instance-num-size);font-weight:var(--cc-sf-instance-num-weight);color:var(--cc-sf-instance-num-color)}.fb-config-panel ::ng-deep .btn-instance-remove{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-sf-btn-remove-padding);border-radius:var(--cc-sf-btn-remove-radius);border:var(--cc-sf-btn-remove-border)!important;background:var(--cc-sf-btn-remove-bg);color:var(--cc-sf-btn-remove-color)!important;font-size:var(--cc-sf-btn-remove-font-size);font-weight:var(--cc-sf-btn-remove-font-weight);cursor:pointer;transition:all .15s ease}.fb-config-panel ::ng-deep .btn-instance-remove:hover{background:var(--cc-sf-btn-remove-hover-bg)}.fb-config-panel ::ng-deep .btn-add-section{display:inline-flex;align-items:center;gap:8px;padding:var(--cc-sf-btn-add-padding);border-radius:var(--cc-sf-btn-add-radius);border:var(--cc-sf-btn-add-border)!important;background:var(--cc-sf-btn-add-bg);color:var(--cc-sf-btn-add-color);font-size:var(--cc-sf-btn-add-font-size);font-weight:var(--cc-sf-btn-add-font-weight);cursor:pointer;transition:all .18s ease}.fb-config-panel ::ng-deep .btn-add-section:hover{background:var(--cc-sf-btn-add-hover-bg);border-color:var(--cc-sf-btn-add-hover-border)!important}.fb-config-panel ::ng-deep .section-stepper-nav:before{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-badge{background:linear-gradient(135deg,var(--cc-sf-section-stepper-accent) 0%,var(--cc-sf-section-stepper-accent-end) 100%)!important;box-shadow:0 0 0 4px var(--cc-sf-section-stepper-active-glow),0 4px 12px var(--cc-sf-section-stepper-active-glow)!important}.fb-config-panel ::ng-deep .section-stepper-step.ss-active .ss-label{color:var(--cc-sf-section-stepper-active-label)!important}.fb-config-panel ::ng-deep .section-stepper-step:not(.ss-active):not(.ss-completed):not(.ss-warning):hover .ss-badge{color:var(--cc-sf-section-stepper-accent)!important;border-color:var(--cc-sf-section-stepper-accent-end)!important}.fb-config-panel ::ng-deep .section-stepper-step .ss-connector:after{background:linear-gradient(90deg,var(--cc-sf-section-stepper-accent),var(--cc-sf-section-stepper-accent-end))!important}}.fb-config-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--fb-fc-empty-color, #9ca3af);text-align:center;padding:48px 24px}@media (max-width: 640px){.fb-config-panel__empty{padding:24px 16px}}.fb-config-panel__empty-icon{margin-bottom:24px;opacity:.4;color:var(--fb-fc-accent, #3b82f6)}@media (max-width: 640px){.fb-config-panel__empty-icon{margin-bottom:16px}}.fb-config-panel__empty-text{font-size:15px;max-width:320px;line-height:1.6;font-weight:500}@media (max-width: 640px){.fb-config-panel__empty-text{font-size:14px;max-width:100%}}.fb-config-panel__header{background:var(--fb-fc-header-bg, #ffffff);padding:1.4rem;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:16px;flex-wrap:wrap}@media (max-width: 768px){.fb-config-panel__header{padding:16px 24px;gap:12px}}@media (max-width: 640px){.fb-config-panel__header{padding:12px 16px;gap:8px}}.fb-config-panel__header-left{display:flex;align-items:center;gap:12px;min-width:0;flex-wrap:wrap}@media (max-width: 640px){.fb-config-panel__header-left{gap:8px}}.fb-config-panel__type-switcher{display:flex;align-items:center;gap:8px;flex-shrink:0}@media (max-width: 640px){.fb-config-panel__type-switcher{gap:4px}}.fb-config-panel__type-label{font-size:var(--fb-fc-type-label-size, .75rem);font-weight:600;color:var(--fb-fc-type-label-color, #6b7280);white-space:nowrap}@media (max-width: 640px){.fb-config-panel__type-label{font-size:.7rem}}.fb-config-panel__type-select{height:var(--fb-fc-type-select-height, 36px);padding:0 32px 0 10px;border:1px solid var(--fb-fc-type-select-border, #d1d5db);border-radius:var(--fb-fc-type-select-radius, 8px);background-color:var(--fb-fc-type-select-bg, #ffffff);color:var(--fb-fc-type-select-color, #111827);font-size:.8125rem;font-weight:500;cursor:pointer;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 8px center;min-width:160px;transition:border-color .15s ease,box-shadow .15s ease}@media (max-width: 640px){.fb-config-panel__type-select{height:32px;font-size:.75rem;min-width:140px;padding:0 28px 0 8px}}.fb-config-panel__type-select:hover{border-color:var(--fb-fc-type-select-hover-border, #9ca3af)}.fb-config-panel__type-select:focus{outline:none;border-color:var(--fb-fc-accent, #3b82f6);box-shadow:0 0 0 3px #3b82f61f}.fb-config-panel__title{margin:0;font-size:1.25rem;font-weight:700;color:var(--fb-fc-title-color, #111827)}@media (max-width: 1024px){.fb-config-panel__title{font-size:1.125rem}}@media (max-width: 640px){.fb-config-panel__title{font-size:1rem}}.fb-config-panel__badge{padding:4px 12px;background:var(--fb-fc-badge-bg, #eff6ff);color:var(--fb-fc-badge-color, #3b82f6);border-radius:20px;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;border:1px solid var(--fb-fc-badge-border, #dbeafe)}@media (max-width: 640px){.fb-config-panel__badge{padding:3px 8px;font-size:9px}}.fb-config-panel__form-wrapper{flex:1;overflow-y:auto;overflow-x:hidden;width:100%;min-width:0;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;padding:12px 16px}@media (min-width: 600px){.fb-config-panel__form-wrapper{padding:16px 20px}}@media (min-width: 768px){.fb-config-panel__form-wrapper{padding:20px 24px}}@media (min-width: 1024px){.fb-config-panel__form-wrapper{padding:1rem}}@media (min-width: 1440px){.fb-config-panel__form-wrapper{padding:28px 40px}}@media (min-width: 1920px){.fb-config-panel__form-wrapper{padding:32px 48px}}.fb-config-panel__form-wrapper .fb-config-card{width:100%;max-width:none;margin:0;background:transparent;border:none;box-shadow:none;display:flex;flex-direction:column;min-width:0;flex:1;box-sizing:border-box}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .sf-col{min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{display:grid;grid-auto-flow:dense;gap:12px;width:100%;align-items:start}@media (max-width: 599px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:12px}}@media (min-width: 600px) and (max-width: 767px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:1fr;gap:14px}}@media (min-width: 768px) and (max-width: 1023px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:14px}}@media (min-width: 1024px) and (max-width: 1439px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(2,1fr);gap:16px}}@media (min-width: 1440px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:18px}}@media (min-width: 1920px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal{grid-template-columns:repeat(3,1fr);gap:20px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>*{display:flex;flex-direction:column;min-width:0;overflow:hidden}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .form-field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep .field-wrapper,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep input,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep select,.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal>* ::ng-deep textarea{width:100%;min-width:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media (max-width: 768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media (max-width: 768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.7rem}}@media (max-width: 640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .form-row.horizontal .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{display:flex;flex-direction:row;align-items:center;gap:8px;white-space:nowrap;min-width:0}@media (max-width: 768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper{gap:6px}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.75rem;font-weight:600;margin:0;flex-shrink:1;min-width:0;word-break:keep-all}@media (max-width: 768px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.7rem}}@media (max-width: 640px){.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .field-label{font-size:.65rem}}.fb-config-panel__form-wrapper .fb-config-card ::ng-deep .grid-row .sf-col .sf-switch-wrapper .switch{flex-shrink:0}.fb-config-panel__error{padding:24px;background:var(--fb-fc-error-bg, #fef2f2);color:var(--fb-fc-error-color, #dc2626);border:1px solid var(--fb-fc-error-border, #fee2e2);border-radius:8px;font-size:14px;font-weight:500}@media (max-width: 768px){.fb-config-panel__error{padding:16px;font-size:13px}}@media (max-width: 640px){.fb-config-panel__error{padding:12px;font-size:12px}}\n"] }]
|
|
8156
8296
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: SnackbarService }], propDecorators: { selectedField: [{
|
|
8157
8297
|
type: Input
|
|
8158
8298
|
}], selectedFieldInfo: [{
|
|
@@ -8227,11 +8367,11 @@ class FieldConfiguratorComponent {
|
|
|
8227
8367
|
}
|
|
8228
8368
|
}
|
|
8229
8369
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FieldConfiguratorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8230
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FieldConfiguratorComponent, isStandalone: false, selector: "lib-field-configurator", inputs: { schema: "schema", showOptionConfig: "showOptionConfig", lockedFieldNames: "lockedFieldNames" }, outputs: { schemaChange: "schemaChange" }, providers: [FieldConfiguratorService], usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-configurator\">\r\n <div class=\"fb-configurator__layout\">\r\n <div class=\"fb-configurator__sidebar\">\r\n <lib-configurator-tree\r\n [tree]=\"store.tree()\"\r\n [selectedFieldPath]=\"store.selectedFieldPath()\"\r\n (selectField)=\"onFieldSelected($event)\"\r\n (toggleExpanded)=\"onNodeToggleExpanded($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"fb-configurator__main\">\r\n <lib-configurator-config-panel\r\n [selectedField]=\"store.selectedField()\"\r\n [selectedFieldInfo]=\"store.selectedFieldInfo()\"\r\n [builderFieldType]=\"store.selectedFieldBuilderType()\"\r\n [fieldTypeSchemaMap]=\"finalFieldTypeSchemaMap\"\r\n [showOptionConfig]=\"showOptionConfig\"\r\n [lockedFieldNames]=\"lockedFieldNames\"\r\n (configChange)=\"onConfigChange($event)\"\r\n (typeChange)=\"onTypeChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fb-configurator{display:flex;flex-direction:column;height:100%;width:100%;background:var(--fb-fc-bg, #ffffff);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-configurator__layout{flex:1;display:flex;overflow:hidden;width:100%}@media(max-width:768px){.fb-configurator__layout{flex-direction:column}}.fb-configurator__sidebar{flex:0 0 280px;border-right:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-sidebar-bg, #f9fafb);display:flex;flex-direction:column;overflow:hidden;min-width:0}@media(max-width:1024px){.fb-configurator__sidebar{flex:0 0 250px}}@media(min-width:1440px){.fb-configurator__sidebar{flex:0 0 300px}}@media(max-width:768px){.fb-configurator__sidebar{flex:0 0 auto;width:100%;border-right:none;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);max-height:40vh}}@media(max-width:640px){.fb-configurator__sidebar{max-height:35vh}}.fb-configurator__main{flex:1;min-width:0;overflow-y:auto;overflow-x:hidden;background:var(--fb-fc-main-bg, #ffffff);display:flex;flex-direction:column}@media(max-width:768px){.fb-configurator__main{width:100%;flex:1;min-height:0}}\n"], dependencies: [{ kind: "component", type: ConfiguratorTreeComponent, selector: "lib-configurator-tree", inputs: ["tree", "selectedFieldPath"], outputs: ["selectField", "toggleExpanded"] }, { kind: "component", type: ConfiguratorConfigPanelComponent, selector: "lib-configurator-config-panel", inputs: ["selectedField", "selectedFieldInfo", "builderFieldType", "fieldTypeSchemaMap", "showOptionConfig", "lockedFieldNames"], outputs: ["configChange", "typeChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8370
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FieldConfiguratorComponent, isStandalone: false, selector: "lib-field-configurator", inputs: { schema: "schema", showOptionConfig: "showOptionConfig", lockedFieldNames: "lockedFieldNames" }, outputs: { schemaChange: "schemaChange" }, providers: [FieldConfiguratorService], usesOnChanges: true, ngImport: i0, template: "<div class=\"fb-configurator\">\r\n <div class=\"fb-configurator__layout\">\r\n <div class=\"fb-configurator__sidebar\">\r\n <lib-configurator-tree\r\n [tree]=\"store.tree()\"\r\n [selectedFieldPath]=\"store.selectedFieldPath()\"\r\n (selectField)=\"onFieldSelected($event)\"\r\n (toggleExpanded)=\"onNodeToggleExpanded($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"fb-configurator__main\">\r\n <lib-configurator-config-panel\r\n [selectedField]=\"store.selectedField()\"\r\n [selectedFieldInfo]=\"store.selectedFieldInfo()\"\r\n [builderFieldType]=\"store.selectedFieldBuilderType()\"\r\n [fieldTypeSchemaMap]=\"finalFieldTypeSchemaMap\"\r\n [showOptionConfig]=\"showOptionConfig\"\r\n [lockedFieldNames]=\"lockedFieldNames\"\r\n (configChange)=\"onConfigChange($event)\"\r\n (typeChange)=\"onTypeChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fb-configurator{display:flex;flex-direction:column;height:100%;width:100%;background:var(--fb-fc-bg, #ffffff);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-configurator__layout{flex:1;display:flex;overflow:hidden;width:100%}@media (max-width: 768px){.fb-configurator__layout{flex-direction:column}}.fb-configurator__sidebar{flex:0 0 280px;border-right:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-sidebar-bg, #f9fafb);display:flex;flex-direction:column;overflow:hidden;min-width:0}@media (max-width: 1024px){.fb-configurator__sidebar{flex:0 0 250px}}@media (min-width: 1440px){.fb-configurator__sidebar{flex:0 0 300px}}@media (max-width: 768px){.fb-configurator__sidebar{flex:0 0 auto;width:100%;border-right:none;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);max-height:40vh}}@media (max-width: 640px){.fb-configurator__sidebar{max-height:35vh}}.fb-configurator__main{flex:1;min-width:0;overflow-y:auto;overflow-x:hidden;background:var(--fb-fc-main-bg, #ffffff);display:flex;flex-direction:column}@media (max-width: 768px){.fb-configurator__main{width:100%;flex:1;min-height:0}}\n"], dependencies: [{ kind: "component", type: ConfiguratorTreeComponent, selector: "lib-configurator-tree", inputs: ["tree", "selectedFieldPath"], outputs: ["selectField", "toggleExpanded"] }, { kind: "component", type: ConfiguratorConfigPanelComponent, selector: "lib-configurator-config-panel", inputs: ["selectedField", "selectedFieldInfo", "builderFieldType", "fieldTypeSchemaMap", "showOptionConfig", "lockedFieldNames"], outputs: ["configChange", "typeChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8231
8371
|
}
|
|
8232
8372
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FieldConfiguratorComponent, decorators: [{
|
|
8233
8373
|
type: Component,
|
|
8234
|
-
args: [{ selector: 'lib-field-configurator', standalone: false, providers: [FieldConfiguratorService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-configurator\">\r\n <div class=\"fb-configurator__layout\">\r\n <div class=\"fb-configurator__sidebar\">\r\n <lib-configurator-tree\r\n [tree]=\"store.tree()\"\r\n [selectedFieldPath]=\"store.selectedFieldPath()\"\r\n (selectField)=\"onFieldSelected($event)\"\r\n (toggleExpanded)=\"onNodeToggleExpanded($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"fb-configurator__main\">\r\n <lib-configurator-config-panel\r\n [selectedField]=\"store.selectedField()\"\r\n [selectedFieldInfo]=\"store.selectedFieldInfo()\"\r\n [builderFieldType]=\"store.selectedFieldBuilderType()\"\r\n [fieldTypeSchemaMap]=\"finalFieldTypeSchemaMap\"\r\n [showOptionConfig]=\"showOptionConfig\"\r\n [lockedFieldNames]=\"lockedFieldNames\"\r\n (configChange)=\"onConfigChange($event)\"\r\n (typeChange)=\"onTypeChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fb-configurator{display:flex;flex-direction:column;height:100%;width:100%;background:var(--fb-fc-bg, #ffffff);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-configurator__layout{flex:1;display:flex;overflow:hidden;width:100%}@media(max-width:768px){.fb-configurator__layout{flex-direction:column}}.fb-configurator__sidebar{flex:0 0 280px;border-right:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-sidebar-bg, #f9fafb);display:flex;flex-direction:column;overflow:hidden;min-width:0}@media(max-width:1024px){.fb-configurator__sidebar{flex:0 0 250px}}@media(min-width:1440px){.fb-configurator__sidebar{flex:0 0 300px}}@media(max-width:768px){.fb-configurator__sidebar{flex:0 0 auto;width:100%;border-right:none;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);max-height:40vh}}@media(max-width:640px){.fb-configurator__sidebar{max-height:35vh}}.fb-configurator__main{flex:1;min-width:0;overflow-y:auto;overflow-x:hidden;background:var(--fb-fc-main-bg, #ffffff);display:flex;flex-direction:column}@media(max-width:768px){.fb-configurator__main{width:100%;flex:1;min-height:0}}\n"] }]
|
|
8374
|
+
args: [{ selector: 'lib-field-configurator', standalone: false, providers: [FieldConfiguratorService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-configurator\">\r\n <div class=\"fb-configurator__layout\">\r\n <div class=\"fb-configurator__sidebar\">\r\n <lib-configurator-tree\r\n [tree]=\"store.tree()\"\r\n [selectedFieldPath]=\"store.selectedFieldPath()\"\r\n (selectField)=\"onFieldSelected($event)\"\r\n (toggleExpanded)=\"onNodeToggleExpanded($event)\"\r\n />\r\n </div>\r\n\r\n <div class=\"fb-configurator__main\">\r\n <lib-configurator-config-panel\r\n [selectedField]=\"store.selectedField()\"\r\n [selectedFieldInfo]=\"store.selectedFieldInfo()\"\r\n [builderFieldType]=\"store.selectedFieldBuilderType()\"\r\n [fieldTypeSchemaMap]=\"finalFieldTypeSchemaMap\"\r\n [showOptionConfig]=\"showOptionConfig\"\r\n [lockedFieldNames]=\"lockedFieldNames\"\r\n (configChange)=\"onConfigChange($event)\"\r\n (typeChange)=\"onTypeChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".fb-configurator{display:flex;flex-direction:column;height:100%;width:100%;background:var(--fb-fc-bg, #ffffff);font-family:var(--fb-font-family, \"Inter\", sans-serif)}.fb-configurator__layout{flex:1;display:flex;overflow:hidden;width:100%}@media (max-width: 768px){.fb-configurator__layout{flex-direction:column}}.fb-configurator__sidebar{flex:0 0 280px;border-right:1px solid var(--fb-fc-border, #e5e7eb);background:var(--fb-fc-sidebar-bg, #f9fafb);display:flex;flex-direction:column;overflow:hidden;min-width:0}@media (max-width: 1024px){.fb-configurator__sidebar{flex:0 0 250px}}@media (min-width: 1440px){.fb-configurator__sidebar{flex:0 0 300px}}@media (max-width: 768px){.fb-configurator__sidebar{flex:0 0 auto;width:100%;border-right:none;border-bottom:1px solid var(--fb-fc-border, #e5e7eb);max-height:40vh}}@media (max-width: 640px){.fb-configurator__sidebar{max-height:35vh}}.fb-configurator__main{flex:1;min-width:0;overflow-y:auto;overflow-x:hidden;background:var(--fb-fc-main-bg, #ffffff);display:flex;flex-direction:column}@media (max-width: 768px){.fb-configurator__main{width:100%;flex:1;min-height:0}}\n"] }]
|
|
8235
8375
|
}], propDecorators: { schema: [{
|
|
8236
8376
|
type: Input,
|
|
8237
8377
|
args: [{ required: true }]
|
|
@@ -8505,11 +8645,11 @@ class ConfirmationModalComponent {
|
|
|
8505
8645
|
return typeof icon === 'object' ? icon.color : undefined;
|
|
8506
8646
|
}
|
|
8507
8647
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8508
|
-
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", confirmDisabled: "confirmDisabled", confirmLoading: "confirmLoading" }, 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\" \r\n [ngClass]=\"{'cc-modal-backdrop--side-panel': mergedConfig.type === 'side-panel'}\"\r\n (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 }}\" \r\n [ngClass]=\"{'side-panel': mergedConfig.type === 'side-panel'}\"\r\n [ngStyle]=\"getModalStyles()\" (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\" [ngClass]=\"{'cc-modal-body--form-mode': mergedConfig.formMode}\" [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]=\"confirmDisabled || mergedConfig.confirmButton.disabled || confirmLoading || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"confirmLoading || 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-backdrop--side-panel{align-items:stretch;justify-content:flex-end}.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}.cc-modal-container.side-panel{max-height:100vh;animation:slideInRight .3s ease-out;z-index:1001}.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, #262125);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark, #FFFFFF)}.modal-header--dark .modal-header__close{color:var(--cc-modal-header-close-color-dark, rgba(255, 255, 255, .7))}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:var(--cc-modal-header-code-btn-color-dark, rgba(255, 255, 255, .7))}.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-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 slideInRight{0%{transform:translate(100%)}to{transform:translate(0)}}@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%}}.cc-modal-body--form-mode{padding:0}.cc-modal-body--form-mode ::ng-deep .smart-form-wrapper,.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton{box-shadow:none!important;border:none!important;padding:0!important;border-radius:0!important}.cc-modal-body--form-mode ::ng-deep .smart-form-wrapper{animation:none!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton{display:flex!important;align-items:center!important;justify-content:center!important;min-height:360px!important;gap:0!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton>*{display:none!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton:after{content:\"\";display:block;width:28px;height:28px;border:3px solid #E5E7EB;border-top-color:#6366f1;border-radius:50%;animation:cc-modal-skeleton-spin .7s linear infinite}.cc-modal-body--form-mode ::ng-deep .form-section-container{box-shadow:none!important;border:none!important}@keyframes cc-modal-skeleton-spin{to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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"] }] });
|
|
8648
|
+
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", confirmDisabled: "confirmDisabled", confirmLoading: "confirmLoading" }, 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\" \r\n [ngClass]=\"{'cc-modal-backdrop--side-panel': mergedConfig.type === 'side-panel'}\"\r\n (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 }}\" \r\n [ngClass]=\"{'side-panel': mergedConfig.type === 'side-panel'}\"\r\n [ngStyle]=\"getModalStyles()\" (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\" [ngClass]=\"{'cc-modal-body--form-mode': mergedConfig.formMode}\" [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]=\"confirmDisabled || mergedConfig.confirmButton.disabled || confirmLoading || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"confirmLoading || 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-backdrop--side-panel{align-items:stretch;justify-content:flex-end}.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}.cc-modal-container.side-panel{max-height:100vh;animation:slideInRight .3s ease-out;z-index:1001}.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, #262125);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark, #FFFFFF)}.modal-header--dark .modal-header__close{color:var(--cc-modal-header-close-color-dark, rgba(255, 255, 255, .7))}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:var(--cc-modal-header-code-btn-color-dark, rgba(255, 255, 255, .7))}.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-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 slideInRight{0%{transform:translate(100%)}to{transform:translate(0)}}@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%}}.cc-modal-body--form-mode{padding:0}.cc-modal-body--form-mode ::ng-deep .smart-form-wrapper,.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton{box-shadow:none!important;border:none!important;padding:0!important;border-radius:0!important}.cc-modal-body--form-mode ::ng-deep .smart-form-wrapper{animation:none!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton{display:flex!important;align-items:center!important;justify-content:center!important;min-height:360px!important;gap:0!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton>*{display:none!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton:after{content:\"\";display:block;width:28px;height:28px;border:3px solid #E5E7EB;border-top-color:#6366f1;border-radius:50%;animation:cc-modal-skeleton-spin .7s linear infinite}.cc-modal-body--form-mode ::ng-deep .form-section-container{box-shadow:none!important;border:none!important}@keyframes cc-modal-skeleton-spin{to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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"] }] });
|
|
8509
8649
|
}
|
|
8510
8650
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfirmationModalComponent, decorators: [{
|
|
8511
8651
|
type: Component,
|
|
8512
|
-
args: [{ selector: 'cc-confirmation-modal', standalone: false, template: "<div *ngIf=\"isOpen\" class=\"cc-modal-backdrop\" \r\n [ngClass]=\"{'cc-modal-backdrop--side-panel': mergedConfig.type === 'side-panel'}\"\r\n (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 }}\" \r\n [ngClass]=\"{'side-panel': mergedConfig.type === 'side-panel'}\"\r\n [ngStyle]=\"getModalStyles()\" (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\" [ngClass]=\"{'cc-modal-body--form-mode': mergedConfig.formMode}\" [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]=\"confirmDisabled || mergedConfig.confirmButton.disabled || confirmLoading || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"confirmLoading || 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-backdrop--side-panel{align-items:stretch;justify-content:flex-end}.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}.cc-modal-container.side-panel{max-height:100vh;animation:slideInRight .3s ease-out;z-index:1001}.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, #262125);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark, #FFFFFF)}.modal-header--dark .modal-header__close{color:var(--cc-modal-header-close-color-dark, rgba(255, 255, 255, .7))}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:var(--cc-modal-header-code-btn-color-dark, rgba(255, 255, 255, .7))}.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-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 slideInRight{0%{transform:translate(100%)}to{transform:translate(0)}}@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%}}.cc-modal-body--form-mode{padding:0}.cc-modal-body--form-mode ::ng-deep .smart-form-wrapper,.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton{box-shadow:none!important;border:none!important;padding:0!important;border-radius:0!important}.cc-modal-body--form-mode ::ng-deep .smart-form-wrapper{animation:none!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton{display:flex!important;align-items:center!important;justify-content:center!important;min-height:360px!important;gap:0!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton>*{display:none!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton:after{content:\"\";display:block;width:28px;height:28px;border:3px solid #E5E7EB;border-top-color:#6366f1;border-radius:50%;animation:cc-modal-skeleton-spin .7s linear infinite}.cc-modal-body--form-mode ::ng-deep .form-section-container{box-shadow:none!important;border:none!important}@keyframes cc-modal-skeleton-spin{to{transform:rotate(360deg)}}\n"] }]
|
|
8652
|
+
args: [{ selector: 'cc-confirmation-modal', standalone: false, template: "<div *ngIf=\"isOpen\" class=\"cc-modal-backdrop\" \r\n [ngClass]=\"{'cc-modal-backdrop--side-panel': mergedConfig.type === 'side-panel'}\"\r\n (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 }}\" \r\n [ngClass]=\"{'side-panel': mergedConfig.type === 'side-panel'}\"\r\n [ngStyle]=\"getModalStyles()\" (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\" [ngClass]=\"{'cc-modal-body--form-mode': mergedConfig.formMode}\" [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]=\"confirmDisabled || mergedConfig.confirmButton.disabled || confirmLoading || mergedConfig.confirmButton.loading\"\r\n (click)=\"onConfirm()\">\r\n <span *ngIf=\"confirmLoading || 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-backdrop--side-panel{align-items:stretch;justify-content:flex-end}.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}.cc-modal-container.side-panel{max-height:100vh;animation:slideInRight .3s ease-out;z-index:1001}.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, #262125);border-bottom:none}.modal-header--dark .modal-header__title{color:var(--cc-modal-header-title-color-dark, #FFFFFF)}.modal-header--dark .modal-header__close{color:var(--cc-modal-header-close-color-dark, rgba(255, 255, 255, .7))}.modal-header--dark .modal-header__close:hover{color:#fff}.modal-header--dark .modal-header__code-btn{color:var(--cc-modal-header-code-btn-color-dark, rgba(255, 255, 255, .7))}.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-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 slideInRight{0%{transform:translate(100%)}to{transform:translate(0)}}@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%}}.cc-modal-body--form-mode{padding:0}.cc-modal-body--form-mode ::ng-deep .smart-form-wrapper,.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton{box-shadow:none!important;border:none!important;padding:0!important;border-radius:0!important}.cc-modal-body--form-mode ::ng-deep .smart-form-wrapper{animation:none!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton{display:flex!important;align-items:center!important;justify-content:center!important;min-height:360px!important;gap:0!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton>*{display:none!important}.cc-modal-body--form-mode ::ng-deep .smart-form-skeleton:after{content:\"\";display:block;width:28px;height:28px;border:3px solid #E5E7EB;border-top-color:#6366f1;border-radius:50%;animation:cc-modal-skeleton-spin .7s linear infinite}.cc-modal-body--form-mode ::ng-deep .form-section-container{box-shadow:none!important;border:none!important}@keyframes cc-modal-skeleton-spin{to{transform:rotate(360deg)}}\n"] }]
|
|
8513
8653
|
}], propDecorators: { config: [{
|
|
8514
8654
|
type: Input
|
|
8515
8655
|
}], isOpen: [{
|
|
@@ -8663,11 +8803,11 @@ class ButtonDropdownComponent {
|
|
|
8663
8803
|
this.confirmMessage = '';
|
|
8664
8804
|
}
|
|
8665
8805
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonDropdownComponent, deps: [{ token: i0.ElementRef }, { token: i1$4.Router }, { token: i3.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
8666
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ButtonDropdownComponent, isStandalone: false, selector: "lib-button-dropdown", inputs: { label: "label", variant: "variant", menuTheme: "menuTheme", icon: "icon", actions: "actions", data: "data", disabled: "disabled" }, outputs: { apiActionStart: "apiActionStart", apiActionSuccess: "apiActionSuccess", apiActionError: "apiActionError", actionClick: "actionClick" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, ngImport: i0, template: "<div class=\"cc-btn-dropdown-container\">\
|
|
8806
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ButtonDropdownComponent, isStandalone: false, selector: "lib-button-dropdown", inputs: { label: "label", variant: "variant", menuTheme: "menuTheme", icon: "icon", actions: "actions", data: "data", disabled: "disabled" }, outputs: { apiActionStart: "apiActionStart", apiActionSuccess: "apiActionSuccess", apiActionError: "apiActionError", actionClick: "actionClick" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, ngImport: i0, template: "<div class=\"cc-btn-dropdown-container\">\n <!-- Main Toggle Button -->\n <lib-button \n [variant]=\"variant\" \n [disabled]=\"disabled\"\n (click)=\"toggleDropdown($event)\">\n <span class=\"cc-btn-dropdown-content\">\n {{ label }}\n <i *ngIf=\"icon\" [class]=\"icon\" class=\"cc-btn-dropdown-icon\"></i>\n </span>\n </lib-button>\n\n <!-- Dropdown Menu -->\n <div class=\"cc-dropdown-menu\" [ngClass]=\"'cc-dropdown-menu--' + menuTheme\" *ngIf=\"isOpen\">\n <button \n type=\"button\" \n class=\"cc-dropdown-item\" \n *ngFor=\"let action of actions\"\n [disabled]=\"action.disabled\"\n [ngClass]=\"action.variant ? 'cc-dropdown-item--' + action.variant : (action.color === 'red' || action.color === 'danger') ? 'cc-dropdown-item--danger' : ''\"\n [style.color]=\"action.color && !action.variant && action.color !== 'red' && action.color !== 'danger' ? action.color : null\"\n (click)=\"onActionItemClick(action, $event)\">\n <i *ngIf=\"action.icon\" [class]=\"action.icon\" class=\"cc-dropdown-item-icon\"></i>\n <span>{{ action.label }}</span>\n </button>\n <div class=\"cc-dropdown-empty\" *ngIf=\"!actions || actions.length === 0\">\n No actions available\n </div>\n </div>\n</div>\n\n<!-- Confirmation Modal for Critical Actions -->\n<cc-confirmation-modal \n *ngIf=\"isConfirmModalOpen\"\n [isOpen]=\"isConfirmModalOpen\" \n [config]=\"confirmConfig!\"\n (confirm)=\"invokePendingAction()\"\n (close)=\"closeConfirmModal()\"\n (cancel)=\"closeConfirmModal()\">\n <p>{{ confirmMessage }}</p>\n</cc-confirmation-modal>\n", styles: [".cc-btn-dropdown-container{position:relative;display:inline-block}.cc-btn-dropdown-container .cc-btn-dropdown-content{display:flex;align-items:center;gap:.5rem}.cc-btn-dropdown-container .cc-btn-dropdown-icon{font-size:.85em;margin-left:2px}.cc-dropdown-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:1000;min-width:140px;border-radius:var(--cc-btn-dropdown-radius, 4px);padding:.25rem 0;font-family:var(--cc-btn-font-family, \"Inter\", sans-serif);font-size:var(--cc-btn-font-size, .875rem)}.cc-dropdown-menu--light{background-color:var(--cc-btn-dropdown-light-bg, #ffffff);border:var(--cc-btn-dropdown-border-light, 1px solid #e0e0e0);box-shadow:var(--cc-btn-dropdown-shadow-light, 0 4px 6px rgba(0, 0, 0, .1))}.cc-dropdown-menu--light .cc-dropdown-item{color:var(--cc-btn-dropdown-light-item-color, #333333)}.cc-dropdown-menu--light .cc-dropdown-item:hover:not(:disabled){background-color:var(--cc-btn-dropdown-light-item-hover-bg, #f5f5f5)}.cc-dropdown-menu--light .cc-dropdown-empty{color:#888}.cc-dropdown-menu--dark{background-color:var(--cc-btn-dropdown-dark-bg, #1a1a1a);border:var(--cc-btn-dropdown-border-dark, 1px solid #444444);box-shadow:var(--cc-btn-dropdown-shadow-dark, 0 4px 6px rgba(0, 0, 0, .5))}.cc-dropdown-menu--dark .cc-dropdown-item{color:var(--cc-btn-dropdown-dark-item-color, #ffffff)}.cc-dropdown-menu--dark .cc-dropdown-item:hover:not(:disabled){background-color:var(--cc-btn-dropdown-dark-item-hover-bg, #2d2d2d)}.cc-dropdown-menu--dark .cc-dropdown-empty{color:#bbb}.cc-dropdown-menu .cc-dropdown-empty{padding:.5rem 1rem;font-style:italic}.cc-dropdown-menu .cc-dropdown-item{display:flex;align-items:center;width:100%;padding:.5rem 1rem;border:none;background:transparent;text-align:left;cursor:pointer;transition:background-color .2s,color .2s}.cc-dropdown-menu .cc-dropdown-item:disabled{opacity:.5;cursor:not-allowed}.cc-dropdown-menu .cc-dropdown-item .cc-dropdown-item-icon{margin-right:.5rem;width:1rem;text-align:center}.cc-dropdown-menu .cc-dropdown-item--primary{background-color:var(--cc-btn-dropdown-primary-bg, #262125);color:var(--cc-btn-dropdown-primary-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--primary:hover:not(:disabled){background-color:var(--cc-btn-dropdown-primary-hover, #3d353b)}.cc-dropdown-menu .cc-dropdown-item--warning{background-color:var(--cc-btn-dropdown-warning-bg, #F9C80E);color:var(--cc-btn-dropdown-warning-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--warning:hover:not(:disabled){background-color:var(--cc-btn-dropdown-warning-hover, #ebd573)}.cc-dropdown-menu .cc-dropdown-item--danger{background-color:var(--cc-btn-dropdown-danger-bg, #E63E30);color:var(--cc-btn-dropdown-danger-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--danger:hover:not(:disabled){background-color:var(--cc-btn-dropdown-danger-hover, #c93528)}.cc-dropdown-menu .cc-dropdown-item--success{background-color:var(--cc-btn-dropdown-success-bg, #16A34A);color:var(--cc-btn-dropdown-success-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--success:hover:not(:disabled){background-color:var(--cc-btn-dropdown-success-hover, #148f41)}.cc-dropdown-menu .cc-dropdown-item--secondary{background-color:var(--cc-btn-dropdown-secondary-bg, #E8EAED);color:var(--cc-btn-dropdown-secondary-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--secondary:hover:not(:disabled){background-color:var(--cc-btn-dropdown-secondary-hover, #d1d5db)}.cc-dropdown-menu .cc-dropdown-item--outline{background-color:var(--cc-btn-dropdown-outline-bg, transparent);color:var(--cc-btn-dropdown-outline-color, #000000);border:1px solid var(--cc-btn-dropdown-outline-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--outline:hover:not(:disabled){background-color:var(--cc-btn-dropdown-outline-hover, rgba(0, 0, 0, .05))}\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: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: ConfirmationModalComponent, selector: "cc-confirmation-modal", inputs: ["config", "isOpen", "confirmDisabled", "confirmLoading"], outputs: ["confirm", "cancel", "close", "showCodeSnippet"] }] });
|
|
8667
8807
|
}
|
|
8668
8808
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ButtonDropdownComponent, decorators: [{
|
|
8669
8809
|
type: Component,
|
|
8670
|
-
args: [{ selector: 'lib-button-dropdown', standalone: false, template: "<div class=\"cc-btn-dropdown-container\">\
|
|
8810
|
+
args: [{ selector: 'lib-button-dropdown', standalone: false, template: "<div class=\"cc-btn-dropdown-container\">\n <!-- Main Toggle Button -->\n <lib-button \n [variant]=\"variant\" \n [disabled]=\"disabled\"\n (click)=\"toggleDropdown($event)\">\n <span class=\"cc-btn-dropdown-content\">\n {{ label }}\n <i *ngIf=\"icon\" [class]=\"icon\" class=\"cc-btn-dropdown-icon\"></i>\n </span>\n </lib-button>\n\n <!-- Dropdown Menu -->\n <div class=\"cc-dropdown-menu\" [ngClass]=\"'cc-dropdown-menu--' + menuTheme\" *ngIf=\"isOpen\">\n <button \n type=\"button\" \n class=\"cc-dropdown-item\" \n *ngFor=\"let action of actions\"\n [disabled]=\"action.disabled\"\n [ngClass]=\"action.variant ? 'cc-dropdown-item--' + action.variant : (action.color === 'red' || action.color === 'danger') ? 'cc-dropdown-item--danger' : ''\"\n [style.color]=\"action.color && !action.variant && action.color !== 'red' && action.color !== 'danger' ? action.color : null\"\n (click)=\"onActionItemClick(action, $event)\">\n <i *ngIf=\"action.icon\" [class]=\"action.icon\" class=\"cc-dropdown-item-icon\"></i>\n <span>{{ action.label }}</span>\n </button>\n <div class=\"cc-dropdown-empty\" *ngIf=\"!actions || actions.length === 0\">\n No actions available\n </div>\n </div>\n</div>\n\n<!-- Confirmation Modal for Critical Actions -->\n<cc-confirmation-modal \n *ngIf=\"isConfirmModalOpen\"\n [isOpen]=\"isConfirmModalOpen\" \n [config]=\"confirmConfig!\"\n (confirm)=\"invokePendingAction()\"\n (close)=\"closeConfirmModal()\"\n (cancel)=\"closeConfirmModal()\">\n <p>{{ confirmMessage }}</p>\n</cc-confirmation-modal>\n", styles: [".cc-btn-dropdown-container{position:relative;display:inline-block}.cc-btn-dropdown-container .cc-btn-dropdown-content{display:flex;align-items:center;gap:.5rem}.cc-btn-dropdown-container .cc-btn-dropdown-icon{font-size:.85em;margin-left:2px}.cc-dropdown-menu{position:absolute;top:calc(100% + 4px);right:0;z-index:1000;min-width:140px;border-radius:var(--cc-btn-dropdown-radius, 4px);padding:.25rem 0;font-family:var(--cc-btn-font-family, \"Inter\", sans-serif);font-size:var(--cc-btn-font-size, .875rem)}.cc-dropdown-menu--light{background-color:var(--cc-btn-dropdown-light-bg, #ffffff);border:var(--cc-btn-dropdown-border-light, 1px solid #e0e0e0);box-shadow:var(--cc-btn-dropdown-shadow-light, 0 4px 6px rgba(0, 0, 0, .1))}.cc-dropdown-menu--light .cc-dropdown-item{color:var(--cc-btn-dropdown-light-item-color, #333333)}.cc-dropdown-menu--light .cc-dropdown-item:hover:not(:disabled){background-color:var(--cc-btn-dropdown-light-item-hover-bg, #f5f5f5)}.cc-dropdown-menu--light .cc-dropdown-empty{color:#888}.cc-dropdown-menu--dark{background-color:var(--cc-btn-dropdown-dark-bg, #1a1a1a);border:var(--cc-btn-dropdown-border-dark, 1px solid #444444);box-shadow:var(--cc-btn-dropdown-shadow-dark, 0 4px 6px rgba(0, 0, 0, .5))}.cc-dropdown-menu--dark .cc-dropdown-item{color:var(--cc-btn-dropdown-dark-item-color, #ffffff)}.cc-dropdown-menu--dark .cc-dropdown-item:hover:not(:disabled){background-color:var(--cc-btn-dropdown-dark-item-hover-bg, #2d2d2d)}.cc-dropdown-menu--dark .cc-dropdown-empty{color:#bbb}.cc-dropdown-menu .cc-dropdown-empty{padding:.5rem 1rem;font-style:italic}.cc-dropdown-menu .cc-dropdown-item{display:flex;align-items:center;width:100%;padding:.5rem 1rem;border:none;background:transparent;text-align:left;cursor:pointer;transition:background-color .2s,color .2s}.cc-dropdown-menu .cc-dropdown-item:disabled{opacity:.5;cursor:not-allowed}.cc-dropdown-menu .cc-dropdown-item .cc-dropdown-item-icon{margin-right:.5rem;width:1rem;text-align:center}.cc-dropdown-menu .cc-dropdown-item--primary{background-color:var(--cc-btn-dropdown-primary-bg, #262125);color:var(--cc-btn-dropdown-primary-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--primary:hover:not(:disabled){background-color:var(--cc-btn-dropdown-primary-hover, #3d353b)}.cc-dropdown-menu .cc-dropdown-item--warning{background-color:var(--cc-btn-dropdown-warning-bg, #F9C80E);color:var(--cc-btn-dropdown-warning-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--warning:hover:not(:disabled){background-color:var(--cc-btn-dropdown-warning-hover, #ebd573)}.cc-dropdown-menu .cc-dropdown-item--danger{background-color:var(--cc-btn-dropdown-danger-bg, #E63E30);color:var(--cc-btn-dropdown-danger-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--danger:hover:not(:disabled){background-color:var(--cc-btn-dropdown-danger-hover, #c93528)}.cc-dropdown-menu .cc-dropdown-item--success{background-color:var(--cc-btn-dropdown-success-bg, #16A34A);color:var(--cc-btn-dropdown-success-color, #ffffff)}.cc-dropdown-menu .cc-dropdown-item--success:hover:not(:disabled){background-color:var(--cc-btn-dropdown-success-hover, #148f41)}.cc-dropdown-menu .cc-dropdown-item--secondary{background-color:var(--cc-btn-dropdown-secondary-bg, #E8EAED);color:var(--cc-btn-dropdown-secondary-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--secondary:hover:not(:disabled){background-color:var(--cc-btn-dropdown-secondary-hover, #d1d5db)}.cc-dropdown-menu .cc-dropdown-item--outline{background-color:var(--cc-btn-dropdown-outline-bg, transparent);color:var(--cc-btn-dropdown-outline-color, #000000);border:1px solid var(--cc-btn-dropdown-outline-color, #000000)}.cc-dropdown-menu .cc-dropdown-item--outline:hover:not(:disabled){background-color:var(--cc-btn-dropdown-outline-hover, rgba(0, 0, 0, .05))}\n"] }]
|
|
8671
8811
|
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1$4.Router }, { type: i3.HttpClient }], propDecorators: { label: [{
|
|
8672
8812
|
type: Input
|
|
8673
8813
|
}], variant: [{
|
|
@@ -9008,11 +9148,11 @@ class SummaryCardComponent {
|
|
|
9008
9148
|
return styles;
|
|
9009
9149
|
}
|
|
9010
9150
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SummaryCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9011
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SummaryCardComponent, isStandalone: false, selector: "lib-summary-card", inputs: { config: "config", theme: "theme", labels: "labels" }, outputs: { cardClick: "cardClick" }, ngImport: i0, template: "<div class=\"cc-summary-card\" (click)=\"onCardClick()\">\r\n <!-- Icon Section (Left Side) -->\r\n <div class=\"icon-section\" *ngIf=\"config.icon || config.iconImage\" [ngClass]=\"config.iconClass\"\r\n [ngStyle]=\"iconStyles\">\r\n <mat-icon *ngIf=\"config.icon\">{{ config.icon }}</mat-icon>\r\n <img *ngIf=\"!config.icon && config.iconImage\" [src]=\"config.iconImage\" [alt]=\"labels.iconAlt\">\r\n </div>\r\n\r\n <!-- Right Section (Header + Value/Meta) -->\r\n <div class=\"right-section\">\r\n <!-- Header (Full Width on Right) -->\r\n <div class=\"header\" [ngClass]=\"config.headerClass\" [ngStyle]=\"headerStyles\">\r\n {{ config.header }}\r\n </div>\r\n\r\n <!-- Value and Meta Row -->\r\n <div class=\"value-meta-row\">\r\n <!-- Content Section -->\r\n <div class=\"content-section\">\r\n <!-- Value Row (with optional inline description) -->\r\n <div class=\"value-row\" [class.inline-layout]=\"isDescriptionInline\">\r\n <div class=\"value-container\">\r\n <div class=\"value\" [ngClass]=\"config.valueClass\" [ngStyle]=\"valueStyles\">\r\n {{ config.value }}\r\n <span *ngIf=\"config.valueSubtext\" class=\"value-subtext\">{{ config.valueSubtext }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Description (inline or bottom based on config) -->\r\n <div class=\"description\" *ngIf=\"config.description\" [ngClass]=\"config.descriptionClass\"\r\n [ngStyle]=\"descriptionStyles\">\r\n {{ config.description }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Meta/Status Section (Aligned with Value) -->\r\n <div class=\"meta-section\" *ngIf=\"config.metaData && config.metaData.length > 0\">\r\n <div *ngFor=\"let meta of config.metaData\" class=\"meta-item\"\r\n [ngClass]=\"[meta.type === 'pill' ? 'meta-pill' : 'meta-text', meta.cssClass || '']\"\r\n [ngStyle]=\"getMetaStyles(meta)\">\r\n {{ meta.text }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [":host{display:block;width:100%}.cc-summary-card{display:flex;flex-direction:row;align-items:stretch;box-sizing:border-box;font-family:var(--cc-sc-font-family, \"Inter\", sans-serif);background-color:var(--cc-sc-bg-color, #ffffff);border-radius:var(--cc-sc-border-radius, 8px);border:var(--cc-sc-border, 1px solid #e0e0e0);padding:var(--cc-sc-padding, 16px);box-shadow:var(--cc-sc-shadow, 0 2px 4px rgba(0, 0, 0, .05));transition:all var(--cc-sc-transition-duration, .2s) ease;height:100%;width:100%;overflow:hidden;gap:var(--cc-sc-icon-margin, 1rem)}.cc-summary-card.clickable{cursor:pointer}.cc-summary-card.clickable:hover{transform:var(--cc-sc-hover-transform);box-shadow:var(--cc-sc-hover-shadow)}.cc-summary-card.disabled{opacity:var(--cc-sc-disabled-opacity);cursor:not-allowed;pointer-events:none}.cc-summary-card .icon-section{width:var(--cc-sc-icon-box-size);height:var(--cc-sc-icon-box-size);min-width:var(--cc-sc-icon-box-size);display:flex;align-items:center;justify-content:center;border-radius:var(--cc-sc-icon-radius);background-color:var(--cc-sc-icon-bg);color:var(--cc-sc-icon-color);flex-shrink:0;align-self:center}.cc-summary-card .icon-section mat-icon{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);font-size:var(--cc-sc-icon-size);line-height:var(--cc-sc-icon-size)}.cc-summary-card .icon-section img{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);object-fit:contain}.cc-summary-card .right-section{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--cc-sc-content-gap, .5rem)}.cc-summary-card .right-section .header{font-size:var(--cc-sc-header-size);font-weight:var(--cc-sc-header-weight);text-transform:var(--cc-sc-header-transform);color:var(--cc-sc-header-color);letter-spacing:var(--cc-sc-header-letter-spacing);line-height:var(--cc-sc-header-line-height);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%}.cc-summary-card .right-section .value-meta-row{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1rem;flex:1}.cc-summary-card .right-section .value-meta-row .content-section{display:flex;flex-direction:column;justify-content:flex-start;flex:1;min-width:0}.cc-summary-card .right-section .value-meta-row .content-section .value-row{display:flex;flex-direction:column;gap:var(--cc-sc-value-desc-gap)}.cc-summary-card .right-section .value-meta-row .content-section .value-row.inline-layout{flex-direction:row;align-items:baseline;flex-wrap:wrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value{font-size:var(--cc-sc-value-size);font-weight:var(--cc-sc-value-weight);color:var(--cc-sc-value-color);line-height:var(--cc-sc-value-line-height);white-space:nowrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value .value-subtext{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);margin-left:4px}.cc-summary-card .right-section .value-meta-row .content-section .value-row .description{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);line-height:var(--cc-sc-desc-line-height)}.cc-summary-card .right-section .value-meta-row .meta-section{display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-start;flex-shrink:0;gap:6px}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item{font-size:.8125rem;line-height:1.4;white-space:nowrap;text-align:right;flex-shrink:0}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-text{color:var(--cc-sc-desc-color, #64748b);font-weight:500}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-pill{display:inline-flex;align-items:center;justify-content:center;padding:var(--cc-sc-meta-pill-padding, 4px 12px);border-radius:var(--cc-sc-meta-pill-radius, 20px);font-size:var(--cc-sc-meta-pill-font-size, .75rem);font-weight:var(--cc-sc-meta-pill-font-weight, 600);line-height:1.2;background-color:var(--cc-sc-meta-pill-bg, #f1f5f9);color:var(--cc-sc-meta-pill-color, #475569)}@media(max-width:600px){.cc-summary-card .icon-section{margin-right:var(--cc-sc-icon-margin-mobile, .75rem)}.cc-summary-card .content-section .header{font-size:var(--cc-sc-header-size-mobile, .7rem)}.cc-summary-card .content-section .value-row .value{font-size:var(--cc-sc-value-size-mobile, 1.25rem)}.cc-summary-card .content-section .value-row .description{font-size:var(--cc-sc-desc-size-mobile, .7rem)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
9151
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SummaryCardComponent, isStandalone: false, selector: "lib-summary-card", inputs: { config: "config", theme: "theme", labels: "labels" }, outputs: { cardClick: "cardClick" }, ngImport: i0, template: "<div class=\"cc-summary-card\" (click)=\"onCardClick()\">\r\n <!-- Icon Section (Left Side) -->\r\n <div class=\"icon-section\" *ngIf=\"config.icon || config.iconImage\" [ngClass]=\"config.iconClass\"\r\n [ngStyle]=\"iconStyles\">\r\n <mat-icon *ngIf=\"config.icon\">{{ config.icon }}</mat-icon>\r\n <img *ngIf=\"!config.icon && config.iconImage\" [src]=\"config.iconImage\" [alt]=\"labels.iconAlt\">\r\n </div>\r\n\r\n <!-- Right Section (Header + Value/Meta) -->\r\n <div class=\"right-section\">\r\n <!-- Header (Full Width on Right) -->\r\n <div class=\"header\" [ngClass]=\"config.headerClass\" [ngStyle]=\"headerStyles\">\r\n {{ config.header }}\r\n </div>\r\n\r\n <!-- Value and Meta Row -->\r\n <div class=\"value-meta-row\">\r\n <!-- Content Section -->\r\n <div class=\"content-section\">\r\n <!-- Value Row (with optional inline description) -->\r\n <div class=\"value-row\" [class.inline-layout]=\"isDescriptionInline\">\r\n <div class=\"value-container\">\r\n <div class=\"value\" [ngClass]=\"config.valueClass\" [ngStyle]=\"valueStyles\">\r\n {{ config.value }}\r\n <span *ngIf=\"config.valueSubtext\" class=\"value-subtext\">{{ config.valueSubtext }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Description (inline or bottom based on config) -->\r\n <div class=\"description\" *ngIf=\"config.description\" [ngClass]=\"config.descriptionClass\"\r\n [ngStyle]=\"descriptionStyles\">\r\n {{ config.description }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Meta/Status Section (Aligned with Value) -->\r\n <div class=\"meta-section\" *ngIf=\"config.metaData && config.metaData.length > 0\">\r\n <div *ngFor=\"let meta of config.metaData\" class=\"meta-item\"\r\n [ngClass]=\"[meta.type === 'pill' ? 'meta-pill' : 'meta-text', meta.cssClass || '']\"\r\n [ngStyle]=\"getMetaStyles(meta)\">\r\n {{ meta.text }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [":host{display:block;width:100%}.cc-summary-card{display:flex;flex-direction:row;align-items:stretch;box-sizing:border-box;font-family:var(--cc-sc-font-family, \"Inter\", sans-serif);background-color:var(--cc-sc-bg-color, #ffffff);border-radius:var(--cc-sc-border-radius, 8px);border:var(--cc-sc-border, 1px solid #e0e0e0);padding:var(--cc-sc-padding, 16px);box-shadow:var(--cc-sc-shadow, 0 2px 4px rgba(0, 0, 0, .05));transition:all var(--cc-sc-transition-duration, .2s) ease;height:100%;width:100%;overflow:hidden;gap:var(--cc-sc-icon-margin, 1rem)}.cc-summary-card.clickable{cursor:pointer}.cc-summary-card.clickable:hover{transform:var(--cc-sc-hover-transform);box-shadow:var(--cc-sc-hover-shadow)}.cc-summary-card.disabled{opacity:var(--cc-sc-disabled-opacity);cursor:not-allowed;pointer-events:none}.cc-summary-card .icon-section{width:var(--cc-sc-icon-box-size);height:var(--cc-sc-icon-box-size);min-width:var(--cc-sc-icon-box-size);display:flex;align-items:center;justify-content:center;border-radius:var(--cc-sc-icon-radius);background-color:var(--cc-sc-icon-bg);color:var(--cc-sc-icon-color);flex-shrink:0;align-self:center}.cc-summary-card .icon-section mat-icon{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);font-size:var(--cc-sc-icon-size);line-height:var(--cc-sc-icon-size)}.cc-summary-card .icon-section img{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);object-fit:contain}.cc-summary-card .right-section{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--cc-sc-content-gap, .5rem)}.cc-summary-card .right-section .header{font-size:var(--cc-sc-header-size);font-weight:var(--cc-sc-header-weight);text-transform:var(--cc-sc-header-transform);color:var(--cc-sc-header-color);letter-spacing:var(--cc-sc-header-letter-spacing);line-height:var(--cc-sc-header-line-height);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%}.cc-summary-card .right-section .value-meta-row{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1rem;flex:1}.cc-summary-card .right-section .value-meta-row .content-section{display:flex;flex-direction:column;justify-content:flex-start;flex:1;min-width:0}.cc-summary-card .right-section .value-meta-row .content-section .value-row{display:flex;flex-direction:column;gap:var(--cc-sc-value-desc-gap)}.cc-summary-card .right-section .value-meta-row .content-section .value-row.inline-layout{flex-direction:row;align-items:baseline;flex-wrap:wrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value{font-size:var(--cc-sc-value-size);font-weight:var(--cc-sc-value-weight);color:var(--cc-sc-value-color);line-height:var(--cc-sc-value-line-height);white-space:nowrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value .value-subtext{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);margin-left:4px}.cc-summary-card .right-section .value-meta-row .content-section .value-row .description{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);line-height:var(--cc-sc-desc-line-height)}.cc-summary-card .right-section .value-meta-row .meta-section{display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-start;flex-shrink:0;gap:6px}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item{font-size:.8125rem;line-height:1.4;white-space:nowrap;text-align:right;flex-shrink:0}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-text{color:var(--cc-sc-desc-color, #64748b);font-weight:500}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-pill{display:inline-flex;align-items:center;justify-content:center;padding:var(--cc-sc-meta-pill-padding, 4px 12px);border-radius:var(--cc-sc-meta-pill-radius, 20px);font-size:var(--cc-sc-meta-pill-font-size, .75rem);font-weight:var(--cc-sc-meta-pill-font-weight, 600);line-height:1.2;background-color:var(--cc-sc-meta-pill-bg, #f1f5f9);color:var(--cc-sc-meta-pill-color, #475569)}@media (max-width: 600px){.cc-summary-card .icon-section{margin-right:var(--cc-sc-icon-margin-mobile, .75rem)}.cc-summary-card .content-section .header{font-size:var(--cc-sc-header-size-mobile, .7rem)}.cc-summary-card .content-section .value-row .value{font-size:var(--cc-sc-value-size-mobile, 1.25rem)}.cc-summary-card .content-section .value-row .description{font-size:var(--cc-sc-desc-size-mobile, .7rem)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
9012
9152
|
}
|
|
9013
9153
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SummaryCardComponent, decorators: [{
|
|
9014
9154
|
type: Component,
|
|
9015
|
-
args: [{ selector: 'lib-summary-card', standalone: false, template: "<div class=\"cc-summary-card\" (click)=\"onCardClick()\">\r\n <!-- Icon Section (Left Side) -->\r\n <div class=\"icon-section\" *ngIf=\"config.icon || config.iconImage\" [ngClass]=\"config.iconClass\"\r\n [ngStyle]=\"iconStyles\">\r\n <mat-icon *ngIf=\"config.icon\">{{ config.icon }}</mat-icon>\r\n <img *ngIf=\"!config.icon && config.iconImage\" [src]=\"config.iconImage\" [alt]=\"labels.iconAlt\">\r\n </div>\r\n\r\n <!-- Right Section (Header + Value/Meta) -->\r\n <div class=\"right-section\">\r\n <!-- Header (Full Width on Right) -->\r\n <div class=\"header\" [ngClass]=\"config.headerClass\" [ngStyle]=\"headerStyles\">\r\n {{ config.header }}\r\n </div>\r\n\r\n <!-- Value and Meta Row -->\r\n <div class=\"value-meta-row\">\r\n <!-- Content Section -->\r\n <div class=\"content-section\">\r\n <!-- Value Row (with optional inline description) -->\r\n <div class=\"value-row\" [class.inline-layout]=\"isDescriptionInline\">\r\n <div class=\"value-container\">\r\n <div class=\"value\" [ngClass]=\"config.valueClass\" [ngStyle]=\"valueStyles\">\r\n {{ config.value }}\r\n <span *ngIf=\"config.valueSubtext\" class=\"value-subtext\">{{ config.valueSubtext }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Description (inline or bottom based on config) -->\r\n <div class=\"description\" *ngIf=\"config.description\" [ngClass]=\"config.descriptionClass\"\r\n [ngStyle]=\"descriptionStyles\">\r\n {{ config.description }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Meta/Status Section (Aligned with Value) -->\r\n <div class=\"meta-section\" *ngIf=\"config.metaData && config.metaData.length > 0\">\r\n <div *ngFor=\"let meta of config.metaData\" class=\"meta-item\"\r\n [ngClass]=\"[meta.type === 'pill' ? 'meta-pill' : 'meta-text', meta.cssClass || '']\"\r\n [ngStyle]=\"getMetaStyles(meta)\">\r\n {{ meta.text }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [":host{display:block;width:100%}.cc-summary-card{display:flex;flex-direction:row;align-items:stretch;box-sizing:border-box;font-family:var(--cc-sc-font-family, \"Inter\", sans-serif);background-color:var(--cc-sc-bg-color, #ffffff);border-radius:var(--cc-sc-border-radius, 8px);border:var(--cc-sc-border, 1px solid #e0e0e0);padding:var(--cc-sc-padding, 16px);box-shadow:var(--cc-sc-shadow, 0 2px 4px rgba(0, 0, 0, .05));transition:all var(--cc-sc-transition-duration, .2s) ease;height:100%;width:100%;overflow:hidden;gap:var(--cc-sc-icon-margin, 1rem)}.cc-summary-card.clickable{cursor:pointer}.cc-summary-card.clickable:hover{transform:var(--cc-sc-hover-transform);box-shadow:var(--cc-sc-hover-shadow)}.cc-summary-card.disabled{opacity:var(--cc-sc-disabled-opacity);cursor:not-allowed;pointer-events:none}.cc-summary-card .icon-section{width:var(--cc-sc-icon-box-size);height:var(--cc-sc-icon-box-size);min-width:var(--cc-sc-icon-box-size);display:flex;align-items:center;justify-content:center;border-radius:var(--cc-sc-icon-radius);background-color:var(--cc-sc-icon-bg);color:var(--cc-sc-icon-color);flex-shrink:0;align-self:center}.cc-summary-card .icon-section mat-icon{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);font-size:var(--cc-sc-icon-size);line-height:var(--cc-sc-icon-size)}.cc-summary-card .icon-section img{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);object-fit:contain}.cc-summary-card .right-section{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--cc-sc-content-gap, .5rem)}.cc-summary-card .right-section .header{font-size:var(--cc-sc-header-size);font-weight:var(--cc-sc-header-weight);text-transform:var(--cc-sc-header-transform);color:var(--cc-sc-header-color);letter-spacing:var(--cc-sc-header-letter-spacing);line-height:var(--cc-sc-header-line-height);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%}.cc-summary-card .right-section .value-meta-row{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1rem;flex:1}.cc-summary-card .right-section .value-meta-row .content-section{display:flex;flex-direction:column;justify-content:flex-start;flex:1;min-width:0}.cc-summary-card .right-section .value-meta-row .content-section .value-row{display:flex;flex-direction:column;gap:var(--cc-sc-value-desc-gap)}.cc-summary-card .right-section .value-meta-row .content-section .value-row.inline-layout{flex-direction:row;align-items:baseline;flex-wrap:wrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value{font-size:var(--cc-sc-value-size);font-weight:var(--cc-sc-value-weight);color:var(--cc-sc-value-color);line-height:var(--cc-sc-value-line-height);white-space:nowrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value .value-subtext{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);margin-left:4px}.cc-summary-card .right-section .value-meta-row .content-section .value-row .description{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);line-height:var(--cc-sc-desc-line-height)}.cc-summary-card .right-section .value-meta-row .meta-section{display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-start;flex-shrink:0;gap:6px}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item{font-size:.8125rem;line-height:1.4;white-space:nowrap;text-align:right;flex-shrink:0}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-text{color:var(--cc-sc-desc-color, #64748b);font-weight:500}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-pill{display:inline-flex;align-items:center;justify-content:center;padding:var(--cc-sc-meta-pill-padding, 4px 12px);border-radius:var(--cc-sc-meta-pill-radius, 20px);font-size:var(--cc-sc-meta-pill-font-size, .75rem);font-weight:var(--cc-sc-meta-pill-font-weight, 600);line-height:1.2;background-color:var(--cc-sc-meta-pill-bg, #f1f5f9);color:var(--cc-sc-meta-pill-color, #475569)}@media(max-width:600px){.cc-summary-card .icon-section{margin-right:var(--cc-sc-icon-margin-mobile, .75rem)}.cc-summary-card .content-section .header{font-size:var(--cc-sc-header-size-mobile, .7rem)}.cc-summary-card .content-section .value-row .value{font-size:var(--cc-sc-value-size-mobile, 1.25rem)}.cc-summary-card .content-section .value-row .description{font-size:var(--cc-sc-desc-size-mobile, .7rem)}}\n"] }]
|
|
9155
|
+
args: [{ selector: 'lib-summary-card', standalone: false, template: "<div class=\"cc-summary-card\" (click)=\"onCardClick()\">\r\n <!-- Icon Section (Left Side) -->\r\n <div class=\"icon-section\" *ngIf=\"config.icon || config.iconImage\" [ngClass]=\"config.iconClass\"\r\n [ngStyle]=\"iconStyles\">\r\n <mat-icon *ngIf=\"config.icon\">{{ config.icon }}</mat-icon>\r\n <img *ngIf=\"!config.icon && config.iconImage\" [src]=\"config.iconImage\" [alt]=\"labels.iconAlt\">\r\n </div>\r\n\r\n <!-- Right Section (Header + Value/Meta) -->\r\n <div class=\"right-section\">\r\n <!-- Header (Full Width on Right) -->\r\n <div class=\"header\" [ngClass]=\"config.headerClass\" [ngStyle]=\"headerStyles\">\r\n {{ config.header }}\r\n </div>\r\n\r\n <!-- Value and Meta Row -->\r\n <div class=\"value-meta-row\">\r\n <!-- Content Section -->\r\n <div class=\"content-section\">\r\n <!-- Value Row (with optional inline description) -->\r\n <div class=\"value-row\" [class.inline-layout]=\"isDescriptionInline\">\r\n <div class=\"value-container\">\r\n <div class=\"value\" [ngClass]=\"config.valueClass\" [ngStyle]=\"valueStyles\">\r\n {{ config.value }}\r\n <span *ngIf=\"config.valueSubtext\" class=\"value-subtext\">{{ config.valueSubtext }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Description (inline or bottom based on config) -->\r\n <div class=\"description\" *ngIf=\"config.description\" [ngClass]=\"config.descriptionClass\"\r\n [ngStyle]=\"descriptionStyles\">\r\n {{ config.description }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Meta/Status Section (Aligned with Value) -->\r\n <div class=\"meta-section\" *ngIf=\"config.metaData && config.metaData.length > 0\">\r\n <div *ngFor=\"let meta of config.metaData\" class=\"meta-item\"\r\n [ngClass]=\"[meta.type === 'pill' ? 'meta-pill' : 'meta-text', meta.cssClass || '']\"\r\n [ngStyle]=\"getMetaStyles(meta)\">\r\n {{ meta.text }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [":host{display:block;width:100%}.cc-summary-card{display:flex;flex-direction:row;align-items:stretch;box-sizing:border-box;font-family:var(--cc-sc-font-family, \"Inter\", sans-serif);background-color:var(--cc-sc-bg-color, #ffffff);border-radius:var(--cc-sc-border-radius, 8px);border:var(--cc-sc-border, 1px solid #e0e0e0);padding:var(--cc-sc-padding, 16px);box-shadow:var(--cc-sc-shadow, 0 2px 4px rgba(0, 0, 0, .05));transition:all var(--cc-sc-transition-duration, .2s) ease;height:100%;width:100%;overflow:hidden;gap:var(--cc-sc-icon-margin, 1rem)}.cc-summary-card.clickable{cursor:pointer}.cc-summary-card.clickable:hover{transform:var(--cc-sc-hover-transform);box-shadow:var(--cc-sc-hover-shadow)}.cc-summary-card.disabled{opacity:var(--cc-sc-disabled-opacity);cursor:not-allowed;pointer-events:none}.cc-summary-card .icon-section{width:var(--cc-sc-icon-box-size);height:var(--cc-sc-icon-box-size);min-width:var(--cc-sc-icon-box-size);display:flex;align-items:center;justify-content:center;border-radius:var(--cc-sc-icon-radius);background-color:var(--cc-sc-icon-bg);color:var(--cc-sc-icon-color);flex-shrink:0;align-self:center}.cc-summary-card .icon-section mat-icon{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);font-size:var(--cc-sc-icon-size);line-height:var(--cc-sc-icon-size)}.cc-summary-card .icon-section img{width:var(--cc-sc-icon-size);height:var(--cc-sc-icon-size);object-fit:contain}.cc-summary-card .right-section{display:flex;flex-direction:column;flex:1;min-width:0;gap:var(--cc-sc-content-gap, .5rem)}.cc-summary-card .right-section .header{font-size:var(--cc-sc-header-size);font-weight:var(--cc-sc-header-weight);text-transform:var(--cc-sc-header-transform);color:var(--cc-sc-header-color);letter-spacing:var(--cc-sc-header-letter-spacing);line-height:var(--cc-sc-header-line-height);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%}.cc-summary-card .right-section .value-meta-row{display:flex;flex-direction:row;align-items:flex-start;justify-content:space-between;gap:1rem;flex:1}.cc-summary-card .right-section .value-meta-row .content-section{display:flex;flex-direction:column;justify-content:flex-start;flex:1;min-width:0}.cc-summary-card .right-section .value-meta-row .content-section .value-row{display:flex;flex-direction:column;gap:var(--cc-sc-value-desc-gap)}.cc-summary-card .right-section .value-meta-row .content-section .value-row.inline-layout{flex-direction:row;align-items:baseline;flex-wrap:wrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value{font-size:var(--cc-sc-value-size);font-weight:var(--cc-sc-value-weight);color:var(--cc-sc-value-color);line-height:var(--cc-sc-value-line-height);white-space:nowrap}.cc-summary-card .right-section .value-meta-row .content-section .value-row .value .value-subtext{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);margin-left:4px}.cc-summary-card .right-section .value-meta-row .content-section .value-row .description{font-size:var(--cc-sc-desc-size);font-weight:var(--cc-sc-desc-weight);color:var(--cc-sc-desc-color);line-height:var(--cc-sc-desc-line-height)}.cc-summary-card .right-section .value-meta-row .meta-section{display:flex;flex-direction:column;align-items:flex-end;justify-content:flex-start;flex-shrink:0;gap:6px}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item{font-size:.8125rem;line-height:1.4;white-space:nowrap;text-align:right;flex-shrink:0}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-text{color:var(--cc-sc-desc-color, #64748b);font-weight:500}.cc-summary-card .right-section .value-meta-row .meta-section .meta-item.meta-pill{display:inline-flex;align-items:center;justify-content:center;padding:var(--cc-sc-meta-pill-padding, 4px 12px);border-radius:var(--cc-sc-meta-pill-radius, 20px);font-size:var(--cc-sc-meta-pill-font-size, .75rem);font-weight:var(--cc-sc-meta-pill-font-weight, 600);line-height:1.2;background-color:var(--cc-sc-meta-pill-bg, #f1f5f9);color:var(--cc-sc-meta-pill-color, #475569)}@media (max-width: 600px){.cc-summary-card .icon-section{margin-right:var(--cc-sc-icon-margin-mobile, .75rem)}.cc-summary-card .content-section .header{font-size:var(--cc-sc-header-size-mobile, .7rem)}.cc-summary-card .content-section .value-row .value{font-size:var(--cc-sc-value-size-mobile, 1.25rem)}.cc-summary-card .content-section .value-row .description{font-size:var(--cc-sc-desc-size-mobile, .7rem)}}\n"] }]
|
|
9016
9156
|
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
9017
9157
|
type: Input
|
|
9018
9158
|
}], theme: [{
|
|
@@ -9644,11 +9784,11 @@ class ConfigurableFormComponent {
|
|
|
9644
9784
|
return this.passwordFieldState.get(fieldName) || false;
|
|
9645
9785
|
}
|
|
9646
9786
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormComponent, deps: [{ token: i1$3.FormBuilder }, { token: i1$1.MatSnackBar }, { token: i3.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
|
|
9647
|
-
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", labels: "labels" }, 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 || labels.repeaterItemDefaultLabel }} {{i\r\n + 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 || labels.addMoreDefaultLabel }}\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 }} {{ labels.charactersLabel }}\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 }} {{ labels.charactersLabel }}\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 }} {{ labels.charactersLabel }}\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\">{{ labels.selectDefaultPlaceholder }}\r\n </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 {{ labels.errorMinValue }}\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 {{ labels.errorPercentageTotal }}\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\">{{ labels.uploadDragDropText }}</div>\r\n <div class=\"upload-hint\">{{ labels.uploadHint }}</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$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.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$3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$3.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"] }] });
|
|
9787
|
+
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", labels: "labels" }, 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 || labels.repeaterItemDefaultLabel }} {{i\r\n + 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 || labels.addMoreDefaultLabel }}\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 }} {{ labels.charactersLabel }}\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 }} {{ labels.charactersLabel }}\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 }} {{ labels.charactersLabel }}\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\">{{ labels.selectDefaultPlaceholder }}\r\n </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 {{ labels.errorMinValue }}\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 {{ labels.errorPercentageTotal }}\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\">{{ labels.uploadDragDropText }}</div>\r\n <div class=\"upload-hint\">{{ labels.uploadHint }}</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$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.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$3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$3.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"] }] });
|
|
9648
9788
|
}
|
|
9649
9789
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurableFormComponent, decorators: [{
|
|
9650
9790
|
type: Component,
|
|
9651
|
-
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 || labels.repeaterItemDefaultLabel }} {{i\r\n + 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 || labels.addMoreDefaultLabel }}\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 }} {{ labels.charactersLabel }}\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 }} {{ labels.charactersLabel }}\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 }} {{ labels.charactersLabel }}\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\">{{ labels.selectDefaultPlaceholder }}\r\n </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 {{ labels.errorMinValue }}\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 {{ labels.errorPercentageTotal }}\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\">{{ labels.uploadDragDropText }}</div>\r\n <div class=\"upload-hint\">{{ labels.uploadHint }}</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"] }]
|
|
9791
|
+
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 || labels.repeaterItemDefaultLabel }} {{i\r\n + 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 || labels.addMoreDefaultLabel }}\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 }} {{ labels.charactersLabel }}\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 }} {{ labels.charactersLabel }}\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 }} {{ labels.charactersLabel }}\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\">{{ labels.selectDefaultPlaceholder }}\r\n </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 {{ labels.errorMinValue }}\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 {{ labels.errorPercentageTotal }}\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\">{{ labels.uploadDragDropText }}</div>\r\n <div class=\"upload-hint\">{{ labels.uploadHint }}</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"] }]
|
|
9652
9792
|
}], ctorParameters: () => [{ type: i1$3.FormBuilder }, { type: i1$1.MatSnackBar }, { type: i3.HttpClient }], propDecorators: { config: [{
|
|
9653
9793
|
type: Input
|
|
9654
9794
|
}], jsonConfig: [{
|
|
@@ -10213,11 +10353,11 @@ class PaginationComponent {
|
|
|
10213
10353
|
}
|
|
10214
10354
|
}
|
|
10215
10355
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10216
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: PaginationComponent, isStandalone: false, selector: "lib-pagination", inputs: { totalItems: "totalItems", itemsPerPage: "itemsPerPage", currentPage: "currentPage", pageSizeOptions: "pageSizeOptions", theme: "theme", labels: "labels" }, outputs: { pageChange: "pageChange", itemsPerPageChange: "itemsPerPageChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-pagination\" [ngClass]=\"theme\">\r\n <!-- Left Side: Items Info & Per Page -->\r\n <div class=\"pagination-left\" *ngIf=\"pageSizeOptions.length > 1 || totalItems > 0\">\r\n <span class=\"items-info\">\r\n {{ startItem }}-{{ endItem }} {{ labels.of }} {{ totalItems }} {{ labels.items }}\r\n </span>\r\n\r\n <div class=\"per-page-selector\" *ngIf=\"pageSizeOptions.length > 1\">\r\n <div class=\"select-wrapper\">\r\n <select (change)=\"onItemsPerPageChange($event)\">\r\n <option *ngFor=\"let option of pageSizeOptions\" [value]=\"option\" [selected]=\"option === itemsPerPage\">\r\n {{ option }}\r\n </option>\r\n </select>\r\n <span class=\"select-arrow\"></span>\r\n </div>\r\n <span class=\"per-page-label\">{{ labels.perPage }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Page Controls -->\r\n <div class=\"pagination-right\">\r\n <button \r\n class=\"page-btn prev-btn\" \r\n [disabled]=\"currentPage === 1\" \r\n (click)=\"prevPage()\"\r\n aria-label=\"Previous Page\">\r\n <span class=\"icon\">‹</span>\r\n </button>\r\n\r\n <div class=\"page-numbers\">\r\n <ng-container *ngFor=\"let page of pages\">\r\n <button \r\n *ngIf=\"page !== '...'\"\r\n class=\"page-btn number-btn\" \r\n [class.active]=\"page === currentPage\"\r\n (click)=\"onPageChange(page)\">\r\n {{ page }}\r\n </button>\r\n <span *ngIf=\"page === '...'\" class=\"ellipsis\">...</span>\r\n </ng-container>\r\n </div>\r\n\r\n <button \r\n class=\"page-btn next-btn\" \r\n [disabled]=\"currentPage === totalPages || totalPages === 0\" \r\n (click)=\"nextPage()\"\r\n aria-label=\"Next Page\">\r\n <span class=\"icon\">›</span>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.cc-pagination{display:flex;justify-content:space-between;align-items:center;padding:1rem;font-family:var(--cc-pagination-font-family);color:var(--cc-pagination-text-color);font-size:var(--cc-pagination-font-size);flex-wrap:wrap;gap:1rem;width:100%;box-sizing:border-box}.cc-pagination .pagination-left{display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap}.cc-pagination .pagination-left .items-info{white-space:nowrap}.cc-pagination .pagination-left .per-page-selector{display:flex;align-items:center;gap:.5rem}.cc-pagination .pagination-left .per-page-selector .select-wrapper{position:relative;display:inline-block}.cc-pagination .pagination-left .per-page-selector .select-wrapper select{appearance:none;background-color:var(--cc-pagination-select-bg);border:var(--cc-pagination-select-border);border-radius:var(--cc-pagination-select-radius);padding:var(--cc-pagination-select-padding);padding-right:2rem;color:var(--cc-pagination-select-text-color);font-family:inherit;font-size:inherit;cursor:pointer;min-width:60px}.cc-pagination .pagination-left .per-page-selector .select-wrapper select:focus{outline:none;box-shadow:0 0 0 2px #0000001a}.cc-pagination .pagination-left .per-page-selector .select-wrapper:after{content:\"\\25bc\";position:absolute;right:10px;top:50%;transform:translateY(-50%);font-size:.7em;color:var(--cc-pagination-select-arrow-color);pointer-events:none}.cc-pagination .pagination-left .per-page-selector .per-page-label{white-space:nowrap}.cc-pagination .pagination-right{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .page-btn{display:flex;align-items:center;justify-content:center;min-width:var(--cc-pagination-btn-size);height:var(--cc-pagination-btn-size);background-color:var(--cc-pagination-btn-bg);border:var(--cc-pagination-btn-border);border-radius:var(--cc-pagination-btn-radius);color:var(--cc-pagination-btn-text-color);font-family:inherit;cursor:pointer;transition:all .2s ease;padding:0 .5rem;-webkit-user-select:none;user-select:none}.cc-pagination .pagination-right .page-btn:hover:not(:disabled){background-color:var(--cc-pagination-btn-hover-bg)}.cc-pagination .pagination-right .page-btn:disabled{opacity:var(--cc-pagination-disabled-opacity);background-color:var(--cc-pagination-disabled-bg);cursor:not-allowed}.cc-pagination .pagination-right .page-btn.active{background-color:var(--cc-pagination-btn-active-bg);border:var(--cc-pagination-btn-active-border);color:var(--cc-pagination-btn-active-text);font-weight:700}.cc-pagination .pagination-right .page-btn .icon{font-size:1.2em;line-height:1}.cc-pagination .pagination-right .page-numbers{display:flex;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .ellipsis{display:flex;align-items:center;justify-content:center;color:var(--cc-pagination-text-color);width:20px}@media(max-width:600px){.cc-pagination{flex-direction:column;align-items:center;gap:1.5rem}.cc-pagination .pagination-left{width:100%;justify-content:space-between;order:2}.cc-pagination .pagination-right{width:100%;justify-content:center;order:1}.cc-pagination .pagination-right .page-numbers{justify-content:center}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
10356
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: PaginationComponent, isStandalone: false, selector: "lib-pagination", inputs: { totalItems: "totalItems", itemsPerPage: "itemsPerPage", currentPage: "currentPage", pageSizeOptions: "pageSizeOptions", theme: "theme", labels: "labels" }, outputs: { pageChange: "pageChange", itemsPerPageChange: "itemsPerPageChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-pagination\" [ngClass]=\"theme\">\r\n <!-- Left Side: Items Info & Per Page -->\r\n <div class=\"pagination-left\" *ngIf=\"pageSizeOptions.length > 1 || totalItems > 0\">\r\n <span class=\"items-info\">\r\n {{ startItem }}-{{ endItem }} {{ labels.of }} {{ totalItems }} {{ labels.items }}\r\n </span>\r\n\r\n <div class=\"per-page-selector\" *ngIf=\"pageSizeOptions.length > 1\">\r\n <div class=\"select-wrapper\">\r\n <select (change)=\"onItemsPerPageChange($event)\">\r\n <option *ngFor=\"let option of pageSizeOptions\" [value]=\"option\" [selected]=\"option === itemsPerPage\">\r\n {{ option }}\r\n </option>\r\n </select>\r\n <span class=\"select-arrow\"></span>\r\n </div>\r\n <span class=\"per-page-label\">{{ labels.perPage }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Page Controls -->\r\n <div class=\"pagination-right\">\r\n <button \r\n class=\"page-btn prev-btn\" \r\n [disabled]=\"currentPage === 1\" \r\n (click)=\"prevPage()\"\r\n aria-label=\"Previous Page\">\r\n <span class=\"icon\">‹</span>\r\n </button>\r\n\r\n <div class=\"page-numbers\">\r\n <ng-container *ngFor=\"let page of pages\">\r\n <button \r\n *ngIf=\"page !== '...'\"\r\n class=\"page-btn number-btn\" \r\n [class.active]=\"page === currentPage\"\r\n (click)=\"onPageChange(page)\">\r\n {{ page }}\r\n </button>\r\n <span *ngIf=\"page === '...'\" class=\"ellipsis\">...</span>\r\n </ng-container>\r\n </div>\r\n\r\n <button \r\n class=\"page-btn next-btn\" \r\n [disabled]=\"currentPage === totalPages || totalPages === 0\" \r\n (click)=\"nextPage()\"\r\n aria-label=\"Next Page\">\r\n <span class=\"icon\">›</span>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.cc-pagination{display:flex;justify-content:space-between;align-items:center;padding:1rem;font-family:var(--cc-pagination-font-family);color:var(--cc-pagination-text-color);font-size:var(--cc-pagination-font-size);flex-wrap:wrap;gap:1rem;width:100%;box-sizing:border-box}.cc-pagination .pagination-left{display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap}.cc-pagination .pagination-left .items-info{white-space:nowrap}.cc-pagination .pagination-left .per-page-selector{display:flex;align-items:center;gap:.5rem}.cc-pagination .pagination-left .per-page-selector .select-wrapper{position:relative;display:inline-block}.cc-pagination .pagination-left .per-page-selector .select-wrapper select{appearance:none;background-color:var(--cc-pagination-select-bg);border:var(--cc-pagination-select-border);border-radius:var(--cc-pagination-select-radius);padding:var(--cc-pagination-select-padding);padding-right:2rem;color:var(--cc-pagination-select-text-color);font-family:inherit;font-size:inherit;cursor:pointer;min-width:60px}.cc-pagination .pagination-left .per-page-selector .select-wrapper select:focus{outline:none;box-shadow:0 0 0 2px #0000001a}.cc-pagination .pagination-left .per-page-selector .select-wrapper:after{content:\"\\25bc\";position:absolute;right:10px;top:50%;transform:translateY(-50%);font-size:.7em;color:var(--cc-pagination-select-arrow-color);pointer-events:none}.cc-pagination .pagination-left .per-page-selector .per-page-label{white-space:nowrap}.cc-pagination .pagination-right{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .page-btn{display:flex;align-items:center;justify-content:center;min-width:var(--cc-pagination-btn-size);height:var(--cc-pagination-btn-size);background-color:var(--cc-pagination-btn-bg);border:var(--cc-pagination-btn-border);border-radius:var(--cc-pagination-btn-radius);color:var(--cc-pagination-btn-text-color);font-family:inherit;cursor:pointer;transition:all .2s ease;padding:0 .5rem;-webkit-user-select:none;user-select:none}.cc-pagination .pagination-right .page-btn:hover:not(:disabled){background-color:var(--cc-pagination-btn-hover-bg)}.cc-pagination .pagination-right .page-btn:disabled{opacity:var(--cc-pagination-disabled-opacity);background-color:var(--cc-pagination-disabled-bg);cursor:not-allowed}.cc-pagination .pagination-right .page-btn.active{background-color:var(--cc-pagination-btn-active-bg);border:var(--cc-pagination-btn-active-border);color:var(--cc-pagination-btn-active-text);font-weight:700}.cc-pagination .pagination-right .page-btn .icon{font-size:1.2em;line-height:1}.cc-pagination .pagination-right .page-numbers{display:flex;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .ellipsis{display:flex;align-items:center;justify-content:center;color:var(--cc-pagination-text-color);width:20px}@media (max-width: 600px){.cc-pagination{flex-direction:column;align-items:center;gap:1.5rem}.cc-pagination .pagination-left{width:100%;justify-content:space-between;order:2}.cc-pagination .pagination-right{width:100%;justify-content:center;order:1}.cc-pagination .pagination-right .page-numbers{justify-content:center}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
10217
10357
|
}
|
|
10218
10358
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: PaginationComponent, decorators: [{
|
|
10219
10359
|
type: Component,
|
|
10220
|
-
args: [{ selector: 'lib-pagination', standalone: false, template: "<div class=\"cc-pagination\" [ngClass]=\"theme\">\r\n <!-- Left Side: Items Info & Per Page -->\r\n <div class=\"pagination-left\" *ngIf=\"pageSizeOptions.length > 1 || totalItems > 0\">\r\n <span class=\"items-info\">\r\n {{ startItem }}-{{ endItem }} {{ labels.of }} {{ totalItems }} {{ labels.items }}\r\n </span>\r\n\r\n <div class=\"per-page-selector\" *ngIf=\"pageSizeOptions.length > 1\">\r\n <div class=\"select-wrapper\">\r\n <select (change)=\"onItemsPerPageChange($event)\">\r\n <option *ngFor=\"let option of pageSizeOptions\" [value]=\"option\" [selected]=\"option === itemsPerPage\">\r\n {{ option }}\r\n </option>\r\n </select>\r\n <span class=\"select-arrow\"></span>\r\n </div>\r\n <span class=\"per-page-label\">{{ labels.perPage }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Page Controls -->\r\n <div class=\"pagination-right\">\r\n <button \r\n class=\"page-btn prev-btn\" \r\n [disabled]=\"currentPage === 1\" \r\n (click)=\"prevPage()\"\r\n aria-label=\"Previous Page\">\r\n <span class=\"icon\">‹</span>\r\n </button>\r\n\r\n <div class=\"page-numbers\">\r\n <ng-container *ngFor=\"let page of pages\">\r\n <button \r\n *ngIf=\"page !== '...'\"\r\n class=\"page-btn number-btn\" \r\n [class.active]=\"page === currentPage\"\r\n (click)=\"onPageChange(page)\">\r\n {{ page }}\r\n </button>\r\n <span *ngIf=\"page === '...'\" class=\"ellipsis\">...</span>\r\n </ng-container>\r\n </div>\r\n\r\n <button \r\n class=\"page-btn next-btn\" \r\n [disabled]=\"currentPage === totalPages || totalPages === 0\" \r\n (click)=\"nextPage()\"\r\n aria-label=\"Next Page\">\r\n <span class=\"icon\">›</span>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.cc-pagination{display:flex;justify-content:space-between;align-items:center;padding:1rem;font-family:var(--cc-pagination-font-family);color:var(--cc-pagination-text-color);font-size:var(--cc-pagination-font-size);flex-wrap:wrap;gap:1rem;width:100%;box-sizing:border-box}.cc-pagination .pagination-left{display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap}.cc-pagination .pagination-left .items-info{white-space:nowrap}.cc-pagination .pagination-left .per-page-selector{display:flex;align-items:center;gap:.5rem}.cc-pagination .pagination-left .per-page-selector .select-wrapper{position:relative;display:inline-block}.cc-pagination .pagination-left .per-page-selector .select-wrapper select{appearance:none;background-color:var(--cc-pagination-select-bg);border:var(--cc-pagination-select-border);border-radius:var(--cc-pagination-select-radius);padding:var(--cc-pagination-select-padding);padding-right:2rem;color:var(--cc-pagination-select-text-color);font-family:inherit;font-size:inherit;cursor:pointer;min-width:60px}.cc-pagination .pagination-left .per-page-selector .select-wrapper select:focus{outline:none;box-shadow:0 0 0 2px #0000001a}.cc-pagination .pagination-left .per-page-selector .select-wrapper:after{content:\"\\25bc\";position:absolute;right:10px;top:50%;transform:translateY(-50%);font-size:.7em;color:var(--cc-pagination-select-arrow-color);pointer-events:none}.cc-pagination .pagination-left .per-page-selector .per-page-label{white-space:nowrap}.cc-pagination .pagination-right{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .page-btn{display:flex;align-items:center;justify-content:center;min-width:var(--cc-pagination-btn-size);height:var(--cc-pagination-btn-size);background-color:var(--cc-pagination-btn-bg);border:var(--cc-pagination-btn-border);border-radius:var(--cc-pagination-btn-radius);color:var(--cc-pagination-btn-text-color);font-family:inherit;cursor:pointer;transition:all .2s ease;padding:0 .5rem;-webkit-user-select:none;user-select:none}.cc-pagination .pagination-right .page-btn:hover:not(:disabled){background-color:var(--cc-pagination-btn-hover-bg)}.cc-pagination .pagination-right .page-btn:disabled{opacity:var(--cc-pagination-disabled-opacity);background-color:var(--cc-pagination-disabled-bg);cursor:not-allowed}.cc-pagination .pagination-right .page-btn.active{background-color:var(--cc-pagination-btn-active-bg);border:var(--cc-pagination-btn-active-border);color:var(--cc-pagination-btn-active-text);font-weight:700}.cc-pagination .pagination-right .page-btn .icon{font-size:1.2em;line-height:1}.cc-pagination .pagination-right .page-numbers{display:flex;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .ellipsis{display:flex;align-items:center;justify-content:center;color:var(--cc-pagination-text-color);width:20px}@media(max-width:600px){.cc-pagination{flex-direction:column;align-items:center;gap:1.5rem}.cc-pagination .pagination-left{width:100%;justify-content:space-between;order:2}.cc-pagination .pagination-right{width:100%;justify-content:center;order:1}.cc-pagination .pagination-right .page-numbers{justify-content:center}}\n"] }]
|
|
10360
|
+
args: [{ selector: 'lib-pagination', standalone: false, template: "<div class=\"cc-pagination\" [ngClass]=\"theme\">\r\n <!-- Left Side: Items Info & Per Page -->\r\n <div class=\"pagination-left\" *ngIf=\"pageSizeOptions.length > 1 || totalItems > 0\">\r\n <span class=\"items-info\">\r\n {{ startItem }}-{{ endItem }} {{ labels.of }} {{ totalItems }} {{ labels.items }}\r\n </span>\r\n\r\n <div class=\"per-page-selector\" *ngIf=\"pageSizeOptions.length > 1\">\r\n <div class=\"select-wrapper\">\r\n <select (change)=\"onItemsPerPageChange($event)\">\r\n <option *ngFor=\"let option of pageSizeOptions\" [value]=\"option\" [selected]=\"option === itemsPerPage\">\r\n {{ option }}\r\n </option>\r\n </select>\r\n <span class=\"select-arrow\"></span>\r\n </div>\r\n <span class=\"per-page-label\">{{ labels.perPage }}</span>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Page Controls -->\r\n <div class=\"pagination-right\">\r\n <button \r\n class=\"page-btn prev-btn\" \r\n [disabled]=\"currentPage === 1\" \r\n (click)=\"prevPage()\"\r\n aria-label=\"Previous Page\">\r\n <span class=\"icon\">‹</span>\r\n </button>\r\n\r\n <div class=\"page-numbers\">\r\n <ng-container *ngFor=\"let page of pages\">\r\n <button \r\n *ngIf=\"page !== '...'\"\r\n class=\"page-btn number-btn\" \r\n [class.active]=\"page === currentPage\"\r\n (click)=\"onPageChange(page)\">\r\n {{ page }}\r\n </button>\r\n <span *ngIf=\"page === '...'\" class=\"ellipsis\">...</span>\r\n </ng-container>\r\n </div>\r\n\r\n <button \r\n class=\"page-btn next-btn\" \r\n [disabled]=\"currentPage === totalPages || totalPages === 0\" \r\n (click)=\"nextPage()\"\r\n aria-label=\"Next Page\">\r\n <span class=\"icon\">›</span>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.cc-pagination{display:flex;justify-content:space-between;align-items:center;padding:1rem;font-family:var(--cc-pagination-font-family);color:var(--cc-pagination-text-color);font-size:var(--cc-pagination-font-size);flex-wrap:wrap;gap:1rem;width:100%;box-sizing:border-box}.cc-pagination .pagination-left{display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap}.cc-pagination .pagination-left .items-info{white-space:nowrap}.cc-pagination .pagination-left .per-page-selector{display:flex;align-items:center;gap:.5rem}.cc-pagination .pagination-left .per-page-selector .select-wrapper{position:relative;display:inline-block}.cc-pagination .pagination-left .per-page-selector .select-wrapper select{appearance:none;background-color:var(--cc-pagination-select-bg);border:var(--cc-pagination-select-border);border-radius:var(--cc-pagination-select-radius);padding:var(--cc-pagination-select-padding);padding-right:2rem;color:var(--cc-pagination-select-text-color);font-family:inherit;font-size:inherit;cursor:pointer;min-width:60px}.cc-pagination .pagination-left .per-page-selector .select-wrapper select:focus{outline:none;box-shadow:0 0 0 2px #0000001a}.cc-pagination .pagination-left .per-page-selector .select-wrapper:after{content:\"\\25bc\";position:absolute;right:10px;top:50%;transform:translateY(-50%);font-size:.7em;color:var(--cc-pagination-select-arrow-color);pointer-events:none}.cc-pagination .pagination-left .per-page-selector .per-page-label{white-space:nowrap}.cc-pagination .pagination-right{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .page-btn{display:flex;align-items:center;justify-content:center;min-width:var(--cc-pagination-btn-size);height:var(--cc-pagination-btn-size);background-color:var(--cc-pagination-btn-bg);border:var(--cc-pagination-btn-border);border-radius:var(--cc-pagination-btn-radius);color:var(--cc-pagination-btn-text-color);font-family:inherit;cursor:pointer;transition:all .2s ease;padding:0 .5rem;-webkit-user-select:none;user-select:none}.cc-pagination .pagination-right .page-btn:hover:not(:disabled){background-color:var(--cc-pagination-btn-hover-bg)}.cc-pagination .pagination-right .page-btn:disabled{opacity:var(--cc-pagination-disabled-opacity);background-color:var(--cc-pagination-disabled-bg);cursor:not-allowed}.cc-pagination .pagination-right .page-btn.active{background-color:var(--cc-pagination-btn-active-bg);border:var(--cc-pagination-btn-active-border);color:var(--cc-pagination-btn-active-text);font-weight:700}.cc-pagination .pagination-right .page-btn .icon{font-size:1.2em;line-height:1}.cc-pagination .pagination-right .page-numbers{display:flex;gap:.5rem;flex-wrap:wrap}.cc-pagination .pagination-right .ellipsis{display:flex;align-items:center;justify-content:center;color:var(--cc-pagination-text-color);width:20px}@media (max-width: 600px){.cc-pagination{flex-direction:column;align-items:center;gap:1.5rem}.cc-pagination .pagination-left{width:100%;justify-content:space-between;order:2}.cc-pagination .pagination-right{width:100%;justify-content:center;order:1}.cc-pagination .pagination-right .page-numbers{justify-content:center}}\n"] }]
|
|
10221
10361
|
}], ctorParameters: () => [], propDecorators: { totalItems: [{
|
|
10222
10362
|
type: Input
|
|
10223
10363
|
}], itemsPerPage: [{
|
|
@@ -11254,11 +11394,11 @@ class SmartTableComponent {
|
|
|
11254
11394
|
});
|
|
11255
11395
|
}
|
|
11256
11396
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableComponent, deps: [{ token: i3.HttpClient }, { token: i1$4.Router }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
11257
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartTableComponent, isStandalone: false, selector: "lib-smart-table", inputs: { config: "config", tableData: "tableData", totalItemsCount: "totalItemsCount", selectedRows: "selectedRows" }, outputs: { action: "action", topAction: "topAction", filterChange: "filterChange", rowSelect: "rowSelect", columnClick: "columnClick", sortChange: "sortChange", pageChange: "pageChange", searchChange: "searchChange", rowSave: "rowSave" }, host: { listeners: { "document:click": "closeDropdown()" } }, viewQueries: [{ propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-table-outer\">\r\n <!-- Table Card -->\r\n <div class=\"smart-table-wrapper\">\r\n <!-- Top Toolbar -->\r\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\r\n\r\n <!-- Search -->\r\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\r\n <i class=\"fa fa-search\"></i>\r\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\r\n </div>\r\n\r\n <!-- Filters -->\r\n <div class=\"st-filters\" *ngIf=\"config.filters\">\r\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\r\n <!-- Trigger -->\r\n <div class=\"st-filter-trigger\"\r\n [class.active]=\"openFilterKey === filter.key\"\r\n [class.has-value]=\"isFilterActive(filter)\"\r\n (click)=\"toggleFilter(filter.key, $event)\">\r\n <span class=\"st-filter-trigger-label\">{{ getFilterDisplay(filter) }}</span>\r\n <svg class=\"st-filter-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2.5 4.5L6 8L9.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Top Bar Buttons -->\r\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\r\n <lib-button *ngFor=\"let btn of config.topBarButtons\"\r\n [variant]=\"btn.btnVariant || 'primary'\"\r\n [icon]=\"btn.icon || ''\"\r\n (click)=\"onTopAction(btn)\">\r\n {{ btn.label }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Selection count strip \u2014 visible whenever selectable is enabled -->\r\n <div class=\"st-selection-strip\" *ngIf=\"config.selectable\">\r\n <span class=\"st-selection-count\">{{ selectedRows.length }} of {{ totalItems > 0 ? totalItems : data.length }} selected</span>\r\n </div>\r\n\r\n <!-- Table Container -->\r\n <div class=\"st-table-container\">\r\n <div class=\"st-check-loader\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n <table class=\"st-table\" [class.loading-data]=\"loading\" [class.is-selectable]=\"config.selectable\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\r\n </th>\r\n <th *ngFor=\"let col of config.columns; let colIndex = index\"\r\n #stickyHeader\r\n [class.sortable]=\"col.sortable\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n (click)=\"onSort(col)\">\r\n {{ col.label }}\r\n <span *ngIf=\"col.sortable\" class=\"sort-icon-wrap\">\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <!-- Down arrow \u2014 RIGHT side, prominent when DESC -->\r\n <path d=\"M11.258 15.8153L14.5913 13.2699C14.7483 13.15 14.8364 12.9875 14.8364 12.818C14.8364 12.6486 14.7483 12.4861 14.5913 12.3662C14.4344 12.2464 14.2216 12.1791 13.9997 12.1791C13.7778 12.1791 13.5649 12.2464 13.408 12.3662L11.4997 13.8299V2.63636C11.4997 2.46758 11.4119 2.30572 11.2556 2.18638C11.0993 2.06704 10.8874 2 10.6663 2C10.4453 2 10.2334 2.06704 10.0771 2.18638C9.92081 2.30572 9.83301 2.46758 9.83301 2.63636V15.3635C9.83383 15.4891 9.88333 15.6117 9.97528 15.7159C10.0672 15.8201 10.1975 15.9012 10.3497 15.9489C10.4486 15.9845 10.557 16.002 10.6663 15.9998C10.776 16.0003 10.8847 15.9843 10.9863 15.9526C11.0878 15.9209 11.1801 15.8743 11.258 15.8153Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getDescOpacity(col.key)\"/>\r\n <!-- Up arrow \u2014 LEFT side, prominent when ASC -->\r\n <path d=\"M7.33316 16C7.11215 16 6.90019 15.933 6.74391 15.8136C6.58763 15.6942 6.49983 15.5324 6.49983 15.3636V4.16902L4.5915 5.63278C4.43458 5.75262 4.22175 5.81995 3.99983 5.81995C3.77791 5.81995 3.56508 5.75262 3.40816 5.63278C3.25124 5.51294 3.16309 5.3504 3.16309 5.18093C3.16309 5.01145 3.25124 4.84891 3.40816 4.72907L6.7415 2.18341C6.85868 2.0951 7.00749 2.03528 7.16915 2.01149C7.33081 1.98771 7.49807 2.00102 7.64983 2.04976C7.80201 2.0975 7.93228 2.17858 8.02423 2.28278C8.11617 2.38697 8.16567 2.50962 8.1665 2.63526V15.3636C8.1665 15.5324 8.0787 15.6942 7.92242 15.8136C7.76614 15.933 7.55418 16 7.33316 16Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getAscOpacity(col.key)\"/>\r\n </svg>\r\n </span>\r\n </th>\r\n <th *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-actions-col\">\r\n {{ config.labels?.actionColumnHeader || 'Actions' }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of data; let rowIndex = index\" [class.editing-row]=\"row.isEditing\" [ngClass]=\"row.isEditing && config.editingRowClass ? config.editingRowClass : ''\">\r\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\r\n </td>\r\n <td *ngFor=\"let col of config.columns; let colIndex = index\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n [class.clickable-cell]=\"col.clickAction\"\r\n (click)=\"onColumnClick(row, col)\">\r\n <!-- READ MODE -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <!-- Text/Number/Date -->\r\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n <!-- HTML -->\r\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col) | safeHtml\"></div>\r\n <!-- Badge -->\r\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n </ng-container>\r\n\r\n <!-- EDIT/ADD MODE -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <!-- Multi-field cell (stacked inputs) -->\r\n <div *ngIf=\"col.subFields\" class=\"st-stacked-inputs\">\r\n <ng-container *ngFor=\"let sub of col.subFields\">\r\n <select *ngIf=\"sub.dataType === 'select'\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of sub.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"sub.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"subPicker\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\"\r\n (click)=\"subPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"subPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #subPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"sub.dataType !== 'select' && sub.dataType !== 'date'\"\r\n [type]=\"sub.dataType\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\">\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Single field cell input -->\r\n <div *ngIf=\"!col.subFields\">\r\n <select *ngIf=\"col.dataType === 'select'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of col.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"col.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"colPicker\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\"\r\n (click)=\"colPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"colPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #colPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"col.dataType !== 'select' && col.dataType !== 'date'\"\r\n [type]=\"col.dataType || 'text'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\">\r\n </div>\r\n </ng-container>\r\n </td>\r\n\r\n <!-- Row Actions -->\r\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions st-actions-col\">\r\n <div class=\"action-buttons\">\r\n <!-- EDIT MODE ACTIONS -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <div class=\"edit-mode-actions\">\r\n <lib-button variant=\"outline\" (click)=\"onCancelRow(row, rowIndex); $event.stopPropagation()\">\r\n {{ config.labels?.cancelLabel || 'Cancel' }}\r\n </lib-button>\r\n <lib-button [variant]=\"row.isNew ? (config.labels?.addButtonVariant || 'danger') : (config.labels?.saveButtonVariant || 'primary')\" (click)=\"onSaveRow(row); $event.stopPropagation()\">\r\n {{ row.isNew ? (config.labels?.addLabel || 'Add') : (config.labels?.saveLabel || 'Save') }}\r\n </lib-button>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- READ MODE ACTIONS -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <ng-container *ngFor=\"let action of config.actions; let i = index\">\r\n <ng-container *ngIf=\"action.type === 'dropdown'\">\r\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-btn\"\r\n [class.active]=\"openDropdownId === (rowIndex + '-' + i)\"\r\n (click)=\"toggleDropdown(rowIndex + '-' + i, $event, action.items, row)\">\r\n <span class=\"action-circle\">\r\n <i class=\"fa fa-ellipsis-h\"></i>\r\n </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\r\n <lib-button\r\n [variant]=\"action.btnVariant || 'secondary'\"\r\n [icon]=\"action.icon || ''\"\r\n (click)=\"onAction(action, row)\">\r\n {{ action.label }}\r\n </lib-button>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"data.length === 0 && !loading\">\r\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\r\n {{ config.labels?.noDataMessage || 'No data available' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Pagination \u2014 inside the card, sticks to the bottom -->\r\n <div class=\"st-pagination\" *ngIf=\"showPagination\">\r\n <lib-pagination\r\n [totalItems]=\"totalItems\"\r\n [itemsPerPage]=\"config.pagination!.pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [pageSizeOptions]=\"config.pagination!.pageSizeOptions\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n\r\n <!-- Built-in Delete Confirmation Modal -->\r\n <cc-confirmation-modal\r\n [isOpen]=\"deleteModalOpen\"\r\n [config]=\"deleteModalConfig\"\r\n (confirm)=\"onDeleteConfirm()\"\r\n (cancel)=\"onDeleteCancel()\"\r\n (close)=\"onDeleteCancel()\">\r\n <p>{{ deleteModalMessage }}</p>\r\n </cc-confirmation-modal>\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Filter panel portal \u2014 position:fixed keeps it above all overflow/sticky containers.\r\n-->\r\n<div class=\"st-filter-panel\"\r\n *ngIf=\"openFilterKey !== null && activeFilterData\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: filterPosition.top + 'px',\r\n left: filterPosition.left + 'px',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"st-filter-option\"\r\n [class.selected]=\"!isFilterActive(activeFilterData)\"\r\n (click)=\"selectFilterOption(activeFilterData, null)\">\r\n All {{ activeFilterData.label }}\r\n </div>\r\n <div class=\"st-filter-option\"\r\n *ngFor=\"let opt of getValidFilterOptions(activeFilterData)\"\r\n [class.selected]=\"activeFilters[activeFilterData.key] === opt.value\"\r\n (click)=\"selectFilterOption(activeFilterData, opt)\">\r\n {{ opt.label }}\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Dropdown portal \u2014 rendered OUTSIDE every scroll/sticky container.\r\n position:fixed + z-index:99999 here is unconditionally above all sticky table cells.\r\n-->\r\n<div class=\"st-dropdown-menu st-dropdown-portal\"\r\n *ngIf=\"openDropdownId !== null && activeDropdownItems\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: dropdownPosition.top + 'px',\r\n right: dropdownPosition.right + 'px',\r\n left: 'auto',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-item\"\r\n *ngFor=\"let item of activeDropdownItems\"\r\n (click)=\"onActionItemClick(item, activeDropdownRow, $event); closeDropdown()\">\r\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.smart-table-outer{display:flex;flex-direction:column;gap:0}.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 8px rgba(0, 0, 0, .08));display:flex;flex-direction:column;gap:0;padding:0;border:none;margin-bottom:1.5rem}.st-toolbar{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1.2rem 0rem);background:var(--st-toolbar-bg, #fff);gap:var(--st-toolbar-gap, 1rem);border-bottom:var(--st-toolbar-border-bottom, 1px solid rgba(0, 0, 0, .08));box-shadow:#959da533 0 8px 24px}.st-toolbar .st-search{position:relative;display:flex;align-items:center;background:var(--st-search-bg, #f5f5f5);border-radius:var(--st-search-radius, 8px);padding:var(--st-search-wrapper-padding, 0 .875rem);height:var(--st-search-height, 36px);min-width:var(--st-search-min-width, 200px);width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:0 .5rem 0 1.5rem;border:none;background:transparent;font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333);outline:none;line-height:var(--st-search-height, 36px)}.st-toolbar .st-search input::placeholder{color:var(--st-search-placeholder-color, #999)}.st-toolbar .st-search i{position:absolute;left:.875rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #888);font-size:13px;pointer-events:none}.st-toolbar .st-filters{display:flex;align-items:center;gap:.5rem}.st-toolbar .st-filters .st-filter-item{position:relative}.st-toolbar .st-filters .st-filter-trigger{display:flex;align-items:center;gap:6px;padding:var(--st-filter-trigger-padding, 0 .75rem);height:var(--st-filter-height, 36px);border:var(--st-filter-border, 1px solid #e0e0e0);border-radius:var(--st-filter-radius, 8px);cursor:pointer;font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #555);background:var(--st-filter-bg, #fff);transition:border-color .15s,background .15s;white-space:nowrap;-webkit-user-select:none;user-select:none}.st-toolbar .st-filters .st-filter-trigger:hover{border-color:var(--st-filter-hover-border-color, #bbb);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active{border-color:var(--st-filter-active-border-color, #999);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active .st-filter-chevron{transform:rotate(180deg)}.st-toolbar .st-filters .st-filter-trigger.has-value{color:var(--st-filter-selected-color, #222);font-weight:500;border-color:var(--st-filter-selected-border-color, #333)}.st-toolbar .st-filters .st-filter-trigger .st-filter-trigger-label{flex:1}.st-toolbar .st-filters .st-filter-trigger .st-filter-chevron{color:var(--st-filter-chevron-color, #999);flex-shrink:0;transition:transform .15s ease}.st-toolbar .st-actions{display:flex;gap:.5rem;margin-left:auto}.st-filter-panel{min-width:var(--st-filter-panel-min-width, 180px);background:var(--st-filter-panel-bg, #fff);border:var(--st-filter-panel-border, 1px solid #ebebeb);border-radius:var(--st-filter-panel-radius, 12px);box-shadow:var(--st-filter-panel-shadow, 0 8px 28px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06));padding:var(--st-filter-panel-padding, 6px)}.st-filter-option{display:flex;align-items:center;padding:var(--st-filter-option-padding, 8px 12px);margin-bottom:.3rem;border-radius:var(--st-filter-option-radius, 7px);font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #333);cursor:pointer;transition:background .1s;white-space:nowrap}.st-filter-option:hover{background:var(--st-filter-option-hover-bg, #f5f5f5)}.st-filter-option.selected{background:var(--st-filter-option-selected-bg, #f0f0f0);font-weight:500;color:var(--st-filter-option-selected-color, #111)}.st-table-container{overflow-x:auto;overflow-y:visible;padding:0}.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, #f5f5f5);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, #f5f5f5)}.st-table-container table thead th{padding:.4rem 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-top:none;border-bottom:none;white-space:nowrap}.st-table-container table thead th:first-child{border-top-left-radius:var(--st-border-radius, 8px)}.st-table-container table thead th:last-child{border-top-right-radius:var(--st-border-radius, 8px)}.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.st-checkbox-col{width:40px;background:var(--st-header-bg, #f5f5f5);position:sticky;left:0;z-index:3}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-header-bg, #f5f5f5);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:4}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:.5rem 1rem;color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee);font-weight:400}.st-table-container table tbody tr td.st-checkbox-col{position:sticky;left:0;z-index:2}.st-table-container table tbody tr td.first-data-col{color:var(--st-text-color, #333);font-weight:500}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr td.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-frozen-col-bg, #f9f9f9);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:2}.st-table-container table tbody tr:last-child td{border-bottom:none}.st-table-container table tbody tr:last-child td:first-child{border-bottom-left-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:last-child td:last-child{border-bottom-right-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:hover td{font-weight:500;background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table tbody tr:hover td.first-data-col{color:var(--st-first-col-color, #E84646)}.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-cell{cursor:pointer;transition:background .2s}.st-table-container table.is-selectable tbody td.first-data-col,.st-table-container table.is-selectable tbody td.first-data-col.sticky-col{background:var(--st-row-bg, #fff)}.st-table-container table.is-selectable tbody tr:hover td.first-data-col,.st-table-container table.is-selectable tbody tr:hover td.first-data-col.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table.is-selectable tbody tr.selected td.first-data-col{background:var(--st-row-selected-bg, #f3e5f5)}.sort-icon-wrap{display:inline-flex;align-items:center;vertical-align:middle;flex-shrink:0;margin-left:4px;position:relative;top:-3px}.sort-icon-wrap svg{display:block}.st-selection-strip{display:flex;align-items:center;padding:var(--st-selection-strip-padding, .45rem 1rem);background:var(--st-selection-strip-bg, #fafafa);border-bottom:var(--st-selection-strip-border, 1px solid rgba(0, 0, 0, .08))}.st-selection-strip .st-selection-count{font-size:var(--st-selection-count-font-size, 13px);color:var(--st-selection-count-color, #444);font-weight:var(--st-selection-count-font-weight, 500)}input[type=checkbox]{accent-color:var(--st-checkbox-color, #e63e30);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;justify-content:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}.st-dropdown-btn:hover .action-circle{background:#0000000f}.action-circle{display:inline-flex;align-items:center;justify-content:center;width:var(--st-action-circle-size, 32px);height:var(--st-action-circle-size, 32px);border-radius:50%;background:var(--st-table-bg, #fff);border:none;color:var(--st-text-color, #555);font-size:1rem;transition:background .15s}.st-dropdown-menu{min-width:var(--st-dropdown-min-width, 150px);background:var(--st-dropdown-bg, #fff);border:var(--st-dropdown-border, 1px solid #e0e0e0);border-radius:var(--st-dropdown-radius, 8px);box-shadow:var(--st-dropdown-shadow, 0 8px 24px rgba(0, 0, 0, .12));z-index:9999;display:flex;flex-direction:column;padding:var(--st-dropdown-padding, 4px);margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:var(--st-dropdown-item-padding, 8px 12px);border-radius:var(--st-dropdown-item-radius, 6px);text-align:left;cursor:pointer;display:flex;align-items:center;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);transition:background .15s}.st-dropdown-item:hover{background:var(--st-dropdown-item-hover-bg, #f5f5f5)}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, .6rem 1rem);border-top:1px solid rgba(0,0,0,.07);background:var(--st-table-bg, #fff);border-bottom-left-radius:var(--st-border-radius, 8px);border-bottom-right-radius:var(--st-border-radius, 8px)}@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{font-size:13px}}.st-table-container{position:relative}.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)}}.st-stacked-inputs{display:flex;flex-direction:column;gap:.35rem;width:100%}.st-cell-input,.st-cell-select{width:100%;box-sizing:border-box;padding:.35rem .5rem;font-family:inherit;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);background-color:var(--st-cell-input-bg, #fcfcfc);border:var(--st-cell-input-border, 1px solid #dee2e6);border-radius:var(--st-border-radius, 8px);outline:none;transition:border-color .15s,box-shadow .15s}.st-cell-input:focus,.st-cell-select:focus{border-color:var(--st-cell-input-focus-outline-color, #00bcd4)}.st-cell-input:disabled,.st-cell-select:disabled{background-color:#f1f3f5;color:#6c757d;cursor:not-allowed;border-color:#dee2e6}.edit-mode-actions{display:flex;gap:.5rem;align-items:center;justify-content:center;white-space:nowrap}.st-date-cell{display:flex;align-items:center;gap:.25rem;width:100%}.st-date-cell .st-cell-input{flex:1;min-width:0}.st-date-cell mat-datepicker-toggle{flex-shrink:0}.st-date-cell mat-datepicker-toggle ::ng-deep .mat-mdc-icon-button{width:28px;height:28px;padding:2px;color:var(--st-text-color, #333)}\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$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.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$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.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"] }, { 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: ConfirmationModalComponent, selector: "cc-confirmation-modal", inputs: ["config", "isOpen", "confirmDisabled", "confirmLoading"], outputs: ["confirm", "cancel", "close", "showCodeSnippet"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] });
|
|
11397
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SmartTableComponent, isStandalone: false, selector: "lib-smart-table", inputs: { config: "config", tableData: "tableData", totalItemsCount: "totalItemsCount", selectedRows: "selectedRows" }, outputs: { action: "action", topAction: "topAction", filterChange: "filterChange", rowSelect: "rowSelect", columnClick: "columnClick", sortChange: "sortChange", pageChange: "pageChange", searchChange: "searchChange", rowSave: "rowSave" }, host: { listeners: { "document:click": "closeDropdown()" } }, viewQueries: [{ propertyName: "stickyHeaders", predicate: ["stickyHeader"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"smart-table-outer\">\r\n <!-- Table Card -->\r\n <div class=\"smart-table-wrapper\">\r\n <!-- Top Toolbar -->\r\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\r\n\r\n <!-- Search -->\r\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\r\n <i class=\"fa fa-search\"></i>\r\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\r\n </div>\r\n\r\n <!-- Filters -->\r\n <div class=\"st-filters\" *ngIf=\"config.filters\">\r\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\r\n <!-- Trigger -->\r\n <div class=\"st-filter-trigger\"\r\n [class.active]=\"openFilterKey === filter.key\"\r\n [class.has-value]=\"isFilterActive(filter)\"\r\n (click)=\"toggleFilter(filter.key, $event)\">\r\n <span class=\"st-filter-trigger-label\">{{ getFilterDisplay(filter) }}</span>\r\n <svg class=\"st-filter-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2.5 4.5L6 8L9.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Top Bar Buttons -->\r\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\r\n <lib-button *ngFor=\"let btn of config.topBarButtons\"\r\n [variant]=\"btn.btnVariant || 'primary'\"\r\n [icon]=\"btn.icon || ''\"\r\n (click)=\"onTopAction(btn)\">\r\n {{ btn.label }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Selection count strip \u2014 visible whenever selectable is enabled -->\r\n <div class=\"st-selection-strip\" *ngIf=\"config.selectable\">\r\n <span class=\"st-selection-count\">{{ selectedRows.length }} of {{ totalItems > 0 ? totalItems : data.length }} selected</span>\r\n </div>\r\n\r\n <!-- Table Container -->\r\n <div class=\"st-table-container\">\r\n <div class=\"st-check-loader\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n <table class=\"st-table\" [class.loading-data]=\"loading\" [class.is-selectable]=\"config.selectable\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\r\n </th>\r\n <th *ngFor=\"let col of config.columns; let colIndex = index\"\r\n #stickyHeader\r\n [class.sortable]=\"col.sortable\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n (click)=\"onSort(col)\">\r\n {{ col.label }}\r\n <span *ngIf=\"col.sortable\" class=\"sort-icon-wrap\">\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <!-- Down arrow \u2014 RIGHT side, prominent when DESC -->\r\n <path d=\"M11.258 15.8153L14.5913 13.2699C14.7483 13.15 14.8364 12.9875 14.8364 12.818C14.8364 12.6486 14.7483 12.4861 14.5913 12.3662C14.4344 12.2464 14.2216 12.1791 13.9997 12.1791C13.7778 12.1791 13.5649 12.2464 13.408 12.3662L11.4997 13.8299V2.63636C11.4997 2.46758 11.4119 2.30572 11.2556 2.18638C11.0993 2.06704 10.8874 2 10.6663 2C10.4453 2 10.2334 2.06704 10.0771 2.18638C9.92081 2.30572 9.83301 2.46758 9.83301 2.63636V15.3635C9.83383 15.4891 9.88333 15.6117 9.97528 15.7159C10.0672 15.8201 10.1975 15.9012 10.3497 15.9489C10.4486 15.9845 10.557 16.002 10.6663 15.9998C10.776 16.0003 10.8847 15.9843 10.9863 15.9526C11.0878 15.9209 11.1801 15.8743 11.258 15.8153Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getDescOpacity(col.key)\"/>\r\n <!-- Up arrow \u2014 LEFT side, prominent when ASC -->\r\n <path d=\"M7.33316 16C7.11215 16 6.90019 15.933 6.74391 15.8136C6.58763 15.6942 6.49983 15.5324 6.49983 15.3636V4.16902L4.5915 5.63278C4.43458 5.75262 4.22175 5.81995 3.99983 5.81995C3.77791 5.81995 3.56508 5.75262 3.40816 5.63278C3.25124 5.51294 3.16309 5.3504 3.16309 5.18093C3.16309 5.01145 3.25124 4.84891 3.40816 4.72907L6.7415 2.18341C6.85868 2.0951 7.00749 2.03528 7.16915 2.01149C7.33081 1.98771 7.49807 2.00102 7.64983 2.04976C7.80201 2.0975 7.93228 2.17858 8.02423 2.28278C8.11617 2.38697 8.16567 2.50962 8.1665 2.63526V15.3636C8.1665 15.5324 8.0787 15.6942 7.92242 15.8136C7.76614 15.933 7.55418 16 7.33316 16Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getAscOpacity(col.key)\"/>\r\n </svg>\r\n </span>\r\n </th>\r\n <th *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-actions-col\">\r\n {{ config.labels?.actionColumnHeader || 'Actions' }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of data; let rowIndex = index\" [class.editing-row]=\"row.isEditing\" [ngClass]=\"row.isEditing && config.editingRowClass ? config.editingRowClass : ''\">\r\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\r\n </td>\r\n <td *ngFor=\"let col of config.columns; let colIndex = index\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n [class.clickable-cell]=\"col.clickAction\"\r\n (click)=\"onColumnClick(row, col)\">\r\n <!-- READ MODE -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <!-- Text/Number/Date -->\r\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n <!-- HTML -->\r\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col) | safeHtml\"></div>\r\n <!-- Badge -->\r\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n </ng-container>\r\n\r\n <!-- EDIT/ADD MODE -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <!-- Multi-field cell (stacked inputs) -->\r\n <div *ngIf=\"col.subFields\" class=\"st-stacked-inputs\">\r\n <ng-container *ngFor=\"let sub of col.subFields\">\r\n <select *ngIf=\"sub.dataType === 'select'\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of sub.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"sub.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"subPicker\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\"\r\n (click)=\"subPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"subPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #subPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"sub.dataType !== 'select' && sub.dataType !== 'date'\"\r\n [type]=\"sub.dataType\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\">\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Single field cell input -->\r\n <div *ngIf=\"!col.subFields\">\r\n <select *ngIf=\"col.dataType === 'select'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of col.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"col.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"colPicker\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\"\r\n (click)=\"colPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"colPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #colPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"col.dataType !== 'select' && col.dataType !== 'date'\"\r\n [type]=\"col.dataType || 'text'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\">\r\n </div>\r\n </ng-container>\r\n </td>\r\n\r\n <!-- Row Actions -->\r\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions st-actions-col\">\r\n <div class=\"action-buttons\">\r\n <!-- EDIT MODE ACTIONS -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <div class=\"edit-mode-actions\">\r\n <lib-button variant=\"outline\" (click)=\"onCancelRow(row, rowIndex); $event.stopPropagation()\">\r\n {{ config.labels?.cancelLabel || 'Cancel' }}\r\n </lib-button>\r\n <lib-button [variant]=\"row.isNew ? (config.labels?.addButtonVariant || 'danger') : (config.labels?.saveButtonVariant || 'primary')\" (click)=\"onSaveRow(row); $event.stopPropagation()\">\r\n {{ row.isNew ? (config.labels?.addLabel || 'Add') : (config.labels?.saveLabel || 'Save') }}\r\n </lib-button>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- READ MODE ACTIONS -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <ng-container *ngFor=\"let action of config.actions; let i = index\">\r\n <ng-container *ngIf=\"action.type === 'dropdown'\">\r\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-btn\"\r\n [class.active]=\"openDropdownId === (rowIndex + '-' + i)\"\r\n (click)=\"toggleDropdown(rowIndex + '-' + i, $event, action.items, row)\">\r\n <span class=\"action-circle\">\r\n <i class=\"fa fa-ellipsis-h\"></i>\r\n </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\r\n <lib-button\r\n [variant]=\"action.btnVariant || 'secondary'\"\r\n [icon]=\"action.icon || ''\"\r\n (click)=\"onAction(action, row)\">\r\n {{ action.label }}\r\n </lib-button>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"data.length === 0 && !loading\">\r\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\r\n {{ config.labels?.noDataMessage || 'No data available' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Pagination \u2014 inside the card, sticks to the bottom -->\r\n <div class=\"st-pagination\" *ngIf=\"showPagination\">\r\n <lib-pagination\r\n [totalItems]=\"totalItems\"\r\n [itemsPerPage]=\"config.pagination!.pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [pageSizeOptions]=\"config.pagination!.pageSizeOptions\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n\r\n <!-- Built-in Delete Confirmation Modal -->\r\n <cc-confirmation-modal\r\n [isOpen]=\"deleteModalOpen\"\r\n [config]=\"deleteModalConfig\"\r\n (confirm)=\"onDeleteConfirm()\"\r\n (cancel)=\"onDeleteCancel()\"\r\n (close)=\"onDeleteCancel()\">\r\n <p>{{ deleteModalMessage }}</p>\r\n </cc-confirmation-modal>\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Filter panel portal \u2014 position:fixed keeps it above all overflow/sticky containers.\r\n-->\r\n<div class=\"st-filter-panel\"\r\n *ngIf=\"openFilterKey !== null && activeFilterData\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: filterPosition.top + 'px',\r\n left: filterPosition.left + 'px',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"st-filter-option\"\r\n [class.selected]=\"!isFilterActive(activeFilterData)\"\r\n (click)=\"selectFilterOption(activeFilterData, null)\">\r\n All {{ activeFilterData.label }}\r\n </div>\r\n <div class=\"st-filter-option\"\r\n *ngFor=\"let opt of getValidFilterOptions(activeFilterData)\"\r\n [class.selected]=\"activeFilters[activeFilterData.key] === opt.value\"\r\n (click)=\"selectFilterOption(activeFilterData, opt)\">\r\n {{ opt.label }}\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Dropdown portal \u2014 rendered OUTSIDE every scroll/sticky container.\r\n position:fixed + z-index:99999 here is unconditionally above all sticky table cells.\r\n-->\r\n<div class=\"st-dropdown-menu st-dropdown-portal\"\r\n *ngIf=\"openDropdownId !== null && activeDropdownItems\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: dropdownPosition.top + 'px',\r\n right: dropdownPosition.right + 'px',\r\n left: 'auto',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-item\"\r\n *ngFor=\"let item of activeDropdownItems\"\r\n (click)=\"onActionItemClick(item, activeDropdownRow, $event); closeDropdown()\">\r\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.smart-table-outer{display:flex;flex-direction:column;gap:0}.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 8px rgba(0, 0, 0, .08));display:flex;flex-direction:column;gap:0;padding:0;border:none;margin-bottom:1.5rem}.st-toolbar{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1.2rem 0rem);background:var(--st-toolbar-bg, #fff);gap:var(--st-toolbar-gap, 1rem);border-bottom:var(--st-toolbar-border-bottom, 1px solid rgba(0, 0, 0, .08));box-shadow:#959da533 0 8px 24px}.st-toolbar .st-search{position:relative;display:flex;align-items:center;background:var(--st-search-bg, #f5f5f5);border-radius:var(--st-search-radius, 8px);padding:var(--st-search-wrapper-padding, 0 .875rem);height:var(--st-search-height, 36px);min-width:var(--st-search-min-width, 200px);width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:0 .5rem 0 1.5rem;border:none;background:transparent;font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333);outline:none;line-height:var(--st-search-height, 36px)}.st-toolbar .st-search input::placeholder{color:var(--st-search-placeholder-color, #999)}.st-toolbar .st-search i{position:absolute;left:.875rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #888);font-size:13px;pointer-events:none}.st-toolbar .st-filters{display:flex;align-items:center;gap:.5rem}.st-toolbar .st-filters .st-filter-item{position:relative}.st-toolbar .st-filters .st-filter-trigger{display:flex;align-items:center;gap:6px;padding:var(--st-filter-trigger-padding, 0 .75rem);height:var(--st-filter-height, 36px);border:var(--st-filter-border, 1px solid #e0e0e0);border-radius:var(--st-filter-radius, 8px);cursor:pointer;font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #555);background:var(--st-filter-bg, #fff);transition:border-color .15s,background .15s;white-space:nowrap;-webkit-user-select:none;user-select:none}.st-toolbar .st-filters .st-filter-trigger:hover{border-color:var(--st-filter-hover-border-color, #bbb);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active{border-color:var(--st-filter-active-border-color, #999);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active .st-filter-chevron{transform:rotate(180deg)}.st-toolbar .st-filters .st-filter-trigger.has-value{color:var(--st-filter-selected-color, #222);font-weight:500;border-color:var(--st-filter-selected-border-color, #333)}.st-toolbar .st-filters .st-filter-trigger .st-filter-trigger-label{flex:1}.st-toolbar .st-filters .st-filter-trigger .st-filter-chevron{color:var(--st-filter-chevron-color, #999);flex-shrink:0;transition:transform .15s ease}.st-toolbar .st-actions{display:flex;gap:.5rem;margin-left:auto}.st-filter-panel{min-width:var(--st-filter-panel-min-width, 180px);background:var(--st-filter-panel-bg, #fff);border:var(--st-filter-panel-border, 1px solid #ebebeb);border-radius:var(--st-filter-panel-radius, 12px);box-shadow:var(--st-filter-panel-shadow, 0 8px 28px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06));padding:var(--st-filter-panel-padding, 6px)}.st-filter-option{display:flex;align-items:center;padding:var(--st-filter-option-padding, 8px 12px);margin-bottom:.3rem;border-radius:var(--st-filter-option-radius, 7px);font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #333);cursor:pointer;transition:background .1s;white-space:nowrap}.st-filter-option:hover{background:var(--st-filter-option-hover-bg, #f5f5f5)}.st-filter-option.selected{background:var(--st-filter-option-selected-bg, #f0f0f0);font-weight:500;color:var(--st-filter-option-selected-color, #111)}.st-table-container{overflow-x:auto;overflow-y:visible;padding:0}.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, #f5f5f5);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, #f5f5f5)}.st-table-container table thead th{padding:.4rem 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-top:none;border-bottom:none;white-space:nowrap}.st-table-container table thead th:first-child{border-top-left-radius:var(--st-border-radius, 8px)}.st-table-container table thead th:last-child{border-top-right-radius:var(--st-border-radius, 8px)}.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.st-checkbox-col{width:40px;background:var(--st-header-bg, #f5f5f5);position:sticky;left:0;z-index:3}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-header-bg, #f5f5f5);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:4}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:.5rem 1rem;color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee);font-weight:400}.st-table-container table tbody tr td.st-checkbox-col{position:sticky;left:0;z-index:2}.st-table-container table tbody tr td.first-data-col{color:var(--st-text-color, #333);font-weight:500}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr td.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-frozen-col-bg, #f9f9f9);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:2}.st-table-container table tbody tr:last-child td{border-bottom:none}.st-table-container table tbody tr:last-child td:first-child{border-bottom-left-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:last-child td:last-child{border-bottom-right-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:hover td{font-weight:500;background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table tbody tr:hover td.first-data-col{color:var(--st-first-col-color, #E84646)}.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-cell{cursor:pointer;transition:background .2s}.st-table-container table.is-selectable tbody td.first-data-col,.st-table-container table.is-selectable tbody td.first-data-col.sticky-col{background:var(--st-row-bg, #fff)}.st-table-container table.is-selectable tbody tr:hover td.first-data-col,.st-table-container table.is-selectable tbody tr:hover td.first-data-col.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table.is-selectable tbody tr.selected td.first-data-col{background:var(--st-row-selected-bg, #f3e5f5)}.sort-icon-wrap{display:inline-flex;align-items:center;vertical-align:middle;flex-shrink:0;margin-left:4px;position:relative;top:-3px}.sort-icon-wrap svg{display:block}.st-selection-strip{display:flex;align-items:center;padding:var(--st-selection-strip-padding, .45rem 1rem);background:var(--st-selection-strip-bg, #fafafa);border-bottom:var(--st-selection-strip-border, 1px solid rgba(0, 0, 0, .08))}.st-selection-strip .st-selection-count{font-size:var(--st-selection-count-font-size, 13px);color:var(--st-selection-count-color, #444);font-weight:var(--st-selection-count-font-weight, 500)}input[type=checkbox]{accent-color:var(--st-checkbox-color, #e63e30);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;justify-content:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}.st-dropdown-btn:hover .action-circle{background:#0000000f}.action-circle{display:inline-flex;align-items:center;justify-content:center;width:var(--st-action-circle-size, 32px);height:var(--st-action-circle-size, 32px);border-radius:50%;background:var(--st-table-bg, #fff);border:none;color:var(--st-text-color, #555);font-size:1rem;transition:background .15s}.st-dropdown-menu{min-width:var(--st-dropdown-min-width, 150px);background:var(--st-dropdown-bg, #fff);border:var(--st-dropdown-border, 1px solid #e0e0e0);border-radius:var(--st-dropdown-radius, 8px);box-shadow:var(--st-dropdown-shadow, 0 8px 24px rgba(0, 0, 0, .12));z-index:9999;display:flex;flex-direction:column;padding:var(--st-dropdown-padding, 4px);margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:var(--st-dropdown-item-padding, 8px 12px);border-radius:var(--st-dropdown-item-radius, 6px);text-align:left;cursor:pointer;display:flex;align-items:center;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);transition:background .15s}.st-dropdown-item:hover{background:var(--st-dropdown-item-hover-bg, #f5f5f5)}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, .6rem 1rem);border-top:1px solid rgba(0,0,0,.07);background:var(--st-table-bg, #fff);border-bottom-left-radius:var(--st-border-radius, 8px);border-bottom-right-radius:var(--st-border-radius, 8px)}@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{font-size:13px}}.st-table-container{position:relative}.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)}}.st-stacked-inputs{display:flex;flex-direction:column;gap:.35rem;width:100%}.st-cell-input,.st-cell-select{width:100%;box-sizing:border-box;padding:.35rem .5rem;font-family:inherit;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);background-color:var(--st-cell-input-bg, #fcfcfc);border:var(--st-cell-input-border, 1px solid #dee2e6);border-radius:var(--st-border-radius, 8px);outline:none;transition:border-color .15s,box-shadow .15s}.st-cell-input:focus,.st-cell-select:focus{border-color:var(--st-cell-input-focus-outline-color, #00bcd4)}.st-cell-input:disabled,.st-cell-select:disabled{background-color:#f1f3f5;color:#6c757d;cursor:not-allowed;border-color:#dee2e6}.edit-mode-actions{display:flex;gap:.5rem;align-items:center;justify-content:center;white-space:nowrap}.st-date-cell{display:flex;align-items:center;gap:.25rem;width:100%}.st-date-cell .st-cell-input{flex:1;min-width:0}.st-date-cell mat-datepicker-toggle{flex-shrink:0}.st-date-cell mat-datepicker-toggle ::ng-deep .mat-mdc-icon-button{width:28px;height:28px;padding:2px;color:var(--st-text-color, #333)}\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$3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$3.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$3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.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"] }, { 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: ConfirmationModalComponent, selector: "cc-confirmation-modal", inputs: ["config", "isOpen", "confirmDisabled", "confirmLoading"], outputs: ["confirm", "cancel", "close", "showCodeSnippet"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }] });
|
|
11258
11398
|
}
|
|
11259
11399
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SmartTableComponent, decorators: [{
|
|
11260
11400
|
type: Component,
|
|
11261
|
-
args: [{ selector: 'lib-smart-table', standalone: false, template: "<div class=\"smart-table-outer\">\r\n <!-- Table Card -->\r\n <div class=\"smart-table-wrapper\">\r\n <!-- Top Toolbar -->\r\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\r\n\r\n <!-- Search -->\r\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\r\n <i class=\"fa fa-search\"></i>\r\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\r\n </div>\r\n\r\n <!-- Filters -->\r\n <div class=\"st-filters\" *ngIf=\"config.filters\">\r\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\r\n <!-- Trigger -->\r\n <div class=\"st-filter-trigger\"\r\n [class.active]=\"openFilterKey === filter.key\"\r\n [class.has-value]=\"isFilterActive(filter)\"\r\n (click)=\"toggleFilter(filter.key, $event)\">\r\n <span class=\"st-filter-trigger-label\">{{ getFilterDisplay(filter) }}</span>\r\n <svg class=\"st-filter-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2.5 4.5L6 8L9.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Top Bar Buttons -->\r\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\r\n <lib-button *ngFor=\"let btn of config.topBarButtons\"\r\n [variant]=\"btn.btnVariant || 'primary'\"\r\n [icon]=\"btn.icon || ''\"\r\n (click)=\"onTopAction(btn)\">\r\n {{ btn.label }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Selection count strip \u2014 visible whenever selectable is enabled -->\r\n <div class=\"st-selection-strip\" *ngIf=\"config.selectable\">\r\n <span class=\"st-selection-count\">{{ selectedRows.length }} of {{ totalItems > 0 ? totalItems : data.length }} selected</span>\r\n </div>\r\n\r\n <!-- Table Container -->\r\n <div class=\"st-table-container\">\r\n <div class=\"st-check-loader\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n <table class=\"st-table\" [class.loading-data]=\"loading\" [class.is-selectable]=\"config.selectable\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\r\n </th>\r\n <th *ngFor=\"let col of config.columns; let colIndex = index\"\r\n #stickyHeader\r\n [class.sortable]=\"col.sortable\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n (click)=\"onSort(col)\">\r\n {{ col.label }}\r\n <span *ngIf=\"col.sortable\" class=\"sort-icon-wrap\">\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <!-- Down arrow \u2014 RIGHT side, prominent when DESC -->\r\n <path d=\"M11.258 15.8153L14.5913 13.2699C14.7483 13.15 14.8364 12.9875 14.8364 12.818C14.8364 12.6486 14.7483 12.4861 14.5913 12.3662C14.4344 12.2464 14.2216 12.1791 13.9997 12.1791C13.7778 12.1791 13.5649 12.2464 13.408 12.3662L11.4997 13.8299V2.63636C11.4997 2.46758 11.4119 2.30572 11.2556 2.18638C11.0993 2.06704 10.8874 2 10.6663 2C10.4453 2 10.2334 2.06704 10.0771 2.18638C9.92081 2.30572 9.83301 2.46758 9.83301 2.63636V15.3635C9.83383 15.4891 9.88333 15.6117 9.97528 15.7159C10.0672 15.8201 10.1975 15.9012 10.3497 15.9489C10.4486 15.9845 10.557 16.002 10.6663 15.9998C10.776 16.0003 10.8847 15.9843 10.9863 15.9526C11.0878 15.9209 11.1801 15.8743 11.258 15.8153Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getDescOpacity(col.key)\"/>\r\n <!-- Up arrow \u2014 LEFT side, prominent when ASC -->\r\n <path d=\"M7.33316 16C7.11215 16 6.90019 15.933 6.74391 15.8136C6.58763 15.6942 6.49983 15.5324 6.49983 15.3636V4.16902L4.5915 5.63278C4.43458 5.75262 4.22175 5.81995 3.99983 5.81995C3.77791 5.81995 3.56508 5.75262 3.40816 5.63278C3.25124 5.51294 3.16309 5.3504 3.16309 5.18093C3.16309 5.01145 3.25124 4.84891 3.40816 4.72907L6.7415 2.18341C6.85868 2.0951 7.00749 2.03528 7.16915 2.01149C7.33081 1.98771 7.49807 2.00102 7.64983 2.04976C7.80201 2.0975 7.93228 2.17858 8.02423 2.28278C8.11617 2.38697 8.16567 2.50962 8.1665 2.63526V15.3636C8.1665 15.5324 8.0787 15.6942 7.92242 15.8136C7.76614 15.933 7.55418 16 7.33316 16Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getAscOpacity(col.key)\"/>\r\n </svg>\r\n </span>\r\n </th>\r\n <th *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-actions-col\">\r\n {{ config.labels?.actionColumnHeader || 'Actions' }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of data; let rowIndex = index\" [class.editing-row]=\"row.isEditing\" [ngClass]=\"row.isEditing && config.editingRowClass ? config.editingRowClass : ''\">\r\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\r\n </td>\r\n <td *ngFor=\"let col of config.columns; let colIndex = index\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n [class.clickable-cell]=\"col.clickAction\"\r\n (click)=\"onColumnClick(row, col)\">\r\n <!-- READ MODE -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <!-- Text/Number/Date -->\r\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n <!-- HTML -->\r\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col) | safeHtml\"></div>\r\n <!-- Badge -->\r\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n </ng-container>\r\n\r\n <!-- EDIT/ADD MODE -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <!-- Multi-field cell (stacked inputs) -->\r\n <div *ngIf=\"col.subFields\" class=\"st-stacked-inputs\">\r\n <ng-container *ngFor=\"let sub of col.subFields\">\r\n <select *ngIf=\"sub.dataType === 'select'\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of sub.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"sub.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"subPicker\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\"\r\n (click)=\"subPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"subPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #subPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"sub.dataType !== 'select' && sub.dataType !== 'date'\"\r\n [type]=\"sub.dataType\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\">\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Single field cell input -->\r\n <div *ngIf=\"!col.subFields\">\r\n <select *ngIf=\"col.dataType === 'select'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of col.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"col.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"colPicker\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\"\r\n (click)=\"colPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"colPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #colPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"col.dataType !== 'select' && col.dataType !== 'date'\"\r\n [type]=\"col.dataType || 'text'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\">\r\n </div>\r\n </ng-container>\r\n </td>\r\n\r\n <!-- Row Actions -->\r\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions st-actions-col\">\r\n <div class=\"action-buttons\">\r\n <!-- EDIT MODE ACTIONS -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <div class=\"edit-mode-actions\">\r\n <lib-button variant=\"outline\" (click)=\"onCancelRow(row, rowIndex); $event.stopPropagation()\">\r\n {{ config.labels?.cancelLabel || 'Cancel' }}\r\n </lib-button>\r\n <lib-button [variant]=\"row.isNew ? (config.labels?.addButtonVariant || 'danger') : (config.labels?.saveButtonVariant || 'primary')\" (click)=\"onSaveRow(row); $event.stopPropagation()\">\r\n {{ row.isNew ? (config.labels?.addLabel || 'Add') : (config.labels?.saveLabel || 'Save') }}\r\n </lib-button>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- READ MODE ACTIONS -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <ng-container *ngFor=\"let action of config.actions; let i = index\">\r\n <ng-container *ngIf=\"action.type === 'dropdown'\">\r\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-btn\"\r\n [class.active]=\"openDropdownId === (rowIndex + '-' + i)\"\r\n (click)=\"toggleDropdown(rowIndex + '-' + i, $event, action.items, row)\">\r\n <span class=\"action-circle\">\r\n <i class=\"fa fa-ellipsis-h\"></i>\r\n </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\r\n <lib-button\r\n [variant]=\"action.btnVariant || 'secondary'\"\r\n [icon]=\"action.icon || ''\"\r\n (click)=\"onAction(action, row)\">\r\n {{ action.label }}\r\n </lib-button>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"data.length === 0 && !loading\">\r\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\r\n {{ config.labels?.noDataMessage || 'No data available' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Pagination \u2014 inside the card, sticks to the bottom -->\r\n <div class=\"st-pagination\" *ngIf=\"showPagination\">\r\n <lib-pagination\r\n [totalItems]=\"totalItems\"\r\n [itemsPerPage]=\"config.pagination!.pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [pageSizeOptions]=\"config.pagination!.pageSizeOptions\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n\r\n <!-- Built-in Delete Confirmation Modal -->\r\n <cc-confirmation-modal\r\n [isOpen]=\"deleteModalOpen\"\r\n [config]=\"deleteModalConfig\"\r\n (confirm)=\"onDeleteConfirm()\"\r\n (cancel)=\"onDeleteCancel()\"\r\n (close)=\"onDeleteCancel()\">\r\n <p>{{ deleteModalMessage }}</p>\r\n </cc-confirmation-modal>\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Filter panel portal \u2014 position:fixed keeps it above all overflow/sticky containers.\r\n-->\r\n<div class=\"st-filter-panel\"\r\n *ngIf=\"openFilterKey !== null && activeFilterData\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: filterPosition.top + 'px',\r\n left: filterPosition.left + 'px',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"st-filter-option\"\r\n [class.selected]=\"!isFilterActive(activeFilterData)\"\r\n (click)=\"selectFilterOption(activeFilterData, null)\">\r\n All {{ activeFilterData.label }}\r\n </div>\r\n <div class=\"st-filter-option\"\r\n *ngFor=\"let opt of getValidFilterOptions(activeFilterData)\"\r\n [class.selected]=\"activeFilters[activeFilterData.key] === opt.value\"\r\n (click)=\"selectFilterOption(activeFilterData, opt)\">\r\n {{ opt.label }}\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Dropdown portal \u2014 rendered OUTSIDE every scroll/sticky container.\r\n position:fixed + z-index:99999 here is unconditionally above all sticky table cells.\r\n-->\r\n<div class=\"st-dropdown-menu st-dropdown-portal\"\r\n *ngIf=\"openDropdownId !== null && activeDropdownItems\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: dropdownPosition.top + 'px',\r\n right: dropdownPosition.right + 'px',\r\n left: 'auto',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-item\"\r\n *ngFor=\"let item of activeDropdownItems\"\r\n (click)=\"onActionItemClick(item, activeDropdownRow, $event); closeDropdown()\">\r\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.smart-table-outer{display:flex;flex-direction:column;gap:0}.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 8px rgba(0, 0, 0, .08));display:flex;flex-direction:column;gap:0;padding:0;border:none;margin-bottom:1.5rem}.st-toolbar{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1.2rem 0rem);background:var(--st-toolbar-bg, #fff);gap:var(--st-toolbar-gap, 1rem);border-bottom:var(--st-toolbar-border-bottom, 1px solid rgba(0, 0, 0, .08));box-shadow:#959da533 0 8px 24px}.st-toolbar .st-search{position:relative;display:flex;align-items:center;background:var(--st-search-bg, #f5f5f5);border-radius:var(--st-search-radius, 8px);padding:var(--st-search-wrapper-padding, 0 .875rem);height:var(--st-search-height, 36px);min-width:var(--st-search-min-width, 200px);width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:0 .5rem 0 1.5rem;border:none;background:transparent;font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333);outline:none;line-height:var(--st-search-height, 36px)}.st-toolbar .st-search input::placeholder{color:var(--st-search-placeholder-color, #999)}.st-toolbar .st-search i{position:absolute;left:.875rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #888);font-size:13px;pointer-events:none}.st-toolbar .st-filters{display:flex;align-items:center;gap:.5rem}.st-toolbar .st-filters .st-filter-item{position:relative}.st-toolbar .st-filters .st-filter-trigger{display:flex;align-items:center;gap:6px;padding:var(--st-filter-trigger-padding, 0 .75rem);height:var(--st-filter-height, 36px);border:var(--st-filter-border, 1px solid #e0e0e0);border-radius:var(--st-filter-radius, 8px);cursor:pointer;font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #555);background:var(--st-filter-bg, #fff);transition:border-color .15s,background .15s;white-space:nowrap;-webkit-user-select:none;user-select:none}.st-toolbar .st-filters .st-filter-trigger:hover{border-color:var(--st-filter-hover-border-color, #bbb);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active{border-color:var(--st-filter-active-border-color, #999);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active .st-filter-chevron{transform:rotate(180deg)}.st-toolbar .st-filters .st-filter-trigger.has-value{color:var(--st-filter-selected-color, #222);font-weight:500;border-color:var(--st-filter-selected-border-color, #333)}.st-toolbar .st-filters .st-filter-trigger .st-filter-trigger-label{flex:1}.st-toolbar .st-filters .st-filter-trigger .st-filter-chevron{color:var(--st-filter-chevron-color, #999);flex-shrink:0;transition:transform .15s ease}.st-toolbar .st-actions{display:flex;gap:.5rem;margin-left:auto}.st-filter-panel{min-width:var(--st-filter-panel-min-width, 180px);background:var(--st-filter-panel-bg, #fff);border:var(--st-filter-panel-border, 1px solid #ebebeb);border-radius:var(--st-filter-panel-radius, 12px);box-shadow:var(--st-filter-panel-shadow, 0 8px 28px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06));padding:var(--st-filter-panel-padding, 6px)}.st-filter-option{display:flex;align-items:center;padding:var(--st-filter-option-padding, 8px 12px);margin-bottom:.3rem;border-radius:var(--st-filter-option-radius, 7px);font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #333);cursor:pointer;transition:background .1s;white-space:nowrap}.st-filter-option:hover{background:var(--st-filter-option-hover-bg, #f5f5f5)}.st-filter-option.selected{background:var(--st-filter-option-selected-bg, #f0f0f0);font-weight:500;color:var(--st-filter-option-selected-color, #111)}.st-table-container{overflow-x:auto;overflow-y:visible;padding:0}.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, #f5f5f5);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, #f5f5f5)}.st-table-container table thead th{padding:.4rem 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-top:none;border-bottom:none;white-space:nowrap}.st-table-container table thead th:first-child{border-top-left-radius:var(--st-border-radius, 8px)}.st-table-container table thead th:last-child{border-top-right-radius:var(--st-border-radius, 8px)}.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.st-checkbox-col{width:40px;background:var(--st-header-bg, #f5f5f5);position:sticky;left:0;z-index:3}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-header-bg, #f5f5f5);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:4}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:.5rem 1rem;color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee);font-weight:400}.st-table-container table tbody tr td.st-checkbox-col{position:sticky;left:0;z-index:2}.st-table-container table tbody tr td.first-data-col{color:var(--st-text-color, #333);font-weight:500}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr td.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-frozen-col-bg, #f9f9f9);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:2}.st-table-container table tbody tr:last-child td{border-bottom:none}.st-table-container table tbody tr:last-child td:first-child{border-bottom-left-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:last-child td:last-child{border-bottom-right-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:hover td{font-weight:500;background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table tbody tr:hover td.first-data-col{color:var(--st-first-col-color, #E84646)}.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-cell{cursor:pointer;transition:background .2s}.st-table-container table.is-selectable tbody td.first-data-col,.st-table-container table.is-selectable tbody td.first-data-col.sticky-col{background:var(--st-row-bg, #fff)}.st-table-container table.is-selectable tbody tr:hover td.first-data-col,.st-table-container table.is-selectable tbody tr:hover td.first-data-col.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table.is-selectable tbody tr.selected td.first-data-col{background:var(--st-row-selected-bg, #f3e5f5)}.sort-icon-wrap{display:inline-flex;align-items:center;vertical-align:middle;flex-shrink:0;margin-left:4px;position:relative;top:-3px}.sort-icon-wrap svg{display:block}.st-selection-strip{display:flex;align-items:center;padding:var(--st-selection-strip-padding, .45rem 1rem);background:var(--st-selection-strip-bg, #fafafa);border-bottom:var(--st-selection-strip-border, 1px solid rgba(0, 0, 0, .08))}.st-selection-strip .st-selection-count{font-size:var(--st-selection-count-font-size, 13px);color:var(--st-selection-count-color, #444);font-weight:var(--st-selection-count-font-weight, 500)}input[type=checkbox]{accent-color:var(--st-checkbox-color, #e63e30);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;justify-content:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}.st-dropdown-btn:hover .action-circle{background:#0000000f}.action-circle{display:inline-flex;align-items:center;justify-content:center;width:var(--st-action-circle-size, 32px);height:var(--st-action-circle-size, 32px);border-radius:50%;background:var(--st-table-bg, #fff);border:none;color:var(--st-text-color, #555);font-size:1rem;transition:background .15s}.st-dropdown-menu{min-width:var(--st-dropdown-min-width, 150px);background:var(--st-dropdown-bg, #fff);border:var(--st-dropdown-border, 1px solid #e0e0e0);border-radius:var(--st-dropdown-radius, 8px);box-shadow:var(--st-dropdown-shadow, 0 8px 24px rgba(0, 0, 0, .12));z-index:9999;display:flex;flex-direction:column;padding:var(--st-dropdown-padding, 4px);margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:var(--st-dropdown-item-padding, 8px 12px);border-radius:var(--st-dropdown-item-radius, 6px);text-align:left;cursor:pointer;display:flex;align-items:center;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);transition:background .15s}.st-dropdown-item:hover{background:var(--st-dropdown-item-hover-bg, #f5f5f5)}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, .6rem 1rem);border-top:1px solid rgba(0,0,0,.07);background:var(--st-table-bg, #fff);border-bottom-left-radius:var(--st-border-radius, 8px);border-bottom-right-radius:var(--st-border-radius, 8px)}@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{font-size:13px}}.st-table-container{position:relative}.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)}}.st-stacked-inputs{display:flex;flex-direction:column;gap:.35rem;width:100%}.st-cell-input,.st-cell-select{width:100%;box-sizing:border-box;padding:.35rem .5rem;font-family:inherit;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);background-color:var(--st-cell-input-bg, #fcfcfc);border:var(--st-cell-input-border, 1px solid #dee2e6);border-radius:var(--st-border-radius, 8px);outline:none;transition:border-color .15s,box-shadow .15s}.st-cell-input:focus,.st-cell-select:focus{border-color:var(--st-cell-input-focus-outline-color, #00bcd4)}.st-cell-input:disabled,.st-cell-select:disabled{background-color:#f1f3f5;color:#6c757d;cursor:not-allowed;border-color:#dee2e6}.edit-mode-actions{display:flex;gap:.5rem;align-items:center;justify-content:center;white-space:nowrap}.st-date-cell{display:flex;align-items:center;gap:.25rem;width:100%}.st-date-cell .st-cell-input{flex:1;min-width:0}.st-date-cell mat-datepicker-toggle{flex-shrink:0}.st-date-cell mat-datepicker-toggle ::ng-deep .mat-mdc-icon-button{width:28px;height:28px;padding:2px;color:var(--st-text-color, #333)}\n"] }]
|
|
11401
|
+
args: [{ selector: 'lib-smart-table', standalone: false, template: "<div class=\"smart-table-outer\">\r\n <!-- Table Card -->\r\n <div class=\"smart-table-wrapper\">\r\n <!-- Top Toolbar -->\r\n <div class=\"st-toolbar\" *ngIf=\"config.searchConfig?.enabled || (config.filters && config.filters.length > 0) || (config.topBarButtons && config.topBarButtons.length > 0)\">\r\n\r\n <!-- Search -->\r\n <div class=\"st-search\" *ngIf=\"config.searchConfig?.enabled\">\r\n <i class=\"fa fa-search\"></i>\r\n <input type=\"text\" [placeholder]=\"config.labels?.searchPlaceholder || 'Search'\" (input)=\"onSearch($event)\">\r\n </div>\r\n\r\n <!-- Filters -->\r\n <div class=\"st-filters\" *ngIf=\"config.filters\">\r\n <div class=\"st-filter-item\" *ngFor=\"let filter of config.filters\">\r\n <!-- Trigger -->\r\n <div class=\"st-filter-trigger\"\r\n [class.active]=\"openFilterKey === filter.key\"\r\n [class.has-value]=\"isFilterActive(filter)\"\r\n (click)=\"toggleFilter(filter.key, $event)\">\r\n <span class=\"st-filter-trigger-label\">{{ getFilterDisplay(filter) }}</span>\r\n <svg class=\"st-filter-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2.5 4.5L6 8L9.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Top Bar Buttons -->\r\n <div class=\"st-actions\" *ngIf=\"config.topBarButtons\">\r\n <lib-button *ngFor=\"let btn of config.topBarButtons\"\r\n [variant]=\"btn.btnVariant || 'primary'\"\r\n [icon]=\"btn.icon || ''\"\r\n (click)=\"onTopAction(btn)\">\r\n {{ btn.label }}\r\n </lib-button>\r\n </div>\r\n </div>\r\n\r\n <!-- Selection count strip \u2014 visible whenever selectable is enabled -->\r\n <div class=\"st-selection-strip\" *ngIf=\"config.selectable\">\r\n <span class=\"st-selection-count\">{{ selectedRows.length }} of {{ totalItems > 0 ? totalItems : data.length }} selected</span>\r\n </div>\r\n\r\n <!-- Table Container -->\r\n <div class=\"st-table-container\">\r\n <div class=\"st-check-loader\" *ngIf=\"loading\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n <table class=\"st-table\" [class.loading-data]=\"loading\" [class.is-selectable]=\"config.selectable\">\r\n <thead>\r\n <tr>\r\n <th *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" (change)=\"onSelectAll($event)\">\r\n </th>\r\n <th *ngFor=\"let col of config.columns; let colIndex = index\"\r\n #stickyHeader\r\n [class.sortable]=\"col.sortable\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n (click)=\"onSort(col)\">\r\n {{ col.label }}\r\n <span *ngIf=\"col.sortable\" class=\"sort-icon-wrap\">\r\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <!-- Down arrow \u2014 RIGHT side, prominent when DESC -->\r\n <path d=\"M11.258 15.8153L14.5913 13.2699C14.7483 13.15 14.8364 12.9875 14.8364 12.818C14.8364 12.6486 14.7483 12.4861 14.5913 12.3662C14.4344 12.2464 14.2216 12.1791 13.9997 12.1791C13.7778 12.1791 13.5649 12.2464 13.408 12.3662L11.4997 13.8299V2.63636C11.4997 2.46758 11.4119 2.30572 11.2556 2.18638C11.0993 2.06704 10.8874 2 10.6663 2C10.4453 2 10.2334 2.06704 10.0771 2.18638C9.92081 2.30572 9.83301 2.46758 9.83301 2.63636V15.3635C9.83383 15.4891 9.88333 15.6117 9.97528 15.7159C10.0672 15.8201 10.1975 15.9012 10.3497 15.9489C10.4486 15.9845 10.557 16.002 10.6663 15.9998C10.776 16.0003 10.8847 15.9843 10.9863 15.9526C11.0878 15.9209 11.1801 15.8743 11.258 15.8153Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getDescOpacity(col.key)\"/>\r\n <!-- Up arrow \u2014 LEFT side, prominent when ASC -->\r\n <path d=\"M7.33316 16C7.11215 16 6.90019 15.933 6.74391 15.8136C6.58763 15.6942 6.49983 15.5324 6.49983 15.3636V4.16902L4.5915 5.63278C4.43458 5.75262 4.22175 5.81995 3.99983 5.81995C3.77791 5.81995 3.56508 5.75262 3.40816 5.63278C3.25124 5.51294 3.16309 5.3504 3.16309 5.18093C3.16309 5.01145 3.25124 4.84891 3.40816 4.72907L6.7415 2.18341C6.85868 2.0951 7.00749 2.03528 7.16915 2.01149C7.33081 1.98771 7.49807 2.00102 7.64983 2.04976C7.80201 2.0975 7.93228 2.17858 8.02423 2.28278C8.11617 2.38697 8.16567 2.50962 8.1665 2.63526V15.3636C8.1665 15.5324 8.0787 15.6942 7.92242 15.8136C7.76614 15.933 7.55418 16 7.33316 16Z\"\r\n fill=\"black\" [attr.fill-opacity]=\"getAscOpacity(col.key)\"/>\r\n </svg>\r\n </span>\r\n </th>\r\n <th *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-actions-col\">\r\n {{ config.labels?.actionColumnHeader || 'Actions' }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let row of data; let rowIndex = index\" [class.editing-row]=\"row.isEditing\" [ngClass]=\"row.isEditing && config.editingRowClass ? config.editingRowClass : ''\">\r\n <td *ngIf=\"config.selectable\" class=\"st-checkbox-col\">\r\n <input type=\"checkbox\" [(ngModel)]=\"row.selected\" (change)=\"onRowSelect(row)\">\r\n </td>\r\n <td *ngFor=\"let col of config.columns; let colIndex = index\"\r\n [class.sticky-col]=\"col.sticky\"\r\n [class.first-data-col]=\"colIndex === 0\"\r\n [ngStyle]=\"stickyColumnStyles[col.key]\"\r\n [class.clickable-cell]=\"col.clickAction\"\r\n (click)=\"onColumnClick(row, col)\">\r\n <!-- READ MODE -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <!-- Text/Number/Date -->\r\n <span *ngIf=\"col.type !== 'custom' && col.type !== 'html' && col.type !== 'badge'\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n <!-- HTML -->\r\n <div *ngIf=\"col.type === 'html'\" [innerHTML]=\"getCellValue(row, col) | safeHtml\"></div>\r\n <!-- Badge -->\r\n <span *ngIf=\"col.type === 'badge'\" class=\"st-badge\" [ngClass]=\"getBadgeClass(row, col)\">\r\n {{ getCellValue(row, col) }}\r\n </span>\r\n </ng-container>\r\n\r\n <!-- EDIT/ADD MODE -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <!-- Multi-field cell (stacked inputs) -->\r\n <div *ngIf=\"col.subFields\" class=\"st-stacked-inputs\">\r\n <ng-container *ngFor=\"let sub of col.subFields\">\r\n <select *ngIf=\"sub.dataType === 'select'\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of sub.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"sub.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"subPicker\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\"\r\n (click)=\"subPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"subPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #subPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"sub.dataType !== 'select' && sub.dataType !== 'date'\"\r\n [type]=\"sub.dataType\"\r\n [(ngModel)]=\"row[sub.key]\"\r\n [disabled]=\"sub.editable === false || col.editConfig?.disabled\"\r\n [placeholder]=\"sub.placeholder || ''\"\r\n class=\"st-cell-input\">\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Single field cell input -->\r\n <div *ngIf=\"!col.subFields\">\r\n <select *ngIf=\"col.dataType === 'select'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-select\">\r\n <option *ngFor=\"let opt of col.options\" [value]=\"opt.value\">{{ opt.label }}</option>\r\n </select>\r\n <!-- Date picker -->\r\n <div *ngIf=\"col.dataType === 'date'\" class=\"st-date-cell\">\r\n <input matInput [matDatepicker]=\"colPicker\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\"\r\n (click)=\"colPicker.open()\">\r\n <mat-datepicker-toggle [for]=\"colPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #colPicker></mat-datepicker>\r\n </div>\r\n <input *ngIf=\"col.dataType !== 'select' && col.dataType !== 'date'\"\r\n [type]=\"col.dataType || 'text'\"\r\n [(ngModel)]=\"row[col.key]\"\r\n [disabled]=\"col.editable === false || col.editConfig?.disabled\"\r\n class=\"st-cell-input\">\r\n </div>\r\n </ng-container>\r\n </td>\r\n\r\n <!-- Row Actions -->\r\n <td *ngIf=\"config.actions && config.actions.length > 0\" class=\"st-row-actions st-actions-col\">\r\n <div class=\"action-buttons\">\r\n <!-- EDIT MODE ACTIONS -->\r\n <ng-container *ngIf=\"row.isEditing\">\r\n <div class=\"edit-mode-actions\">\r\n <lib-button variant=\"outline\" (click)=\"onCancelRow(row, rowIndex); $event.stopPropagation()\">\r\n {{ config.labels?.cancelLabel || 'Cancel' }}\r\n </lib-button>\r\n <lib-button [variant]=\"row.isNew ? (config.labels?.addButtonVariant || 'danger') : (config.labels?.saveButtonVariant || 'primary')\" (click)=\"onSaveRow(row); $event.stopPropagation()\">\r\n {{ row.isNew ? (config.labels?.addLabel || 'Add') : (config.labels?.saveLabel || 'Save') }}\r\n </lib-button>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- READ MODE ACTIONS -->\r\n <ng-container *ngIf=\"!row.isEditing\">\r\n <ng-container *ngFor=\"let action of config.actions; let i = index\">\r\n <ng-container *ngIf=\"action.type === 'dropdown'\">\r\n <div class=\"st-dropdown-container\" (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-btn\"\r\n [class.active]=\"openDropdownId === (rowIndex + '-' + i)\"\r\n (click)=\"toggleDropdown(rowIndex + '-' + i, $event, action.items, row)\">\r\n <span class=\"action-circle\">\r\n <i class=\"fa fa-ellipsis-h\"></i>\r\n </span>\r\n </button>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"action.type !== 'dropdown'\">\r\n <lib-button\r\n [variant]=\"action.btnVariant || 'secondary'\"\r\n [icon]=\"action.icon || ''\"\r\n (click)=\"onAction(action, row)\">\r\n {{ action.label }}\r\n </lib-button>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"data.length === 0 && !loading\">\r\n <td [attr.colspan]=\"columnCount + (config.selectable ? 1 : 0) + (config.actions ? 1 : 0)\" class=\"no-data\">\r\n {{ config.labels?.noDataMessage || 'No data available' }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Pagination \u2014 inside the card, sticks to the bottom -->\r\n <div class=\"st-pagination\" *ngIf=\"showPagination\">\r\n <lib-pagination\r\n [totalItems]=\"totalItems\"\r\n [itemsPerPage]=\"config.pagination!.pageSize\"\r\n [currentPage]=\"currentPage\"\r\n [pageSizeOptions]=\"config.pagination!.pageSizeOptions\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (itemsPerPageChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n\r\n <!-- Built-in Delete Confirmation Modal -->\r\n <cc-confirmation-modal\r\n [isOpen]=\"deleteModalOpen\"\r\n [config]=\"deleteModalConfig\"\r\n (confirm)=\"onDeleteConfirm()\"\r\n (cancel)=\"onDeleteCancel()\"\r\n (close)=\"onDeleteCancel()\">\r\n <p>{{ deleteModalMessage }}</p>\r\n </cc-confirmation-modal>\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Filter panel portal \u2014 position:fixed keeps it above all overflow/sticky containers.\r\n-->\r\n<div class=\"st-filter-panel\"\r\n *ngIf=\"openFilterKey !== null && activeFilterData\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: filterPosition.top + 'px',\r\n left: filterPosition.left + 'px',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"st-filter-option\"\r\n [class.selected]=\"!isFilterActive(activeFilterData)\"\r\n (click)=\"selectFilterOption(activeFilterData, null)\">\r\n All {{ activeFilterData.label }}\r\n </div>\r\n <div class=\"st-filter-option\"\r\n *ngFor=\"let opt of getValidFilterOptions(activeFilterData)\"\r\n [class.selected]=\"activeFilters[activeFilterData.key] === opt.value\"\r\n (click)=\"selectFilterOption(activeFilterData, opt)\">\r\n {{ opt.label }}\r\n </div>\r\n</div>\r\n\r\n<!--\r\n Dropdown portal \u2014 rendered OUTSIDE every scroll/sticky container.\r\n position:fixed + z-index:99999 here is unconditionally above all sticky table cells.\r\n-->\r\n<div class=\"st-dropdown-menu st-dropdown-portal\"\r\n *ngIf=\"openDropdownId !== null && activeDropdownItems\"\r\n [ngStyle]=\"{\r\n position: 'fixed',\r\n top: dropdownPosition.top + 'px',\r\n right: dropdownPosition.right + 'px',\r\n left: 'auto',\r\n 'z-index': '99999'\r\n }\"\r\n (click)=\"$event.stopPropagation()\">\r\n <button class=\"st-dropdown-item\"\r\n *ngFor=\"let item of activeDropdownItems\"\r\n (click)=\"onActionItemClick(item, activeDropdownRow, $event); closeDropdown()\">\r\n <i *ngIf=\"item.icon\" [class]=\"item.icon + ' st-action-icon'\"></i>\r\n <span>{{ item.label }}</span>\r\n </button>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";.smart-table-outer{display:flex;flex-direction:column;gap:0}.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 8px rgba(0, 0, 0, .08));display:flex;flex-direction:column;gap:0;padding:0;border:none;margin-bottom:1.5rem}.st-toolbar{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap;padding:var(--st-toolbar-padding, 1.2rem 0rem);background:var(--st-toolbar-bg, #fff);gap:var(--st-toolbar-gap, 1rem);border-bottom:var(--st-toolbar-border-bottom, 1px solid rgba(0, 0, 0, .08));box-shadow:#959da533 0 8px 24px}.st-toolbar .st-search{position:relative;display:flex;align-items:center;background:var(--st-search-bg, #f5f5f5);border-radius:var(--st-search-radius, 8px);padding:var(--st-search-wrapper-padding, 0 .875rem);height:var(--st-search-height, 36px);min-width:var(--st-search-min-width, 200px);width:var(--st-search-width, auto)}.st-toolbar .st-search input{padding:0 .5rem 0 1.5rem;border:none;background:transparent;font-size:var(--st-font-size, 14px);width:100%;color:var(--st-text-color, #333);outline:none;line-height:var(--st-search-height, 36px)}.st-toolbar .st-search input::placeholder{color:var(--st-search-placeholder-color, #999)}.st-toolbar .st-search i{position:absolute;left:.875rem;top:50%;transform:translateY(-50%);color:var(--st-search-icon-color, #888);font-size:13px;pointer-events:none}.st-toolbar .st-filters{display:flex;align-items:center;gap:.5rem}.st-toolbar .st-filters .st-filter-item{position:relative}.st-toolbar .st-filters .st-filter-trigger{display:flex;align-items:center;gap:6px;padding:var(--st-filter-trigger-padding, 0 .75rem);height:var(--st-filter-height, 36px);border:var(--st-filter-border, 1px solid #e0e0e0);border-radius:var(--st-filter-radius, 8px);cursor:pointer;font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #555);background:var(--st-filter-bg, #fff);transition:border-color .15s,background .15s;white-space:nowrap;-webkit-user-select:none;user-select:none}.st-toolbar .st-filters .st-filter-trigger:hover{border-color:var(--st-filter-hover-border-color, #bbb);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active{border-color:var(--st-filter-active-border-color, #999);background:var(--st-filter-hover-bg, #fafafa)}.st-toolbar .st-filters .st-filter-trigger.active .st-filter-chevron{transform:rotate(180deg)}.st-toolbar .st-filters .st-filter-trigger.has-value{color:var(--st-filter-selected-color, #222);font-weight:500;border-color:var(--st-filter-selected-border-color, #333)}.st-toolbar .st-filters .st-filter-trigger .st-filter-trigger-label{flex:1}.st-toolbar .st-filters .st-filter-trigger .st-filter-chevron{color:var(--st-filter-chevron-color, #999);flex-shrink:0;transition:transform .15s ease}.st-toolbar .st-actions{display:flex;gap:.5rem;margin-left:auto}.st-filter-panel{min-width:var(--st-filter-panel-min-width, 180px);background:var(--st-filter-panel-bg, #fff);border:var(--st-filter-panel-border, 1px solid #ebebeb);border-radius:var(--st-filter-panel-radius, 12px);box-shadow:var(--st-filter-panel-shadow, 0 8px 28px rgba(0, 0, 0, .12), 0 2px 8px rgba(0, 0, 0, .06));padding:var(--st-filter-panel-padding, 6px)}.st-filter-option{display:flex;align-items:center;padding:var(--st-filter-option-padding, 8px 12px);margin-bottom:.3rem;border-radius:var(--st-filter-option-radius, 7px);font-size:var(--st-filter-font-size, 14px);color:var(--st-filter-color, #333);cursor:pointer;transition:background .1s;white-space:nowrap}.st-filter-option:hover{background:var(--st-filter-option-hover-bg, #f5f5f5)}.st-filter-option.selected{background:var(--st-filter-option-selected-bg, #f0f0f0);font-weight:500;color:var(--st-filter-option-selected-color, #111)}.st-table-container{overflow-x:auto;overflow-y:visible;padding:0}.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, #f5f5f5);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, #f5f5f5)}.st-table-container table thead th{padding:.4rem 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-top:none;border-bottom:none;white-space:nowrap}.st-table-container table thead th:first-child{border-top-left-radius:var(--st-border-radius, 8px)}.st-table-container table thead th:last-child{border-top-right-radius:var(--st-border-radius, 8px)}.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.st-checkbox-col{width:40px;background:var(--st-header-bg, #f5f5f5);position:sticky;left:0;z-index:3}.st-table-container table thead th.sticky-col{position:sticky;z-index:3;background:var(--st-header-bg, #f5f5f5)}.st-table-container table thead th.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-header-bg, #f5f5f5);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:4}.st-table-container table tbody tr{background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td{padding:.5rem 1rem;color:var(--st-text-color, #333);vertical-align:middle;border-bottom:var(--st-row-border, 1px solid #eee);font-weight:400}.st-table-container table tbody tr td.st-checkbox-col{position:sticky;left:0;z-index:2}.st-table-container table tbody tr td.first-data-col{color:var(--st-text-color, #333);font-weight:500}.st-table-container table tbody tr td.sticky-col{position:sticky;z-index:2;background:var(--st-row-bg, #fff)}.st-table-container table tbody tr td.sticky-col:first-child{left:0}.st-table-container table tbody tr td.st-actions-col{width:100px;min-width:100px;max-width:100px;background:var(--st-frozen-col-bg, #f9f9f9);box-shadow:var(--st-actions-col-shadow, -4px 0 8px rgba(0, 0, 0, .06));text-align:center;position:sticky;right:0;z-index:2}.st-table-container table tbody tr:last-child td{border-bottom:none}.st-table-container table tbody tr:last-child td:first-child{border-bottom-left-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:last-child td:last-child{border-bottom-right-radius:var(--st-border-radius, 8px)}.st-table-container table tbody tr:hover td{font-weight:500;background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table tbody tr:hover td.first-data-col{color:var(--st-first-col-color, #E84646)}.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-cell{cursor:pointer;transition:background .2s}.st-table-container table.is-selectable tbody td.first-data-col,.st-table-container table.is-selectable tbody td.first-data-col.sticky-col{background:var(--st-row-bg, #fff)}.st-table-container table.is-selectable tbody tr:hover td.first-data-col,.st-table-container table.is-selectable tbody tr:hover td.first-data-col.sticky-col{background:var(--st-row-hover-bg, #f5f5f5)}.st-table-container table.is-selectable tbody tr.selected td.first-data-col{background:var(--st-row-selected-bg, #f3e5f5)}.sort-icon-wrap{display:inline-flex;align-items:center;vertical-align:middle;flex-shrink:0;margin-left:4px;position:relative;top:-3px}.sort-icon-wrap svg{display:block}.st-selection-strip{display:flex;align-items:center;padding:var(--st-selection-strip-padding, .45rem 1rem);background:var(--st-selection-strip-bg, #fafafa);border-bottom:var(--st-selection-strip-border, 1px solid rgba(0, 0, 0, .08))}.st-selection-strip .st-selection-count{font-size:var(--st-selection-count-font-size, 13px);color:var(--st-selection-count-color, #444);font-weight:var(--st-selection-count-font-weight, 500)}input[type=checkbox]{accent-color:var(--st-checkbox-color, #e63e30);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;justify-content:center}.st-action-icon{margin-right:var(--st-action-icon-margin, 8px)}.st-dropdown-container{position:relative;display:inline-block}.st-dropdown-btn{background:transparent;border:none;cursor:pointer;padding:0;display:flex;align-items:center;justify-content:center}.st-dropdown-btn:hover .action-circle{background:#0000000f}.action-circle{display:inline-flex;align-items:center;justify-content:center;width:var(--st-action-circle-size, 32px);height:var(--st-action-circle-size, 32px);border-radius:50%;background:var(--st-table-bg, #fff);border:none;color:var(--st-text-color, #555);font-size:1rem;transition:background .15s}.st-dropdown-menu{min-width:var(--st-dropdown-min-width, 150px);background:var(--st-dropdown-bg, #fff);border:var(--st-dropdown-border, 1px solid #e0e0e0);border-radius:var(--st-dropdown-radius, 8px);box-shadow:var(--st-dropdown-shadow, 0 8px 24px rgba(0, 0, 0, .12));z-index:9999;display:flex;flex-direction:column;padding:var(--st-dropdown-padding, 4px);margin-top:4px}.st-dropdown-item{background:transparent;border:none;padding:var(--st-dropdown-item-padding, 8px 12px);border-radius:var(--st-dropdown-item-radius, 6px);text-align:left;cursor:pointer;display:flex;align-items:center;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);transition:background .15s}.st-dropdown-item:hover{background:var(--st-dropdown-item-hover-bg, #f5f5f5)}.st-dropdown-item .st-action-icon{margin-right:8px;width:16px;text-align:center}.no-data{padding:2rem;color:var(--st-no-data-color, #888);text-align:center}.st-pagination{padding:var(--st-pagination-padding, .6rem 1rem);border-top:1px solid rgba(0,0,0,.07);background:var(--st-table-bg, #fff);border-bottom-left-radius:var(--st-border-radius, 8px);border-bottom-right-radius:var(--st-border-radius, 8px)}@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{font-size:13px}}.st-table-container{position:relative}.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)}}.st-stacked-inputs{display:flex;flex-direction:column;gap:.35rem;width:100%}.st-cell-input,.st-cell-select{width:100%;box-sizing:border-box;padding:.35rem .5rem;font-family:inherit;font-size:var(--st-font-size, 14px);color:var(--st-text-color, #333);background-color:var(--st-cell-input-bg, #fcfcfc);border:var(--st-cell-input-border, 1px solid #dee2e6);border-radius:var(--st-border-radius, 8px);outline:none;transition:border-color .15s,box-shadow .15s}.st-cell-input:focus,.st-cell-select:focus{border-color:var(--st-cell-input-focus-outline-color, #00bcd4)}.st-cell-input:disabled,.st-cell-select:disabled{background-color:#f1f3f5;color:#6c757d;cursor:not-allowed;border-color:#dee2e6}.edit-mode-actions{display:flex;gap:.5rem;align-items:center;justify-content:center;white-space:nowrap}.st-date-cell{display:flex;align-items:center;gap:.25rem;width:100%}.st-date-cell .st-cell-input{flex:1;min-width:0}.st-date-cell mat-datepicker-toggle{flex-shrink:0}.st-date-cell mat-datepicker-toggle ::ng-deep .mat-mdc-icon-button{width:28px;height:28px;padding:2px;color:var(--st-text-color, #333)}\n"] }]
|
|
11262
11402
|
}], ctorParameters: () => [{ type: i3.HttpClient }, { type: i1$4.Router }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }], propDecorators: { config: [{
|
|
11263
11403
|
type: Input
|
|
11264
11404
|
}], tableData: [{
|
|
@@ -11978,11 +12118,11 @@ class NavComponent {
|
|
|
11978
12118
|
return item.id;
|
|
11979
12119
|
}
|
|
11980
12120
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11981
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: NavComponent, isStandalone: false, selector: "lib-nav", inputs: { items: "items", activeId: "activeId", variant: "variant", orientation: "orientation", styleConfig: "styleConfig" }, outputs: { selectionChange: "selectionChange" }, usesOnChanges: true, ngImport: i0, template: "<nav\r\n class=\"cc-nav\"\r\n [ngClass]=\"[variant, orientation]\"\r\n [ngStyle]=\"computedStyles\"\r\n role=\"tablist\"\r\n [attr.aria-orientation]=\"orientation\">\r\n\r\n <button\r\n *ngFor=\"let item of items; trackBy: trackById\"\r\n class=\"cc-nav-item\"\r\n [class.active]=\"item.id === activeId\"\r\n [class.disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"item.id === activeId\"\r\n [attr.aria-disabled]=\"item.disabled || null\"\r\n (click)=\"onItemClick(item)\">\r\n\r\n <!-- Icon (optional) -->\r\n <span *ngIf=\"item.icon\" class=\"cc-nav-item-icon\">\r\n <i [ngClass]=\"item.icon\"></i>\r\n </span>\r\n\r\n <!-- Label -->\r\n <span class=\"cc-nav-item-label\">{{ item.label }}</span>\r\n\r\n <!-- Badge (optional) -->\r\n <span *ngIf=\"item.badge != null\" class=\"cc-nav-item-badge\">\r\n {{ item.badge }}\r\n </span>\r\n\r\n </button>\r\n\r\n</nav>\r\n", styles: [".cc-nav{display:flex;align-items:center;background-color:var(--cc-nav-container-bg);padding:var(--cc-nav-container-padding);border-radius:var(--cc-nav-container-radius);border:var(--cc-nav-container-border);gap:var(--cc-nav-container-gap);font-family:var(--cc-nav-font-family);font-size:var(--cc-nav-font-size);box-sizing:border-box;width:100%}.cc-nav.horizontal{flex-direction:row;overflow-x:auto;-ms-overflow-style:none;scrollbar-width:none}.cc-nav.horizontal::-webkit-scrollbar{display:none}.cc-nav.vertical{flex-direction:column;align-items:stretch}.cc-nav .cc-nav-item{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-nav-item-padding);border-radius:var(--cc-nav-item-radius);border:var(--cc-nav-item-border);background-color:var(--cc-nav-item-bg);color:var(--cc-nav-item-color);font-family:inherit;font-size:inherit;font-weight:var(--cc-nav-font-weight);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:all .2s ease;position:relative;outline:none;margin-right:.3rem}.cc-nav .cc-nav-item:hover:not(:disabled):not(.active){background-color:var(--cc-nav-item-hover-bg);color:var(--cc-nav-item-hover-color)}.cc-nav .cc-nav-item.active{background-color:var(--cc-nav-item-active-bg);color:var(--cc-nav-item-active-color);font-weight:var(--cc-nav-item-active-font-weight);box-shadow:var(--cc-nav-item-active-shadow)}.cc-nav .cc-nav-item:disabled,.cc-nav .cc-nav-item.disabled{opacity:var(--cc-nav-disabled-opacity);cursor:not-allowed}.cc-nav .cc-nav-item .cc-nav-item-icon{display:inline-flex;align-items:center;font-size:1.1em;line-height:1}.cc-nav .cc-nav-item .cc-nav-item-badge{display:inline-flex;align-items:center;justify-content:center;min-width:var(--cc-nav-badge-size);height:var(--cc-nav-badge-size);border-radius:50%;background-color:var(--cc-nav-badge-bg);color:var(--cc-nav-badge-color);font-size:var(--cc-nav-badge-font-size);font-weight:var(--cc-nav-badge-font-weight, 600);padding:0 4px;line-height:1}.cc-nav.filled .cc-nav-item.active{border-bottom:var(--cc-nav-item-active-border-width) solid var(--cc-nav-item-active-border-color)}.cc-nav.underline{background-color:transparent;border-radius:0;padding:0;border-bottom:1px solid #e0e0e0}.cc-nav.underline .cc-nav-item{background-color:transparent;border-radius:0;border:none;border-bottom:var(--cc-nav-item-active-border-width) solid transparent;box-shadow:none}.cc-nav.underline .cc-nav-item:hover:not(:disabled):not(.active){background-color:transparent;border-bottom-color:#ccc}.cc-nav.underline .cc-nav-item.active{background-color:transparent;border-bottom-color:var(--cc-nav-item-active-border-color);box-shadow:none}.cc-nav.pills{background-color:transparent;padding:0}.cc-nav.pills .cc-nav-item,.cc-nav.pills .cc-nav-item.active{border-radius:999px}@media(max-width:600px){.cc-nav.horizontal{gap:2px}.cc-nav.horizontal .cc-nav-item{padding:6px 12px;font-size:13px}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
12121
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: NavComponent, isStandalone: false, selector: "lib-nav", inputs: { items: "items", activeId: "activeId", variant: "variant", orientation: "orientation", styleConfig: "styleConfig" }, outputs: { selectionChange: "selectionChange" }, usesOnChanges: true, ngImport: i0, template: "<nav\r\n class=\"cc-nav\"\r\n [ngClass]=\"[variant, orientation]\"\r\n [ngStyle]=\"computedStyles\"\r\n role=\"tablist\"\r\n [attr.aria-orientation]=\"orientation\">\r\n\r\n <button\r\n *ngFor=\"let item of items; trackBy: trackById\"\r\n class=\"cc-nav-item\"\r\n [class.active]=\"item.id === activeId\"\r\n [class.disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"item.id === activeId\"\r\n [attr.aria-disabled]=\"item.disabled || null\"\r\n (click)=\"onItemClick(item)\">\r\n\r\n <!-- Icon (optional) -->\r\n <span *ngIf=\"item.icon\" class=\"cc-nav-item-icon\">\r\n <i [ngClass]=\"item.icon\"></i>\r\n </span>\r\n\r\n <!-- Label -->\r\n <span class=\"cc-nav-item-label\">{{ item.label }}</span>\r\n\r\n <!-- Badge (optional) -->\r\n <span *ngIf=\"item.badge != null\" class=\"cc-nav-item-badge\">\r\n {{ item.badge }}\r\n </span>\r\n\r\n </button>\r\n\r\n</nav>\r\n", styles: [".cc-nav{display:flex;align-items:center;background-color:var(--cc-nav-container-bg);padding:var(--cc-nav-container-padding);border-radius:var(--cc-nav-container-radius);border:var(--cc-nav-container-border);gap:var(--cc-nav-container-gap);font-family:var(--cc-nav-font-family);font-size:var(--cc-nav-font-size);box-sizing:border-box;width:100%}.cc-nav.horizontal{flex-direction:row;overflow-x:auto;-ms-overflow-style:none;scrollbar-width:none}.cc-nav.horizontal::-webkit-scrollbar{display:none}.cc-nav.vertical{flex-direction:column;align-items:stretch}.cc-nav .cc-nav-item{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-nav-item-padding);border-radius:var(--cc-nav-item-radius);border:var(--cc-nav-item-border);background-color:var(--cc-nav-item-bg);color:var(--cc-nav-item-color);font-family:inherit;font-size:inherit;font-weight:var(--cc-nav-font-weight);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:all .2s ease;position:relative;outline:none;margin-right:.3rem}.cc-nav .cc-nav-item:hover:not(:disabled):not(.active){background-color:var(--cc-nav-item-hover-bg);color:var(--cc-nav-item-hover-color)}.cc-nav .cc-nav-item.active{background-color:var(--cc-nav-item-active-bg);color:var(--cc-nav-item-active-color);font-weight:var(--cc-nav-item-active-font-weight);box-shadow:var(--cc-nav-item-active-shadow)}.cc-nav .cc-nav-item:disabled,.cc-nav .cc-nav-item.disabled{opacity:var(--cc-nav-disabled-opacity);cursor:not-allowed}.cc-nav .cc-nav-item .cc-nav-item-icon{display:inline-flex;align-items:center;font-size:1.1em;line-height:1}.cc-nav .cc-nav-item .cc-nav-item-badge{display:inline-flex;align-items:center;justify-content:center;min-width:var(--cc-nav-badge-size);height:var(--cc-nav-badge-size);border-radius:50%;background-color:var(--cc-nav-badge-bg);color:var(--cc-nav-badge-color);font-size:var(--cc-nav-badge-font-size);font-weight:var(--cc-nav-badge-font-weight, 600);padding:0 4px;line-height:1}.cc-nav.filled .cc-nav-item.active{border-bottom:var(--cc-nav-item-active-border-width) solid var(--cc-nav-item-active-border-color)}.cc-nav.underline{background-color:transparent;border-radius:0;padding:0;border-bottom:1px solid #e0e0e0}.cc-nav.underline .cc-nav-item{background-color:transparent;border-radius:0;border:none;border-bottom:var(--cc-nav-item-active-border-width) solid transparent;box-shadow:none}.cc-nav.underline .cc-nav-item:hover:not(:disabled):not(.active){background-color:transparent;border-bottom-color:#ccc}.cc-nav.underline .cc-nav-item.active{background-color:transparent;border-bottom-color:var(--cc-nav-item-active-border-color);box-shadow:none}.cc-nav.pills{background-color:transparent;padding:0}.cc-nav.pills .cc-nav-item,.cc-nav.pills .cc-nav-item.active{border-radius:999px}@media (max-width: 600px){.cc-nav.horizontal{gap:2px}.cc-nav.horizontal .cc-nav-item{padding:6px 12px;font-size:13px}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
11982
12122
|
}
|
|
11983
12123
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: NavComponent, decorators: [{
|
|
11984
12124
|
type: Component,
|
|
11985
|
-
args: [{ selector: 'lib-nav', standalone: false, template: "<nav\r\n class=\"cc-nav\"\r\n [ngClass]=\"[variant, orientation]\"\r\n [ngStyle]=\"computedStyles\"\r\n role=\"tablist\"\r\n [attr.aria-orientation]=\"orientation\">\r\n\r\n <button\r\n *ngFor=\"let item of items; trackBy: trackById\"\r\n class=\"cc-nav-item\"\r\n [class.active]=\"item.id === activeId\"\r\n [class.disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"item.id === activeId\"\r\n [attr.aria-disabled]=\"item.disabled || null\"\r\n (click)=\"onItemClick(item)\">\r\n\r\n <!-- Icon (optional) -->\r\n <span *ngIf=\"item.icon\" class=\"cc-nav-item-icon\">\r\n <i [ngClass]=\"item.icon\"></i>\r\n </span>\r\n\r\n <!-- Label -->\r\n <span class=\"cc-nav-item-label\">{{ item.label }}</span>\r\n\r\n <!-- Badge (optional) -->\r\n <span *ngIf=\"item.badge != null\" class=\"cc-nav-item-badge\">\r\n {{ item.badge }}\r\n </span>\r\n\r\n </button>\r\n\r\n</nav>\r\n", styles: [".cc-nav{display:flex;align-items:center;background-color:var(--cc-nav-container-bg);padding:var(--cc-nav-container-padding);border-radius:var(--cc-nav-container-radius);border:var(--cc-nav-container-border);gap:var(--cc-nav-container-gap);font-family:var(--cc-nav-font-family);font-size:var(--cc-nav-font-size);box-sizing:border-box;width:100%}.cc-nav.horizontal{flex-direction:row;overflow-x:auto;-ms-overflow-style:none;scrollbar-width:none}.cc-nav.horizontal::-webkit-scrollbar{display:none}.cc-nav.vertical{flex-direction:column;align-items:stretch}.cc-nav .cc-nav-item{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-nav-item-padding);border-radius:var(--cc-nav-item-radius);border:var(--cc-nav-item-border);background-color:var(--cc-nav-item-bg);color:var(--cc-nav-item-color);font-family:inherit;font-size:inherit;font-weight:var(--cc-nav-font-weight);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:all .2s ease;position:relative;outline:none;margin-right:.3rem}.cc-nav .cc-nav-item:hover:not(:disabled):not(.active){background-color:var(--cc-nav-item-hover-bg);color:var(--cc-nav-item-hover-color)}.cc-nav .cc-nav-item.active{background-color:var(--cc-nav-item-active-bg);color:var(--cc-nav-item-active-color);font-weight:var(--cc-nav-item-active-font-weight);box-shadow:var(--cc-nav-item-active-shadow)}.cc-nav .cc-nav-item:disabled,.cc-nav .cc-nav-item.disabled{opacity:var(--cc-nav-disabled-opacity);cursor:not-allowed}.cc-nav .cc-nav-item .cc-nav-item-icon{display:inline-flex;align-items:center;font-size:1.1em;line-height:1}.cc-nav .cc-nav-item .cc-nav-item-badge{display:inline-flex;align-items:center;justify-content:center;min-width:var(--cc-nav-badge-size);height:var(--cc-nav-badge-size);border-radius:50%;background-color:var(--cc-nav-badge-bg);color:var(--cc-nav-badge-color);font-size:var(--cc-nav-badge-font-size);font-weight:var(--cc-nav-badge-font-weight, 600);padding:0 4px;line-height:1}.cc-nav.filled .cc-nav-item.active{border-bottom:var(--cc-nav-item-active-border-width) solid var(--cc-nav-item-active-border-color)}.cc-nav.underline{background-color:transparent;border-radius:0;padding:0;border-bottom:1px solid #e0e0e0}.cc-nav.underline .cc-nav-item{background-color:transparent;border-radius:0;border:none;border-bottom:var(--cc-nav-item-active-border-width) solid transparent;box-shadow:none}.cc-nav.underline .cc-nav-item:hover:not(:disabled):not(.active){background-color:transparent;border-bottom-color:#ccc}.cc-nav.underline .cc-nav-item.active{background-color:transparent;border-bottom-color:var(--cc-nav-item-active-border-color);box-shadow:none}.cc-nav.pills{background-color:transparent;padding:0}.cc-nav.pills .cc-nav-item,.cc-nav.pills .cc-nav-item.active{border-radius:999px}@media(max-width:600px){.cc-nav.horizontal{gap:2px}.cc-nav.horizontal .cc-nav-item{padding:6px 12px;font-size:13px}}\n"] }]
|
|
12125
|
+
args: [{ selector: 'lib-nav', standalone: false, template: "<nav\r\n class=\"cc-nav\"\r\n [ngClass]=\"[variant, orientation]\"\r\n [ngStyle]=\"computedStyles\"\r\n role=\"tablist\"\r\n [attr.aria-orientation]=\"orientation\">\r\n\r\n <button\r\n *ngFor=\"let item of items; trackBy: trackById\"\r\n class=\"cc-nav-item\"\r\n [class.active]=\"item.id === activeId\"\r\n [class.disabled]=\"item.disabled\"\r\n [disabled]=\"item.disabled\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"item.id === activeId\"\r\n [attr.aria-disabled]=\"item.disabled || null\"\r\n (click)=\"onItemClick(item)\">\r\n\r\n <!-- Icon (optional) -->\r\n <span *ngIf=\"item.icon\" class=\"cc-nav-item-icon\">\r\n <i [ngClass]=\"item.icon\"></i>\r\n </span>\r\n\r\n <!-- Label -->\r\n <span class=\"cc-nav-item-label\">{{ item.label }}</span>\r\n\r\n <!-- Badge (optional) -->\r\n <span *ngIf=\"item.badge != null\" class=\"cc-nav-item-badge\">\r\n {{ item.badge }}\r\n </span>\r\n\r\n </button>\r\n\r\n</nav>\r\n", styles: [".cc-nav{display:flex;align-items:center;background-color:var(--cc-nav-container-bg);padding:var(--cc-nav-container-padding);border-radius:var(--cc-nav-container-radius);border:var(--cc-nav-container-border);gap:var(--cc-nav-container-gap);font-family:var(--cc-nav-font-family);font-size:var(--cc-nav-font-size);box-sizing:border-box;width:100%}.cc-nav.horizontal{flex-direction:row;overflow-x:auto;-ms-overflow-style:none;scrollbar-width:none}.cc-nav.horizontal::-webkit-scrollbar{display:none}.cc-nav.vertical{flex-direction:column;align-items:stretch}.cc-nav .cc-nav-item{display:inline-flex;align-items:center;gap:6px;padding:var(--cc-nav-item-padding);border-radius:var(--cc-nav-item-radius);border:var(--cc-nav-item-border);background-color:var(--cc-nav-item-bg);color:var(--cc-nav-item-color);font-family:inherit;font-size:inherit;font-weight:var(--cc-nav-font-weight);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:all .2s ease;position:relative;outline:none;margin-right:.3rem}.cc-nav .cc-nav-item:hover:not(:disabled):not(.active){background-color:var(--cc-nav-item-hover-bg);color:var(--cc-nav-item-hover-color)}.cc-nav .cc-nav-item.active{background-color:var(--cc-nav-item-active-bg);color:var(--cc-nav-item-active-color);font-weight:var(--cc-nav-item-active-font-weight);box-shadow:var(--cc-nav-item-active-shadow)}.cc-nav .cc-nav-item:disabled,.cc-nav .cc-nav-item.disabled{opacity:var(--cc-nav-disabled-opacity);cursor:not-allowed}.cc-nav .cc-nav-item .cc-nav-item-icon{display:inline-flex;align-items:center;font-size:1.1em;line-height:1}.cc-nav .cc-nav-item .cc-nav-item-badge{display:inline-flex;align-items:center;justify-content:center;min-width:var(--cc-nav-badge-size);height:var(--cc-nav-badge-size);border-radius:50%;background-color:var(--cc-nav-badge-bg);color:var(--cc-nav-badge-color);font-size:var(--cc-nav-badge-font-size);font-weight:var(--cc-nav-badge-font-weight, 600);padding:0 4px;line-height:1}.cc-nav.filled .cc-nav-item.active{border-bottom:var(--cc-nav-item-active-border-width) solid var(--cc-nav-item-active-border-color)}.cc-nav.underline{background-color:transparent;border-radius:0;padding:0;border-bottom:1px solid #e0e0e0}.cc-nav.underline .cc-nav-item{background-color:transparent;border-radius:0;border:none;border-bottom:var(--cc-nav-item-active-border-width) solid transparent;box-shadow:none}.cc-nav.underline .cc-nav-item:hover:not(:disabled):not(.active){background-color:transparent;border-bottom-color:#ccc}.cc-nav.underline .cc-nav-item.active{background-color:transparent;border-bottom-color:var(--cc-nav-item-active-border-color);box-shadow:none}.cc-nav.pills{background-color:transparent;padding:0}.cc-nav.pills .cc-nav-item,.cc-nav.pills .cc-nav-item.active{border-radius:999px}@media (max-width: 600px){.cc-nav.horizontal{gap:2px}.cc-nav.horizontal .cc-nav-item{padding:6px 12px;font-size:13px}}\n"] }]
|
|
11986
12126
|
}], propDecorators: { items: [{
|
|
11987
12127
|
type: Input
|
|
11988
12128
|
}], activeId: [{
|