@sdcorejs/angular 20.0.1 → 20.0.3

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.
Files changed (130) hide show
  1. package/README.md +22 -4
  2. package/assets/scss/core/_inline-edit.scss +105 -0
  3. package/assets/scss/core/form.scss +15 -0
  4. package/components/autoid-inspector/index.d.ts +53 -4
  5. package/components/form-generic/index.d.ts +12 -13
  6. package/components/index.d.ts +1 -0
  7. package/components/modal-resizable/index.d.ts +32 -0
  8. package/components/table/index.d.ts +99 -10
  9. package/components/view/index.d.ts +33 -0
  10. package/fesm2022/sdcorejs-angular-components-anchor.mjs +9 -9
  11. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs +111 -24
  12. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
  13. package/fesm2022/sdcorejs-angular-components-avatar.mjs +4 -4
  14. package/fesm2022/sdcorejs-angular-components-avatar.mjs.map +1 -1
  15. package/fesm2022/sdcorejs-angular-components-badge.mjs +3 -3
  16. package/fesm2022/sdcorejs-angular-components-base.mjs +3 -3
  17. package/fesm2022/sdcorejs-angular-components-button.mjs +4 -4
  18. package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
  19. package/fesm2022/sdcorejs-angular-components-chart.mjs +12 -12
  20. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs +3 -3
  21. package/fesm2022/sdcorejs-angular-components-code-editor.mjs +3 -3
  22. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +6 -6
  23. package/fesm2022/sdcorejs-angular-components-editor.mjs +3 -3
  24. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +288 -375
  25. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  26. package/fesm2022/sdcorejs-angular-components-history.mjs +7 -7
  27. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +10 -10
  28. package/fesm2022/sdcorejs-angular-components-inform.mjs +6 -6
  29. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs +3 -3
  30. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs +158 -0
  31. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs.map +1 -0
  32. package/fesm2022/sdcorejs-angular-components-modal.mjs +3 -3
  33. package/fesm2022/sdcorejs-angular-components-operator.mjs +6 -4
  34. package/fesm2022/sdcorejs-angular-components-operator.mjs.map +1 -1
  35. package/fesm2022/sdcorejs-angular-components-preview.mjs +8 -8
  36. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  37. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +60 -106
  38. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  39. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +3 -3
  40. package/fesm2022/sdcorejs-angular-components-quick-action.mjs +3 -3
  41. package/fesm2022/sdcorejs-angular-components-section.mjs +6 -6
  42. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +4 -4
  43. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  44. package/fesm2022/sdcorejs-angular-components-splitter.mjs +12 -12
  45. package/fesm2022/sdcorejs-angular-components-stepper.mjs +6 -6
  46. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +18 -18
  47. package/fesm2022/sdcorejs-angular-components-tab.mjs +6 -6
  48. package/fesm2022/sdcorejs-angular-components-table.mjs +335 -208
  49. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  50. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +16 -16
  51. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  52. package/fesm2022/sdcorejs-angular-components-view.mjs +45 -13
  53. package/fesm2022/sdcorejs-angular-components-view.mjs.map +1 -1
  54. package/fesm2022/sdcorejs-angular-components.mjs +1 -0
  55. package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
  56. package/fesm2022/sdcorejs-angular-directives.mjs +21 -21
  57. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +28 -8
  58. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  59. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +11 -6
  60. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  61. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +15 -10
  62. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  63. package/fesm2022/sdcorejs-angular-forms-chip.mjs +15 -10
  64. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  65. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +21 -12
  66. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  67. package/fesm2022/sdcorejs-angular-forms-date.mjs +29 -17
  68. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  69. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +34 -22
  70. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  71. package/fesm2022/sdcorejs-angular-forms-directives.mjs +12 -12
  72. package/fesm2022/sdcorejs-angular-forms-inline-text.mjs +167 -0
  73. package/fesm2022/sdcorejs-angular-forms-inline-text.mjs.map +1 -0
  74. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +7 -5
  75. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  76. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +37 -10
  77. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  78. package/fesm2022/sdcorejs-angular-forms-input.mjs +38 -12
  79. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  80. package/fesm2022/sdcorejs-angular-forms-label.mjs +3 -3
  81. package/fesm2022/sdcorejs-angular-forms-models.mjs +32 -2
  82. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  83. package/fesm2022/sdcorejs-angular-forms-radio.mjs +11 -6
  84. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  85. package/fesm2022/sdcorejs-angular-forms-select.mjs +36 -12
  86. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  87. package/fesm2022/sdcorejs-angular-forms-switch.mjs +11 -6
  88. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  89. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +17 -7
  90. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  91. package/fesm2022/sdcorejs-angular-forms.mjs +4 -4
  92. package/fesm2022/sdcorejs-angular-handlers.mjs +3 -3
  93. package/fesm2022/sdcorejs-angular-i18n.mjs +26 -6
  94. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  95. package/fesm2022/sdcorejs-angular-interceptors.mjs +6 -6
  96. package/fesm2022/sdcorejs-angular-modules-auth.mjs +9 -9
  97. package/fesm2022/sdcorejs-angular-modules-authom.mjs +7 -7
  98. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +7 -7
  99. package/fesm2022/sdcorejs-angular-modules-layout.mjs +73 -73
  100. package/fesm2022/sdcorejs-angular-modules-permission.mjs +9 -9
  101. package/fesm2022/sdcorejs-angular-pipes.mjs +14 -14
  102. package/fesm2022/sdcorejs-angular-services-api.mjs +10 -10
  103. package/fesm2022/sdcorejs-angular-services-cache.mjs +3 -3
  104. package/fesm2022/sdcorejs-angular-services-confirm.mjs +6 -6
  105. package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
  106. package/fesm2022/sdcorejs-angular-services-docx.mjs +3 -3
  107. package/fesm2022/sdcorejs-angular-services-excel.mjs +3 -3
  108. package/fesm2022/sdcorejs-angular-services-license.mjs +3 -3
  109. package/fesm2022/sdcorejs-angular-services-loading.mjs +3 -3
  110. package/fesm2022/sdcorejs-angular-services-notify.mjs +23 -10
  111. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  112. package/fesm2022/sdcorejs-angular-services-storage.mjs +3 -3
  113. package/forms/autocomplete/index.d.ts +16 -3
  114. package/forms/checkbox/index.d.ts +5 -1
  115. package/forms/chip/index.d.ts +5 -2
  116. package/forms/chip-calendar/index.d.ts +5 -2
  117. package/forms/date/index.d.ts +14 -5
  118. package/forms/date-range/index.d.ts +12 -5
  119. package/forms/datetime/index.d.ts +14 -5
  120. package/forms/inline-text/index.d.ts +80 -0
  121. package/forms/input/index.d.ts +14 -2
  122. package/forms/input-color/index.d.ts +3 -1
  123. package/forms/input-number/index.d.ts +14 -2
  124. package/forms/models/index.d.ts +40 -2
  125. package/forms/radio/index.d.ts +5 -2
  126. package/forms/select/index.d.ts +23 -5
  127. package/forms/switch/index.d.ts +5 -2
  128. package/forms/textarea/index.d.ts +9 -2
  129. package/i18n/index.d.ts +4 -0
  130. package/package.json +9 -1
@@ -39,11 +39,13 @@ class SdOperator {
39
39
  /** Tooltip = i18n label của operator hiện tại ('' khi chưa chọn). */
40
40
  currentLabel = computed(() => this.#resolve(this.model())?.display ?? '', ...(ngDevMode ? [{ debugName: "currentLabel" }] : []));
41
41
  // Resolve một operator → { inner-svg, nhãn đã dịch } từ bảng OPERATORS dùng chung.
42
+ // why: OPERATORS[].display là i18n KEY ('core.operator.*.display'), KHÔNG phải text —
43
+ // phải dịch qua I18nService, nếu không UI hiện key thô (code) thay vì nhãn đã dịch.
42
44
  #resolve(value) {
43
45
  if (value == null)
44
46
  return undefined;
45
47
  const entry = OPERATORS.find((o) => o.value === value);
46
- return entry ? { icon: entry.icon, display: entry.display } : undefined;
48
+ return entry ? { icon: entry.icon, display: this.#i18n.t(entry.display) } : undefined;
47
49
  }
48
50
  // why: OPERATORS.icon là inner SVG (path/line/rect). Bọc <svg> + bypass sanitizer
49
51
  // (nguồn là hằng số nội bộ, không phải input người dùng) để Angular không strip svg con.
@@ -59,10 +61,10 @@ class SdOperator {
59
61
  select(value) {
60
62
  this.model.set(value);
61
63
  }
62
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdOperator, deps: [], target: i0.ɵɵFactoryTarget.Component });
63
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.23", 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();\n\n<button\n type=\"button\"\n class=\"c-op-trigger\"\n [disabled]=\"disabled()\"\n [matMenuTriggerFor]=\"menu\"\n [matTooltip]=\"currentLabel()\"\n matTooltipPosition=\"above\"\n [attr.data-autoId]=\"autoId() ?? null\">\n <span class=\"c-op-icon\" [innerHTML]=\"currentIcon()\"></span>\n</button>\n\n<mat-menu #menu=\"matMenu\" class=\"c-op-menu\">\n @for (item of items(); track item.value) {\n <button\n type=\"button\"\n mat-menu-item\n class=\"c-op-row\"\n [class.c-op-active]=\"item.value === _current\"\n (click)=\"select(item.value)\">\n <span class=\"c-op-icon\" [innerHTML]=\"item.icon\"></span>\n <span class=\"c-op-label\">{{ item.display }}</span>\n <span class=\"c-op-code\">{{ item.value }}</span>\n </button>\n }\n</mat-menu>\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
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: SdOperator, deps: [], target: i0.ɵɵFactoryTarget.Component });
65
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", 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();\n\n<button\n type=\"button\"\n class=\"c-op-trigger\"\n [disabled]=\"disabled()\"\n [matMenuTriggerFor]=\"menu\"\n [matTooltip]=\"currentLabel()\"\n matTooltipPosition=\"above\"\n [attr.data-autoId]=\"autoId() ?? null\">\n <span class=\"c-op-icon\" [innerHTML]=\"currentIcon()\"></span>\n</button>\n\n<mat-menu #menu=\"matMenu\" class=\"c-op-menu\">\n @for (item of items(); track item.value) {\n <button\n type=\"button\"\n mat-menu-item\n class=\"c-op-row\"\n [class.c-op-active]=\"item.value === _current\"\n (click)=\"select(item.value)\">\n <span class=\"c-op-icon\" [innerHTML]=\"item.icon\"></span>\n <span class=\"c-op-label\">{{ item.display }}</span>\n <span class=\"c-op-code\">{{ item.value }}</span>\n </button>\n }\n</mat-menu>\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
66
  }
65
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdOperator, decorators: [{
67
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: SdOperator, decorators: [{
66
68
  type: Component,
67
69
  args: [{ selector: 'sd-operator', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatMenuModule, MatTooltipModule], template: "@let _current = model();\n\n<button\n type=\"button\"\n class=\"c-op-trigger\"\n [disabled]=\"disabled()\"\n [matMenuTriggerFor]=\"menu\"\n [matTooltip]=\"currentLabel()\"\n matTooltipPosition=\"above\"\n [attr.data-autoId]=\"autoId() ?? null\">\n <span class=\"c-op-icon\" [innerHTML]=\"currentIcon()\"></span>\n</button>\n\n<mat-menu #menu=\"matMenu\" class=\"c-op-menu\">\n @for (item of items(); track item.value) {\n <button\n type=\"button\"\n mat-menu-item\n class=\"c-op-row\"\n [class.c-op-active]=\"item.value === _current\"\n (click)=\"select(item.value)\">\n <span class=\"c-op-icon\" [innerHTML]=\"item.icon\"></span>\n <span class=\"c-op-label\">{{ item.display }}</span>\n <span class=\"c-op-code\">{{ item.value }}</span>\n </button>\n }\n</mat-menu>\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
70
  }], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }, { type: i0.Output, args: ["modelChange"] }], operators: [{ type: i0.Input, args: [{ isSignal: true, alias: "operators", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], autoId: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoId", required: false }] }], trigger: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatMenuTrigger), { isSignal: true }] }] } });
@@ -1 +1 @@
1
- {"version":3,"file":"sdcorejs-angular-components-operator.mjs","sources":["../../../projects/sdcorejs-angular/components/operator/src/operator.component.ts","../../../projects/sdcorejs-angular/components/operator/src/operator.component.html","../../../projects/sdcorejs-angular/components/operator/sdcorejs-angular-components-operator.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, booleanAttribute, computed, inject, input, model, viewChild } from '@angular/core';\nimport { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { OPERATORS } from '@sdcorejs/utils/constants';\nimport { Operator } from '@sdcorejs/utils/models';\nimport { I18nService } from '@sdcorejs/angular/i18n';\n\ninterface OperatorItem {\n value: Operator;\n icon: SafeHtml;\n display: string;\n}\n\n@Component({\n selector: 'sd-operator',\n templateUrl: './operator.component.html',\n styleUrls: ['./operator.component.scss'],\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MatMenuModule, MatTooltipModule],\n})\nexport class SdOperator {\n // Inner SVG markup (hình phễu) dùng khi chưa chọn operator.\n static readonly FALLBACK_ICON = '<path d=\"M4 5h16l-6.5 7.5V19l-3 2v-8.5z\"/>';\n\n readonly #i18n = inject(I18nService);\n readonly #sanitizer = inject(DomSanitizer);\n\n /** Operator hiện tại — binding hai chiều [(model)]. */\n model = model<Operator | undefined>();\n\n /** Danh sách operator cho phép, giữ nguyên thứ tự truyền vào. */\n operators = input<Operator[]>([]);\n\n /** Vô hiệu hóa trigger (không mở được menu). */\n disabled = input(false, { transform: booleanAttribute });\n\n /** data-autoId cho e2e selector. */\n autoId = input<string>();\n\n /** Allowed operators map sang { value, icon, display } theo thứ tự input. */\n readonly items = computed<OperatorItem[]>(() => {\n const out: OperatorItem[] = [];\n for (const value of this.operators()) {\n const r = this.#resolve(value);\n if (!r) continue;\n out.push({ value, icon: this.#svg(r.icon), display: r.display });\n }\n return out;\n });\n\n /** Icon SVG ở trigger — fallback phễu khi model chưa set / không tìm thấy. */\n readonly currentIcon = computed<SafeHtml>(() => {\n return this.#svg(this.#resolve(this.model())?.icon ?? SdOperator.FALLBACK_ICON);\n });\n\n /** Tooltip = i18n label của operator hiện tại ('' khi chưa chọn). */\n readonly currentLabel = computed<string>(() => this.#resolve(this.model())?.display ?? '');\n\n // Resolve một operator → { inner-svg, nhãn đã dịch } từ bảng OPERATORS dùng chung.\n #resolve(value: Operator | undefined): { icon: string; display: string } | undefined {\n if (value == null) return undefined;\n const entry = OPERATORS.find((o) => o.value === value);\n return entry ? { icon: entry.icon, display: entry.display } : undefined;\n }\n\n // why: OPERATORS.icon là inner SVG (path/line/rect). Bọc <svg> + bypass sanitizer\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.\n #svg(inner: string): SafeHtml {\n return this.#sanitizer.bypassSecurityTrustHtml(\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>`,\n );\n }\n\n private readonly trigger = viewChild(MatMenuTrigger);\n\n /** Open the operator menu programmatically (used by the query-bar build flow). */\n open(): void {\n this.trigger()?.openMenu();\n }\n\n /** Chọn operator từ menu. */\n select(value: Operator): void {\n this.model.set(value);\n }\n}\n","@let _current = model();\n\n<button\n type=\"button\"\n class=\"c-op-trigger\"\n [disabled]=\"disabled()\"\n [matMenuTriggerFor]=\"menu\"\n [matTooltip]=\"currentLabel()\"\n matTooltipPosition=\"above\"\n [attr.data-autoId]=\"autoId() ?? null\">\n <span class=\"c-op-icon\" [innerHTML]=\"currentIcon()\"></span>\n</button>\n\n<mat-menu #menu=\"matMenu\" class=\"c-op-menu\">\n @for (item of items(); track item.value) {\n <button\n type=\"button\"\n mat-menu-item\n class=\"c-op-row\"\n [class.c-op-active]=\"item.value === _current\"\n (click)=\"select(item.value)\">\n <span class=\"c-op-icon\" [innerHTML]=\"item.icon\"></span>\n <span class=\"c-op-label\">{{ item.display }}</span>\n <span class=\"c-op-code\">{{ item.value }}</span>\n </button>\n }\n</mat-menu>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdcorejs-angular-components-operator.mjs","sources":["../../../projects/sdcorejs-angular/components/operator/src/operator.component.ts","../../../projects/sdcorejs-angular/components/operator/src/operator.component.html","../../../projects/sdcorejs-angular/components/operator/sdcorejs-angular-components-operator.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, booleanAttribute, computed, inject, input, model, viewChild } from '@angular/core';\nimport { MatMenuModule, MatMenuTrigger } from '@angular/material/menu';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { OPERATORS } from '@sdcorejs/utils/constants';\nimport { Operator } from '@sdcorejs/utils/models';\nimport { I18nService } from '@sdcorejs/angular/i18n';\n\ninterface OperatorItem {\n value: Operator;\n icon: SafeHtml;\n display: string;\n}\n\n@Component({\n selector: 'sd-operator',\n templateUrl: './operator.component.html',\n styleUrls: ['./operator.component.scss'],\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MatMenuModule, MatTooltipModule],\n})\nexport class SdOperator {\n // Inner SVG markup (hình phễu) dùng khi chưa chọn operator.\n static readonly FALLBACK_ICON = '<path d=\"M4 5h16l-6.5 7.5V19l-3 2v-8.5z\"/>';\n\n readonly #i18n = inject(I18nService);\n readonly #sanitizer = inject(DomSanitizer);\n\n /** Operator hiện tại — binding hai chiều [(model)]. */\n model = model<Operator | undefined>();\n\n /** Danh sách operator cho phép, giữ nguyên thứ tự truyền vào. */\n operators = input<Operator[]>([]);\n\n /** Vô hiệu hóa trigger (không mở được menu). */\n disabled = input(false, { transform: booleanAttribute });\n\n /** data-autoId cho e2e selector. */\n autoId = input<string>();\n\n /** Allowed operators map sang { value, icon, display } theo thứ tự input. */\n readonly items = computed<OperatorItem[]>(() => {\n const out: OperatorItem[] = [];\n for (const value of this.operators()) {\n const r = this.#resolve(value);\n if (!r) continue;\n out.push({ value, icon: this.#svg(r.icon), display: r.display });\n }\n return out;\n });\n\n /** Icon SVG ở trigger — fallback phễu khi model chưa set / không tìm thấy. */\n readonly currentIcon = computed<SafeHtml>(() => {\n return this.#svg(this.#resolve(this.model())?.icon ?? SdOperator.FALLBACK_ICON);\n });\n\n /** Tooltip = i18n label của operator hiện tại ('' khi chưa chọn). */\n readonly currentLabel = computed<string>(() => this.#resolve(this.model())?.display ?? '');\n\n // Resolve một operator → { inner-svg, nhãn đã dịch } từ bảng OPERATORS dùng chung.\n // why: OPERATORS[].display là i18n KEY ('core.operator.*.display'), KHÔNG phải text —\n // phải dịch qua I18nService, nếu không UI hiện key thô (code) thay vì nhãn đã dịch.\n #resolve(value: Operator | undefined): { icon: string; display: string } | undefined {\n if (value == null) return undefined;\n const entry = OPERATORS.find((o) => o.value === value);\n return entry ? { icon: entry.icon, display: this.#i18n.t(entry.display) } : undefined;\n }\n\n // why: OPERATORS.icon là inner SVG (path/line/rect). Bọc <svg> + bypass sanitizer\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.\n #svg(inner: string): SafeHtml {\n return this.#sanitizer.bypassSecurityTrustHtml(\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>`,\n );\n }\n\n private readonly trigger = viewChild(MatMenuTrigger);\n\n /** Open the operator menu programmatically (used by the query-bar build flow). */\n open(): void {\n this.trigger()?.openMenu();\n }\n\n /** Chọn operator từ menu. */\n select(value: Operator): void {\n this.model.set(value);\n }\n}\n","@let _current = model();\n\n<button\n type=\"button\"\n class=\"c-op-trigger\"\n [disabled]=\"disabled()\"\n [matMenuTriggerFor]=\"menu\"\n [matTooltip]=\"currentLabel()\"\n matTooltipPosition=\"above\"\n [attr.data-autoId]=\"autoId() ?? null\">\n <span class=\"c-op-icon\" [innerHTML]=\"currentIcon()\"></span>\n</button>\n\n<mat-menu #menu=\"matMenu\" class=\"c-op-menu\">\n @for (item of items(); track item.value) {\n <button\n type=\"button\"\n mat-menu-item\n class=\"c-op-row\"\n [class.c-op-active]=\"item.value === _current\"\n (click)=\"select(item.value)\">\n <span class=\"c-op-icon\" [innerHTML]=\"item.icon\"></span>\n <span class=\"c-op-label\">{{ item.display }}</span>\n <span class=\"c-op-code\">{{ item.value }}</span>\n </button>\n }\n</mat-menu>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}