@cqa-lib/cqa-ui 1.0.120 → 1.0.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/dynamic-select/dynamic-select-field.component.mjs +70 -5
- package/fesm2015/cqa-lib-cqa-ui.mjs +76 -9
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +69 -4
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/dynamic-select/dynamic-select-field.component.d.ts +15 -0
- package/package.json +1 -1
|
@@ -1577,30 +1577,48 @@ class DynamicSelectFieldComponent {
|
|
|
1577
1577
|
return this.hasExistingValue(controlValue) ? undefined : (_d = this.config) === null || _d === void 0 ? void 0 : _d.placeholder;
|
|
1578
1578
|
}
|
|
1579
1579
|
ngOnChanges(changes) {
|
|
1580
|
-
var _a, _b, _c, _d;
|
|
1580
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
1581
1581
|
if ('config' in changes) {
|
|
1582
1582
|
// When config changes (including toggling multiple), ensure control value shape matches
|
|
1583
1583
|
this.syncControlValueForMultipleMode();
|
|
1584
1584
|
this.applySelectedValueIfNeeded();
|
|
1585
|
+
// Sync loadingMore with config.isLoading when provided by parent
|
|
1586
|
+
// This allows parent to control loading state (e.g., during load more operations)
|
|
1587
|
+
if (((_a = this.config) === null || _a === void 0 ? void 0 : _a.isLoading) !== undefined) {
|
|
1588
|
+
this.loadingMore = this.config.isLoading;
|
|
1589
|
+
}
|
|
1585
1590
|
// Reset loadingMore when new options arrive (options length increased)
|
|
1586
|
-
const len = (((
|
|
1591
|
+
const len = (((_b = this.config) === null || _b === void 0 ? void 0 : _b.options) || []).length;
|
|
1587
1592
|
if (len > this.lastOptionsLength) {
|
|
1588
|
-
|
|
1593
|
+
// Reset loading state when new data arrives, unless parent explicitly says still loading
|
|
1594
|
+
if (((_c = this.config) === null || _c === void 0 ? void 0 : _c.isLoading) === false) {
|
|
1595
|
+
this.loadingMore = false;
|
|
1596
|
+
}
|
|
1597
|
+
else if (((_d = this.config) === null || _d === void 0 ? void 0 : _d.isLoading) === undefined) {
|
|
1598
|
+
// Only auto-reset if parent doesn't control loading state
|
|
1599
|
+
this.loadingMore = false;
|
|
1600
|
+
}
|
|
1589
1601
|
}
|
|
1590
1602
|
this.lastOptionsLength = len;
|
|
1591
1603
|
// If consumer indicates no more results, clear loading state and any observers
|
|
1592
|
-
if (!((
|
|
1593
|
-
|
|
1604
|
+
if (!((_e = this.config) === null || _e === void 0 ? void 0 : _e.hasMore)) {
|
|
1605
|
+
// Clear loading state when no more results, unless parent explicitly says still loading
|
|
1606
|
+
if (((_f = this.config) === null || _f === void 0 ? void 0 : _f.isLoading) === false) {
|
|
1607
|
+
this.loadingMore = false;
|
|
1608
|
+
}
|
|
1609
|
+
else if (((_g = this.config) === null || _g === void 0 ? void 0 : _g.isLoading) === undefined) {
|
|
1610
|
+
this.loadingMore = false;
|
|
1611
|
+
}
|
|
1594
1612
|
if (this.loadMoreObserver) {
|
|
1595
1613
|
try {
|
|
1596
1614
|
this.loadMoreObserver.disconnect();
|
|
1597
1615
|
}
|
|
1598
|
-
catch (
|
|
1616
|
+
catch (_k) { }
|
|
1599
1617
|
this.loadMoreObserver = undefined;
|
|
1600
1618
|
}
|
|
1601
1619
|
}
|
|
1602
1620
|
// If panel is open and hasMore is true, ensure the sentinel is being observed.
|
|
1603
|
-
if (((
|
|
1621
|
+
if (((_h = this.selectRef) === null || _h === void 0 ? void 0 : _h.panelOpen) && ((_j = this.config) === null || _j === void 0 ? void 0 : _j.hasMore)) {
|
|
1604
1622
|
setTimeout(() => this.setupLoadMoreObserver(), 0);
|
|
1605
1623
|
}
|
|
1606
1624
|
}
|
|
@@ -1991,6 +2009,55 @@ class DynamicSelectFieldComponent {
|
|
|
1991
2009
|
}
|
|
1992
2010
|
catch (_c) { }
|
|
1993
2011
|
}
|
|
2012
|
+
/**
|
|
2013
|
+
* Highlights text based on the configured highlightPattern.
|
|
2014
|
+
* Returns HTML string with highlighted portions wrapped in <span class="highlight">.
|
|
2015
|
+
*/
|
|
2016
|
+
highlightText(text) {
|
|
2017
|
+
var _a;
|
|
2018
|
+
if (!text || !((_a = this.config) === null || _a === void 0 ? void 0 : _a.highlightPattern)) {
|
|
2019
|
+
return this.escapeHtml(text);
|
|
2020
|
+
}
|
|
2021
|
+
const pattern = this.config.highlightPattern;
|
|
2022
|
+
// If it's a function, use it directly
|
|
2023
|
+
if (typeof pattern === 'function') {
|
|
2024
|
+
return pattern(text);
|
|
2025
|
+
}
|
|
2026
|
+
// Convert string pattern to RegExp if needed
|
|
2027
|
+
let regex;
|
|
2028
|
+
if (typeof pattern === 'string') {
|
|
2029
|
+
try {
|
|
2030
|
+
regex = new RegExp(pattern, 'gi');
|
|
2031
|
+
}
|
|
2032
|
+
catch (e) {
|
|
2033
|
+
console.warn('Invalid highlight pattern:', pattern);
|
|
2034
|
+
return this.escapeHtml(text);
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
else {
|
|
2038
|
+
regex = pattern;
|
|
2039
|
+
}
|
|
2040
|
+
// Escape HTML first, then apply highlighting
|
|
2041
|
+
const escaped = this.escapeHtml(text);
|
|
2042
|
+
return escaped.replace(regex, (match) => `<span class="cqa-primary-text">${match}</span>`);
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
2045
|
+
* Escapes HTML special characters to prevent XSS.
|
|
2046
|
+
*/
|
|
2047
|
+
escapeHtml(text) {
|
|
2048
|
+
if (!text)
|
|
2049
|
+
return '';
|
|
2050
|
+
const div = document.createElement('div');
|
|
2051
|
+
div.textContent = text;
|
|
2052
|
+
return div.innerHTML;
|
|
2053
|
+
}
|
|
2054
|
+
/**
|
|
2055
|
+
* Checks if highlighting is enabled for this component.
|
|
2056
|
+
*/
|
|
2057
|
+
get hasHighlighting() {
|
|
2058
|
+
var _a;
|
|
2059
|
+
return !!((_a = this.config) === null || _a === void 0 ? void 0 : _a.highlightPattern);
|
|
2060
|
+
}
|
|
1994
2061
|
setupLoadMoreObserver() {
|
|
1995
2062
|
var _a;
|
|
1996
2063
|
// Only if consumer indicates more data is available
|
|
@@ -2035,10 +2102,10 @@ class DynamicSelectFieldComponent {
|
|
|
2035
2102
|
}
|
|
2036
2103
|
}
|
|
2037
2104
|
DynamicSelectFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2038
|
-
DynamicSelectFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: { form: "form", config: "config" }, outputs: { selectionChange: "selectionChange", selectClick: "selectClick", searchChange: "searchChange", loadMore: "loadMore" }, host: { listeners: { "document:click": "handleDocumentClick($event)" } }, viewQueries: [{ propertyName: "selectRef", first: true, predicate: ["selectRef"], descendants: true }, { propertyName: "hostEl", first: true, predicate: ["host"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\">\n <ng-container [formGroup]=\"form\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n <mat-form-field #host class=\"mat-select-custom cqa-w-full\" appearance=\"fill\">\n <mat-select #selectRef=\"matSelect\" [placeholder]=\"displayPlaceholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onSelectionChange($event, selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input cqa-text-black-100\" type=\"text\" [value]=\"searchTextByKey[config.key] || ''\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" (input)=\"onSearch(config.key, $any($event.target).value)\"\n placeholder=\"Search...\" />\n </mat-option>\n \n <mat-option [ngClass]=\"{'checkmark': config.optionStyle === 'checkmark','checkbox': config.optionStyle !== 'checkmark','mat-selected': allSelected}\" [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngIf=\"isMultiple && config.showSelectAll\" [value]=\"SELECT_ALL_VALUE\">\n <ng-container *ngIf=\"useCheckboxStyle; else selectAllDefaultTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"allSelected ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"allSelected\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ config.selectAllLabel || 'All' }}</span>\n </span>\n </ng-container>\n <ng-template #selectAllDefaultTpl>\n {{ config.selectAllLabel || 'All' }}\n </ng-template>\n </mat-option>\n\n <mat-option [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\">\n <ng-container *ngIf=\"useCheckboxStyle; else defaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ opt.name ?? opt.label ?? opt.value }}</span>\n </span>\n </ng-container>\n <ng-template #defaultOptionTpl>\n {{ opt.name ?? opt.label ?? opt.value }}
|
|
2105
|
+
DynamicSelectFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: { form: "form", config: "config" }, outputs: { selectionChange: "selectionChange", selectClick: "selectClick", searchChange: "searchChange", loadMore: "loadMore" }, host: { listeners: { "document:click": "handleDocumentClick($event)" } }, viewQueries: [{ propertyName: "selectRef", first: true, predicate: ["selectRef"], descendants: true }, { propertyName: "hostEl", first: true, predicate: ["host"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\">\n <ng-container [formGroup]=\"form\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n <mat-form-field #host class=\"mat-select-custom cqa-w-full\" appearance=\"fill\">\n <mat-select #selectRef=\"matSelect\" [placeholder]=\"displayPlaceholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onSelectionChange($event, selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input cqa-text-black-100\" type=\"text\" [value]=\"searchTextByKey[config.key] || ''\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" (input)=\"onSearch(config.key, $any($event.target).value)\"\n placeholder=\"Search...\" />\n </mat-option>\n \n <mat-option [ngClass]=\"{'checkmark': config.optionStyle === 'checkmark','checkbox': config.optionStyle !== 'checkmark','mat-selected': allSelected}\" [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngIf=\"isMultiple && config.showSelectAll\" [value]=\"SELECT_ALL_VALUE\">\n <ng-container *ngIf=\"useCheckboxStyle; else selectAllDefaultTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"allSelected ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"allSelected\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ config.selectAllLabel || 'All' }}</span>\n </span>\n </ng-container>\n <ng-template #selectAllDefaultTpl>\n {{ config.selectAllLabel || 'All' }}\n </ng-template>\n </mat-option>\n\n <mat-option [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\">\n <ng-container *ngIf=\"useCheckboxStyle; else defaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\" *ngIf=\"hasHighlighting\" [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <span class=\"cqa-min-w-0\" *ngIf=\"!hasHighlighting\">{{ opt.name ?? opt.label ?? opt.value }}</span>\n </span>\n </ng-container>\n <ng-template #defaultOptionTpl>\n <span *ngIf=\"hasHighlighting\" [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <span *ngIf=\"!hasHighlighting\">{{ opt.name ?? opt.label ?? opt.value }}</span>\n </ng-template>\n </mat-option>\n \n <!-- No results state (only when not loading and no options) -->\n <mat-option disabled *ngIf=\"!(config?.options?.length || 0) && !(config?.isLoading || loadingMore)\">\n No results\n </mat-option>\n <!-- Infinite scroll sentinel (serverSearch or explicit hasMore) -->\n <mat-option disabled class=\"load-more-sentinel\" *ngIf=\"config?.hasMore\">\n <span *ngIf=\"loadingMore || config?.isLoading\">Loading...</span>\n <span *ngIf=\"!loadingMore && !config?.isLoading\">Scroll to load more\u2026</span>\n </mat-option>\n </mat-select>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Inline spinner shown when loading more (infinite scroll) or when config.isLoading is true -->\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n </ng-container>\n</div>", components: [{ type: i1$4.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i2$2.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i3$2.MatOption, selector: "mat-option", exportAs: ["matOption"] }], directives: [{ type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2039
2106
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicSelectFieldComponent, decorators: [{
|
|
2040
2107
|
type: Component,
|
|
2041
|
-
args: [{ selector: 'cqa-dynamic-select', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-ui-root\">\n <ng-container [formGroup]=\"form\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n <mat-form-field #host class=\"mat-select-custom cqa-w-full\" appearance=\"fill\">\n <mat-select #selectRef=\"matSelect\" [placeholder]=\"displayPlaceholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onSelectionChange($event, selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input cqa-text-black-100\" type=\"text\" [value]=\"searchTextByKey[config.key] || ''\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" (input)=\"onSearch(config.key, $any($event.target).value)\"\n placeholder=\"Search...\" />\n </mat-option>\n \n <mat-option [ngClass]=\"{'checkmark': config.optionStyle === 'checkmark','checkbox': config.optionStyle !== 'checkmark','mat-selected': allSelected}\" [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngIf=\"isMultiple && config.showSelectAll\" [value]=\"SELECT_ALL_VALUE\">\n <ng-container *ngIf=\"useCheckboxStyle; else selectAllDefaultTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"allSelected ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"allSelected\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ config.selectAllLabel || 'All' }}</span>\n </span>\n </ng-container>\n <ng-template #selectAllDefaultTpl>\n {{ config.selectAllLabel || 'All' }}\n </ng-template>\n </mat-option>\n\n <mat-option [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\">\n <ng-container *ngIf=\"useCheckboxStyle; else defaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ opt.name ?? opt.label ?? opt.value }}</span>\n </span>\n </ng-container>\n <ng-template #defaultOptionTpl>\n {{ opt.name ?? opt.label ?? opt.value }}
|
|
2108
|
+
args: [{ selector: 'cqa-dynamic-select', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-ui-root\">\n <ng-container [formGroup]=\"form\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n <mat-form-field #host class=\"mat-select-custom cqa-w-full\" appearance=\"fill\">\n <mat-select #selectRef=\"matSelect\" [placeholder]=\"displayPlaceholder\" [disabled]=\"isDisabled\" [multiple]=\"isMultiple\"\n disableOptionCentering [panelClass]=\"panelClass\" [formControlName]=\"config.key\"\n (openedChange)=\"onSelectOpenedChange($event, selectRef)\" (selectionChange)=\"onSelectionChange($event, selectRef)\">\n\n <mat-option *ngIf=\"config.searchable\" class=\"ts-select-search\" disabled>\n <input class=\"ts-select-search-input cqa-text-black-100\" type=\"text\" [value]=\"searchTextByKey[config.key] || ''\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" (input)=\"onSearch(config.key, $any($event.target).value)\"\n placeholder=\"Search...\" />\n </mat-option>\n \n <mat-option [ngClass]=\"{'checkmark': config.optionStyle === 'checkmark','checkbox': config.optionStyle !== 'checkmark','mat-selected': allSelected}\" [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngIf=\"isMultiple && config.showSelectAll\" [value]=\"SELECT_ALL_VALUE\">\n <ng-container *ngIf=\"useCheckboxStyle; else selectAllDefaultTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"allSelected ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"allSelected\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\">{{ config.selectAllLabel || 'All' }}</span>\n </span>\n </ng-container>\n <ng-template #selectAllDefaultTpl>\n {{ config.selectAllLabel || 'All' }}\n </ng-template>\n </mat-option>\n\n <mat-option [class]=\"config.optionStyle == 'checkmark' ? 'checkmark' : 'checkbox'\" *ngFor=\"let opt of filteredOptions(config)\" [value]=\"opt.id ?? opt.value\">\n <ng-container *ngIf=\"useCheckboxStyle; else defaultOptionTpl\">\n <span class=\"cqa-flex cqa-items-center\">\n <span class=\"cqa-w-4 cqa-h-4 cqa-flex-shrink-0 cqa-rounded-[4px] cqa-border cqa-border-[#D1D5DB] cqa-mr-2 cqa-flex cqa-items-center cqa-justify-center cqa-border-solid\"\n [ngStyle]=\"isOptionSelected(opt) ? {'background-color':'#4F46E5','border-color':'#4F46E5'} : {}\">\n <svg *ngIf=\"isOptionSelected(opt)\" width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 3L4.5 8.5L2 6\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <span class=\"cqa-min-w-0\" *ngIf=\"hasHighlighting\" [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <span class=\"cqa-min-w-0\" *ngIf=\"!hasHighlighting\">{{ opt.name ?? opt.label ?? opt.value }}</span>\n </span>\n </ng-container>\n <ng-template #defaultOptionTpl>\n <span *ngIf=\"hasHighlighting\" [innerHTML]=\"highlightText(opt.name ?? opt.label ?? opt.value)\"></span>\n <span *ngIf=\"!hasHighlighting\">{{ opt.name ?? opt.label ?? opt.value }}</span>\n </ng-template>\n </mat-option>\n \n <!-- No results state (only when not loading and no options) -->\n <mat-option disabled *ngIf=\"!(config?.options?.length || 0) && !(config?.isLoading || loadingMore)\">\n No results\n </mat-option>\n <!-- Infinite scroll sentinel (serverSearch or explicit hasMore) -->\n <mat-option disabled class=\"load-more-sentinel\" *ngIf=\"config?.hasMore\">\n <span *ngIf=\"loadingMore || config?.isLoading\">Loading...</span>\n <span *ngIf=\"!loadingMore && !config?.isLoading\">Scroll to load more\u2026</span>\n </mat-option>\n </mat-select>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <!-- Inline spinner shown when loading more (infinite scroll) or when config.isLoading is true -->\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </mat-form-field>\n </ng-container>\n</div>" }]
|
|
2042
2109
|
}], propDecorators: { form: [{
|
|
2043
2110
|
type: Input
|
|
2044
2111
|
}], config: [{
|