@sd-angular/core 19.0.0-beta.102 → 19.0.0-beta.104

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.
@@ -10,7 +10,6 @@ import { MatMenuModule, MatMenu, MatMenuTrigger } from '@angular/material/menu';
10
10
  import * as i3 from '@angular/material/tooltip';
11
11
  import { MatTooltipModule } from '@angular/material/tooltip';
12
12
  import { I18nService } from '@sd-angular/core/i18n';
13
- import { SdButton } from '@sd-angular/core/components/button';
14
13
  import { SdOperator } from '@sd-angular/core/components/operator';
15
14
  import { SdDate } from '@sd-angular/core/forms/date';
16
15
  import { SdDateRange } from '@sd-angular/core/forms/date-range';
@@ -19,6 +18,7 @@ import { SdInput } from '@sd-angular/core/forms/input';
19
18
  import { SdInputNumber } from '@sd-angular/core/forms/input-number';
20
19
  import { SdSelect } from '@sd-angular/core/forms/select';
21
20
  import { isObservable } from 'rxjs';
21
+ import { SdButton } from '@sd-angular/core/components/button';
22
22
 
23
23
  /* eslint-disable @typescript-eslint/no-explicit-any */
24
24
  /**
@@ -106,23 +106,23 @@ class SdQuerySavedFiltersMenu {
106
106
  this.#persist(next);
107
107
  }
108
108
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQuerySavedFiltersMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
109
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQuerySavedFiltersMenu, isStandalone: true, selector: "sd-query-saved-filters-menu", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { apply: "apply" }, ngImport: i0, template: "<button\r\n type=\"button\"\r\n class=\"c-saved-filters\"\r\n [disabled]=\"!key()\"\r\n [matMenuTriggerFor]=\"menu\"\r\n [matTooltip]=\"key() ? 'B\u1ED9 l\u1ECDc \u0111\u00E3 l\u01B0u' : 'C\u1EA7n [savedFiltersKey] \u0111\u1EC3 b\u1EADt'\">\r\n <mat-icon fontSet=\"material-icons-outlined\">bookmark_border</mat-icon>\r\n</button>\r\n\r\n<mat-menu #menu=\"matMenu\" class=\"c-saved-filters-menu\" xPosition=\"before\" yPosition=\"below\">\r\n @for (f of savedFilters(); track f.id) {\r\n <button type=\"button\" mat-menu-item class=\"c-sf-row\" (click)=\"pick(f)\">\r\n <mat-icon class=\"c-sf-lead\" fontSet=\"material-icons-outlined\">filter_alt</mat-icon>\r\n <span class=\"c-sf-name\">{{ f.name }}</span>\r\n <span\r\n role=\"button\"\r\n tabindex=\"0\"\r\n class=\"c-sf-del\"\r\n aria-label=\"Xo\u00E1 b\u1ED9 l\u1ECDc\"\r\n (click)=\"remove(f.id, $event)\"\r\n (keydown.enter)=\"remove(f.id, $event)\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </span>\r\n </button>\r\n } @empty {\r\n <div class=\"c-sf-empty\">Ch\u01B0a c\u00F3 b\u1ED9 l\u1ECDc n\u00E0o.</div>\r\n }\r\n</mat-menu>\r\n", styles: [":host{display:inline-flex}.c-saved-filters{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1px solid #d6d8db;border-radius:6px;background:#fff;color:#5f6368;cursor:pointer;padding:0}.c-saved-filters mat-icon{font-size:18px;width:18px;height:18px}.c-saved-filters:hover:not([disabled]){border-color:var(--sd-primary);color:var(--sd-primary)}.c-saved-filters[disabled]{opacity:.5;cursor:not-allowed}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu{min-width:220px;max-width:320px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .mat-mdc-menu-item.c-sf-row{display:flex;align-items:center;min-height:36px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-lead{flex:0 0 auto;font-size:18px;width:18px;height:18px;margin-right:8px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del{flex:0 0 auto;align-self:center;margin-left:auto;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;color:#7a7a7a;cursor:pointer}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del mat-icon{font-size:14px;width:14px;height:14px;line-height:14px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del:hover{background:#0000000f;color:#d23535}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-empty{padding:12px 16px;font-size:13px;color:#7a7a7a}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
109
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQuerySavedFiltersMenu, isStandalone: true, selector: "sd-query-saved-filters-menu", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { apply: "apply" }, ngImport: i0, template: "<button\r\n type=\"button\"\r\n class=\"c-saved-filters\"\r\n [disabled]=\"!key()\"\r\n [matMenuTriggerFor]=\"menu\"\r\n [matTooltip]=\"key() ? 'B\u1ED9 l\u1ECDc \u0111\u00E3 l\u01B0u' : 'C\u1EA7n [savedFiltersKey] \u0111\u1EC3 b\u1EADt'\">\r\n <mat-icon fontSet=\"material-icons-outlined\">bookmark_border</mat-icon>\r\n</button>\r\n\r\n<mat-menu #menu=\"matMenu\" class=\"c-saved-filters-menu\" xPosition=\"before\" yPosition=\"below\">\r\n @for (f of savedFilters(); track f.id) {\r\n <button type=\"button\" mat-menu-item class=\"c-sf-row\" (click)=\"pick(f)\">\r\n <mat-icon class=\"c-sf-lead\" fontSet=\"material-icons-outlined\">filter_alt</mat-icon>\r\n <span class=\"c-sf-name\">{{ f.name }}</span>\r\n <span\r\n role=\"button\"\r\n tabindex=\"0\"\r\n class=\"c-sf-del\"\r\n aria-label=\"Xo\u00E1 b\u1ED9 l\u1ECDc\"\r\n (click)=\"remove(f.id, $event)\"\r\n (keydown.enter)=\"remove(f.id, $event)\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </span>\r\n </button>\r\n } @empty {\r\n <div class=\"c-sf-empty\">Ch\u01B0a c\u00F3 b\u1ED9 l\u1ECDc n\u00E0o.</div>\r\n }\r\n <!-- why: footer save action s\u1ED1ng trong mat-menu \u0111\u1EC3 dropdown gom 1 v\u00F9ng (list +\r\n save) \u2014 user m\u1EDF dropdown th\u1EA5y ngay c\u1EA3 2 h\u00E0nh \u0111\u1ED9ng, kh\u00F4ng ph\u1EA3i t\u00ECm n\u00FAt l\u01B0u\r\n \u1EDF ch\u1ED7 kh\u00E1c tr\u00EAn toolbar. -->\r\n <hr class=\"c-sf-divider\" aria-hidden=\"true\" />\r\n <button type=\"button\" mat-menu-item class=\"c-sf-save\" [disabled]=\"!key()\" (click)=\"promptSave()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">bookmark_add</mat-icon>\r\n <span>L\u01B0u b\u1ED9 l\u1ECDc hi\u1EC7n t\u1EA1i</span>\r\n </button>\r\n</mat-menu>\r\n", styles: [":host{display:inline-flex}.c-saved-filters{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1px solid #d6d8db;border-radius:6px;background:#fff;color:#5f6368;cursor:pointer;padding:0}.c-saved-filters mat-icon{font-size:18px;width:18px;height:18px}.c-saved-filters:hover:not([disabled]){border-color:var(--sd-primary);color:var(--sd-primary)}.c-saved-filters[disabled]{opacity:.5;cursor:not-allowed}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu{min-width:220px;max-width:320px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .mat-mdc-menu-item.c-sf-row{min-height:40px;padding-left:16px;padding-right:4px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .mat-mdc-menu-item.c-sf-row .mat-mdc-menu-item-text{display:flex;align-items:center;gap:8px;min-width:0;line-height:1.4}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-lead{display:inline-flex;align-items:center;justify-content:center;font-size:18px!important;width:18px!important;height:18px!important;line-height:1}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del{flex:0 0 auto;margin-left:auto;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;color:#7a7a7a;cursor:pointer;padding:0}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del mat-icon{margin:0!important;padding:0;font-size:16px!important;width:16px!important;height:16px!important;line-height:16px!important;text-align:center;overflow:hidden}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del:hover{background:#0000000f;color:#d23535}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-empty{padding:12px 16px;font-size:13px;color:#7a7a7a}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-divider{border:0;border-top:1px solid #e2e4e7;margin:4px 0}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-save mat-icon{margin-right:8px}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
110
110
  }
111
111
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQuerySavedFiltersMenu, decorators: [{
112
112
  type: Component,
113
- args: [{ selector: 'sd-query-saved-filters-menu', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatMenuModule, MatIconModule, MatTooltipModule], template: "<button\r\n type=\"button\"\r\n class=\"c-saved-filters\"\r\n [disabled]=\"!key()\"\r\n [matMenuTriggerFor]=\"menu\"\r\n [matTooltip]=\"key() ? 'B\u1ED9 l\u1ECDc \u0111\u00E3 l\u01B0u' : 'C\u1EA7n [savedFiltersKey] \u0111\u1EC3 b\u1EADt'\">\r\n <mat-icon fontSet=\"material-icons-outlined\">bookmark_border</mat-icon>\r\n</button>\r\n\r\n<mat-menu #menu=\"matMenu\" class=\"c-saved-filters-menu\" xPosition=\"before\" yPosition=\"below\">\r\n @for (f of savedFilters(); track f.id) {\r\n <button type=\"button\" mat-menu-item class=\"c-sf-row\" (click)=\"pick(f)\">\r\n <mat-icon class=\"c-sf-lead\" fontSet=\"material-icons-outlined\">filter_alt</mat-icon>\r\n <span class=\"c-sf-name\">{{ f.name }}</span>\r\n <span\r\n role=\"button\"\r\n tabindex=\"0\"\r\n class=\"c-sf-del\"\r\n aria-label=\"Xo\u00E1 b\u1ED9 l\u1ECDc\"\r\n (click)=\"remove(f.id, $event)\"\r\n (keydown.enter)=\"remove(f.id, $event)\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </span>\r\n </button>\r\n } @empty {\r\n <div class=\"c-sf-empty\">Ch\u01B0a c\u00F3 b\u1ED9 l\u1ECDc n\u00E0o.</div>\r\n }\r\n</mat-menu>\r\n", styles: [":host{display:inline-flex}.c-saved-filters{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1px solid #d6d8db;border-radius:6px;background:#fff;color:#5f6368;cursor:pointer;padding:0}.c-saved-filters mat-icon{font-size:18px;width:18px;height:18px}.c-saved-filters:hover:not([disabled]){border-color:var(--sd-primary);color:var(--sd-primary)}.c-saved-filters[disabled]{opacity:.5;cursor:not-allowed}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu{min-width:220px;max-width:320px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .mat-mdc-menu-item.c-sf-row{display:flex;align-items:center;min-height:36px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-lead{flex:0 0 auto;font-size:18px;width:18px;height:18px;margin-right:8px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del{flex:0 0 auto;align-self:center;margin-left:auto;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;color:#7a7a7a;cursor:pointer}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del mat-icon{font-size:14px;width:14px;height:14px;line-height:14px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del:hover{background:#0000000f;color:#d23535}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-empty{padding:12px 16px;font-size:13px;color:#7a7a7a}\n"] }]
113
+ args: [{ selector: 'sd-query-saved-filters-menu', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatMenuModule, MatIconModule, MatTooltipModule], template: "<button\r\n type=\"button\"\r\n class=\"c-saved-filters\"\r\n [disabled]=\"!key()\"\r\n [matMenuTriggerFor]=\"menu\"\r\n [matTooltip]=\"key() ? 'B\u1ED9 l\u1ECDc \u0111\u00E3 l\u01B0u' : 'C\u1EA7n [savedFiltersKey] \u0111\u1EC3 b\u1EADt'\">\r\n <mat-icon fontSet=\"material-icons-outlined\">bookmark_border</mat-icon>\r\n</button>\r\n\r\n<mat-menu #menu=\"matMenu\" class=\"c-saved-filters-menu\" xPosition=\"before\" yPosition=\"below\">\r\n @for (f of savedFilters(); track f.id) {\r\n <button type=\"button\" mat-menu-item class=\"c-sf-row\" (click)=\"pick(f)\">\r\n <mat-icon class=\"c-sf-lead\" fontSet=\"material-icons-outlined\">filter_alt</mat-icon>\r\n <span class=\"c-sf-name\">{{ f.name }}</span>\r\n <span\r\n role=\"button\"\r\n tabindex=\"0\"\r\n class=\"c-sf-del\"\r\n aria-label=\"Xo\u00E1 b\u1ED9 l\u1ECDc\"\r\n (click)=\"remove(f.id, $event)\"\r\n (keydown.enter)=\"remove(f.id, $event)\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </span>\r\n </button>\r\n } @empty {\r\n <div class=\"c-sf-empty\">Ch\u01B0a c\u00F3 b\u1ED9 l\u1ECDc n\u00E0o.</div>\r\n }\r\n <!-- why: footer save action s\u1ED1ng trong mat-menu \u0111\u1EC3 dropdown gom 1 v\u00F9ng (list +\r\n save) \u2014 user m\u1EDF dropdown th\u1EA5y ngay c\u1EA3 2 h\u00E0nh \u0111\u1ED9ng, kh\u00F4ng ph\u1EA3i t\u00ECm n\u00FAt l\u01B0u\r\n \u1EDF ch\u1ED7 kh\u00E1c tr\u00EAn toolbar. -->\r\n <hr class=\"c-sf-divider\" aria-hidden=\"true\" />\r\n <button type=\"button\" mat-menu-item class=\"c-sf-save\" [disabled]=\"!key()\" (click)=\"promptSave()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">bookmark_add</mat-icon>\r\n <span>L\u01B0u b\u1ED9 l\u1ECDc hi\u1EC7n t\u1EA1i</span>\r\n </button>\r\n</mat-menu>\r\n", styles: [":host{display:inline-flex}.c-saved-filters{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1px solid #d6d8db;border-radius:6px;background:#fff;color:#5f6368;cursor:pointer;padding:0}.c-saved-filters mat-icon{font-size:18px;width:18px;height:18px}.c-saved-filters:hover:not([disabled]){border-color:var(--sd-primary);color:var(--sd-primary)}.c-saved-filters[disabled]{opacity:.5;cursor:not-allowed}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu{min-width:220px;max-width:320px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .mat-mdc-menu-item.c-sf-row{min-height:40px;padding-left:16px;padding-right:4px}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .mat-mdc-menu-item.c-sf-row .mat-mdc-menu-item-text{display:flex;align-items:center;gap:8px;min-width:0;line-height:1.4}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-lead{display:inline-flex;align-items:center;justify-content:center;font-size:18px!important;width:18px!important;height:18px!important;line-height:1}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del{flex:0 0 auto;margin-left:auto;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;color:#7a7a7a;cursor:pointer;padding:0}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del mat-icon{margin:0!important;padding:0;font-size:16px!important;width:16px!important;height:16px!important;line-height:16px!important;text-align:center;overflow:hidden}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-del:hover{background:#0000000f;color:#d23535}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-empty{padding:12px 16px;font-size:13px;color:#7a7a7a}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-divider{border:0;border-top:1px solid #e2e4e7;margin:4px 0}::ng-deep .mat-mdc-menu-panel.c-saved-filters-menu .c-sf-save mat-icon{margin-right:8px}\n"] }]
114
114
  }] });
115
115
 
116
116
  /* eslint-disable @typescript-eslint/no-explicit-any */
117
117
  /**
118
- * Right-pinned toolbar for `sd-query-bar`: AND/OR connector toggle, saved-filters
119
- * dropdown, clear-all, a save-filter shortcut, and the deferred Search trigger.
120
- * Owns no business logic — just routes user intent back via outputs
121
- * (`(logic)` model, `(clear)`, `(search)`, `(applyFilter)`).
118
+ * Right-pinned toolbar for `sd-query-bar`: AND/OR connector toggle, clear-all,
119
+ * saved-filters dropdown (with footer "Lưu bộ lọc hiện tại"), and the deferred
120
+ * Search trigger. Owns no business logic — just routes user intent back via
121
+ * outputs (`(logic)` model, `(clear)`, `(search)`, `(applyFilter)`).
122
122
  *
123
- * The "save filter" button forwards to `SdQuerySavedFiltersMenu.promptSave()` so
124
- * the user can save the current query without first opening the saved-filters
125
- * dropdown keeps the save action adjacent to the Search trigger.
123
+ * The "save current query" action lives INSIDE the saved-filters mat-menu
124
+ * footer (one zone for both apply + save). The dropdown trigger sits
125
+ * immediately before Search so the user sees one filter-cluster on the right.
126
126
  */
127
127
  class SdQueryActionsBar {
128
128
  // AND/OR toggle —
@@ -140,24 +140,17 @@ class SdQueryActionsBar {
140
140
  // Search trigger —
141
141
  canSearch = input(false);
142
142
  search = output();
143
- // why: viewChild để có thể gọi promptSave() từ nút "Lưu bộ lọc" đặt cạnh Search.
144
- // Nút lưu nằm ngoài <mat-menu> nên không thể dùng (click) wiring nội bộ.
145
- savedFiltersMenu = viewChild(SdQuerySavedFiltersMenu);
146
143
  setLogic(value) {
147
144
  if (this.logic() === value)
148
145
  return;
149
146
  this.logic.set(value);
150
147
  }
151
- /** Trigger save-current-query via the saved-filters child (no-op when menu absent / no key). */
152
- promptSave() {
153
- this.savedFiltersMenu()?.promptSave();
154
- }
155
148
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQueryActionsBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
156
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQueryActionsBar, isStandalone: true, selector: "sd-query-actions-bar", inputs: { showLogicToggle: { classPropertyName: "showLogicToggle", publicName: "showLogicToggle", isSignal: true, isRequired: false, transformFunction: null }, logic: { classPropertyName: "logic", publicName: "logic", isSignal: true, isRequired: false, transformFunction: null }, filtersCount: { classPropertyName: "filtersCount", publicName: "filtersCount", isSignal: true, isRequired: false, transformFunction: null }, showSavedFilters: { classPropertyName: "showSavedFilters", publicName: "showSavedFilters", isSignal: true, isRequired: false, transformFunction: null }, savedFiltersKey: { classPropertyName: "savedFiltersKey", publicName: "savedFiltersKey", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null }, showClearAll: { classPropertyName: "showClearAll", publicName: "showClearAll", isSignal: true, isRequired: false, transformFunction: null }, canSearch: { classPropertyName: "canSearch", publicName: "canSearch", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { logic: "logicChange", applyFilter: "applyFilter", clear: "clear", search: "search" }, viewQueries: [{ propertyName: "savedFiltersMenu", first: true, predicate: SdQuerySavedFiltersMenu, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Vertical separator between the wrapping filter area (left) and the pinned toolbar. -->\r\n<span class=\"c-bar-divider\" aria-hidden=\"true\"></span>\r\n\r\n<div class=\"c-query-bar__actions\">\r\n <!-- AND / OR toggle -->\r\n @if (showLogicToggle() && filtersCount() >= 2) {\r\n <div class=\"c-logic-toggle\" role=\"group\" aria-label=\"Logic operator\">\r\n <button\r\n type=\"button\"\r\n class=\"c-logic-segment\"\r\n [class.c-logic-active]=\"logic() === 'AND'\"\r\n (click)=\"setLogic('AND')\">\r\n AND\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"c-logic-segment\"\r\n [class.c-logic-active]=\"logic() === 'OR'\"\r\n (click)=\"setLogic('OR')\">\r\n OR\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showSavedFilters()) {\r\n <sd-query-saved-filters-menu\r\n [key]=\"savedFiltersKey()\"\r\n [query]=\"query()\"\r\n (apply)=\"applyFilter.emit($event)\" />\r\n }\r\n\r\n @if (showClearAll() && filtersCount() > 0) {\r\n <button\r\n type=\"button\"\r\n class=\"c-clear-all\"\r\n [matTooltip]=\"'X\u00F3a t\u1EA5t c\u1EA3 (' + filtersCount() + ')'\"\r\n (click)=\"clear.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">delete_sweep</mat-icon>\r\n </button>\r\n }\r\n\r\n <!-- why: n\u00FAt \"L\u01B0u b\u1ED9 l\u1ECDc hi\u1EC7n t\u1EA1i\" \u0111\u1EB7t s\u00E1t Search \u2014 user l\u01B0u xong r\u1ED3i t\u00ECm\r\n lu\u00F4n trong c\u00F9ng v\u00F9ng ph\u1EA3i. Ch\u1EC9 hi\u1EC7n khi showSavedFilters=true V\u00C0 c\u00F3\r\n savedFiltersKey (kh\u00F4ng c\u00F3 key th\u00EC promptSave l\u00E0 no-op). -->\r\n @if (showSavedFilters() && savedFiltersKey()) {\r\n <button\r\n type=\"button\"\r\n class=\"c-save-filter\"\r\n matTooltip=\"L\u01B0u b\u1ED9 l\u1ECDc hi\u1EC7n t\u1EA1i\"\r\n (click)=\"promptSave()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">bookmark_add</mat-icon>\r\n </button>\r\n }\r\n\r\n <!-- why: far-right \"submit at the end of the toolbar\" position; sole query trigger. -->\r\n <button\r\n type=\"button\"\r\n class=\"c-search-trigger\"\r\n [disabled]=\"!canSearch()\"\r\n matTooltip=\"T\u00ECm ki\u1EBFm\"\r\n (click)=\"search.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">search</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [":host{display:contents}.c-bar-divider{flex:0 0 auto;align-self:stretch;width:1px;min-height:28px;background:#e2e4e7}.c-query-bar__actions{flex:0 0 auto;display:flex;align-items:center;gap:6px}.c-logic-toggle{display:inline-flex;align-items:center;padding:2px;background:#f5f6f7;border:1px solid #e2e4e7;border-radius:6px}:host-context(.c-density-compact) .c-logic-toggle{height:28px}:host-context(.c-density-comfortable) .c-logic-toggle{height:32px}.c-logic-toggle .c-logic-segment{height:100%;padding:0 10px;border:none;background:transparent;font-family:Roboto Mono,monospace;font-size:11px;font-weight:600;letter-spacing:.4px;color:#5f6368;cursor:pointer;border-radius:4px}.c-logic-toggle .c-logic-segment.c-logic-active{background:#fff;color:var(--sd-primary);box-shadow:0 1px 2px #00000014}.c-clear-all,.c-search-trigger{display:inline-flex;align-items:center;justify-content:center;border:1px solid #d6d8db;border-radius:6px;background:#fff;color:#5f6368;cursor:pointer;padding:0}:host-context(.c-density-compact) .c-clear-all,:host-context(.c-density-compact) .c-search-trigger{width:28px;height:28px}:host-context(.c-density-comfortable) .c-clear-all,:host-context(.c-density-comfortable) .c-search-trigger{width:32px;height:32px}.c-clear-all mat-icon,.c-search-trigger mat-icon{font-size:18px;width:18px;height:18px}.c-clear-all:hover:not([disabled]),.c-search-trigger:hover:not([disabled]){border-color:var(--sd-primary);color:var(--sd-primary)}.c-clear-all[disabled],.c-search-trigger[disabled]{opacity:.5;cursor:not-allowed}.c-clear-all:hover{border-color:#dc2626;color:#dc2626}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: SdQuerySavedFiltersMenu, selector: "sd-query-saved-filters-menu", inputs: ["key", "query"], outputs: ["apply"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
149
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQueryActionsBar, isStandalone: true, selector: "sd-query-actions-bar", inputs: { showLogicToggle: { classPropertyName: "showLogicToggle", publicName: "showLogicToggle", isSignal: true, isRequired: false, transformFunction: null }, logic: { classPropertyName: "logic", publicName: "logic", isSignal: true, isRequired: false, transformFunction: null }, filtersCount: { classPropertyName: "filtersCount", publicName: "filtersCount", isSignal: true, isRequired: false, transformFunction: null }, showSavedFilters: { classPropertyName: "showSavedFilters", publicName: "showSavedFilters", isSignal: true, isRequired: false, transformFunction: null }, savedFiltersKey: { classPropertyName: "savedFiltersKey", publicName: "savedFiltersKey", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null }, showClearAll: { classPropertyName: "showClearAll", publicName: "showClearAll", isSignal: true, isRequired: false, transformFunction: null }, canSearch: { classPropertyName: "canSearch", publicName: "canSearch", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { logic: "logicChange", applyFilter: "applyFilter", clear: "clear", search: "search" }, ngImport: i0, template: "<!-- Vertical separator between the wrapping filter area (left) and the pinned toolbar. -->\r\n<span class=\"c-bar-divider\" aria-hidden=\"true\"></span>\r\n\r\n<div class=\"c-query-bar__actions\">\r\n <!-- AND / OR toggle -->\r\n @if (showLogicToggle() && filtersCount() >= 2) {\r\n <div class=\"c-logic-toggle\" role=\"group\" aria-label=\"Logic operator\">\r\n <button\r\n type=\"button\"\r\n class=\"c-logic-segment\"\r\n [class.c-logic-active]=\"logic() === 'AND'\"\r\n (click)=\"setLogic('AND')\">\r\n AND\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"c-logic-segment\"\r\n [class.c-logic-active]=\"logic() === 'OR'\"\r\n (click)=\"setLogic('OR')\">\r\n OR\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showClearAll() && filtersCount() > 0) {\r\n <button\r\n type=\"button\"\r\n class=\"c-clear-all\"\r\n [matTooltip]=\"'X\u00F3a t\u1EA5t c\u1EA3 (' + filtersCount() + ')'\"\r\n (click)=\"clear.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">delete_sweep</mat-icon>\r\n </button>\r\n }\r\n\r\n <!-- why: saved-filters dropdown \u0111\u1EB7t s\u00E1t ngay tr\u01B0\u1EDBc Search \u2014 gom to\u00E0n b\u1ED9\r\n h\u00E0nh \u0111\u1ED9ng v\u1EC1 b\u1ED9 l\u1ECDc (apply view c\u0169 / l\u01B0u view hi\u1EC7n t\u1EA1i) c\u1EA1nh n\u00FAt submit,\r\n user th\u1EA5y 1 c\u1EE5m. Footer \"L\u01B0u b\u1ED9 l\u1ECDc hi\u1EC7n t\u1EA1i\" s\u1ED1ng trong mat-menu c\u1EE7a\r\n saved-filters-menu, kh\u00F4ng t\u00E1ch ra n\u00FAt ri\u00EAng n\u1EEFa. -->\r\n @if (showSavedFilters()) {\r\n <sd-query-saved-filters-menu\r\n [key]=\"savedFiltersKey()\"\r\n [query]=\"query()\"\r\n (apply)=\"applyFilter.emit($event)\" />\r\n }\r\n\r\n <!-- why: far-right \"submit at the end of the toolbar\" position; sole query trigger. -->\r\n <button\r\n type=\"button\"\r\n class=\"c-search-trigger\"\r\n [disabled]=\"!canSearch()\"\r\n matTooltip=\"T\u00ECm ki\u1EBFm\"\r\n (click)=\"search.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">search</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [":host{display:contents}.c-bar-divider{flex:0 0 auto;align-self:stretch;width:1px;min-height:28px;background:#e2e4e7}.c-query-bar__actions{flex:0 0 auto;display:flex;align-items:center;gap:6px}.c-logic-toggle{display:inline-flex;align-items:center;padding:2px;background:#f5f6f7;border:1px solid #e2e4e7;border-radius:6px}:host-context(.c-density-compact) .c-logic-toggle{height:28px}:host-context(.c-density-comfortable) .c-logic-toggle{height:32px}.c-logic-toggle .c-logic-segment{height:100%;padding:0 10px;border:none;background:transparent;font-family:Roboto Mono,monospace;font-size:11px;font-weight:600;letter-spacing:.4px;color:#5f6368;cursor:pointer;border-radius:4px}.c-logic-toggle .c-logic-segment.c-logic-active{background:#fff;color:var(--sd-primary);box-shadow:0 1px 2px #00000014}.c-clear-all,.c-search-trigger{display:inline-flex;align-items:center;justify-content:center;border:1px solid #d6d8db;border-radius:6px;background:#fff;color:#5f6368;cursor:pointer;padding:0}:host-context(.c-density-compact) .c-clear-all,:host-context(.c-density-compact) .c-search-trigger{width:28px;height:28px}:host-context(.c-density-comfortable) .c-clear-all,:host-context(.c-density-comfortable) .c-search-trigger{width:32px;height:32px}.c-clear-all mat-icon,.c-search-trigger mat-icon{font-size:18px;width:18px;height:18px}.c-clear-all:hover:not([disabled]),.c-search-trigger:hover:not([disabled]){border-color:var(--sd-primary);color:var(--sd-primary)}.c-clear-all[disabled],.c-search-trigger[disabled]{opacity:.5;cursor:not-allowed}.c-clear-all:hover{border-color:#dc2626;color:#dc2626}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: SdQuerySavedFiltersMenu, selector: "sd-query-saved-filters-menu", inputs: ["key", "query"], outputs: ["apply"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
157
150
  }
158
151
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQueryActionsBar, decorators: [{
159
152
  type: Component,
160
- args: [{ selector: 'sd-query-actions-bar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatIconModule, MatTooltipModule, SdQuerySavedFiltersMenu], template: "<!-- Vertical separator between the wrapping filter area (left) and the pinned toolbar. -->\r\n<span class=\"c-bar-divider\" aria-hidden=\"true\"></span>\r\n\r\n<div class=\"c-query-bar__actions\">\r\n <!-- AND / OR toggle -->\r\n @if (showLogicToggle() && filtersCount() >= 2) {\r\n <div class=\"c-logic-toggle\" role=\"group\" aria-label=\"Logic operator\">\r\n <button\r\n type=\"button\"\r\n class=\"c-logic-segment\"\r\n [class.c-logic-active]=\"logic() === 'AND'\"\r\n (click)=\"setLogic('AND')\">\r\n AND\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"c-logic-segment\"\r\n [class.c-logic-active]=\"logic() === 'OR'\"\r\n (click)=\"setLogic('OR')\">\r\n OR\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showSavedFilters()) {\r\n <sd-query-saved-filters-menu\r\n [key]=\"savedFiltersKey()\"\r\n [query]=\"query()\"\r\n (apply)=\"applyFilter.emit($event)\" />\r\n }\r\n\r\n @if (showClearAll() && filtersCount() > 0) {\r\n <button\r\n type=\"button\"\r\n class=\"c-clear-all\"\r\n [matTooltip]=\"'X\u00F3a t\u1EA5t c\u1EA3 (' + filtersCount() + ')'\"\r\n (click)=\"clear.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">delete_sweep</mat-icon>\r\n </button>\r\n }\r\n\r\n <!-- why: n\u00FAt \"L\u01B0u b\u1ED9 l\u1ECDc hi\u1EC7n t\u1EA1i\" \u0111\u1EB7t s\u00E1t Search \u2014 user l\u01B0u xong r\u1ED3i t\u00ECm\r\n lu\u00F4n trong c\u00F9ng v\u00F9ng ph\u1EA3i. Ch\u1EC9 hi\u1EC7n khi showSavedFilters=true V\u00C0 c\u00F3\r\n savedFiltersKey (kh\u00F4ng c\u00F3 key th\u00EC promptSave l\u00E0 no-op). -->\r\n @if (showSavedFilters() && savedFiltersKey()) {\r\n <button\r\n type=\"button\"\r\n class=\"c-save-filter\"\r\n matTooltip=\"L\u01B0u b\u1ED9 l\u1ECDc hi\u1EC7n t\u1EA1i\"\r\n (click)=\"promptSave()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">bookmark_add</mat-icon>\r\n </button>\r\n }\r\n\r\n <!-- why: far-right \"submit at the end of the toolbar\" position; sole query trigger. -->\r\n <button\r\n type=\"button\"\r\n class=\"c-search-trigger\"\r\n [disabled]=\"!canSearch()\"\r\n matTooltip=\"T\u00ECm ki\u1EBFm\"\r\n (click)=\"search.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">search</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [":host{display:contents}.c-bar-divider{flex:0 0 auto;align-self:stretch;width:1px;min-height:28px;background:#e2e4e7}.c-query-bar__actions{flex:0 0 auto;display:flex;align-items:center;gap:6px}.c-logic-toggle{display:inline-flex;align-items:center;padding:2px;background:#f5f6f7;border:1px solid #e2e4e7;border-radius:6px}:host-context(.c-density-compact) .c-logic-toggle{height:28px}:host-context(.c-density-comfortable) .c-logic-toggle{height:32px}.c-logic-toggle .c-logic-segment{height:100%;padding:0 10px;border:none;background:transparent;font-family:Roboto Mono,monospace;font-size:11px;font-weight:600;letter-spacing:.4px;color:#5f6368;cursor:pointer;border-radius:4px}.c-logic-toggle .c-logic-segment.c-logic-active{background:#fff;color:var(--sd-primary);box-shadow:0 1px 2px #00000014}.c-clear-all,.c-search-trigger{display:inline-flex;align-items:center;justify-content:center;border:1px solid #d6d8db;border-radius:6px;background:#fff;color:#5f6368;cursor:pointer;padding:0}:host-context(.c-density-compact) .c-clear-all,:host-context(.c-density-compact) .c-search-trigger{width:28px;height:28px}:host-context(.c-density-comfortable) .c-clear-all,:host-context(.c-density-comfortable) .c-search-trigger{width:32px;height:32px}.c-clear-all mat-icon,.c-search-trigger mat-icon{font-size:18px;width:18px;height:18px}.c-clear-all:hover:not([disabled]),.c-search-trigger:hover:not([disabled]){border-color:var(--sd-primary);color:var(--sd-primary)}.c-clear-all[disabled],.c-search-trigger[disabled]{opacity:.5;cursor:not-allowed}.c-clear-all:hover{border-color:#dc2626;color:#dc2626}\n"] }]
153
+ args: [{ selector: 'sd-query-actions-bar', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatIconModule, MatTooltipModule, SdQuerySavedFiltersMenu], template: "<!-- Vertical separator between the wrapping filter area (left) and the pinned toolbar. -->\r\n<span class=\"c-bar-divider\" aria-hidden=\"true\"></span>\r\n\r\n<div class=\"c-query-bar__actions\">\r\n <!-- AND / OR toggle -->\r\n @if (showLogicToggle() && filtersCount() >= 2) {\r\n <div class=\"c-logic-toggle\" role=\"group\" aria-label=\"Logic operator\">\r\n <button\r\n type=\"button\"\r\n class=\"c-logic-segment\"\r\n [class.c-logic-active]=\"logic() === 'AND'\"\r\n (click)=\"setLogic('AND')\">\r\n AND\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"c-logic-segment\"\r\n [class.c-logic-active]=\"logic() === 'OR'\"\r\n (click)=\"setLogic('OR')\">\r\n OR\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (showClearAll() && filtersCount() > 0) {\r\n <button\r\n type=\"button\"\r\n class=\"c-clear-all\"\r\n [matTooltip]=\"'X\u00F3a t\u1EA5t c\u1EA3 (' + filtersCount() + ')'\"\r\n (click)=\"clear.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">delete_sweep</mat-icon>\r\n </button>\r\n }\r\n\r\n <!-- why: saved-filters dropdown \u0111\u1EB7t s\u00E1t ngay tr\u01B0\u1EDBc Search \u2014 gom to\u00E0n b\u1ED9\r\n h\u00E0nh \u0111\u1ED9ng v\u1EC1 b\u1ED9 l\u1ECDc (apply view c\u0169 / l\u01B0u view hi\u1EC7n t\u1EA1i) c\u1EA1nh n\u00FAt submit,\r\n user th\u1EA5y 1 c\u1EE5m. Footer \"L\u01B0u b\u1ED9 l\u1ECDc hi\u1EC7n t\u1EA1i\" s\u1ED1ng trong mat-menu c\u1EE7a\r\n saved-filters-menu, kh\u00F4ng t\u00E1ch ra n\u00FAt ri\u00EAng n\u1EEFa. -->\r\n @if (showSavedFilters()) {\r\n <sd-query-saved-filters-menu\r\n [key]=\"savedFiltersKey()\"\r\n [query]=\"query()\"\r\n (apply)=\"applyFilter.emit($event)\" />\r\n }\r\n\r\n <!-- why: far-right \"submit at the end of the toolbar\" position; sole query trigger. -->\r\n <button\r\n type=\"button\"\r\n class=\"c-search-trigger\"\r\n [disabled]=\"!canSearch()\"\r\n matTooltip=\"T\u00ECm ki\u1EBFm\"\r\n (click)=\"search.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">search</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [":host{display:contents}.c-bar-divider{flex:0 0 auto;align-self:stretch;width:1px;min-height:28px;background:#e2e4e7}.c-query-bar__actions{flex:0 0 auto;display:flex;align-items:center;gap:6px}.c-logic-toggle{display:inline-flex;align-items:center;padding:2px;background:#f5f6f7;border:1px solid #e2e4e7;border-radius:6px}:host-context(.c-density-compact) .c-logic-toggle{height:28px}:host-context(.c-density-comfortable) .c-logic-toggle{height:32px}.c-logic-toggle .c-logic-segment{height:100%;padding:0 10px;border:none;background:transparent;font-family:Roboto Mono,monospace;font-size:11px;font-weight:600;letter-spacing:.4px;color:#5f6368;cursor:pointer;border-radius:4px}.c-logic-toggle .c-logic-segment.c-logic-active{background:#fff;color:var(--sd-primary);box-shadow:0 1px 2px #00000014}.c-clear-all,.c-search-trigger{display:inline-flex;align-items:center;justify-content:center;border:1px solid #d6d8db;border-radius:6px;background:#fff;color:#5f6368;cursor:pointer;padding:0}:host-context(.c-density-compact) .c-clear-all,:host-context(.c-density-compact) .c-search-trigger{width:28px;height:28px}:host-context(.c-density-comfortable) .c-clear-all,:host-context(.c-density-comfortable) .c-search-trigger{width:32px;height:32px}.c-clear-all mat-icon,.c-search-trigger mat-icon{font-size:18px;width:18px;height:18px}.c-clear-all:hover:not([disabled]),.c-search-trigger:hover:not([disabled]){border-color:var(--sd-primary);color:var(--sd-primary)}.c-clear-all[disabled],.c-search-trigger[disabled]{opacity:.5;cursor:not-allowed}.c-clear-all:hover{border-color:#dc2626;color:#dc2626}\n"] }]
161
154
  }] });
162
155
 
163
156
  // ---------------------------------------------------------------------------
@@ -400,11 +393,11 @@ class SdQueryInlineValueChip {
400
393
  return { ok: true, value: t };
401
394
  }
402
395
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQueryInlineValueChip, deps: [], target: i0.ɵɵFactoryTarget.Component });
403
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQueryInlineValueChip, isStandalone: true, selector: "sd-query-inline-value-chip", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, operator: { classPropertyName: "operator", publicName: "operator", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, showOperator: { classPropertyName: "showOperator", publicName: "showOperator", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", remove: "remove" }, viewQueries: [{ propertyName: "firstInput", first: true, predicate: ["firstInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Seamless string/number chip \u2014 the pill IS the input. One border, three flush\r\n segments: label \u00B7 input(s) \u00B7 \u00D7. State styling driven by [data-state].\r\n-->\r\n<span\r\n class=\"c-seamless\"\r\n [attr.data-state]=\"state()\"\r\n [class.c-seamless--compact]=\"density() === 'compact'\"\r\n [class.c-seamless--comfortable]=\"density() === 'comfortable'\"\r\n (click)=\"focusFromShell($event)\">\r\n\r\n <!-- Label segment: icon + field name (+ optional operator pill) -->\r\n <span class=\"c-seamless__label\">\r\n <mat-icon class=\"c-seamless__icon\" fontSet=\"material-icons-outlined\">{{ icon() }}</mat-icon>\r\n <span class=\"c-seamless__field\">{{ field().label }}</span>\r\n @if (showOperator() && !isNoData()) {\r\n <sd-operator class=\"c-seamless__op\" [operators]=\"[operator()]\" [model]=\"operator()\" [disabled]=\"true\" />\r\n } @else if (!isNoData()) {\r\n <span class=\"c-seamless__sep\">:</span>\r\n }\r\n </span>\r\n\r\n <!-- Input segment \u2014 transparent, borderless; hidden for NULL / NOT_NULL -->\r\n @if (!isNoData()) {\r\n <span class=\"c-seamless__input\">\r\n @if (isBetween()) {\r\n <input\r\n #firstInput\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ? autoId() + '-from' : null\"\r\n [ngModel]=\"draftFrom()\"\r\n (ngModelChange)=\"draftFrom.set($event)\"\r\n [size]=\"sizeFor(draftFrom(), phFrom())\"\r\n [placeholder]=\"phFrom()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitRange()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n <span class=\"c-seamless__dash\" aria-hidden=\"true\">\u2014</span>\r\n <input\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ? autoId() + '-to' : null\"\r\n [ngModel]=\"draftTo()\"\r\n (ngModelChange)=\"draftTo.set($event)\"\r\n [size]=\"sizeFor(draftTo(), phTo())\"\r\n [placeholder]=\"phTo()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitRange()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n } @else {\r\n <input\r\n #firstInput\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ?? null\"\r\n [ngModel]=\"draft()\"\r\n (ngModelChange)=\"draft.set($event)\"\r\n [size]=\"sizeFor(draft(), ph())\"\r\n [placeholder]=\"ph()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitSingle()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n }\r\n </span>\r\n }\r\n\r\n <!-- \u00D7 segment -->\r\n <button type=\"button\" class=\"c-seamless__x\" aria-label=\"Remove filter\" (click)=\"onRemove($event)\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n</span>\r\n", styles: [":host{display:inline-flex}.c-seamless{display:inline-flex;align-items:stretch;border-radius:999px;overflow:hidden;font-family:inherit;font-size:13px;line-height:1;cursor:text;border:1px solid #d6d8db;background:#fff;color:#5f6368;transition:border-color .12s ease,background-color .12s ease,box-shadow .12s ease,color .12s ease}.c-seamless--compact{height:28px}.c-seamless--comfortable{height:32px}.c-seamless:hover:not([data-state=focus]):not([data-state=error]){border-color:var(--sd-primary)}.c-seamless[data-state=pending]{border-style:dashed;border-color:#d6d8db;background:#fff;color:#5f6368}.c-seamless[data-state=pending] .c-seamless__field-input{color:#212121}.c-seamless[data-state=pending] .c-seamless__field-input::placeholder{color:#7a7a7a;font-style:italic}.c-seamless[data-state=active]{border-color:var(--sd-primary-light);background:var(--sd-primary-light)}.c-seamless[data-state=active] .c-seamless__field-input{color:var(--sd-primary)}.c-seamless[data-state=focus]{border-color:var(--sd-primary);background:#fff;box-shadow:0 0 0 3px var(--sd-primary-light)}.c-seamless[data-state=focus] .c-seamless__field-input{color:#212121}.c-seamless[data-state=error]{border-color:#d23535;background:#fff5f5;color:#d23535;box-shadow:0 0 0 3px #d235351f}.c-seamless[data-state=error] .c-seamless__field-input{color:#d23535}.c-seamless__label{display:inline-flex;align-items:center;gap:4px;font-weight:500;white-space:nowrap;cursor:text;color:inherit}.c-seamless--compact .c-seamless__label{padding:0 4px 0 12px}.c-seamless--comfortable .c-seamless__label{padding:0 6px 0 14px}.c-seamless__icon{font-size:14px;width:14px;height:14px;color:inherit}.c-seamless__field{color:inherit}.c-seamless__op{display:inline-flex;align-items:center;color:inherit}.c-seamless__sep{color:#7a7a7a}.c-seamless__input{display:inline-flex;align-items:center;gap:4px}.c-seamless--compact .c-seamless__input{padding:0 4px}.c-seamless--comfortable .c-seamless__input{padding:0 6px}.c-seamless__dash{color:#7a7a7a}.c-seamless__field-input{appearance:none;border:0;outline:0;background:transparent;font:inherit;font-weight:500;padding:0;min-width:24px;max-width:200px}.c-seamless__x{display:inline-flex;align-items:center;justify-content:center;border:0;border-left:1px solid rgba(0,0,0,.04);background:transparent;cursor:pointer;color:inherit}.c-seamless--compact .c-seamless__x{width:26px}.c-seamless--comfortable .c-seamless__x{width:28px}.c-seamless__x mat-icon{font-size:14px;width:14px;height:14px}.c-seamless__x:hover{background:#0000000d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SdOperator, selector: "sd-operator", inputs: ["model", "operators", "disabled", "autoId"], outputs: ["modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
396
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQueryInlineValueChip, isStandalone: true, selector: "sd-query-inline-value-chip", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, operator: { classPropertyName: "operator", publicName: "operator", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, showOperator: { classPropertyName: "showOperator", publicName: "showOperator", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", remove: "remove" }, viewQueries: [{ propertyName: "firstInput", first: true, predicate: ["firstInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Seamless string/number chip \u2014 the pill IS the input. One border, three flush\r\n segments: label \u00B7 input(s) \u00B7 \u00D7. State styling driven by [data-state].\r\n-->\r\n<span\r\n class=\"c-seamless\"\r\n [attr.data-state]=\"state()\"\r\n [class.c-seamless--compact]=\"density() === 'compact'\"\r\n [class.c-seamless--comfortable]=\"density() === 'comfortable'\"\r\n (click)=\"focusFromShell($event)\">\r\n\r\n <!-- Label segment: icon + field name (+ optional operator pill) -->\r\n <span class=\"c-seamless__label\">\r\n <mat-icon class=\"c-seamless__icon\" fontSet=\"material-icons-outlined\">{{ icon() }}</mat-icon>\r\n <span class=\"c-seamless__field\">{{ field().label }}</span>\r\n @if (showOperator() && !isNoData()) {\r\n <sd-operator class=\"c-seamless__op\" [operators]=\"[operator()]\" [model]=\"operator()\" [disabled]=\"true\" />\r\n } @else if (!isNoData()) {\r\n <span class=\"c-seamless__sep\">:</span>\r\n }\r\n </span>\r\n\r\n <!-- Input segment \u2014 transparent, borderless; hidden for NULL / NOT_NULL -->\r\n @if (!isNoData()) {\r\n <span class=\"c-seamless__input\">\r\n @if (isBetween()) {\r\n <input\r\n #firstInput\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ? autoId() + '-from' : null\"\r\n [ngModel]=\"draftFrom()\"\r\n (ngModelChange)=\"draftFrom.set($event)\"\r\n [size]=\"sizeFor(draftFrom(), phFrom())\"\r\n [placeholder]=\"phFrom()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitRange()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n <span class=\"c-seamless__dash\" aria-hidden=\"true\">\u2014</span>\r\n <input\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ? autoId() + '-to' : null\"\r\n [ngModel]=\"draftTo()\"\r\n (ngModelChange)=\"draftTo.set($event)\"\r\n [size]=\"sizeFor(draftTo(), phTo())\"\r\n [placeholder]=\"phTo()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitRange()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n } @else {\r\n <input\r\n #firstInput\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ?? null\"\r\n [ngModel]=\"draft()\"\r\n (ngModelChange)=\"draft.set($event)\"\r\n [size]=\"sizeFor(draft(), ph())\"\r\n [placeholder]=\"ph()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitSingle()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n }\r\n </span>\r\n }\r\n\r\n <!-- \u00D7 segment -->\r\n <button type=\"button\" class=\"c-seamless__x\" aria-label=\"Remove filter\" (click)=\"onRemove($event)\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n</span>\r\n", styles: [":host{display:inline-flex}.c-seamless{display:inline-flex;align-items:stretch;border-radius:999px;overflow:hidden;font-family:inherit;font-size:13px;line-height:1;cursor:text;border:1px solid #d6d8db;background:#fff;color:#5f6368;transition:border-color .12s ease,background-color .12s ease,box-shadow .12s ease,color .12s ease}.c-seamless--compact{height:28px}.c-seamless--comfortable{height:32px}.c-seamless:hover:not([data-state=focus]):not([data-state=error]){border-color:var(--sd-primary)}.c-seamless[data-state=pending]{border-style:dashed;border-color:#d6d8db;background:#fff;color:#5f6368}.c-seamless[data-state=pending] .c-seamless__field-input{color:#212121}.c-seamless[data-state=pending] .c-seamless__field-input::placeholder{color:#7a7a7a;font-style:italic}.c-seamless[data-state=active]{border-color:var(--sd-primary-light);background:var(--sd-primary-light)}.c-seamless[data-state=active] .c-seamless__field-input{color:var(--sd-primary)}.c-seamless[data-state=focus]{border-color:var(--sd-primary);background:#fff;box-shadow:0 0 0 3px var(--sd-primary-light)}.c-seamless[data-state=focus] .c-seamless__field-input{color:#212121}.c-seamless[data-state=error]{border-color:#d23535;background:#fff5f5;color:#d23535;box-shadow:0 0 0 3px #d235351f}.c-seamless[data-state=error] .c-seamless__field-input{color:#d23535}.c-seamless__label{display:inline-flex;align-items:center;gap:4px;font-weight:500;white-space:nowrap;cursor:text;color:inherit}.c-seamless--compact .c-seamless__label{padding:0 0 0 12px}.c-seamless--comfortable .c-seamless__label{padding:0 0 0 14px}.c-seamless__icon{font-size:14px;width:14px;height:14px;color:inherit}.c-seamless__field{color:inherit}.c-seamless__op{display:inline-flex;align-items:center;color:inherit}.c-seamless__sep{color:#7a7a7a}.c-seamless__input{display:inline-flex;align-items:center;gap:4px}.c-seamless--compact .c-seamless__input{padding:0 8px 0 4px}.c-seamless--comfortable .c-seamless__input{padding:0 10px 0 6px}.c-seamless__dash{color:#7a7a7a}.c-seamless__field-input{appearance:none;border:0;outline:0;background:transparent;font:inherit;font-weight:500;padding:0;min-width:24px;max-width:200px}.c-seamless__x{display:inline-flex;align-items:center;justify-content:center;border:0;border-left:1px solid rgba(0,0,0,.04);background:transparent;cursor:pointer;color:inherit}.c-seamless--compact .c-seamless__x{width:26px}.c-seamless--comfortable .c-seamless__x{width:28px}.c-seamless__x mat-icon{font-size:14px;width:14px;height:14px}.c-seamless__x:hover{background:#0000000d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SdOperator, selector: "sd-operator", inputs: ["model", "operators", "disabled", "autoId"], outputs: ["modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
404
397
  }
405
398
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQueryInlineValueChip, decorators: [{
406
399
  type: Component,
407
- args: [{ selector: 'sd-query-inline-value-chip', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, MatIconModule, SdOperator], template: "<!--\r\n Seamless string/number chip \u2014 the pill IS the input. One border, three flush\r\n segments: label \u00B7 input(s) \u00B7 \u00D7. State styling driven by [data-state].\r\n-->\r\n<span\r\n class=\"c-seamless\"\r\n [attr.data-state]=\"state()\"\r\n [class.c-seamless--compact]=\"density() === 'compact'\"\r\n [class.c-seamless--comfortable]=\"density() === 'comfortable'\"\r\n (click)=\"focusFromShell($event)\">\r\n\r\n <!-- Label segment: icon + field name (+ optional operator pill) -->\r\n <span class=\"c-seamless__label\">\r\n <mat-icon class=\"c-seamless__icon\" fontSet=\"material-icons-outlined\">{{ icon() }}</mat-icon>\r\n <span class=\"c-seamless__field\">{{ field().label }}</span>\r\n @if (showOperator() && !isNoData()) {\r\n <sd-operator class=\"c-seamless__op\" [operators]=\"[operator()]\" [model]=\"operator()\" [disabled]=\"true\" />\r\n } @else if (!isNoData()) {\r\n <span class=\"c-seamless__sep\">:</span>\r\n }\r\n </span>\r\n\r\n <!-- Input segment \u2014 transparent, borderless; hidden for NULL / NOT_NULL -->\r\n @if (!isNoData()) {\r\n <span class=\"c-seamless__input\">\r\n @if (isBetween()) {\r\n <input\r\n #firstInput\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ? autoId() + '-from' : null\"\r\n [ngModel]=\"draftFrom()\"\r\n (ngModelChange)=\"draftFrom.set($event)\"\r\n [size]=\"sizeFor(draftFrom(), phFrom())\"\r\n [placeholder]=\"phFrom()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitRange()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n <span class=\"c-seamless__dash\" aria-hidden=\"true\">\u2014</span>\r\n <input\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ? autoId() + '-to' : null\"\r\n [ngModel]=\"draftTo()\"\r\n (ngModelChange)=\"draftTo.set($event)\"\r\n [size]=\"sizeFor(draftTo(), phTo())\"\r\n [placeholder]=\"phTo()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitRange()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n } @else {\r\n <input\r\n #firstInput\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ?? null\"\r\n [ngModel]=\"draft()\"\r\n (ngModelChange)=\"draft.set($event)\"\r\n [size]=\"sizeFor(draft(), ph())\"\r\n [placeholder]=\"ph()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitSingle()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n }\r\n </span>\r\n }\r\n\r\n <!-- \u00D7 segment -->\r\n <button type=\"button\" class=\"c-seamless__x\" aria-label=\"Remove filter\" (click)=\"onRemove($event)\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n</span>\r\n", styles: [":host{display:inline-flex}.c-seamless{display:inline-flex;align-items:stretch;border-radius:999px;overflow:hidden;font-family:inherit;font-size:13px;line-height:1;cursor:text;border:1px solid #d6d8db;background:#fff;color:#5f6368;transition:border-color .12s ease,background-color .12s ease,box-shadow .12s ease,color .12s ease}.c-seamless--compact{height:28px}.c-seamless--comfortable{height:32px}.c-seamless:hover:not([data-state=focus]):not([data-state=error]){border-color:var(--sd-primary)}.c-seamless[data-state=pending]{border-style:dashed;border-color:#d6d8db;background:#fff;color:#5f6368}.c-seamless[data-state=pending] .c-seamless__field-input{color:#212121}.c-seamless[data-state=pending] .c-seamless__field-input::placeholder{color:#7a7a7a;font-style:italic}.c-seamless[data-state=active]{border-color:var(--sd-primary-light);background:var(--sd-primary-light)}.c-seamless[data-state=active] .c-seamless__field-input{color:var(--sd-primary)}.c-seamless[data-state=focus]{border-color:var(--sd-primary);background:#fff;box-shadow:0 0 0 3px var(--sd-primary-light)}.c-seamless[data-state=focus] .c-seamless__field-input{color:#212121}.c-seamless[data-state=error]{border-color:#d23535;background:#fff5f5;color:#d23535;box-shadow:0 0 0 3px #d235351f}.c-seamless[data-state=error] .c-seamless__field-input{color:#d23535}.c-seamless__label{display:inline-flex;align-items:center;gap:4px;font-weight:500;white-space:nowrap;cursor:text;color:inherit}.c-seamless--compact .c-seamless__label{padding:0 4px 0 12px}.c-seamless--comfortable .c-seamless__label{padding:0 6px 0 14px}.c-seamless__icon{font-size:14px;width:14px;height:14px;color:inherit}.c-seamless__field{color:inherit}.c-seamless__op{display:inline-flex;align-items:center;color:inherit}.c-seamless__sep{color:#7a7a7a}.c-seamless__input{display:inline-flex;align-items:center;gap:4px}.c-seamless--compact .c-seamless__input{padding:0 4px}.c-seamless--comfortable .c-seamless__input{padding:0 6px}.c-seamless__dash{color:#7a7a7a}.c-seamless__field-input{appearance:none;border:0;outline:0;background:transparent;font:inherit;font-weight:500;padding:0;min-width:24px;max-width:200px}.c-seamless__x{display:inline-flex;align-items:center;justify-content:center;border:0;border-left:1px solid rgba(0,0,0,.04);background:transparent;cursor:pointer;color:inherit}.c-seamless--compact .c-seamless__x{width:26px}.c-seamless--comfortable .c-seamless__x{width:28px}.c-seamless__x mat-icon{font-size:14px;width:14px;height:14px}.c-seamless__x:hover{background:#0000000d}\n"] }]
400
+ args: [{ selector: 'sd-query-inline-value-chip', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, MatIconModule, SdOperator], template: "<!--\r\n Seamless string/number chip \u2014 the pill IS the input. One border, three flush\r\n segments: label \u00B7 input(s) \u00B7 \u00D7. State styling driven by [data-state].\r\n-->\r\n<span\r\n class=\"c-seamless\"\r\n [attr.data-state]=\"state()\"\r\n [class.c-seamless--compact]=\"density() === 'compact'\"\r\n [class.c-seamless--comfortable]=\"density() === 'comfortable'\"\r\n (click)=\"focusFromShell($event)\">\r\n\r\n <!-- Label segment: icon + field name (+ optional operator pill) -->\r\n <span class=\"c-seamless__label\">\r\n <mat-icon class=\"c-seamless__icon\" fontSet=\"material-icons-outlined\">{{ icon() }}</mat-icon>\r\n <span class=\"c-seamless__field\">{{ field().label }}</span>\r\n @if (showOperator() && !isNoData()) {\r\n <sd-operator class=\"c-seamless__op\" [operators]=\"[operator()]\" [model]=\"operator()\" [disabled]=\"true\" />\r\n } @else if (!isNoData()) {\r\n <span class=\"c-seamless__sep\">:</span>\r\n }\r\n </span>\r\n\r\n <!-- Input segment \u2014 transparent, borderless; hidden for NULL / NOT_NULL -->\r\n @if (!isNoData()) {\r\n <span class=\"c-seamless__input\">\r\n @if (isBetween()) {\r\n <input\r\n #firstInput\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ? autoId() + '-from' : null\"\r\n [ngModel]=\"draftFrom()\"\r\n (ngModelChange)=\"draftFrom.set($event)\"\r\n [size]=\"sizeFor(draftFrom(), phFrom())\"\r\n [placeholder]=\"phFrom()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitRange()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n <span class=\"c-seamless__dash\" aria-hidden=\"true\">\u2014</span>\r\n <input\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ? autoId() + '-to' : null\"\r\n [ngModel]=\"draftTo()\"\r\n (ngModelChange)=\"draftTo.set($event)\"\r\n [size]=\"sizeFor(draftTo(), phTo())\"\r\n [placeholder]=\"phTo()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitRange()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n } @else {\r\n <input\r\n #firstInput\r\n type=\"text\"\r\n class=\"c-seamless__field-input\"\r\n [attr.data-autoid]=\"autoId() ?? null\"\r\n [ngModel]=\"draft()\"\r\n (ngModelChange)=\"draft.set($event)\"\r\n [size]=\"sizeFor(draft(), ph())\"\r\n [placeholder]=\"ph()\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"commitSingle()\"\r\n (keydown.enter)=\"$any($event.target).blur()\"\r\n (keydown.escape)=\"revertAndBlur($any($event.target))\" />\r\n }\r\n </span>\r\n }\r\n\r\n <!-- \u00D7 segment -->\r\n <button type=\"button\" class=\"c-seamless__x\" aria-label=\"Remove filter\" (click)=\"onRemove($event)\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n</span>\r\n", styles: [":host{display:inline-flex}.c-seamless{display:inline-flex;align-items:stretch;border-radius:999px;overflow:hidden;font-family:inherit;font-size:13px;line-height:1;cursor:text;border:1px solid #d6d8db;background:#fff;color:#5f6368;transition:border-color .12s ease,background-color .12s ease,box-shadow .12s ease,color .12s ease}.c-seamless--compact{height:28px}.c-seamless--comfortable{height:32px}.c-seamless:hover:not([data-state=focus]):not([data-state=error]){border-color:var(--sd-primary)}.c-seamless[data-state=pending]{border-style:dashed;border-color:#d6d8db;background:#fff;color:#5f6368}.c-seamless[data-state=pending] .c-seamless__field-input{color:#212121}.c-seamless[data-state=pending] .c-seamless__field-input::placeholder{color:#7a7a7a;font-style:italic}.c-seamless[data-state=active]{border-color:var(--sd-primary-light);background:var(--sd-primary-light)}.c-seamless[data-state=active] .c-seamless__field-input{color:var(--sd-primary)}.c-seamless[data-state=focus]{border-color:var(--sd-primary);background:#fff;box-shadow:0 0 0 3px var(--sd-primary-light)}.c-seamless[data-state=focus] .c-seamless__field-input{color:#212121}.c-seamless[data-state=error]{border-color:#d23535;background:#fff5f5;color:#d23535;box-shadow:0 0 0 3px #d235351f}.c-seamless[data-state=error] .c-seamless__field-input{color:#d23535}.c-seamless__label{display:inline-flex;align-items:center;gap:4px;font-weight:500;white-space:nowrap;cursor:text;color:inherit}.c-seamless--compact .c-seamless__label{padding:0 0 0 12px}.c-seamless--comfortable .c-seamless__label{padding:0 0 0 14px}.c-seamless__icon{font-size:14px;width:14px;height:14px;color:inherit}.c-seamless__field{color:inherit}.c-seamless__op{display:inline-flex;align-items:center;color:inherit}.c-seamless__sep{color:#7a7a7a}.c-seamless__input{display:inline-flex;align-items:center;gap:4px}.c-seamless--compact .c-seamless__input{padding:0 8px 0 4px}.c-seamless--comfortable .c-seamless__input{padding:0 10px 0 6px}.c-seamless__dash{color:#7a7a7a}.c-seamless__field-input{appearance:none;border:0;outline:0;background:transparent;font:inherit;font-weight:500;padding:0;min-width:24px;max-width:200px}.c-seamless__x{display:inline-flex;align-items:center;justify-content:center;border:0;border-left:1px solid rgba(0,0,0,.04);background:transparent;cursor:pointer;color:inherit}.c-seamless--compact .c-seamless__x{width:26px}.c-seamless--comfortable .c-seamless__x{width:28px}.c-seamless__x mat-icon{font-size:14px;width:14px;height:14px}.c-seamless__x:hover{background:#0000000d}\n"] }]
408
401
  }], ctorParameters: () => [] });
409
402
 
410
403
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -487,14 +480,13 @@ class SdQueryBuildChip {
487
480
  return t === 'string' || t === 'number';
488
481
  });
489
482
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQueryBuildChip, deps: [], target: i0.ɵɵFactoryTarget.Component });
490
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQueryBuildChip, isStandalone: true, selector: "sd-query-build-chip", inputs: { building: { classPropertyName: "building", publicName: "building", isSignal: true, isRequired: true, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, allowedOperators: { classPropertyName: "allowedOperators", publicName: "allowedOperators", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, showOperator: { classPropertyName: "showOperator", publicName: "showOperator", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pickOperator: "pickOperator", commitValue: "commitValue", cancel: "cancel", seamlessCommit: "seamlessCommit", draftChange: "draftChange", draftCommit: "draftCommit" }, viewQueries: [{ propertyName: "opMenu", first: true, predicate: ["buildOperator"], descendants: true, isSignal: true }, { propertyName: "picker", first: true, predicate: ["bPicker"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n In-progress chip (inline-mode token build flow).\r\n Seamless string/number branch keeps its own pill; everything else renders inside\r\n the dashed .c-token.c-token-building shell.\r\n-->\r\n@let _b = building();\r\n\r\n@if (isSeamless()) {\r\n <sd-query-inline-value-chip\r\n [field]=\"_b.field\"\r\n [operator]=\"$any(_b.operator)\"\r\n [value]=\"_b.value ?? null\"\r\n [density]=\"density()\"\r\n [showOperator]=\"showOperator()\"\r\n [autoId]=\"autoId()\"\r\n [autofocus]=\"true\"\r\n (valueChange)=\"seamlessCommit.emit($event)\"\r\n (remove)=\"cancel.emit()\" />\r\n} @else {\r\n <div class=\"c-token c-token-building\">\r\n <span class=\"c-token-field\">{{ _b.field.label }}</span>\r\n\r\n @if (_b.step === 'operator') {\r\n <sd-operator\r\n #buildOperator\r\n class=\"c-token-op\"\r\n [operators]=\"allowedOperators()\"\r\n [model]=\"_b.operator\"\r\n (modelChange)=\"pickOperator.emit($any($event))\" />\r\n } @else {\r\n <!-- why: badge readonly cho operator \u0111\u00E3 ch\u1ECDn \u2014 v\u1EABn render <sd-operator>\r\n \u0111\u1EC3 gi\u1EEF th\u1ECB gi\u00E1c gi\u1ED1ng chip ho\u00E0n th\u00E0nh (icon + tooltip). -->\r\n <sd-operator\r\n class=\"c-token-op\"\r\n [operators]=\"[$any(_b.operator)]\"\r\n [model]=\"$any(_b.operator)\"\r\n [disabled]=\"true\" />\r\n\r\n @if (_b.field.type === 'values' || _b.field.type === 'lazy-values') {\r\n @let _bopt = $any(_b.field).option;\r\n <span class=\"c-token-value c-token-value-edit\">\r\n <sd-select #bPicker bare size=\"sm\" minWidthPanel=\"300px\"\r\n [autoId]=\"autoId()\"\r\n [items]=\"_b.field.type === 'lazy-values' ? $any(_bopt).search : $any(_bopt.items)\"\r\n [valueField]=\"_bopt.valueField\"\r\n [displayField]=\"_bopt.displayField\"\r\n [multiple]=\"multiple()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\">\r\n <!-- why: build chip multi-select c\u0169ng c\u1EA7n \"head +N\" \u0111\u1EC3 g\u1ECDn (gi\u1ED1ng completed chip). -->\r\n <ng-template #sdValue let-selectedItems=\"selectedItems\">\r\n @if ((selectedItems?.length ?? 0) > 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_bopt.displayField] }}</span> +{{ selectedItems.length - 1 }}\r\n } @else if ((selectedItems?.length ?? 0) === 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_bopt.displayField] }}</span>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n </span>\r\n } @else if (_b.field.type === 'date') {\r\n <span class=\"c-token-value c-token-value-edit\">\r\n @if (_b.operator === 'BETWEEN') {\r\n <!-- why: 1 sd-date-range thay 2 sd-date \u2014 g\u1ECDn h\u01A1n, h\u00E0nh vi th\u1ED1ng nh\u1EA5t v\u1EDBi completed chip. -->\r\n <sd-date-range #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date-range>\r\n } @else {\r\n <sd-date #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date>\r\n }\r\n </span>\r\n } @else if (_b.field.type === 'datetime') {\r\n <span class=\"c-token-value c-token-value-edit\">\r\n @if (_b.operator === 'BETWEEN') {\r\n <!-- why: datetime BETWEEN downgrade v\u1EC1 date-range (m\u1EA5t time precision; \u0111\u00E3 th\u1ED1ng nh\u1EA5t). -->\r\n <sd-date-range #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date-range>\r\n } @else {\r\n <sd-datetime #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-datetime>\r\n }\r\n </span>\r\n } @else if (_b.field.type === 'boolean') {\r\n <!-- why: boolean c\u0169ng d\u00F9ng nguy\u00EAn giao di\u1EC7n 2 n\u00FAt toggle \u1EDF build chip (gi\u1ED1ng popover);\r\n click commit tr\u1EF1c ti\u1EBFp gi\u00E1 tr\u1ECB, kh\u00F4ng qua draft. -->\r\n <span class=\"c-token-value c-token-value-edit c-bool-toggle\">\r\n <sd-button\r\n [autoId]=\"autoId() + '-true'\"\r\n [type]=\"_b.value === true ? 'fill' : 'outline'\"\r\n color=\"success\"\r\n [title]=\"$any(_b.field).trueLabel || 'C\u00F3'\"\r\n (click)=\"commitValue.emit(true)\"></sd-button>\r\n <sd-button\r\n [autoId]=\"autoId() + '-false'\"\r\n [type]=\"_b.value === false ? 'fill' : 'outline'\"\r\n color=\"warning\"\r\n [title]=\"$any(_b.field).falseLabel || 'Kh\u00F4ng'\"\r\n (click)=\"commitValue.emit(false)\"></sd-button>\r\n </span>\r\n } @else {\r\n <!-- Fallback (e.g. unforeseen type) \u2014 generic sd-input wired via draft outputs. -->\r\n <span class=\"c-token-value c-token-value-edit\">\r\n <sd-input size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"draftChange.emit($event)\"\r\n (keyupEnter)=\"draftCommit.emit()\"></sd-input>\r\n </span>\r\n }\r\n }\r\n\r\n <button type=\"button\" class=\"c-token-remove\" aria-label=\"Cancel\" (click)=\"cancel.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n </div>\r\n}\r\n", styles: [":host{display:contents}.c-token{display:inline-flex;align-items:center;gap:4px;padding:0 0 0 12px;border:1px solid var(--sd-primary-light);border-radius:999px;background:var(--sd-primary-light);font-size:13px;color:#5f6368;white-space:nowrap;overflow:hidden}:host-context(.c-density-compact) .c-token{height:28px}:host-context(.c-density-comfortable) .c-token{height:32px}.c-token-field{font-weight:500;line-height:1}.c-token-op{display:inline-flex;align-items:center;color:inherit}.c-token-op ::ng-deep .c-op-trigger{padding:0;color:inherit}.c-token-op ::ng-deep .c-op-icon svg{width:14px;height:14px;display:block}.c-token-value{border:none;background:transparent;padding:0;font:inherit;font-weight:500;color:var(--sd-primary)}.c-token-value-edit{display:inline-flex;align-items:center;gap:4px;max-width:240px}.c-token-value-edit sd-input,.c-token-value-edit sd-input-number{display:inline-flex;max-width:140px}.c-token-value-edit sd-date-range{display:inline-flex;max-width:220px;min-width:0;flex:0 1 auto}.c-token-value-edit sd-select,.c-token-value-edit sd-date,.c-token-value-edit sd-datetime{display:inline-flex;align-items:center;line-height:1}.c-token ::ng-deep .mat-mdc-form-field{line-height:1}.c-token ::ng-deep .mat-mdc-text-field-wrapper,.c-token ::ng-deep .mat-mdc-form-field-flex{padding:0;min-height:0;background:transparent}.c-token ::ng-deep .mat-mdc-form-field-infix{padding:0;min-height:0;width:auto;border:0;display:inline-flex;align-items:center}.c-token ::ng-deep .mat-mdc-select-value,.c-token ::ng-deep .mat-mdc-input-element,.c-token ::ng-deep input{line-height:1;font-size:13px;padding:0;height:auto;color:inherit}.c-token ::ng-deep .mat-mdc-select-value{display:inline-flex;align-items:center;min-width:0;max-width:200px;overflow:hidden;text-overflow:ellipsis;color:var(--sd-primary);font-weight:500}.c-token ::ng-deep .sd-suffix-icon{display:none}.c-token-multi-head{display:inline-block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.c-token-building{border-style:dashed}.c-token-remove{align-self:stretch;display:inline-flex;align-items:center;justify-content:center;border:none;border-left:1px solid rgba(0,0,0,.04);border-radius:0;background:transparent;cursor:pointer;color:inherit}:host-context(.c-density-compact) .c-token-remove{width:26px}:host-context(.c-density-comfortable) .c-token-remove{width:28px}.c-token-remove mat-icon{font-size:14px;width:14px;height:14px}.c-token-remove:hover{background:#0000000d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdOperator, selector: "sd-operator", inputs: ["model", "operators", "disabled", "autoId"], outputs: ["modelChange"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdQueryInlineValueChip, selector: "sd-query-inline-value-chip", inputs: ["field", "operator", "value", "density", "showOperator", "autoId", "autofocus"], outputs: ["valueChange", "remove"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
483
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQueryBuildChip, isStandalone: true, selector: "sd-query-build-chip", inputs: { building: { classPropertyName: "building", publicName: "building", isSignal: true, isRequired: true, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, allowedOperators: { classPropertyName: "allowedOperators", publicName: "allowedOperators", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, showOperator: { classPropertyName: "showOperator", publicName: "showOperator", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pickOperator: "pickOperator", commitValue: "commitValue", cancel: "cancel", seamlessCommit: "seamlessCommit", draftChange: "draftChange", draftCommit: "draftCommit" }, viewQueries: [{ propertyName: "opMenu", first: true, predicate: ["buildOperator"], descendants: true, isSignal: true }, { propertyName: "picker", first: true, predicate: ["bPicker"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n In-progress chip (inline-mode token build flow).\r\n Seamless string/number branch keeps its own pill; everything else renders inside\r\n the dashed .c-token.c-token-building shell.\r\n-->\r\n@let _b = building();\r\n\r\n@if (isSeamless()) {\r\n <sd-query-inline-value-chip\r\n [field]=\"_b.field\"\r\n [operator]=\"$any(_b.operator)\"\r\n [value]=\"_b.value ?? null\"\r\n [density]=\"density()\"\r\n [showOperator]=\"showOperator()\"\r\n [autoId]=\"autoId()\"\r\n [autofocus]=\"true\"\r\n (valueChange)=\"seamlessCommit.emit($event)\"\r\n (remove)=\"cancel.emit()\" />\r\n} @else {\r\n <div class=\"c-token c-token-building\">\r\n <span class=\"c-token-field\">{{ _b.field.label }}</span>\r\n\r\n @if (_b.step === 'operator') {\r\n <sd-operator\r\n #buildOperator\r\n class=\"c-token-op\"\r\n [operators]=\"allowedOperators()\"\r\n [model]=\"_b.operator\"\r\n (modelChange)=\"pickOperator.emit($any($event))\" />\r\n } @else {\r\n <!-- why: badge readonly cho operator \u0111\u00E3 ch\u1ECDn \u2014 v\u1EABn render <sd-operator>\r\n \u0111\u1EC3 gi\u1EEF th\u1ECB gi\u00E1c gi\u1ED1ng chip ho\u00E0n th\u00E0nh (icon + tooltip). -->\r\n <sd-operator\r\n class=\"c-token-op\"\r\n [operators]=\"[$any(_b.operator)]\"\r\n [model]=\"$any(_b.operator)\"\r\n [disabled]=\"true\" />\r\n\r\n @if (_b.field.type === 'values' || _b.field.type === 'lazy-values') {\r\n @let _bopt = $any(_b.field).option;\r\n <span class=\"c-token-value c-token-value-edit\">\r\n <sd-select #bPicker bare size=\"sm\" minWidthPanel=\"300px\"\r\n [autoId]=\"autoId()\"\r\n [items]=\"_b.field.type === 'lazy-values' ? $any(_bopt).search : $any(_bopt.items)\"\r\n [valueField]=\"_bopt.valueField\"\r\n [displayField]=\"_bopt.displayField\"\r\n [multiple]=\"multiple()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\">\r\n <!-- why: build chip multi-select c\u0169ng c\u1EA7n \"head +N\" \u0111\u1EC3 g\u1ECDn (gi\u1ED1ng completed chip). -->\r\n <ng-template #sdValue let-selectedItems=\"selectedItems\">\r\n @if ((selectedItems?.length ?? 0) > 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_bopt.displayField] }}</span> +{{ selectedItems.length - 1 }}\r\n } @else if ((selectedItems?.length ?? 0) === 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_bopt.displayField] }}</span>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n </span>\r\n } @else if (_b.field.type === 'date') {\r\n <span class=\"c-token-value c-token-value-edit\">\r\n @if (_b.operator === 'BETWEEN') {\r\n <!-- why: 1 sd-date-range thay 2 sd-date \u2014 g\u1ECDn h\u01A1n, h\u00E0nh vi th\u1ED1ng nh\u1EA5t v\u1EDBi completed chip. -->\r\n <sd-date-range #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date-range>\r\n } @else {\r\n <sd-date #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date>\r\n }\r\n </span>\r\n } @else if (_b.field.type === 'datetime') {\r\n <span class=\"c-token-value c-token-value-edit\">\r\n @if (_b.operator === 'BETWEEN') {\r\n <!-- why: datetime BETWEEN downgrade v\u1EC1 date-range (m\u1EA5t time precision; \u0111\u00E3 th\u1ED1ng nh\u1EA5t). -->\r\n <sd-date-range #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date-range>\r\n } @else {\r\n <sd-datetime #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-datetime>\r\n }\r\n </span>\r\n } @else if (_b.field.type === 'boolean') {\r\n <!-- why: native button thay sd-button (tr\u00E1nh mat-button baseline 36px g\u00E2y tr\u00E0n).\r\n Pill nh\u1ECF v\u1EBD b\u1EB1ng CSS scoped trong chip \u2014 gi\u1EEF semantic colour qua class\r\n .c-bool-true / .c-bool-false. -->\r\n <span class=\"c-token-value c-token-value-edit c-bool-toggle\">\r\n <button\r\n type=\"button\"\r\n class=\"c-bool-btn c-bool-true\"\r\n [class.c-bool-active]=\"_b.value === true\"\r\n [attr.data-autoId]=\"autoId() + '-true'\"\r\n (click)=\"commitValue.emit(true)\">\r\n {{ $any(_b.field).trueLabel || 'C\u00F3' }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"c-bool-btn c-bool-false\"\r\n [class.c-bool-active]=\"_b.value === false\"\r\n [attr.data-autoId]=\"autoId() + '-false'\"\r\n (click)=\"commitValue.emit(false)\">\r\n {{ $any(_b.field).falseLabel || 'Kh\u00F4ng' }}\r\n </button>\r\n </span>\r\n } @else {\r\n <!-- Fallback (e.g. unforeseen type) \u2014 generic sd-input wired via draft outputs. -->\r\n <span class=\"c-token-value c-token-value-edit\">\r\n <sd-input size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"draftChange.emit($event)\"\r\n (keyupEnter)=\"draftCommit.emit()\"></sd-input>\r\n </span>\r\n }\r\n }\r\n\r\n <button type=\"button\" class=\"c-token-remove\" aria-label=\"Cancel\" (click)=\"cancel.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n </div>\r\n}\r\n", styles: [":host{display:contents}.c-token{display:inline-flex;align-items:center;gap:4px;padding:0 0 0 12px;border:1px solid var(--sd-primary-light);border-radius:999px;background:var(--sd-primary-light);font-size:13px;color:#5f6368;white-space:nowrap;overflow:hidden}:host-context(.c-density-compact) .c-token{height:28px}:host-context(.c-density-comfortable) .c-token{height:32px}.c-token-field{font-weight:500;line-height:1}.c-token-op{display:inline-flex;align-items:center;color:inherit}.c-token-op ::ng-deep .c-op-trigger{padding:0;color:inherit}.c-token-op ::ng-deep .c-op-icon svg{width:14px;height:14px;display:block}.c-token-value{border:none;background:transparent;padding:0;font:inherit;font-weight:500;color:var(--sd-primary)}.c-token-value-edit{display:inline-flex;align-items:center;gap:4px;max-width:240px}.c-token-value-edit sd-input,.c-token-value-edit sd-input-number{display:inline-flex;max-width:140px}.c-token-value-edit sd-date-range{display:inline-flex;max-width:220px;min-width:0;flex:0 1 auto}.c-token-value-edit sd-select,.c-token-value-edit sd-date,.c-token-value-edit sd-datetime{display:inline-flex;align-items:center;line-height:1}.c-token ::ng-deep .mat-mdc-form-field{line-height:1}.c-token ::ng-deep .mat-mdc-text-field-wrapper,.c-token ::ng-deep .mat-mdc-form-field-flex{padding:0;min-height:0;background:transparent}.c-token ::ng-deep .mat-mdc-form-field-infix{padding:0;min-height:0;width:auto;border:0;display:inline-flex;align-items:center}.c-token ::ng-deep .mat-mdc-select-value,.c-token ::ng-deep .mat-mdc-input-element,.c-token ::ng-deep input{line-height:1;font-size:13px;padding:0;height:auto;color:inherit}.c-token ::ng-deep .mat-mdc-select-value{display:inline-flex;align-items:center;min-width:0;max-width:200px;overflow:hidden;text-overflow:ellipsis;color:var(--sd-primary);font-weight:500}.c-token ::ng-deep .sd-suffix-icon{display:none}.c-token-multi-head{display:inline-block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.c-token-building{border-style:dashed}.c-bool-toggle{display:inline-flex;align-items:center;gap:4px}.c-bool-btn{display:inline-flex;align-items:center;justify-content:center;height:18px;min-width:0;padding:0 8px;border:1px solid currentColor;border-radius:999px;background:transparent;font:inherit;font-size:11px;font-weight:500;line-height:1;cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:background .12s ease,color .12s ease}:host-context(.c-density-comfortable) .c-bool-btn{height:20px;padding:0 10px;font-size:12px}.c-bool-true{color:var(--sd-success)}.c-bool-false{color:var(--sd-warning)}.c-bool-active.c-bool-true{background:var(--sd-success);color:#fff;border-color:var(--sd-success)}.c-bool-active.c-bool-false{background:var(--sd-warning);color:#fff;border-color:var(--sd-warning)}.c-bool-btn:hover:not(.c-bool-active).c-bool-true{background:var(--sd-success-light)}.c-bool-btn:hover:not(.c-bool-active).c-bool-false{background:var(--sd-warning-light)}.c-token-remove{align-self:stretch;display:inline-flex;align-items:center;justify-content:center;border:none;border-left:1px solid rgba(0,0,0,.04);border-radius:0;background:transparent;cursor:pointer;color:inherit}:host-context(.c-density-compact) .c-token-remove{width:26px}:host-context(.c-density-comfortable) .c-token-remove{width:28px}.c-token-remove mat-icon{font-size:14px;width:14px;height:14px}.c-token-remove:hover{background:#0000000d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SdOperator, selector: "sd-operator", inputs: ["model", "operators", "disabled", "autoId"], outputs: ["modelChange"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdQueryInlineValueChip, selector: "sd-query-inline-value-chip", inputs: ["field", "operator", "value", "density", "showOperator", "autoId", "autofocus"], outputs: ["valueChange", "remove"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
491
484
  }
492
485
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQueryBuildChip, decorators: [{
493
486
  type: Component,
494
487
  args: [{ selector: 'sd-query-build-chip', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
495
488
  CommonModule,
496
489
  MatIconModule,
497
- SdButton,
498
490
  SdOperator,
499
491
  SdDate,
500
492
  SdDateRange,
@@ -503,7 +495,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
503
495
  SdInputNumber,
504
496
  SdSelect,
505
497
  SdQueryInlineValueChip,
506
- ], template: "<!--\r\n In-progress chip (inline-mode token build flow).\r\n Seamless string/number branch keeps its own pill; everything else renders inside\r\n the dashed .c-token.c-token-building shell.\r\n-->\r\n@let _b = building();\r\n\r\n@if (isSeamless()) {\r\n <sd-query-inline-value-chip\r\n [field]=\"_b.field\"\r\n [operator]=\"$any(_b.operator)\"\r\n [value]=\"_b.value ?? null\"\r\n [density]=\"density()\"\r\n [showOperator]=\"showOperator()\"\r\n [autoId]=\"autoId()\"\r\n [autofocus]=\"true\"\r\n (valueChange)=\"seamlessCommit.emit($event)\"\r\n (remove)=\"cancel.emit()\" />\r\n} @else {\r\n <div class=\"c-token c-token-building\">\r\n <span class=\"c-token-field\">{{ _b.field.label }}</span>\r\n\r\n @if (_b.step === 'operator') {\r\n <sd-operator\r\n #buildOperator\r\n class=\"c-token-op\"\r\n [operators]=\"allowedOperators()\"\r\n [model]=\"_b.operator\"\r\n (modelChange)=\"pickOperator.emit($any($event))\" />\r\n } @else {\r\n <!-- why: badge readonly cho operator \u0111\u00E3 ch\u1ECDn \u2014 v\u1EABn render <sd-operator>\r\n \u0111\u1EC3 gi\u1EEF th\u1ECB gi\u00E1c gi\u1ED1ng chip ho\u00E0n th\u00E0nh (icon + tooltip). -->\r\n <sd-operator\r\n class=\"c-token-op\"\r\n [operators]=\"[$any(_b.operator)]\"\r\n [model]=\"$any(_b.operator)\"\r\n [disabled]=\"true\" />\r\n\r\n @if (_b.field.type === 'values' || _b.field.type === 'lazy-values') {\r\n @let _bopt = $any(_b.field).option;\r\n <span class=\"c-token-value c-token-value-edit\">\r\n <sd-select #bPicker bare size=\"sm\" minWidthPanel=\"300px\"\r\n [autoId]=\"autoId()\"\r\n [items]=\"_b.field.type === 'lazy-values' ? $any(_bopt).search : $any(_bopt.items)\"\r\n [valueField]=\"_bopt.valueField\"\r\n [displayField]=\"_bopt.displayField\"\r\n [multiple]=\"multiple()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\">\r\n <!-- why: build chip multi-select c\u0169ng c\u1EA7n \"head +N\" \u0111\u1EC3 g\u1ECDn (gi\u1ED1ng completed chip). -->\r\n <ng-template #sdValue let-selectedItems=\"selectedItems\">\r\n @if ((selectedItems?.length ?? 0) > 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_bopt.displayField] }}</span> +{{ selectedItems.length - 1 }}\r\n } @else if ((selectedItems?.length ?? 0) === 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_bopt.displayField] }}</span>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n </span>\r\n } @else if (_b.field.type === 'date') {\r\n <span class=\"c-token-value c-token-value-edit\">\r\n @if (_b.operator === 'BETWEEN') {\r\n <!-- why: 1 sd-date-range thay 2 sd-date \u2014 g\u1ECDn h\u01A1n, h\u00E0nh vi th\u1ED1ng nh\u1EA5t v\u1EDBi completed chip. -->\r\n <sd-date-range #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date-range>\r\n } @else {\r\n <sd-date #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date>\r\n }\r\n </span>\r\n } @else if (_b.field.type === 'datetime') {\r\n <span class=\"c-token-value c-token-value-edit\">\r\n @if (_b.operator === 'BETWEEN') {\r\n <!-- why: datetime BETWEEN downgrade v\u1EC1 date-range (m\u1EA5t time precision; \u0111\u00E3 th\u1ED1ng nh\u1EA5t). -->\r\n <sd-date-range #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date-range>\r\n } @else {\r\n <sd-datetime #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-datetime>\r\n }\r\n </span>\r\n } @else if (_b.field.type === 'boolean') {\r\n <!-- why: boolean c\u0169ng d\u00F9ng nguy\u00EAn giao di\u1EC7n 2 n\u00FAt toggle \u1EDF build chip (gi\u1ED1ng popover);\r\n click commit tr\u1EF1c ti\u1EBFp gi\u00E1 tr\u1ECB, kh\u00F4ng qua draft. -->\r\n <span class=\"c-token-value c-token-value-edit c-bool-toggle\">\r\n <sd-button\r\n [autoId]=\"autoId() + '-true'\"\r\n [type]=\"_b.value === true ? 'fill' : 'outline'\"\r\n color=\"success\"\r\n [title]=\"$any(_b.field).trueLabel || 'C\u00F3'\"\r\n (click)=\"commitValue.emit(true)\"></sd-button>\r\n <sd-button\r\n [autoId]=\"autoId() + '-false'\"\r\n [type]=\"_b.value === false ? 'fill' : 'outline'\"\r\n color=\"warning\"\r\n [title]=\"$any(_b.field).falseLabel || 'Kh\u00F4ng'\"\r\n (click)=\"commitValue.emit(false)\"></sd-button>\r\n </span>\r\n } @else {\r\n <!-- Fallback (e.g. unforeseen type) \u2014 generic sd-input wired via draft outputs. -->\r\n <span class=\"c-token-value c-token-value-edit\">\r\n <sd-input size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"draftChange.emit($event)\"\r\n (keyupEnter)=\"draftCommit.emit()\"></sd-input>\r\n </span>\r\n }\r\n }\r\n\r\n <button type=\"button\" class=\"c-token-remove\" aria-label=\"Cancel\" (click)=\"cancel.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n </div>\r\n}\r\n", styles: [":host{display:contents}.c-token{display:inline-flex;align-items:center;gap:4px;padding:0 0 0 12px;border:1px solid var(--sd-primary-light);border-radius:999px;background:var(--sd-primary-light);font-size:13px;color:#5f6368;white-space:nowrap;overflow:hidden}:host-context(.c-density-compact) .c-token{height:28px}:host-context(.c-density-comfortable) .c-token{height:32px}.c-token-field{font-weight:500;line-height:1}.c-token-op{display:inline-flex;align-items:center;color:inherit}.c-token-op ::ng-deep .c-op-trigger{padding:0;color:inherit}.c-token-op ::ng-deep .c-op-icon svg{width:14px;height:14px;display:block}.c-token-value{border:none;background:transparent;padding:0;font:inherit;font-weight:500;color:var(--sd-primary)}.c-token-value-edit{display:inline-flex;align-items:center;gap:4px;max-width:240px}.c-token-value-edit sd-input,.c-token-value-edit sd-input-number{display:inline-flex;max-width:140px}.c-token-value-edit sd-date-range{display:inline-flex;max-width:220px;min-width:0;flex:0 1 auto}.c-token-value-edit sd-select,.c-token-value-edit sd-date,.c-token-value-edit sd-datetime{display:inline-flex;align-items:center;line-height:1}.c-token ::ng-deep .mat-mdc-form-field{line-height:1}.c-token ::ng-deep .mat-mdc-text-field-wrapper,.c-token ::ng-deep .mat-mdc-form-field-flex{padding:0;min-height:0;background:transparent}.c-token ::ng-deep .mat-mdc-form-field-infix{padding:0;min-height:0;width:auto;border:0;display:inline-flex;align-items:center}.c-token ::ng-deep .mat-mdc-select-value,.c-token ::ng-deep .mat-mdc-input-element,.c-token ::ng-deep input{line-height:1;font-size:13px;padding:0;height:auto;color:inherit}.c-token ::ng-deep .mat-mdc-select-value{display:inline-flex;align-items:center;min-width:0;max-width:200px;overflow:hidden;text-overflow:ellipsis;color:var(--sd-primary);font-weight:500}.c-token ::ng-deep .sd-suffix-icon{display:none}.c-token-multi-head{display:inline-block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.c-token-building{border-style:dashed}.c-token-remove{align-self:stretch;display:inline-flex;align-items:center;justify-content:center;border:none;border-left:1px solid rgba(0,0,0,.04);border-radius:0;background:transparent;cursor:pointer;color:inherit}:host-context(.c-density-compact) .c-token-remove{width:26px}:host-context(.c-density-comfortable) .c-token-remove{width:28px}.c-token-remove mat-icon{font-size:14px;width:14px;height:14px}.c-token-remove:hover{background:#0000000d}\n"] }]
498
+ ], template: "<!--\r\n In-progress chip (inline-mode token build flow).\r\n Seamless string/number branch keeps its own pill; everything else renders inside\r\n the dashed .c-token.c-token-building shell.\r\n-->\r\n@let _b = building();\r\n\r\n@if (isSeamless()) {\r\n <sd-query-inline-value-chip\r\n [field]=\"_b.field\"\r\n [operator]=\"$any(_b.operator)\"\r\n [value]=\"_b.value ?? null\"\r\n [density]=\"density()\"\r\n [showOperator]=\"showOperator()\"\r\n [autoId]=\"autoId()\"\r\n [autofocus]=\"true\"\r\n (valueChange)=\"seamlessCommit.emit($event)\"\r\n (remove)=\"cancel.emit()\" />\r\n} @else {\r\n <div class=\"c-token c-token-building\">\r\n <span class=\"c-token-field\">{{ _b.field.label }}</span>\r\n\r\n @if (_b.step === 'operator') {\r\n <sd-operator\r\n #buildOperator\r\n class=\"c-token-op\"\r\n [operators]=\"allowedOperators()\"\r\n [model]=\"_b.operator\"\r\n (modelChange)=\"pickOperator.emit($any($event))\" />\r\n } @else {\r\n <!-- why: badge readonly cho operator \u0111\u00E3 ch\u1ECDn \u2014 v\u1EABn render <sd-operator>\r\n \u0111\u1EC3 gi\u1EEF th\u1ECB gi\u00E1c gi\u1ED1ng chip ho\u00E0n th\u00E0nh (icon + tooltip). -->\r\n <sd-operator\r\n class=\"c-token-op\"\r\n [operators]=\"[$any(_b.operator)]\"\r\n [model]=\"$any(_b.operator)\"\r\n [disabled]=\"true\" />\r\n\r\n @if (_b.field.type === 'values' || _b.field.type === 'lazy-values') {\r\n @let _bopt = $any(_b.field).option;\r\n <span class=\"c-token-value c-token-value-edit\">\r\n <sd-select #bPicker bare size=\"sm\" minWidthPanel=\"300px\"\r\n [autoId]=\"autoId()\"\r\n [items]=\"_b.field.type === 'lazy-values' ? $any(_bopt).search : $any(_bopt.items)\"\r\n [valueField]=\"_bopt.valueField\"\r\n [displayField]=\"_bopt.displayField\"\r\n [multiple]=\"multiple()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\">\r\n <!-- why: build chip multi-select c\u0169ng c\u1EA7n \"head +N\" \u0111\u1EC3 g\u1ECDn (gi\u1ED1ng completed chip). -->\r\n <ng-template #sdValue let-selectedItems=\"selectedItems\">\r\n @if ((selectedItems?.length ?? 0) > 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_bopt.displayField] }}</span> +{{ selectedItems.length - 1 }}\r\n } @else if ((selectedItems?.length ?? 0) === 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_bopt.displayField] }}</span>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n </span>\r\n } @else if (_b.field.type === 'date') {\r\n <span class=\"c-token-value c-token-value-edit\">\r\n @if (_b.operator === 'BETWEEN') {\r\n <!-- why: 1 sd-date-range thay 2 sd-date \u2014 g\u1ECDn h\u01A1n, h\u00E0nh vi th\u1ED1ng nh\u1EA5t v\u1EDBi completed chip. -->\r\n <sd-date-range #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date-range>\r\n } @else {\r\n <sd-date #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date>\r\n }\r\n </span>\r\n } @else if (_b.field.type === 'datetime') {\r\n <span class=\"c-token-value c-token-value-edit\">\r\n @if (_b.operator === 'BETWEEN') {\r\n <!-- why: datetime BETWEEN downgrade v\u1EC1 date-range (m\u1EA5t time precision; \u0111\u00E3 th\u1ED1ng nh\u1EA5t). -->\r\n <sd-date-range #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-date-range>\r\n } @else {\r\n <sd-datetime #bPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"commitValue.emit($event)\"></sd-datetime>\r\n }\r\n </span>\r\n } @else if (_b.field.type === 'boolean') {\r\n <!-- why: native button thay sd-button (tr\u00E1nh mat-button baseline 36px g\u00E2y tr\u00E0n).\r\n Pill nh\u1ECF v\u1EBD b\u1EB1ng CSS scoped trong chip \u2014 gi\u1EEF semantic colour qua class\r\n .c-bool-true / .c-bool-false. -->\r\n <span class=\"c-token-value c-token-value-edit c-bool-toggle\">\r\n <button\r\n type=\"button\"\r\n class=\"c-bool-btn c-bool-true\"\r\n [class.c-bool-active]=\"_b.value === true\"\r\n [attr.data-autoId]=\"autoId() + '-true'\"\r\n (click)=\"commitValue.emit(true)\">\r\n {{ $any(_b.field).trueLabel || 'C\u00F3' }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"c-bool-btn c-bool-false\"\r\n [class.c-bool-active]=\"_b.value === false\"\r\n [attr.data-autoId]=\"autoId() + '-false'\"\r\n (click)=\"commitValue.emit(false)\">\r\n {{ $any(_b.field).falseLabel || 'Kh\u00F4ng' }}\r\n </button>\r\n </span>\r\n } @else {\r\n <!-- Fallback (e.g. unforeseen type) \u2014 generic sd-input wired via draft outputs. -->\r\n <span class=\"c-token-value c-token-value-edit\">\r\n <sd-input size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [model]=\"$any(_b.value)\"\r\n (sdChange)=\"draftChange.emit($event)\"\r\n (keyupEnter)=\"draftCommit.emit()\"></sd-input>\r\n </span>\r\n }\r\n }\r\n\r\n <button type=\"button\" class=\"c-token-remove\" aria-label=\"Cancel\" (click)=\"cancel.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n </div>\r\n}\r\n", styles: [":host{display:contents}.c-token{display:inline-flex;align-items:center;gap:4px;padding:0 0 0 12px;border:1px solid var(--sd-primary-light);border-radius:999px;background:var(--sd-primary-light);font-size:13px;color:#5f6368;white-space:nowrap;overflow:hidden}:host-context(.c-density-compact) .c-token{height:28px}:host-context(.c-density-comfortable) .c-token{height:32px}.c-token-field{font-weight:500;line-height:1}.c-token-op{display:inline-flex;align-items:center;color:inherit}.c-token-op ::ng-deep .c-op-trigger{padding:0;color:inherit}.c-token-op ::ng-deep .c-op-icon svg{width:14px;height:14px;display:block}.c-token-value{border:none;background:transparent;padding:0;font:inherit;font-weight:500;color:var(--sd-primary)}.c-token-value-edit{display:inline-flex;align-items:center;gap:4px;max-width:240px}.c-token-value-edit sd-input,.c-token-value-edit sd-input-number{display:inline-flex;max-width:140px}.c-token-value-edit sd-date-range{display:inline-flex;max-width:220px;min-width:0;flex:0 1 auto}.c-token-value-edit sd-select,.c-token-value-edit sd-date,.c-token-value-edit sd-datetime{display:inline-flex;align-items:center;line-height:1}.c-token ::ng-deep .mat-mdc-form-field{line-height:1}.c-token ::ng-deep .mat-mdc-text-field-wrapper,.c-token ::ng-deep .mat-mdc-form-field-flex{padding:0;min-height:0;background:transparent}.c-token ::ng-deep .mat-mdc-form-field-infix{padding:0;min-height:0;width:auto;border:0;display:inline-flex;align-items:center}.c-token ::ng-deep .mat-mdc-select-value,.c-token ::ng-deep .mat-mdc-input-element,.c-token ::ng-deep input{line-height:1;font-size:13px;padding:0;height:auto;color:inherit}.c-token ::ng-deep .mat-mdc-select-value{display:inline-flex;align-items:center;min-width:0;max-width:200px;overflow:hidden;text-overflow:ellipsis;color:var(--sd-primary);font-weight:500}.c-token ::ng-deep .sd-suffix-icon{display:none}.c-token-multi-head{display:inline-block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.c-token-building{border-style:dashed}.c-bool-toggle{display:inline-flex;align-items:center;gap:4px}.c-bool-btn{display:inline-flex;align-items:center;justify-content:center;height:18px;min-width:0;padding:0 8px;border:1px solid currentColor;border-radius:999px;background:transparent;font:inherit;font-size:11px;font-weight:500;line-height:1;cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:background .12s ease,color .12s ease}:host-context(.c-density-comfortable) .c-bool-btn{height:20px;padding:0 10px;font-size:12px}.c-bool-true{color:var(--sd-success)}.c-bool-false{color:var(--sd-warning)}.c-bool-active.c-bool-true{background:var(--sd-success);color:#fff;border-color:var(--sd-success)}.c-bool-active.c-bool-false{background:var(--sd-warning);color:#fff;border-color:var(--sd-warning)}.c-bool-btn:hover:not(.c-bool-active).c-bool-true{background:var(--sd-success-light)}.c-bool-btn:hover:not(.c-bool-active).c-bool-false{background:var(--sd-warning-light)}.c-token-remove{align-self:stretch;display:inline-flex;align-items:center;justify-content:center;border:none;border-left:1px solid rgba(0,0,0,.04);border-radius:0;background:transparent;cursor:pointer;color:inherit}:host-context(.c-density-compact) .c-token-remove{width:26px}:host-context(.c-density-comfortable) .c-token-remove{width:28px}.c-token-remove mat-icon{font-size:14px;width:14px;height:14px}.c-token-remove:hover{background:#0000000d}\n"] }]
507
499
  }] });
508
500
 
509
501
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -892,6 +884,11 @@ class SdQueryInlineChip {
892
884
  if (this.#editing()) {
893
885
  this.#editing.set(false);
894
886
  this.#cdr.markForCheck();
887
+ // why: sd-date-range / sd-datetime đôi khi emit sdChange NGAY SAU focusout —
888
+ // viewed flip xảy ra trước khi model mới về tới [model] input → viewed text
889
+ // format dùng giá trị cũ. Schedule thêm 1 CD pass để re-render với model mới
890
+ // (user-visible bug: "click ra lần đầu chưa update, click vào rồi ra lần 2 mới đúng").
891
+ queueMicrotask(() => this.#cdr.markForCheck());
895
892
  }
896
893
  }
897
894
  /** Test-only shim — direct call avoids dispatching real FocusEvent in JSDOM. */
@@ -906,9 +903,18 @@ class SdQueryInlineChip {
906
903
  this.commit.emit(v);
907
904
  this.#editing.set(false);
908
905
  }
909
- /** BETWEEN commit — sd-date-range emits {from, to}. */
906
+ /**
907
+ * BETWEEN commit — sd-date-range emits {from, to}.
908
+ * why: nếu cả from + to đều có giá trị → coi như range đã chọn xong → exit edit
909
+ * ngay tại commit (đồng bộ với model.set của parent), không chờ focusout. Tránh
910
+ * race "focusout firing trước sdChange" làm viewed text render với model cũ.
911
+ */
910
912
  emitRangeCommit(ev) {
911
913
  this.commitRange.emit(ev ?? null);
914
+ if (ev && ev.from != null && ev.to != null) {
915
+ this.#editing.set(false);
916
+ this.#cdr.markForCheck();
917
+ }
912
918
  }
913
919
  /** Multi-select live emit — does NOT exit edit (focusout handles exit). */
914
920
  emitLive(v) {
@@ -920,20 +926,19 @@ class SdQueryInlineChip {
920
926
  this.#editing.set(false);
921
927
  }
922
928
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQueryInlineChip, deps: [], target: i0.ɵɵFactoryTarget.Component });
923
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQueryInlineChip, isStandalone: true, selector: "sd-query-inline-chip", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, showOperator: { classPropertyName: "showOperator", publicName: "showOperator", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, valueText: { classPropertyName: "valueText", publicName: "valueText", isSignal: true, isRequired: false, transformFunction: null }, isNoData: { classPropertyName: "isNoData", publicName: "isNoData", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { commit: "commit", commitRange: "commitRange", liveChange: "liveChange", remove: "remove" }, viewQueries: [{ propertyName: "chipPicker", first: true, predicate: ["chipPicker"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Completed inline chip \u2014 non-string/number/seamless branches.\r\n Edit lifecycle is self-managed: click enters edit + auto-opens picker,\r\n focusout outside the wrapper exits edit, picker emits commit single OR\r\n liveChange (multi) OR commitRange (BETWEEN).\r\n-->\r\n@let _f = field();\r\n@let _op = operator();\r\n@let _data = data();\r\n@let _multi = multiple();\r\n@let _editing = editing();\r\n@let _isNoData = isNoData();\r\n\r\n<div class=\"c-token\" [class.c-token-editing]=\"_editing\">\r\n <mat-icon class=\"c-token-icon\" fontSet=\"material-icons-outlined\">{{ iconName() }}</mat-icon>\r\n <span class=\"c-token-field\">{{ _f.label }}</span>\r\n\r\n @if (!_isNoData && showOperator()) {\r\n <sd-operator class=\"c-token-op\" [operators]=\"[_op]\" [model]=\"_op\" [disabled]=\"true\" />\r\n } @else if (!_isNoData) {\r\n <span class=\"c-token-sep\">:</span>\r\n }\r\n\r\n @if (!_isNoData) {\r\n @if (_f.type === 'boolean') {\r\n @if (_editing) {\r\n <!-- why: boolean edit d\u00F9ng 2 n\u00FAt toggle (gi\u1ED1ng popover). Click commit\r\n tr\u1EF1c ti\u1EBFp gi\u00E1 tr\u1ECB (true/false) qua emitBoolean \u2192 exit edit. -->\r\n <span class=\"c-token-value c-token-value-edit c-bool-toggle\">\r\n <sd-button\r\n [autoId]=\"autoId() + '-true'\"\r\n [type]=\"_data === true ? 'fill' : 'outline'\"\r\n color=\"success\"\r\n [title]=\"$any(_f).trueLabel || 'C\u00F3'\"\r\n (click)=\"emitBoolean(true)\"></sd-button>\r\n <sd-button\r\n [autoId]=\"autoId() + '-false'\"\r\n [type]=\"_data === false ? 'fill' : 'outline'\"\r\n color=\"warning\"\r\n [title]=\"$any(_f).falseLabel || 'Kh\u00F4ng'\"\r\n (click)=\"emitBoolean(false)\"></sd-button>\r\n </span>\r\n } @else {\r\n <button type=\"button\" class=\"c-token-value\" (click)=\"enterEdit()\">{{ valueText() }}</button>\r\n }\r\n } @else if ((_f.type === 'date' || _f.type === 'datetime') && _op === 'BETWEEN') {\r\n <!-- why: d\u00F9ng sd-date-range th\u1ED1ng nh\u1EA5t cho c\u1EA3 date + datetime BETWEEN (datetime downgrade v\u1EC1 date). -->\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-date-range #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"emitRangeCommit($any($event))\"></sd-date-range>\r\n </span>\r\n } @else if (_f.type === 'values' || _f.type === 'lazy-values') {\r\n @let _opt = $any(_f).option;\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-select #chipPicker bare size=\"sm\" minWidthPanel=\"300px\"\r\n [autoId]=\"autoId()\"\r\n [items]=\"_f.type === 'lazy-values' ? $any(_opt).search : $any(_opt.items)\"\r\n [valueField]=\"_opt.valueField\"\r\n [displayField]=\"_opt.displayField\"\r\n [multiple]=\"_multi\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"_data\"\r\n (sdChange)=\"_multi ? emitLive($event) : emitSingleCommit($event)\">\r\n <!-- why: viewed mode m\u1EB7c \u0111\u1ECBnh d\u00F9ng comma-joined cho multi \u2014 qu\u00E1 d\u00E0i cho chip.\r\n Override b\u1EB1ng template \"head +N\" gi\u1ED1ng popover chipValueText. -->\r\n <ng-template #sdValue let-selectedItems=\"selectedItems\">\r\n @if ((selectedItems?.length ?? 0) > 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_opt.displayField] }}</span> +{{ selectedItems.length - 1 }}\r\n } @else if ((selectedItems?.length ?? 0) === 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_opt.displayField] }}</span>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n </span>\r\n } @else if (_f.type === 'date') {\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-date #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"_data\"\r\n (sdChange)=\"emitSingleCommit($any($event))\"></sd-date>\r\n </span>\r\n } @else if (_f.type === 'datetime') {\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-datetime #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"_data\"\r\n (sdChange)=\"emitSingleCommit($any($event))\"></sd-datetime>\r\n </span>\r\n } @else {\r\n <!-- Fallback (unforeseen type) \u2014 read-only display via valueText. -->\r\n <span class=\"c-token-value\">{{ valueText() }}</span>\r\n }\r\n }\r\n\r\n <button type=\"button\" class=\"c-token-remove\" aria-label=\"Remove filter\" (click)=\"remove.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [":host{display:contents}.c-token{display:inline-flex;align-items:center;gap:4px;padding:0 0 0 12px;border:1px solid var(--sd-primary-light);border-radius:999px;background:var(--sd-primary-light);font-size:13px;color:#5f6368;white-space:nowrap;overflow:hidden}:host-context(.c-density-compact) .c-token{height:28px}:host-context(.c-density-comfortable) .c-token{height:32px}.c-token-icon{font-size:14px;width:14px;height:14px;line-height:14px;color:inherit}.c-token-field{font-weight:500;line-height:1}.c-token-op{display:inline-flex;align-items:center;color:inherit}.c-token-op ::ng-deep .c-op-trigger{padding:0;color:inherit}.c-token-op ::ng-deep .c-op-icon svg{width:14px;height:14px;display:block}.c-token-sep{color:#7a7a7a}.c-token-value{border:none;background:transparent;padding:0;font:inherit;font-weight:500;color:var(--sd-primary);cursor:pointer}.c-token-value:hover{text-decoration:underline}.c-token-value-edit{display:inline-flex;align-items:center;gap:4px;max-width:240px}.c-token-value-edit sd-date-range{display:inline-flex;max-width:220px;min-width:0;flex:0 1 auto}.c-token-value-edit sd-select,.c-token-value-edit sd-date,.c-token-value-edit sd-datetime{display:inline-flex;align-items:center;line-height:1}.c-token ::ng-deep .mat-mdc-form-field{line-height:1}.c-token ::ng-deep .mat-mdc-text-field-wrapper,.c-token ::ng-deep .mat-mdc-form-field-flex{padding:0;min-height:0;background:transparent}.c-token ::ng-deep .mat-mdc-form-field-infix{padding:0;min-height:0;width:auto;border:0;display:inline-flex;align-items:center}.c-token ::ng-deep .mat-mdc-select-value,.c-token ::ng-deep .mat-mdc-input-element,.c-token ::ng-deep input{line-height:1;font-size:13px;padding:0;height:auto;color:inherit}.c-token ::ng-deep .mat-mdc-select-value{display:inline-flex;align-items:center;min-width:0;max-width:200px;overflow:hidden;text-overflow:ellipsis;color:var(--sd-primary);font-weight:500}.c-token ::ng-deep .sd-suffix-icon{display:none}.c-token-multi-head{display:inline-block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.c-bool-toggle{display:inline-flex;align-items:center;gap:4px}.c-bool-toggle ::ng-deep .mdc-button,.c-bool-toggle ::ng-deep button[mat-button],.c-bool-toggle ::ng-deep button[mat-stroked-button],.c-bool-toggle ::ng-deep button[mat-flat-button]{border-radius:999px;min-width:0;padding:0 12px}.c-token-remove{align-self:stretch;display:inline-flex;align-items:center;justify-content:center;border:none;border-left:1px solid rgba(0,0,0,.04);border-radius:0;background:transparent;cursor:pointer;color:inherit}:host-context(.c-density-compact) .c-token-remove{width:26px}:host-context(.c-density-comfortable) .c-token-remove{width:28px}.c-token-remove mat-icon{font-size:14px;width:14px;height:14px}.c-token-remove:hover{background:#0000000d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdOperator, selector: "sd-operator", inputs: ["model", "operators", "disabled", "autoId"], outputs: ["modelChange"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
929
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdQueryInlineChip, isStandalone: true, selector: "sd-query-inline-chip", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: true, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, showOperator: { classPropertyName: "showOperator", publicName: "showOperator", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, valueText: { classPropertyName: "valueText", publicName: "valueText", isSignal: true, isRequired: false, transformFunction: null }, isNoData: { classPropertyName: "isNoData", publicName: "isNoData", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { commit: "commit", commitRange: "commitRange", liveChange: "liveChange", remove: "remove" }, viewQueries: [{ propertyName: "chipPicker", first: true, predicate: ["chipPicker"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\r\n Completed inline chip \u2014 non-string/number/seamless branches.\r\n Edit lifecycle is self-managed: click enters edit + auto-opens picker,\r\n focusout outside the wrapper exits edit, picker emits commit single OR\r\n liveChange (multi) OR commitRange (BETWEEN).\r\n-->\r\n@let _f = field();\r\n@let _op = operator();\r\n@let _data = data();\r\n@let _multi = multiple();\r\n@let _editing = editing();\r\n@let _isNoData = isNoData();\r\n\r\n<div class=\"c-token\" [class.c-token-editing]=\"_editing\">\r\n <mat-icon class=\"c-token-icon\" fontSet=\"material-icons-outlined\">{{ iconName() }}</mat-icon>\r\n <span class=\"c-token-field\">{{ _f.label }}</span>\r\n\r\n @if (!_isNoData && showOperator()) {\r\n <sd-operator class=\"c-token-op\" [operators]=\"[_op]\" [model]=\"_op\" [disabled]=\"true\" />\r\n } @else if (!_isNoData) {\r\n <span class=\"c-token-sep\">:</span>\r\n }\r\n\r\n @if (!_isNoData) {\r\n @if (_f.type === 'boolean') {\r\n @if (_editing) {\r\n <!-- why: native button thay sd-button \u2014 mat-button MDC baseline 36px bu\u1ED9c\r\n ph\u1EA3i hack height/padding overrides; chip 28/32px nh\u1ECF h\u01A1n nhi\u1EC1u. T\u1EF1 v\u1EBD\r\n pill nh\u1ECF v\u1EDBi CSS scoped trong chip, kh\u00F4ng qua MDC, g\u1ECDn + chu\u1EA9n baseline. -->\r\n <span class=\"c-token-value c-token-value-edit c-bool-toggle\">\r\n <button\r\n type=\"button\"\r\n class=\"c-bool-btn c-bool-true\"\r\n [class.c-bool-active]=\"_data === true\"\r\n [attr.data-autoId]=\"autoId() + '-true'\"\r\n (click)=\"emitBoolean(true)\">\r\n {{ $any(_f).trueLabel || 'C\u00F3' }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"c-bool-btn c-bool-false\"\r\n [class.c-bool-active]=\"_data === false\"\r\n [attr.data-autoId]=\"autoId() + '-false'\"\r\n (click)=\"emitBoolean(false)\">\r\n {{ $any(_f).falseLabel || 'Kh\u00F4ng' }}\r\n </button>\r\n </span>\r\n } @else {\r\n <button type=\"button\" class=\"c-token-value\" (click)=\"enterEdit()\">{{ valueText() }}</button>\r\n }\r\n } @else if ((_f.type === 'date' || _f.type === 'datetime') && _op === 'BETWEEN') {\r\n <!-- why: d\u00F9ng sd-date-range th\u1ED1ng nh\u1EA5t cho c\u1EA3 date + datetime BETWEEN (datetime downgrade v\u1EC1 date). -->\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-date-range #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"emitRangeCommit($any($event))\"></sd-date-range>\r\n </span>\r\n } @else if (_f.type === 'values' || _f.type === 'lazy-values') {\r\n @let _opt = $any(_f).option;\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-select #chipPicker bare size=\"sm\" minWidthPanel=\"300px\"\r\n [autoId]=\"autoId()\"\r\n [items]=\"_f.type === 'lazy-values' ? $any(_opt).search : $any(_opt.items)\"\r\n [valueField]=\"_opt.valueField\"\r\n [displayField]=\"_opt.displayField\"\r\n [multiple]=\"_multi\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"_multi ? emitLive($event) : emitSingleCommit($event)\">\r\n <!-- why: viewed mode m\u1EB7c \u0111\u1ECBnh d\u00F9ng comma-joined cho multi \u2014 qu\u00E1 d\u00E0i cho chip.\r\n Override b\u1EB1ng template \"head +N\" gi\u1ED1ng popover chipValueText. -->\r\n <ng-template #sdValue let-selectedItems=\"selectedItems\">\r\n @if ((selectedItems?.length ?? 0) > 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_opt.displayField] }}</span> +{{ selectedItems.length - 1 }}\r\n } @else if ((selectedItems?.length ?? 0) === 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_opt.displayField] }}</span>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n </span>\r\n } @else if (_f.type === 'date') {\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-date #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"emitSingleCommit($any($event))\"></sd-date>\r\n </span>\r\n } @else if (_f.type === 'datetime') {\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-datetime #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"emitSingleCommit($any($event))\"></sd-datetime>\r\n </span>\r\n } @else {\r\n <!-- Fallback (unforeseen type) \u2014 read-only display via valueText. -->\r\n <span class=\"c-token-value\">{{ valueText() }}</span>\r\n }\r\n }\r\n\r\n <button type=\"button\" class=\"c-token-remove\" aria-label=\"Remove filter\" (click)=\"remove.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [":host{display:contents}.c-token{display:inline-flex;align-items:center;gap:4px;padding:0 0 0 12px;border:1px solid var(--sd-primary-light);border-radius:999px;background:var(--sd-primary-light);font-size:13px;color:#5f6368;white-space:nowrap;overflow:hidden}:host-context(.c-density-compact) .c-token{height:28px}:host-context(.c-density-comfortable) .c-token{height:32px}.c-token-icon{font-size:14px;width:14px;height:14px;line-height:14px;color:inherit}.c-token-field{font-weight:500;line-height:1}.c-token-op{display:inline-flex;align-items:center;color:inherit}.c-token-op ::ng-deep .c-op-trigger{padding:0;color:inherit}.c-token-op ::ng-deep .c-op-icon svg{width:14px;height:14px;display:block}.c-token-sep{color:#7a7a7a}.c-token-value{border:none;background:transparent;padding:0;font:inherit;font-weight:500;color:var(--sd-primary);cursor:pointer}.c-token-value:hover{text-decoration:underline}.c-token-value-edit{display:inline-flex;align-items:center;gap:4px;max-width:240px}.c-token-value-edit sd-date-range{display:inline-flex;max-width:220px;min-width:0;flex:0 1 auto}.c-token-value-edit sd-select,.c-token-value-edit sd-date,.c-token-value-edit sd-datetime{display:inline-flex;align-items:center;line-height:1}.c-token ::ng-deep .mat-mdc-form-field{line-height:1}.c-token ::ng-deep .mat-mdc-text-field-wrapper,.c-token ::ng-deep .mat-mdc-form-field-flex{padding:0;min-height:0;background:transparent}.c-token ::ng-deep .mat-mdc-form-field-infix{padding:0;min-height:0;width:auto;border:0;display:inline-flex;align-items:center}.c-token ::ng-deep .mat-mdc-select-value,.c-token ::ng-deep .mat-mdc-input-element,.c-token ::ng-deep input{line-height:1;font-size:13px;padding:0;height:auto;color:inherit}.c-token ::ng-deep .mat-mdc-select-value{display:inline-flex;align-items:center;min-width:0;max-width:200px;overflow:hidden;text-overflow:ellipsis;color:var(--sd-primary);font-weight:500}.c-token ::ng-deep .sd-suffix-icon{display:none}.c-token-multi-head{display:inline-block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.c-bool-toggle{display:inline-flex;align-items:center;gap:4px}.c-bool-btn{display:inline-flex;align-items:center;justify-content:center;height:18px;min-width:0;padding:0 8px;border:1px solid currentColor;border-radius:999px;background:transparent;font:inherit;font-size:11px;font-weight:500;line-height:1;cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:background .12s ease,color .12s ease}:host-context(.c-density-comfortable) .c-bool-btn{height:20px;padding:0 10px;font-size:12px}.c-bool-true{color:var(--sd-success)}.c-bool-false{color:var(--sd-warning)}.c-bool-active.c-bool-true{background:var(--sd-success);color:#fff;border-color:var(--sd-success)}.c-bool-active.c-bool-false{background:var(--sd-warning);color:#fff;border-color:var(--sd-warning)}.c-bool-btn:hover:not(.c-bool-active).c-bool-true{background:var(--sd-success-light)}.c-bool-btn:hover:not(.c-bool-active).c-bool-false{background:var(--sd-warning-light)}.c-token-remove{align-self:stretch;display:inline-flex;align-items:center;justify-content:center;border:none;border-left:1px solid rgba(0,0,0,.04);border-radius:0;background:transparent;cursor:pointer;color:inherit}:host-context(.c-density-compact) .c-token-remove{width:26px}:host-context(.c-density-comfortable) .c-token-remove{width:28px}.c-token-remove mat-icon{font-size:14px;width:14px;height:14px}.c-token-remove:hover{background:#0000000d}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SdOperator, selector: "sd-operator", inputs: ["model", "operators", "disabled", "autoId"], outputs: ["modelChange"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDateRange, selector: "sd-date-range", inputs: ["autoId", "name", "size", "form", "label", "helperText", "hideInlineError", "required", "disabled", "bare", "viewed", "appearance", "floatLabel", "min", "max", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
924
930
  }
925
931
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdQueryInlineChip, decorators: [{
926
932
  type: Component,
927
933
  args: [{ selector: 'sd-query-inline-chip', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
928
934
  CommonModule,
929
935
  MatIconModule,
930
- SdButton,
931
936
  SdOperator,
932
937
  SdDate,
933
938
  SdDateRange,
934
939
  SdDatetime,
935
940
  SdSelect,
936
- ], template: "<!--\r\n Completed inline chip \u2014 non-string/number/seamless branches.\r\n Edit lifecycle is self-managed: click enters edit + auto-opens picker,\r\n focusout outside the wrapper exits edit, picker emits commit single OR\r\n liveChange (multi) OR commitRange (BETWEEN).\r\n-->\r\n@let _f = field();\r\n@let _op = operator();\r\n@let _data = data();\r\n@let _multi = multiple();\r\n@let _editing = editing();\r\n@let _isNoData = isNoData();\r\n\r\n<div class=\"c-token\" [class.c-token-editing]=\"_editing\">\r\n <mat-icon class=\"c-token-icon\" fontSet=\"material-icons-outlined\">{{ iconName() }}</mat-icon>\r\n <span class=\"c-token-field\">{{ _f.label }}</span>\r\n\r\n @if (!_isNoData && showOperator()) {\r\n <sd-operator class=\"c-token-op\" [operators]=\"[_op]\" [model]=\"_op\" [disabled]=\"true\" />\r\n } @else if (!_isNoData) {\r\n <span class=\"c-token-sep\">:</span>\r\n }\r\n\r\n @if (!_isNoData) {\r\n @if (_f.type === 'boolean') {\r\n @if (_editing) {\r\n <!-- why: boolean edit d\u00F9ng 2 n\u00FAt toggle (gi\u1ED1ng popover). Click commit\r\n tr\u1EF1c ti\u1EBFp gi\u00E1 tr\u1ECB (true/false) qua emitBoolean \u2192 exit edit. -->\r\n <span class=\"c-token-value c-token-value-edit c-bool-toggle\">\r\n <sd-button\r\n [autoId]=\"autoId() + '-true'\"\r\n [type]=\"_data === true ? 'fill' : 'outline'\"\r\n color=\"success\"\r\n [title]=\"$any(_f).trueLabel || 'C\u00F3'\"\r\n (click)=\"emitBoolean(true)\"></sd-button>\r\n <sd-button\r\n [autoId]=\"autoId() + '-false'\"\r\n [type]=\"_data === false ? 'fill' : 'outline'\"\r\n color=\"warning\"\r\n [title]=\"$any(_f).falseLabel || 'Kh\u00F4ng'\"\r\n (click)=\"emitBoolean(false)\"></sd-button>\r\n </span>\r\n } @else {\r\n <button type=\"button\" class=\"c-token-value\" (click)=\"enterEdit()\">{{ valueText() }}</button>\r\n }\r\n } @else if ((_f.type === 'date' || _f.type === 'datetime') && _op === 'BETWEEN') {\r\n <!-- why: d\u00F9ng sd-date-range th\u1ED1ng nh\u1EA5t cho c\u1EA3 date + datetime BETWEEN (datetime downgrade v\u1EC1 date). -->\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-date-range #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"emitRangeCommit($any($event))\"></sd-date-range>\r\n </span>\r\n } @else if (_f.type === 'values' || _f.type === 'lazy-values') {\r\n @let _opt = $any(_f).option;\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-select #chipPicker bare size=\"sm\" minWidthPanel=\"300px\"\r\n [autoId]=\"autoId()\"\r\n [items]=\"_f.type === 'lazy-values' ? $any(_opt).search : $any(_opt.items)\"\r\n [valueField]=\"_opt.valueField\"\r\n [displayField]=\"_opt.displayField\"\r\n [multiple]=\"_multi\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"_data\"\r\n (sdChange)=\"_multi ? emitLive($event) : emitSingleCommit($event)\">\r\n <!-- why: viewed mode m\u1EB7c \u0111\u1ECBnh d\u00F9ng comma-joined cho multi \u2014 qu\u00E1 d\u00E0i cho chip.\r\n Override b\u1EB1ng template \"head +N\" gi\u1ED1ng popover chipValueText. -->\r\n <ng-template #sdValue let-selectedItems=\"selectedItems\">\r\n @if ((selectedItems?.length ?? 0) > 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_opt.displayField] }}</span> +{{ selectedItems.length - 1 }}\r\n } @else if ((selectedItems?.length ?? 0) === 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_opt.displayField] }}</span>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n </span>\r\n } @else if (_f.type === 'date') {\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-date #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"_data\"\r\n (sdChange)=\"emitSingleCommit($any($event))\"></sd-date>\r\n </span>\r\n } @else if (_f.type === 'datetime') {\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-datetime #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"_data\"\r\n (sdChange)=\"emitSingleCommit($any($event))\"></sd-datetime>\r\n </span>\r\n } @else {\r\n <!-- Fallback (unforeseen type) \u2014 read-only display via valueText. -->\r\n <span class=\"c-token-value\">{{ valueText() }}</span>\r\n }\r\n }\r\n\r\n <button type=\"button\" class=\"c-token-remove\" aria-label=\"Remove filter\" (click)=\"remove.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [":host{display:contents}.c-token{display:inline-flex;align-items:center;gap:4px;padding:0 0 0 12px;border:1px solid var(--sd-primary-light);border-radius:999px;background:var(--sd-primary-light);font-size:13px;color:#5f6368;white-space:nowrap;overflow:hidden}:host-context(.c-density-compact) .c-token{height:28px}:host-context(.c-density-comfortable) .c-token{height:32px}.c-token-icon{font-size:14px;width:14px;height:14px;line-height:14px;color:inherit}.c-token-field{font-weight:500;line-height:1}.c-token-op{display:inline-flex;align-items:center;color:inherit}.c-token-op ::ng-deep .c-op-trigger{padding:0;color:inherit}.c-token-op ::ng-deep .c-op-icon svg{width:14px;height:14px;display:block}.c-token-sep{color:#7a7a7a}.c-token-value{border:none;background:transparent;padding:0;font:inherit;font-weight:500;color:var(--sd-primary);cursor:pointer}.c-token-value:hover{text-decoration:underline}.c-token-value-edit{display:inline-flex;align-items:center;gap:4px;max-width:240px}.c-token-value-edit sd-date-range{display:inline-flex;max-width:220px;min-width:0;flex:0 1 auto}.c-token-value-edit sd-select,.c-token-value-edit sd-date,.c-token-value-edit sd-datetime{display:inline-flex;align-items:center;line-height:1}.c-token ::ng-deep .mat-mdc-form-field{line-height:1}.c-token ::ng-deep .mat-mdc-text-field-wrapper,.c-token ::ng-deep .mat-mdc-form-field-flex{padding:0;min-height:0;background:transparent}.c-token ::ng-deep .mat-mdc-form-field-infix{padding:0;min-height:0;width:auto;border:0;display:inline-flex;align-items:center}.c-token ::ng-deep .mat-mdc-select-value,.c-token ::ng-deep .mat-mdc-input-element,.c-token ::ng-deep input{line-height:1;font-size:13px;padding:0;height:auto;color:inherit}.c-token ::ng-deep .mat-mdc-select-value{display:inline-flex;align-items:center;min-width:0;max-width:200px;overflow:hidden;text-overflow:ellipsis;color:var(--sd-primary);font-weight:500}.c-token ::ng-deep .sd-suffix-icon{display:none}.c-token-multi-head{display:inline-block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.c-bool-toggle{display:inline-flex;align-items:center;gap:4px}.c-bool-toggle ::ng-deep .mdc-button,.c-bool-toggle ::ng-deep button[mat-button],.c-bool-toggle ::ng-deep button[mat-stroked-button],.c-bool-toggle ::ng-deep button[mat-flat-button]{border-radius:999px;min-width:0;padding:0 12px}.c-token-remove{align-self:stretch;display:inline-flex;align-items:center;justify-content:center;border:none;border-left:1px solid rgba(0,0,0,.04);border-radius:0;background:transparent;cursor:pointer;color:inherit}:host-context(.c-density-compact) .c-token-remove{width:26px}:host-context(.c-density-comfortable) .c-token-remove{width:28px}.c-token-remove mat-icon{font-size:14px;width:14px;height:14px}.c-token-remove:hover{background:#0000000d}\n"] }]
941
+ ], template: "<!--\r\n Completed inline chip \u2014 non-string/number/seamless branches.\r\n Edit lifecycle is self-managed: click enters edit + auto-opens picker,\r\n focusout outside the wrapper exits edit, picker emits commit single OR\r\n liveChange (multi) OR commitRange (BETWEEN).\r\n-->\r\n@let _f = field();\r\n@let _op = operator();\r\n@let _data = data();\r\n@let _multi = multiple();\r\n@let _editing = editing();\r\n@let _isNoData = isNoData();\r\n\r\n<div class=\"c-token\" [class.c-token-editing]=\"_editing\">\r\n <mat-icon class=\"c-token-icon\" fontSet=\"material-icons-outlined\">{{ iconName() }}</mat-icon>\r\n <span class=\"c-token-field\">{{ _f.label }}</span>\r\n\r\n @if (!_isNoData && showOperator()) {\r\n <sd-operator class=\"c-token-op\" [operators]=\"[_op]\" [model]=\"_op\" [disabled]=\"true\" />\r\n } @else if (!_isNoData) {\r\n <span class=\"c-token-sep\">:</span>\r\n }\r\n\r\n @if (!_isNoData) {\r\n @if (_f.type === 'boolean') {\r\n @if (_editing) {\r\n <!-- why: native button thay sd-button \u2014 mat-button MDC baseline 36px bu\u1ED9c\r\n ph\u1EA3i hack height/padding overrides; chip 28/32px nh\u1ECF h\u01A1n nhi\u1EC1u. T\u1EF1 v\u1EBD\r\n pill nh\u1ECF v\u1EDBi CSS scoped trong chip, kh\u00F4ng qua MDC, g\u1ECDn + chu\u1EA9n baseline. -->\r\n <span class=\"c-token-value c-token-value-edit c-bool-toggle\">\r\n <button\r\n type=\"button\"\r\n class=\"c-bool-btn c-bool-true\"\r\n [class.c-bool-active]=\"_data === true\"\r\n [attr.data-autoId]=\"autoId() + '-true'\"\r\n (click)=\"emitBoolean(true)\">\r\n {{ $any(_f).trueLabel || 'C\u00F3' }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"c-bool-btn c-bool-false\"\r\n [class.c-bool-active]=\"_data === false\"\r\n [attr.data-autoId]=\"autoId() + '-false'\"\r\n (click)=\"emitBoolean(false)\">\r\n {{ $any(_f).falseLabel || 'Kh\u00F4ng' }}\r\n </button>\r\n </span>\r\n } @else {\r\n <button type=\"button\" class=\"c-token-value\" (click)=\"enterEdit()\">{{ valueText() }}</button>\r\n }\r\n } @else if ((_f.type === 'date' || _f.type === 'datetime') && _op === 'BETWEEN') {\r\n <!-- why: d\u00F9ng sd-date-range th\u1ED1ng nh\u1EA5t cho c\u1EA3 date + datetime BETWEEN (datetime downgrade v\u1EC1 date). -->\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-date-range #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"emitRangeCommit($any($event))\"></sd-date-range>\r\n </span>\r\n } @else if (_f.type === 'values' || _f.type === 'lazy-values') {\r\n @let _opt = $any(_f).option;\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-select #chipPicker bare size=\"sm\" minWidthPanel=\"300px\"\r\n [autoId]=\"autoId()\"\r\n [items]=\"_f.type === 'lazy-values' ? $any(_opt).search : $any(_opt.items)\"\r\n [valueField]=\"_opt.valueField\"\r\n [displayField]=\"_opt.displayField\"\r\n [multiple]=\"_multi\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"_multi ? emitLive($event) : emitSingleCommit($event)\">\r\n <!-- why: viewed mode m\u1EB7c \u0111\u1ECBnh d\u00F9ng comma-joined cho multi \u2014 qu\u00E1 d\u00E0i cho chip.\r\n Override b\u1EB1ng template \"head +N\" gi\u1ED1ng popover chipValueText. -->\r\n <ng-template #sdValue let-selectedItems=\"selectedItems\">\r\n @if ((selectedItems?.length ?? 0) > 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_opt.displayField] }}</span> +{{ selectedItems.length - 1 }}\r\n } @else if ((selectedItems?.length ?? 0) === 1) {\r\n <span class=\"c-token-multi-head\">{{ $any(selectedItems)[0][_opt.displayField] }}</span>\r\n }\r\n </ng-template>\r\n </sd-select>\r\n </span>\r\n } @else if (_f.type === 'date') {\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-date #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"emitSingleCommit($any($event))\"></sd-date>\r\n </span>\r\n } @else if (_f.type === 'datetime') {\r\n <span\r\n class=\"c-token-value c-token-value-edit\"\r\n (click)=\"enterEdit()\"\r\n (focusout)=\"onFocusOut($event)\">\r\n <sd-datetime #chipPicker bare size=\"sm\"\r\n [autoId]=\"autoId()\"\r\n [viewed]=\"!_editing\"\r\n [model]=\"$any(_data)\"\r\n (sdChange)=\"emitSingleCommit($any($event))\"></sd-datetime>\r\n </span>\r\n } @else {\r\n <!-- Fallback (unforeseen type) \u2014 read-only display via valueText. -->\r\n <span class=\"c-token-value\">{{ valueText() }}</span>\r\n }\r\n }\r\n\r\n <button type=\"button\" class=\"c-token-remove\" aria-label=\"Remove filter\" (click)=\"remove.emit()\">\r\n <mat-icon fontSet=\"material-icons-outlined\">close</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [":host{display:contents}.c-token{display:inline-flex;align-items:center;gap:4px;padding:0 0 0 12px;border:1px solid var(--sd-primary-light);border-radius:999px;background:var(--sd-primary-light);font-size:13px;color:#5f6368;white-space:nowrap;overflow:hidden}:host-context(.c-density-compact) .c-token{height:28px}:host-context(.c-density-comfortable) .c-token{height:32px}.c-token-icon{font-size:14px;width:14px;height:14px;line-height:14px;color:inherit}.c-token-field{font-weight:500;line-height:1}.c-token-op{display:inline-flex;align-items:center;color:inherit}.c-token-op ::ng-deep .c-op-trigger{padding:0;color:inherit}.c-token-op ::ng-deep .c-op-icon svg{width:14px;height:14px;display:block}.c-token-sep{color:#7a7a7a}.c-token-value{border:none;background:transparent;padding:0;font:inherit;font-weight:500;color:var(--sd-primary);cursor:pointer}.c-token-value:hover{text-decoration:underline}.c-token-value-edit{display:inline-flex;align-items:center;gap:4px;max-width:240px}.c-token-value-edit sd-date-range{display:inline-flex;max-width:220px;min-width:0;flex:0 1 auto}.c-token-value-edit sd-select,.c-token-value-edit sd-date,.c-token-value-edit sd-datetime{display:inline-flex;align-items:center;line-height:1}.c-token ::ng-deep .mat-mdc-form-field{line-height:1}.c-token ::ng-deep .mat-mdc-text-field-wrapper,.c-token ::ng-deep .mat-mdc-form-field-flex{padding:0;min-height:0;background:transparent}.c-token ::ng-deep .mat-mdc-form-field-infix{padding:0;min-height:0;width:auto;border:0;display:inline-flex;align-items:center}.c-token ::ng-deep .mat-mdc-select-value,.c-token ::ng-deep .mat-mdc-input-element,.c-token ::ng-deep input{line-height:1;font-size:13px;padding:0;height:auto;color:inherit}.c-token ::ng-deep .mat-mdc-select-value{display:inline-flex;align-items:center;min-width:0;max-width:200px;overflow:hidden;text-overflow:ellipsis;color:var(--sd-primary);font-weight:500}.c-token ::ng-deep .sd-suffix-icon{display:none}.c-token-multi-head{display:inline-block;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.c-bool-toggle{display:inline-flex;align-items:center;gap:4px}.c-bool-btn{display:inline-flex;align-items:center;justify-content:center;height:18px;min-width:0;padding:0 8px;border:1px solid currentColor;border-radius:999px;background:transparent;font:inherit;font-size:11px;font-weight:500;line-height:1;cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;transition:background .12s ease,color .12s ease}:host-context(.c-density-comfortable) .c-bool-btn{height:20px;padding:0 10px;font-size:12px}.c-bool-true{color:var(--sd-success)}.c-bool-false{color:var(--sd-warning)}.c-bool-active.c-bool-true{background:var(--sd-success);color:#fff;border-color:var(--sd-success)}.c-bool-active.c-bool-false{background:var(--sd-warning);color:#fff;border-color:var(--sd-warning)}.c-bool-btn:hover:not(.c-bool-active).c-bool-true{background:var(--sd-success-light)}.c-bool-btn:hover:not(.c-bool-active).c-bool-false{background:var(--sd-warning-light)}.c-token-remove{align-self:stretch;display:inline-flex;align-items:center;justify-content:center;border:none;border-left:1px solid rgba(0,0,0,.04);border-radius:0;background:transparent;cursor:pointer;color:inherit}:host-context(.c-density-compact) .c-token-remove{width:26px}:host-context(.c-density-comfortable) .c-token-remove{width:28px}.c-token-remove mat-icon{font-size:14px;width:14px;height:14px}.c-token-remove:hover{background:#0000000d}\n"] }]
937
942
  }] });
938
943
 
939
944
  /* eslint-disable @typescript-eslint/no-explicit-any */