@sd-angular/core 19.0.0-beta.100 → 19.0.0-beta.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/images/coming-soon.svg +23 -0
- package/assets/images/data-empty.svg +21 -0
- package/assets/images/expired.svg +22 -0
- package/assets/images/file-error.svg +28 -0
- package/assets/images/filter-empty.svg +20 -0
- package/assets/images/filter-required.svg +21 -0
- package/assets/images/forbidden.svg +15 -0
- package/assets/images/image-error.svg +27 -0
- package/assets/images/maintenance.svg +23 -0
- package/assets/images/not-found.svg +20 -0
- package/assets/images/offline.svg +20 -0
- package/assets/images/submitted.svg +18 -0
- package/assets/images/success.svg +18 -0
- package/assets/images/unauthorized.svg +22 -0
- package/assets/images/unknown-error.svg +18 -0
- package/assets/scss/core/image.scss +35 -0
- package/assets/scss/sd-core.scss +1 -0
- package/components/index.d.ts +1 -0
- package/components/operator/index.d.ts +1 -0
- package/components/operator/src/operator.component.d.ts +34 -0
- package/components/query-bar/index.d.ts +2 -0
- package/components/query-bar/src/actions-bar.component.d.ts +31 -0
- package/components/query-bar/src/build-chip.component.d.ts +67 -0
- package/components/query-bar/src/chip-popover.component.d.ts +73 -0
- package/components/query-bar/src/field-picker.component.d.ts +37 -0
- package/components/query-bar/src/inline-chip.component.d.ts +82 -0
- package/components/query-bar/src/inline-value-chip.component.d.ts +71 -0
- package/components/query-bar/src/popover-chip.component.d.ts +35 -0
- package/components/query-bar/src/query-bar.component.d.ts +137 -0
- package/components/query-bar/src/query-bar.model.d.ts +136 -0
- package/components/query-bar/src/saved-filters-menu.component.d.ts +39 -0
- package/components/table/src/components/column-title/column-title.component.d.ts +1 -1
- package/components/table/src/components/desktop-cell/desktop-cell.component.d.ts +3 -3
- package/components/table/src/components/filter/column-filter/column-filter.component.d.ts +3 -7
- package/components/table/src/directives/sd-table-cell-def.directive.d.ts +12 -4
- package/components/table/src/directives/sd-table-column-filter-def.directive.d.ts +12 -4
- package/components/table/src/directives/sd-table-expand-def.directive.d.ts +10 -4
- package/components/table/src/directives/sd-table-filter-def.directive.d.ts +3 -3
- package/components/table/src/directives/sd-table-footer-def.directive.d.ts +12 -4
- package/components/table/src/directives/sd-table-title-def.directive.d.ts +10 -4
- package/components/table/src/table.component.d.ts +7 -7
- package/components/view/src/view.component.d.ts +2 -1
- package/directives/src/sd-desktop.directive.d.ts +2 -4
- package/directives/src/sd-mobile.directive.d.ts +2 -4
- package/fesm2022/sd-angular-core-components-anchor.mjs +73 -47
- package/fesm2022/sd-angular-core-components-anchor.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-badge.mjs +2 -2
- package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-form-generic.mjs +16 -16
- package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-operator.mjs +75 -0
- package/fesm2022/sd-angular-core-components-operator.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-query-bar.mjs +1425 -0
- package/fesm2022/sd-angular-core-components-query-bar.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-quick-action.mjs +2 -2
- package/fesm2022/sd-angular-core-components-quick-action.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-table.mjs +60 -27
- package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-upload-file.mjs +4 -4
- package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-view.mjs +5 -2
- package/fesm2022/sd-angular-core-components-view.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components.mjs +1 -0
- package/fesm2022/sd-angular-core-components.mjs.map +1 -1
- package/fesm2022/sd-angular-core-directives.mjs +15 -17
- package/fesm2022/sd-angular-core-directives.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs +5 -8
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-checkbox.mjs +83 -87
- package/fesm2022/sd-angular-core-forms-checkbox.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip-calendar.mjs +76 -57
- package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip.mjs +73 -48
- package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date-range.mjs +41 -4
- package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date.mjs +14 -9
- package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-datetime.mjs +8 -9
- package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-directives.mjs +18 -24
- package/fesm2022/sd-angular-core-forms-directives.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-input-number.mjs +5 -8
- package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-input.mjs +5 -9
- package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-models.mjs +13 -1
- package/fesm2022/sd-angular-core-forms-models.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-radio.mjs +116 -176
- package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-select.mjs +23 -10
- package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-switch.mjs +80 -99
- package/fesm2022/sd-angular-core-forms-switch.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-textarea.mjs +5 -8
- package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
- package/fesm2022/sd-angular-core-i18n.mjs +35 -0
- package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-layout.mjs +10 -10
- package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-permission.mjs.map +1 -1
- package/fesm2022/sd-angular-core-services-confirm.mjs +1 -1
- package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
- package/forms/autocomplete/src/autocomplete.component.d.ts +3 -4
- package/forms/checkbox/src/checkbox.component.d.ts +17 -20
- package/forms/chip/src/chip.component.d.ts +17 -17
- package/forms/chip-calendar/src/chip-calendar.component.d.ts +19 -19
- package/forms/date/src/date.component.d.ts +7 -4
- package/forms/date-range/src/date-range.component.d.ts +16 -2
- package/forms/datetime/src/datetime.component.d.ts +5 -4
- package/forms/directives/src/item-def.directive.d.ts +10 -5
- package/forms/directives/src/label-def.directive.d.ts +3 -2
- package/forms/directives/src/suffix-def.directive.d.ts +3 -2
- package/forms/directives/src/view-def.directive.d.ts +9 -9
- package/forms/input/src/input.component.d.ts +3 -5
- package/forms/input-number/src/input-number.component.d.ts +2 -3
- package/forms/models/src/sd-custom-validator.model.d.ts +13 -1
- package/forms/radio/src/radio.component.d.ts +32 -37
- package/forms/select/src/select.component.d.ts +8 -5
- package/forms/switch/src/switch.component.d.ts +17 -22
- package/forms/textarea/src/textarea.component.d.ts +2 -3
- package/i18n/src/en.d.ts +5 -0
- package/package.json +65 -57
- package/sd-angular-core-19.0.0-beta.102.tgz +0 -0
- package/sd-angular-core-19.0.0-beta.100.tgz +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, model, input, booleanAttribute, computed, viewChild, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/material/menu';
|
|
4
|
+
import { MatMenuTrigger, MatMenuModule } from '@angular/material/menu';
|
|
5
|
+
import * as i2 from '@angular/material/tooltip';
|
|
6
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
7
|
+
import { DomSanitizer } from '@angular/platform-browser';
|
|
8
|
+
import { OPERATORS } from '@sdcorejs/utils/constants';
|
|
9
|
+
import { I18nService } from '@sd-angular/core/i18n';
|
|
10
|
+
|
|
11
|
+
class SdOperator {
|
|
12
|
+
// Inner SVG markup (hình phễu) dùng khi chưa chọn operator.
|
|
13
|
+
static FALLBACK_ICON = '<path d="M4 5h16l-6.5 7.5V19l-3 2v-8.5z"/>';
|
|
14
|
+
#i18n = inject(I18nService);
|
|
15
|
+
#sanitizer = inject(DomSanitizer);
|
|
16
|
+
/** Operator hiện tại — binding hai chiều [(model)]. */
|
|
17
|
+
model = model();
|
|
18
|
+
/** Danh sách operator cho phép, giữ nguyên thứ tự truyền vào. */
|
|
19
|
+
operators = input([]);
|
|
20
|
+
/** Vô hiệu hóa trigger (không mở được menu). */
|
|
21
|
+
disabled = input(false, { transform: booleanAttribute });
|
|
22
|
+
/** data-autoId cho e2e selector. */
|
|
23
|
+
autoId = input();
|
|
24
|
+
/** Allowed operators map sang { value, icon, display } theo thứ tự input. */
|
|
25
|
+
items = computed(() => {
|
|
26
|
+
const out = [];
|
|
27
|
+
for (const value of this.operators()) {
|
|
28
|
+
const r = this.#resolve(value);
|
|
29
|
+
if (!r)
|
|
30
|
+
continue;
|
|
31
|
+
out.push({ value, icon: this.#svg(r.icon), display: r.display });
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
});
|
|
35
|
+
/** Icon SVG ở trigger — fallback phễu khi model chưa set / không tìm thấy. */
|
|
36
|
+
currentIcon = computed(() => {
|
|
37
|
+
return this.#svg(this.#resolve(this.model())?.icon ?? SdOperator.FALLBACK_ICON);
|
|
38
|
+
});
|
|
39
|
+
/** Tooltip = i18n label của operator hiện tại ('' khi chưa chọn). */
|
|
40
|
+
currentLabel = computed(() => this.#resolve(this.model())?.display ?? '');
|
|
41
|
+
// Resolve một operator → { inner-svg, nhãn đã dịch } từ bảng OPERATORS dùng chung.
|
|
42
|
+
#resolve(value) {
|
|
43
|
+
if (value == null)
|
|
44
|
+
return undefined;
|
|
45
|
+
const entry = OPERATORS.find((o) => o.value === value);
|
|
46
|
+
return entry ? { icon: entry.icon, display: this.#i18n.t(entry.display) } : undefined;
|
|
47
|
+
}
|
|
48
|
+
// why: OPERATORS.icon là inner SVG (path/line/rect). Bọc <svg> + bypass sanitizer
|
|
49
|
+
// (nguồn là hằng số nội bộ, không phải input người dùng) để Angular không strip svg con.
|
|
50
|
+
#svg(inner) {
|
|
51
|
+
return this.#sanitizer.bypassSecurityTrustHtml(`<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${inner}</svg>`);
|
|
52
|
+
}
|
|
53
|
+
trigger = viewChild(MatMenuTrigger);
|
|
54
|
+
/** Open the operator menu programmatically (used by the query-bar build flow). */
|
|
55
|
+
open() {
|
|
56
|
+
this.trigger()?.openMenu();
|
|
57
|
+
}
|
|
58
|
+
/** Chọn operator từ menu. */
|
|
59
|
+
select(value) {
|
|
60
|
+
this.model.set(value);
|
|
61
|
+
}
|
|
62
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdOperator, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
63
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdOperator, isStandalone: true, selector: "sd-operator", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, operators: { classPropertyName: "operators", publicName: "operators", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { model: "modelChange" }, viewQueries: [{ propertyName: "trigger", first: true, predicate: MatMenuTrigger, descendants: true, isSignal: true }], ngImport: i0, template: "@let _current = model();\r\n\r\n<button\r\n type=\"button\"\r\n class=\"c-op-trigger\"\r\n [disabled]=\"disabled()\"\r\n [matMenuTriggerFor]=\"menu\"\r\n [matTooltip]=\"currentLabel()\"\r\n matTooltipPosition=\"above\"\r\n [attr.data-autoId]=\"autoId() ?? null\">\r\n <span class=\"c-op-icon\" [innerHTML]=\"currentIcon()\"></span>\r\n</button>\r\n\r\n<mat-menu #menu=\"matMenu\" class=\"c-op-menu\">\r\n @for (item of items(); track item.value) {\r\n <button\r\n type=\"button\"\r\n mat-menu-item\r\n class=\"c-op-row\"\r\n [class.c-op-active]=\"item.value === _current\"\r\n (click)=\"select(item.value)\">\r\n <span class=\"c-op-icon\" [innerHTML]=\"item.icon\"></span>\r\n <span class=\"c-op-label\">{{ item.display }}</span>\r\n <span class=\"c-op-code\">{{ item.value }}</span>\r\n </button>\r\n }\r\n</mat-menu>\r\n", styles: [".c-op-trigger{display:inline-flex;align-items:center;justify-content:center;padding:4px;border:none;background:transparent;color:var(--sd-primary, #0f766e);cursor:pointer;border-radius:4px}.c-op-trigger:hover:not([disabled]){background:#0000000a}.c-op-trigger[disabled]{color:#00000042;cursor:default}.c-op-icon{display:inline-flex;align-items:center}.c-op-icon svg{display:block}::ng-deep .c-op-menu .mat-mdc-menu-item-text{display:flex;align-items:center;gap:8px;width:100%}::ng-deep .c-op-menu .c-op-icon{display:inline-flex;align-items:center;flex:0 0 auto}::ng-deep .c-op-menu .c-op-icon svg{display:block}::ng-deep .c-op-menu .c-op-label{flex:1 1 auto}::ng-deep .c-op-menu .c-op-code{margin-left:auto;padding-left:16px;color:var(--sd-text-muted, #7a7a7a);font-size:11px;font-family:monospace}::ng-deep .c-op-menu .c-op-row.c-op-active{background:var(--sd-primary-light, rgba(15, 118, 110, .08))}\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: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
64
|
+
}
|
|
65
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdOperator, decorators: [{
|
|
66
|
+
type: Component,
|
|
67
|
+
args: [{ selector: 'sd-operator', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatMenuModule, MatTooltipModule], template: "@let _current = model();\r\n\r\n<button\r\n type=\"button\"\r\n class=\"c-op-trigger\"\r\n [disabled]=\"disabled()\"\r\n [matMenuTriggerFor]=\"menu\"\r\n [matTooltip]=\"currentLabel()\"\r\n matTooltipPosition=\"above\"\r\n [attr.data-autoId]=\"autoId() ?? null\">\r\n <span class=\"c-op-icon\" [innerHTML]=\"currentIcon()\"></span>\r\n</button>\r\n\r\n<mat-menu #menu=\"matMenu\" class=\"c-op-menu\">\r\n @for (item of items(); track item.value) {\r\n <button\r\n type=\"button\"\r\n mat-menu-item\r\n class=\"c-op-row\"\r\n [class.c-op-active]=\"item.value === _current\"\r\n (click)=\"select(item.value)\">\r\n <span class=\"c-op-icon\" [innerHTML]=\"item.icon\"></span>\r\n <span class=\"c-op-label\">{{ item.display }}</span>\r\n <span class=\"c-op-code\">{{ item.value }}</span>\r\n </button>\r\n }\r\n</mat-menu>\r\n", styles: [".c-op-trigger{display:inline-flex;align-items:center;justify-content:center;padding:4px;border:none;background:transparent;color:var(--sd-primary, #0f766e);cursor:pointer;border-radius:4px}.c-op-trigger:hover:not([disabled]){background:#0000000a}.c-op-trigger[disabled]{color:#00000042;cursor:default}.c-op-icon{display:inline-flex;align-items:center}.c-op-icon svg{display:block}::ng-deep .c-op-menu .mat-mdc-menu-item-text{display:flex;align-items:center;gap:8px;width:100%}::ng-deep .c-op-menu .c-op-icon{display:inline-flex;align-items:center;flex:0 0 auto}::ng-deep .c-op-menu .c-op-icon svg{display:block}::ng-deep .c-op-menu .c-op-label{flex:1 1 auto}::ng-deep .c-op-menu .c-op-code{margin-left:auto;padding-left:16px;color:var(--sd-text-muted, #7a7a7a);font-size:11px;font-family:monospace}::ng-deep .c-op-menu .c-op-row.c-op-active{background:var(--sd-primary-light, rgba(15, 118, 110, .08))}\n"] }]
|
|
68
|
+
}] });
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Generated bundle index. Do not edit.
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
export { SdOperator };
|
|
75
|
+
//# sourceMappingURL=sd-angular-core-components-operator.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sd-angular-core-components-operator.mjs","sources":["../../../projects/sd-angular/components/operator/src/operator.component.ts","../../../projects/sd-angular/components/operator/src/operator.component.html","../../../projects/sd-angular/components/operator/sd-angular-core-components-operator.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, booleanAttribute, computed, inject, input, model, viewChild } from '@angular/core';\r\nimport { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\r\nimport { OPERATORS } from '@sdcorejs/utils/constants';\r\nimport { Operator } from '@sdcorejs/utils/models';\r\nimport { I18nService } from '@sd-angular/core/i18n';\r\n\r\ninterface OperatorItem {\r\n value: Operator;\r\n icon: SafeHtml;\r\n display: string;\r\n}\r\n\r\n@Component({\r\n selector: 'sd-operator',\r\n templateUrl: './operator.component.html',\r\n styleUrls: ['./operator.component.scss'],\r\n standalone: true,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n imports: [MatMenuModule, MatTooltipModule],\r\n})\r\nexport class SdOperator {\r\n // Inner SVG markup (hình phễu) dùng khi chưa chọn operator.\r\n static readonly FALLBACK_ICON = '<path d=\"M4 5h16l-6.5 7.5V19l-3 2v-8.5z\"/>';\r\n\r\n readonly #i18n = inject(I18nService);\r\n readonly #sanitizer = inject(DomSanitizer);\r\n\r\n /** Operator hiện tại — binding hai chiều [(model)]. */\r\n model = model<Operator | undefined>();\r\n\r\n /** Danh sách operator cho phép, giữ nguyên thứ tự truyền vào. */\r\n operators = input<Operator[]>([]);\r\n\r\n /** Vô hiệu hóa trigger (không mở được menu). */\r\n disabled = input(false, { transform: booleanAttribute });\r\n\r\n /** data-autoId cho e2e selector. */\r\n autoId = input<string>();\r\n\r\n /** Allowed operators map sang { value, icon, display } theo thứ tự input. */\r\n readonly items = computed<OperatorItem[]>(() => {\r\n const out: OperatorItem[] = [];\r\n for (const value of this.operators()) {\r\n const r = this.#resolve(value);\r\n if (!r) continue;\r\n out.push({ value, icon: this.#svg(r.icon), display: r.display });\r\n }\r\n return out;\r\n });\r\n\r\n /** Icon SVG ở trigger — fallback phễu khi model chưa set / không tìm thấy. */\r\n readonly currentIcon = computed<SafeHtml>(() => {\r\n return this.#svg(this.#resolve(this.model())?.icon ?? SdOperator.FALLBACK_ICON);\r\n });\r\n\r\n /** Tooltip = i18n label của operator hiện tại ('' khi chưa chọn). */\r\n readonly currentLabel = computed<string>(() => this.#resolve(this.model())?.display ?? '');\r\n\r\n // Resolve một operator → { inner-svg, nhãn đã dịch } từ bảng OPERATORS dùng chung.\r\n #resolve(value: Operator | undefined): { icon: string; display: string } | undefined {\r\n if (value == null) return undefined;\r\n const entry = OPERATORS.find((o) => o.value === value);\r\n return entry ? { icon: entry.icon, display: this.#i18n.t(entry.display) } : undefined;\r\n }\r\n\r\n // why: OPERATORS.icon là inner SVG (path/line/rect). Bọc <svg> + bypass sanitizer\r\n // (nguồn là hằng số nội bộ, không phải input người dùng) để Angular không strip svg con.\r\n #svg(inner: string): SafeHtml {\r\n return this.#sanitizer.bypassSecurityTrustHtml(\r\n `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${inner}</svg>`,\r\n );\r\n }\r\n\r\n private readonly trigger = viewChild(MatMenuTrigger);\r\n\r\n /** Open the operator menu programmatically (used by the query-bar build flow). */\r\n open(): void {\r\n this.trigger()?.openMenu();\r\n }\r\n\r\n /** Chọn operator từ menu. */\r\n select(value: Operator): void {\r\n this.model.set(value);\r\n }\r\n}\r\n","@let _current = model();\r\n\r\n<button\r\n type=\"button\"\r\n class=\"c-op-trigger\"\r\n [disabled]=\"disabled()\"\r\n [matMenuTriggerFor]=\"menu\"\r\n [matTooltip]=\"currentLabel()\"\r\n matTooltipPosition=\"above\"\r\n [attr.data-autoId]=\"autoId() ?? null\">\r\n <span class=\"c-op-icon\" [innerHTML]=\"currentIcon()\"></span>\r\n</button>\r\n\r\n<mat-menu #menu=\"matMenu\" class=\"c-op-menu\">\r\n @for (item of items(); track item.value) {\r\n <button\r\n type=\"button\"\r\n mat-menu-item\r\n class=\"c-op-row\"\r\n [class.c-op-active]=\"item.value === _current\"\r\n (click)=\"select(item.value)\">\r\n <span class=\"c-op-icon\" [innerHTML]=\"item.icon\"></span>\r\n <span class=\"c-op-label\">{{ item.display }}</span>\r\n <span class=\"c-op-code\">{{ item.value }}</span>\r\n </button>\r\n }\r\n</mat-menu>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|