@sdcorejs/angular 20.1.5 → 20.2.0

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 (208) hide show
  1. package/README.md +12 -4
  2. package/assets/scss/core/menu.scss +18 -0
  3. package/assets/scss/core/utilities/_misc.scss +15 -0
  4. package/assets/scss/sd-core.scss +1 -0
  5. package/components/anchor/index.d.ts +3 -1
  6. package/components/badge/index.d.ts +1 -0
  7. package/components/ckeditor-styles/index.d.ts +1 -1
  8. package/components/form-generic/index.d.ts +44 -33
  9. package/components/import-excel/index.d.ts +1 -0
  10. package/components/index.d.ts +6 -1
  11. package/components/mini-editor/index.d.ts +1 -1
  12. package/components/modal/index.d.ts +3 -2
  13. package/components/modal-resizable/index.d.ts +92 -0
  14. package/components/org-chart/index.d.ts +6 -0
  15. package/components/preview/index.d.ts +1 -0
  16. package/components/query-bar/index.d.ts +55 -17
  17. package/components/query-builder/index.d.ts +150 -98
  18. package/components/section/index.d.ts +3 -0
  19. package/components/tab-router/index.d.ts +19 -19
  20. package/components/table/index.d.ts +252 -110
  21. package/components/tree/index.d.ts +48 -30
  22. package/components/upload-file/index.d.ts +6 -3
  23. package/configurations/index.d.ts +1 -2
  24. package/fesm2022/sdcorejs-angular-components-anchor.mjs +37 -13
  25. package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
  26. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs +2 -2
  27. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
  28. package/fesm2022/sdcorejs-angular-components-badge.mjs +15 -2
  29. package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
  30. package/fesm2022/sdcorejs-angular-components-button.mjs +2 -2
  31. package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
  32. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs +1 -1
  33. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs.map +1 -1
  34. package/fesm2022/sdcorejs-angular-components-code-editor.mjs +3 -3
  35. package/fesm2022/sdcorejs-angular-components-code-editor.mjs.map +1 -1
  36. package/fesm2022/sdcorejs-angular-components-data-state.mjs +3 -3
  37. package/fesm2022/sdcorejs-angular-components-data-state.mjs.map +1 -1
  38. package/fesm2022/sdcorejs-angular-components-editor.mjs +2 -2
  39. package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
  40. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +324 -192
  41. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  42. package/fesm2022/sdcorejs-angular-components-history.mjs +4 -4
  43. package/fesm2022/sdcorejs-angular-components-history.mjs.map +1 -1
  44. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +13 -5
  45. package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
  46. package/fesm2022/sdcorejs-angular-components-inform.mjs +3 -3
  47. package/fesm2022/sdcorejs-angular-components-inform.mjs.map +1 -1
  48. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs +164 -8
  49. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs.map +1 -1
  50. package/fesm2022/sdcorejs-angular-components-modal.mjs +30 -18
  51. package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
  52. package/fesm2022/sdcorejs-angular-components-org-chart.mjs +60 -13
  53. package/fesm2022/sdcorejs-angular-components-org-chart.mjs.map +1 -1
  54. package/fesm2022/sdcorejs-angular-components-preview.mjs +58 -19
  55. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  56. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +192 -30
  57. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  58. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +187 -127
  59. package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
  60. package/fesm2022/sdcorejs-angular-components-section.mjs +16 -2
  61. package/fesm2022/sdcorejs-angular-components-section.mjs.map +1 -1
  62. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +83 -24
  63. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  64. package/fesm2022/sdcorejs-angular-components-splitter.mjs +57 -21
  65. package/fesm2022/sdcorejs-angular-components-splitter.mjs.map +1 -1
  66. package/fesm2022/sdcorejs-angular-components-stepper.mjs +2 -2
  67. package/fesm2022/sdcorejs-angular-components-stepper.mjs.map +1 -1
  68. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +68 -20
  69. package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
  70. package/fesm2022/sdcorejs-angular-components-tab.mjs +3 -2
  71. package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
  72. package/fesm2022/sdcorejs-angular-components-table.mjs +557 -255
  73. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  74. package/fesm2022/sdcorejs-angular-components-tree.mjs +80 -17
  75. package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
  76. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +48 -13
  77. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  78. package/fesm2022/sdcorejs-angular-components.mjs +6 -1
  79. package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
  80. package/fesm2022/sdcorejs-angular-configurations.mjs.map +1 -1
  81. package/fesm2022/sdcorejs-angular-directives.mjs +45 -8
  82. package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
  83. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +40 -29
  84. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  85. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +5 -5
  86. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  87. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +67 -50
  88. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  89. package/fesm2022/sdcorejs-angular-forms-chip.mjs +57 -43
  90. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  91. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +234 -64
  92. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  93. package/fesm2022/sdcorejs-angular-forms-date.mjs +209 -42
  94. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  95. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +131 -27
  96. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  97. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs +40 -16
  98. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs.map +1 -1
  99. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +16 -5
  100. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  101. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +24 -9
  102. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  103. package/fesm2022/sdcorejs-angular-forms-input.mjs +58 -10
  104. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  105. package/fesm2022/sdcorejs-angular-forms-models.mjs +279 -6
  106. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  107. package/fesm2022/sdcorejs-angular-forms-radio.mjs +4 -4
  108. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  109. package/fesm2022/sdcorejs-angular-forms-select.mjs +136 -38
  110. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  111. package/fesm2022/sdcorejs-angular-forms-switch.mjs +18 -3
  112. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  113. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +51 -62
  114. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  115. package/fesm2022/sdcorejs-angular-forms-time-range.mjs +57 -12
  116. package/fesm2022/sdcorejs-angular-forms-time-range.mjs.map +1 -1
  117. package/fesm2022/sdcorejs-angular-forms-time.mjs +16 -5
  118. package/fesm2022/sdcorejs-angular-forms-time.mjs.map +1 -1
  119. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs +100 -9
  120. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs.map +1 -1
  121. package/fesm2022/sdcorejs-angular-forms.mjs +91 -46
  122. package/fesm2022/sdcorejs-angular-forms.mjs.map +1 -1
  123. package/fesm2022/sdcorejs-angular-handlers.mjs +18 -3
  124. package/fesm2022/sdcorejs-angular-handlers.mjs.map +1 -1
  125. package/fesm2022/sdcorejs-angular-i18n.mjs +510 -68
  126. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  127. package/fesm2022/sdcorejs-angular-interceptors.mjs +87 -29
  128. package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
  129. package/fesm2022/sdcorejs-angular-modules-auth.mjs +25 -15
  130. package/fesm2022/sdcorejs-angular-modules-auth.mjs.map +1 -1
  131. package/fesm2022/sdcorejs-angular-modules-icon.mjs +2 -2
  132. package/fesm2022/sdcorejs-angular-modules-icon.mjs.map +1 -1
  133. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +32 -3
  134. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs.map +1 -1
  135. package/fesm2022/sdcorejs-angular-modules-layout.mjs +441 -135
  136. package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
  137. package/fesm2022/sdcorejs-angular-modules-permission.mjs +177 -40
  138. package/fesm2022/sdcorejs-angular-modules-permission.mjs.map +1 -1
  139. package/fesm2022/sdcorejs-angular-pipes.mjs +62 -28
  140. package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
  141. package/fesm2022/sdcorejs-angular-services-api.mjs +123 -13
  142. package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
  143. package/fesm2022/sdcorejs-angular-services-cache.mjs +53 -3
  144. package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
  145. package/fesm2022/sdcorejs-angular-services-confirm.mjs +25 -73
  146. package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
  147. package/fesm2022/sdcorejs-angular-services-excel.mjs +12 -10
  148. package/fesm2022/sdcorejs-angular-services-excel.mjs.map +1 -1
  149. package/fesm2022/sdcorejs-angular-services-loading.mjs +75 -84
  150. package/fesm2022/sdcorejs-angular-services-loading.mjs.map +1 -1
  151. package/fesm2022/sdcorejs-angular-services-notify.mjs +46 -5
  152. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  153. package/fesm2022/sdcorejs-angular-services-storage.mjs +4 -0
  154. package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
  155. package/fesm2022/sdcorejs-angular-services.mjs +0 -1
  156. package/fesm2022/sdcorejs-angular-services.mjs.map +1 -1
  157. package/fesm2022/sdcorejs-angular-utilities-extensions.mjs +225 -80
  158. package/fesm2022/sdcorejs-angular-utilities-extensions.mjs.map +1 -1
  159. package/fesm2022/sdcorejs-angular-utilities-models.mjs +1 -63
  160. package/fesm2022/sdcorejs-angular-utilities-models.mjs.map +1 -1
  161. package/fesm2022/sdcorejs-angular.mjs +17 -10
  162. package/fesm2022/sdcorejs-angular.mjs.map +1 -1
  163. package/forms/autocomplete/index.d.ts +5 -2
  164. package/forms/chip-calendar/index.d.ts +10 -0
  165. package/forms/date/index.d.ts +21 -3
  166. package/forms/date-range/index.d.ts +14 -2
  167. package/forms/datetime/index.d.ts +13 -2
  168. package/forms/entity-picker/index.d.ts +9 -3
  169. package/forms/index.d.ts +22 -13
  170. package/forms/input/index.d.ts +3 -0
  171. package/forms/input-color/index.d.ts +4 -0
  172. package/forms/input-number/index.d.ts +3 -0
  173. package/forms/models/index.d.ts +146 -5
  174. package/forms/select/index.d.ts +27 -4
  175. package/forms/switch/index.d.ts +7 -1
  176. package/forms/textarea/index.d.ts +5 -3
  177. package/forms/time-range/index.d.ts +22 -1
  178. package/forms/tree-select/index.d.ts +36 -5
  179. package/i18n/index.d.ts +99 -16
  180. package/index.d.ts +11 -2
  181. package/interceptors/index.d.ts +13 -3
  182. package/modules/auth/index.d.ts +1 -1
  183. package/modules/keycloak/index.d.ts +1 -0
  184. package/modules/layout/index.d.ts +103 -28
  185. package/modules/permission/index.d.ts +66 -4
  186. package/package.json +40 -25
  187. package/pipes/index.d.ts +27 -5
  188. package/services/api/index.d.ts +21 -1
  189. package/services/cache/index.d.ts +11 -1
  190. package/services/index.d.ts +0 -1
  191. package/services/notify/index.d.ts +1 -1
  192. package/utilities/extensions/index.d.ts +83 -61
  193. package/utilities/models/index.d.ts +2 -76
  194. package/components/base/index.d.ts +0 -11
  195. package/components/document-builder/index.d.ts +0 -252
  196. package/fesm2022/sdcorejs-angular-components-base.mjs +0 -23
  197. package/fesm2022/sdcorejs-angular-components-base.mjs.map +0 -1
  198. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +0 -5038
  199. package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +0 -1
  200. package/fesm2022/sdcorejs-angular-models.mjs +0 -6
  201. package/fesm2022/sdcorejs-angular-models.mjs.map +0 -1
  202. package/fesm2022/sdcorejs-angular-services-docx.mjs +0 -291
  203. package/fesm2022/sdcorejs-angular-services-docx.mjs.map +0 -1
  204. package/fesm2022/sdcorejs-angular-services-license.mjs +0 -97
  205. package/fesm2022/sdcorejs-angular-services-license.mjs.map +0 -1
  206. package/models/index.d.ts +0 -2
  207. package/services/docx/index.d.ts +0 -27
  208. package/services/license/index.d.ts +0 -12
@@ -2,14 +2,14 @@ import * as _angular_core from '@angular/core';
2
2
  import { TemplateRef, Signal, InjectionToken, AfterViewInit, OnDestroy } from '@angular/core';
3
3
  import { SdBadge } from '@sdcorejs/angular/components/badge';
4
4
  import { SdSearch } from '@sdcorejs/angular/forms/models';
5
- import { Operator, NestedKeyOf, Order, PagingReq, Color } from '@sdcorejs/utils/models';
5
+ import { Operator, NestedKeyOf, Color, Order, PagingReq } from '@sdcorejs/utils/models';
6
6
  import { SdUnwrapSignal } from '@sdcorejs/angular/utilities/models';
7
- import { MatPaginatorIntl, MatPaginator } from '@angular/material/paginator';
7
+ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
8
8
  import { MatSort } from '@angular/material/sort';
9
9
  import { MatTable } from '@angular/material/table';
10
10
  import { SdExcelColumn } from '@sdcorejs/angular/services';
11
- import { Observable } from 'rxjs';
12
11
  import { SdIconSet } from '@sdcorejs/angular/modules/icon';
12
+ import { Observable } from 'rxjs';
13
13
  import { SdButton } from '@sdcorejs/angular/components/button';
14
14
  import { CdkDrag, CdkDropList, CdkDragDrop } from '@angular/cdk/drag-drop';
15
15
  import { SdQuickAction } from '@sdcorejs/angular/components/quick-action';
@@ -19,8 +19,25 @@ import { SdSideDrawer } from '@sdcorejs/angular/components/side-drawer';
19
19
  import { SdModal } from '@sdcorejs/angular/components/modal';
20
20
  import { MatSelectionList } from '@angular/material/list';
21
21
 
22
- type SdTableColumn<T = any> = SdTableColumnText<T> | SdTableColumnNumber<T> | SdTableColumnBool<T> | SdTableColumnDate<T> | SdTableColumnValues<T> | SdTableColumnLazyValues<T> | SdTableColumnChildren<T>;
23
- type SdTableColumnTransformFunc<T = any> = (value: any, rowData: T, args?: {
22
+ type SdTableColumn<T = unknown> = SdTableColumnText<T> | SdTableColumnNumber<T> | SdTableColumnBool<T> | SdTableColumnDate<T> | SdTableColumnValues<T> | SdTableColumnLazyValues<T> | SdTableColumnChildren<T>;
23
+ /**
24
+ * Cột bảng dùng ở các API **không quan tâm kiểu hàng** — chúng chỉ đọc `field` / `type` / `hidden` /
25
+ * `filter` và không bao giờ chạm vào dữ liệu hàng (service filter, `SdConvertToPagingReq`, …).
26
+ *
27
+ * why: `SdTableColumn<T>` **bất biến (invariant)** theo `T`, vì `T` xuất hiện ở CẢ HAI chiều:
28
+ * - covariant — `field: NestedKeyOf<T>`;
29
+ * - contravariant — `transform` / `tooltip` / `click` / `useBadge` / `htmlTemplate` đều nhận `rowData: T`.
30
+ *
31
+ * Vì bất biến nên KHÔNG tồn tại siêu kiểu chung: `SdTableColumn<unknown>` hỏng ở chiều contravariant,
32
+ * `SdTableColumn<never>` hỏng ở chiều covariant (`field` co về `never`). Trước đây default generic là
33
+ * `any` nên mọi thứ gán được cho nhau — không phải vì kiểu đúng, mà vì `any` tắt kiểm tra hai chiều.
34
+ *
35
+ * Public default đã siết sang `unknown` (consumer viết `SdTableColumn<User>` sẽ được suy luận thật và
36
+ * báo lỗi khi dùng sai). Riêng vài vị trí tham số NỘI BỘ row-agnostic dưới đây vẫn cần một escape
37
+ * hatch: alias này khoanh vùng `any` vào đúng một chỗ có tài liệu, thay vì rải `any` khắp API công khai.
38
+ */
39
+ type SdTableColumnAnyRow = SdTableColumn<any>;
40
+ type SdTableColumnTransformFunc<T = unknown> = (value: any, rowData: T, args?: {
24
41
  isExport?: boolean;
25
42
  }) => string | Promise<string>;
26
43
  interface Badge {
@@ -29,8 +46,8 @@ interface Badge {
29
46
  icon?: SdUnwrapSignal<SdBadge['icon']>;
30
47
  title?: SdUnwrapSignal<SdBadge['title']>;
31
48
  }
32
- type UseBadgeFunc<T = any> = (value: any, rowData: T) => Badge;
33
- type UseBadgeValuesFunc<T = any, K = any> = (value: any, rowData: T, items: K[]) => Badge;
49
+ type UseBadgeFunc<T = unknown> = (value: any, rowData: T) => Badge;
50
+ type UseBadgeValuesFunc<T = unknown, K = unknown> = (value: any, rowData: T, items: K[]) => Badge;
34
51
  interface ColumnTitleOption {
35
52
  title: string;
36
53
  templateRef?: TemplateRef<any>;
@@ -43,7 +60,7 @@ interface ColumnCellOption {
43
60
  type?: 'more' | 'tooltip';
44
61
  };
45
62
  }
46
- interface SdTableColumnBase<T = any> {
63
+ interface SdTableColumnBase<T = unknown> {
47
64
  title: string | ColumnTitleOption;
48
65
  cell?: ColumnCellOption;
49
66
  width?: string;
@@ -74,12 +91,12 @@ interface SdTableColumnBase<T = any> {
74
91
  description?: string;
75
92
  };
76
93
  }
77
- interface SdTableColumnText<T = any> extends SdTableColumnBase<T> {
94
+ interface SdTableColumnText<T = unknown> extends SdTableColumnBase<T> {
78
95
  field: NestedKeyOf<T>;
79
96
  type: 'string';
80
97
  useBadge?: UseBadgeFunc<T>;
81
98
  }
82
- interface SdTableColumnNumber<T = any> extends SdTableColumnBase<T> {
99
+ interface SdTableColumnNumber<T = unknown> extends SdTableColumnBase<T> {
83
100
  field: NestedKeyOf<T>;
84
101
  type: 'number';
85
102
  useBadge?: UseBadgeFunc<T>;
@@ -87,7 +104,7 @@ interface SdTableColumnNumber<T = any> extends SdTableColumnBase<T> {
87
104
  type?: 'split-number';
88
105
  };
89
106
  }
90
- interface SdTableColumnBool<T = any> extends SdTableColumnBase<T> {
107
+ interface SdTableColumnBool<T = unknown> extends SdTableColumnBase<T> {
91
108
  field: NestedKeyOf<T>;
92
109
  type: 'boolean';
93
110
  useBadge?: UseBadgeFunc<T>;
@@ -96,7 +113,7 @@ interface SdTableColumnBool<T = any> extends SdTableColumnBase<T> {
96
113
  displayOnFalse?: string;
97
114
  };
98
115
  }
99
- interface SdTableColumnDate<T = any> extends SdTableColumnBase<T> {
116
+ interface SdTableColumnDate<T = unknown> extends SdTableColumnBase<T> {
100
117
  field: NestedKeyOf<T>;
101
118
  type: 'date' | 'datetime' | 'time';
102
119
  useBadge?: UseBadgeFunc<T>;
@@ -104,7 +121,7 @@ interface SdTableColumnDate<T = any> extends SdTableColumnBase<T> {
104
121
  type?: 'daterange' | 'date' | 'split-date';
105
122
  };
106
123
  }
107
- interface SdTableColumnValues<T = any, K = Record<string, any>> extends SdTableColumnBase<T> {
124
+ interface SdTableColumnValues<T = unknown, K = Record<string, any>> extends SdTableColumnBase<T> {
108
125
  field: NestedKeyOf<T>;
109
126
  type: 'values';
110
127
  useBadge?: UseBadgeValuesFunc<T, K>;
@@ -115,7 +132,7 @@ interface SdTableColumnValues<T = any, K = Record<string, any>> extends SdTableC
115
132
  selection?: 'MULTIPLE';
116
133
  };
117
134
  }
118
- interface SdTableColumnLazyValues<T = any, K = Record<string, any>> extends SdTableColumnBase<T> {
135
+ interface SdTableColumnLazyValues<T = unknown, K = Record<string, any>> extends SdTableColumnBase<T> {
119
136
  field: NestedKeyOf<T>;
120
137
  type: 'lazy-values';
121
138
  useBadge?: UseBadgeFunc<T>;
@@ -127,8 +144,8 @@ interface SdTableColumnLazyValues<T = any, K = Record<string, any>> extends SdTa
127
144
  selection?: 'MULTIPLE';
128
145
  };
129
146
  }
130
- type SdTableColumnNormal<T = any> = Exclude<SdTableColumn<T>, SdTableColumnChildren<T>>;
131
- interface SdTableColumnChildren<T = any> extends SdTableColumnBase<T> {
147
+ type SdTableColumnNormal<T = unknown> = Exclude<SdTableColumn<T>, SdTableColumnChildren<T>>;
148
+ interface SdTableColumnChildren<T = unknown> extends SdTableColumnBase<T> {
132
149
  field: string;
133
150
  type: 'children';
134
151
  children: SdTableColumnNormal<T>[];
@@ -147,6 +164,71 @@ declare class SdTableCellDefDirective<T = any> {
147
164
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableCellDefDirective<any>, "[sdTableCellDef]", never, { "sdTableCellDef": { "alias": "sdTableCellDef"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
148
165
  }
149
166
 
167
+ /**
168
+ * Nội dung cho ô HEADER của cột command.
169
+ *
170
+ * Ô đó vốn để trống — chỉ giữ chỗ cho các nút thao tác bên dưới — nên đây là chỗ tự nhiên để đặt
171
+ * một hành động cấp bảng (thường là "thêm dòng") mà không tốn thêm một dải riêng dưới bảng.
172
+ *
173
+ * Không có input: cột command chỉ có một, khác `sdTableCellDef` / `sdTableTitleDef` vốn phải chỉ
174
+ * đích danh field.
175
+ *
176
+ * ```html
177
+ * <sd-table [option]="option">
178
+ * <ng-template sdTableCommandHeaderDef>
179
+ * <sd-button prefixIcon="add" type="text" (click)="addRow()"></sd-button>
180
+ * </ng-template>
181
+ * </sd-table>
182
+ * ```
183
+ */
184
+ declare class SdTableCommandHeaderDefDirective {
185
+ templateRef: TemplateRef<unknown>;
186
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTableCommandHeaderDefDirective, never>;
187
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableCommandHeaderDefDirective, "[sdTableCommandHeaderDef]", never, {}, {}, never, never, true, never>;
188
+ }
189
+
190
+ interface SdTableGroupDefContext<T = any> {
191
+ /** Children items thuộc group hiện tại (kèm wrapper SdTableItem). */
192
+ items: SdTableItem<T>[];
193
+ /** Children raw data (đã unwrap khỏi SdTableItem) — tiện dùng trong template. */
194
+ data: T[];
195
+ /** Hash key của group (Utilities.hash(values)). */
196
+ key: string;
197
+ /** Resolved giá trị các field group — vd `{ customerId: 1, customerName: 'A' }`. */
198
+ values: Record<string, any>;
199
+ /** true nếu group đang expand, false nếu collapse (chỉ ý nghĩa khi option.group.collapsible). */
200
+ isExpanded: boolean;
201
+ /** true nếu mọi children selectable đều selected. */
202
+ isSelected: boolean;
203
+ /** true nếu một phần children selected (partial). */
204
+ indeterminate: boolean;
205
+ /** Toggle expand/collapse (chỉ chạy nếu collapsible). */
206
+ toggleExpand: () => void;
207
+ /** Toggle select-all cho cả group (chỉ chạy nếu selector visible). */
208
+ toggleSelect: () => void;
209
+ }
210
+ /**
211
+ * Directive cung cấp custom template render group header row trong sd-table.
212
+ * Thay thế cho htmlTemplate callback cũ — cho phép Angular template binding,
213
+ * pipes, components con (sd-badge, sd-button, …) bên trong.
214
+ *
215
+ * Ví dụ:
216
+ * ```html
217
+ * <sd-table [option]="opt">
218
+ * <ng-template sdTableGroupDef let-values="values" let-items="items" let-indeterminate="indeterminate">
219
+ * <b>Khách hàng: {{ values.customerName }}</b>
220
+ * <span>{{ items.length }} đơn hàng</span>
221
+ * </ng-template>
222
+ * </sd-table>
223
+ * ```
224
+ */
225
+ declare class SdTableGroupDefDirective<T = any> {
226
+ static ngTemplateContextGuard<T>(_dir: SdTableGroupDefDirective<T>, _ctx: unknown): _ctx is SdTableGroupDefContext<T>;
227
+ templateRef: TemplateRef<SdTableGroupDefContext<T>>;
228
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTableGroupDefDirective<any>, never>;
229
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableGroupDefDirective<any>, "[sdTableGroupDef]", never, {}, {}, never, never, true, never>;
230
+ }
231
+
150
232
  interface SdTableMetaSelector {
151
233
  selectable?: boolean;
152
234
  isSelected?: boolean;
@@ -188,6 +270,12 @@ interface SdTableDisplay {
188
270
  interface SdTableMetaGroup<T = any> {
189
271
  /** Children items thuộc group này (chỉ set trên group header row). */
190
272
  items?: SdTableItem<T>[];
273
+ /**
274
+ * Raw data của children (`items.map(i => i.data)`).
275
+ * why: precompute 1 lần lúc SdGroupPipe dựng header — trước đây `groupContext()`
276
+ * map lại mảng này ở MỖI change-detection pass cho MỖI group row.
277
+ */
278
+ data?: T[];
191
279
  /** true = row này là synthetic group header (sinh bởi SdGroupPipe). */
192
280
  isGroupHeader?: boolean;
193
281
  /** Hash key của group (= Utilities.hash(values)). */
@@ -196,6 +284,20 @@ interface SdTableMetaGroup<T = any> {
196
284
  values?: Record<string, any>;
197
285
  /** Trạng thái expand. Chỉ ý nghĩa khi `option.group.collapsible = true`. */
198
286
  isExpanded?: boolean;
287
+ /**
288
+ * true nếu MỌI selectable child trong group đã được chọn.
289
+ * why: cache thay cho `isGroupAllSelected(item)` gọi trong template — hàm đó duyệt
290
+ * toàn bộ children mỗi CD pass. Cập nhật ở selection sync path (`#updateSelectedItems`).
291
+ */
292
+ isSelected?: boolean;
293
+ /** true nếu chỉ MỘT PHẦN children được chọn (partial). Cache — xem `isSelected`. */
294
+ indeterminate?: boolean;
295
+ /**
296
+ * Context ổn định truyền cho template `sdTableGroupDef`.
297
+ * why: giữ NGUYÊN reference qua các CD pass để `ngTemplateOutlet` không phải
298
+ * dựng lại embedded view; giá trị bên trong được mutate tại chỗ khi selection đổi.
299
+ */
300
+ context?: SdTableGroupDefContext<T>;
199
301
  }
200
302
  interface SdTableMeta<T> {
201
303
  id: string;
@@ -204,6 +306,12 @@ interface SdTableMeta<T> {
204
306
  expand?: SdTableMetaExpand;
205
307
  group?: SdTableMetaGroup<T>;
206
308
  tree?: SdTableMetaTree<T>;
309
+ /**
310
+ * Style inline của cả row, resolve từ `option.style.rowCss` MỘT LẦN mỗi lần render.
311
+ * why: template bind `[ngStyle]` trực tiếp vào đây; gọi `rowCss(...)` trong binding
312
+ * trả object MỚI mỗi CD pass → KeyValueDiffer phải diff lại toàn bộ row mỗi pass.
313
+ */
314
+ rowStyle?: Record<string, string> | null;
207
315
  }
208
316
  interface SdTableItem<T = any> {
209
317
  meta: SdTableMeta<T>;
@@ -244,48 +352,6 @@ declare class SdMaterialFooterDefDirective<T = any> {
244
352
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdMaterialFooterDefDirective<any>, "[sdTableFooterDef]", never, { "sdTableFooterDef": { "alias": "sdTableFooterDef"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
245
353
  }
246
354
 
247
- interface SdTableGroupDefContext<T = any> {
248
- /** Children items thuộc group hiện tại (kèm wrapper SdTableItem). */
249
- items: SdTableItem<T>[];
250
- /** Children raw data (đã unwrap khỏi SdTableItem) — tiện dùng trong template. */
251
- data: T[];
252
- /** Hash key của group (Utilities.hash(values)). */
253
- key: string;
254
- /** Resolved giá trị các field group — vd `{ customerId: 1, customerName: 'A' }`. */
255
- values: Record<string, any>;
256
- /** true nếu group đang expand, false nếu collapse (chỉ ý nghĩa khi option.group.collapsible). */
257
- isExpanded: boolean;
258
- /** true nếu mọi children selectable đều selected. */
259
- isSelected: boolean;
260
- /** true nếu một phần children selected (partial). */
261
- indeterminate: boolean;
262
- /** Toggle expand/collapse (chỉ chạy nếu collapsible). */
263
- toggleExpand: () => void;
264
- /** Toggle select-all cho cả group (chỉ chạy nếu selector visible). */
265
- toggleSelect: () => void;
266
- }
267
- /**
268
- * Directive cung cấp custom template render group header row trong sd-table.
269
- * Thay thế cho htmlTemplate callback cũ — cho phép Angular template binding,
270
- * pipes, components con (sd-badge, sd-button, …) bên trong.
271
- *
272
- * Ví dụ:
273
- * ```html
274
- * <sd-table [option]="opt">
275
- * <ng-template sdTableGroupDef let-values="values" let-items="items" let-indeterminate="indeterminate">
276
- * <b>Khách hàng: {{ values.customerName }}</b>
277
- * <span>{{ items.length }} đơn hàng</span>
278
- * </ng-template>
279
- * </sd-table>
280
- * ```
281
- */
282
- declare class SdTableGroupDefDirective<T = any> {
283
- static ngTemplateContextGuard<T>(_dir: SdTableGroupDefDirective<T>, _ctx: unknown): _ctx is SdTableGroupDefContext<T>;
284
- templateRef: TemplateRef<SdTableGroupDefContext<T>>;
285
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTableGroupDefDirective<any>, never>;
286
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableGroupDefDirective<any>, "[sdTableGroupDef]", never, {}, {}, never, never, true, never>;
287
- }
288
-
289
355
  interface Context<T = any> {
290
356
  column: SdTableColumn<T>;
291
357
  }
@@ -297,6 +363,30 @@ declare class SdTableTitleDefDirective<T = any> {
297
363
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableTitleDefDirective<any>, "[sdTableTitleDef]", never, { "sdTableTitleDef": { "alias": "sdTableTitleDef"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
298
364
  }
299
365
 
366
+ interface SdTableCommandOption<T = any> {
367
+ align?: 'left' | 'right';
368
+ commands?: SdTableCommand<T>[];
369
+ }
370
+ type SdTableCommand<T = any> = SdTableCommandNormal<T> | SdTableCommandChildren<T>;
371
+ interface SdTableCommandNormal<T = any> {
372
+ color?: Color;
373
+ icon?: string | ((rowData: T) => string);
374
+ fontSet?: SdIconSet;
375
+ title?: string | ((rowData: T) => string);
376
+ disabled?: boolean | ((rowData: T) => boolean);
377
+ hidden?: boolean | ((rowData: T) => boolean | Promise<boolean>);
378
+ click: (rowData: T) => void;
379
+ htmlTemplate?: (rowData: T) => string;
380
+ }
381
+ interface SdTableCommandChildren<T = any> {
382
+ icon?: string | ((rowData: T) => string);
383
+ fontSet?: SdIconSet;
384
+ title?: string | ((rowData: T) => string);
385
+ disabled?: boolean | ((rowData: T) => boolean);
386
+ hidden?: boolean | ((rowData: T) => boolean | Promise<boolean>);
387
+ children: SdTableCommandNormal<T>[];
388
+ }
389
+
300
390
  interface SdTableQuickFilter {
301
391
  code: string;
302
392
  columnFilter: Record<string, any>;
@@ -312,7 +402,7 @@ interface TableFilterValue {
312
402
  notReload?: boolean;
313
403
  filtered?: boolean;
314
404
  }
315
- interface SdTableFilterRequest<T = any> {
405
+ interface SdTableFilterRequest<T = unknown> {
316
406
  columnOperator: Record<NestedKeyOf<T>, Operator>;
317
407
  rawColumnFilter: Record<NestedKeyOf<T>, any>;
318
408
  rawExternalFilter: Record<string, any>;
@@ -323,7 +413,7 @@ interface SdTableFilterRequest<T = any> {
323
413
  isExported?: boolean;
324
414
  visibledColumns?: SdTableColumn[];
325
415
  }
326
- interface SdTableOptionFilter<T = any> {
416
+ interface SdTableOptionFilter<T = unknown> {
327
417
  /** Key định danh nếu muốn lưu cache */
328
418
  key?: string;
329
419
  /** Có bật cache giá trị filter hay không */
@@ -348,13 +438,13 @@ interface SdTableOptionFilter<T = any> {
348
438
  onClearFilter?: () => void;
349
439
  }
350
440
  declare const SdConvertToPagingReq: (filterRequest: SdTableFilterRequest, args: {
351
- columns?: SdTableColumn[];
441
+ columns?: SdTableColumnAnyRow[];
352
442
  externalFilters?: SdTableExternalFilter[];
353
443
  fieldMapping?: Record<string, string>;
354
444
  orders?: Order[];
355
445
  }) => PagingReq;
356
- declare type SdTableExternalFilter<TData = any> = TextFilter<TData> | DateFilter<TData> | DateTimeFilter<TData> | DateRangeFilter<TData> | NumberFilter<TData> | ValuesFilter<TData> | LazyValuesFilter<TData> | BooleanFilter<TData> | CustomFilter<TData>;
357
- interface BaseFilter<TData = any> {
446
+ declare type SdTableExternalFilter<TData = unknown> = TextFilter<TData> | DateFilter<TData> | DateTimeFilter<TData> | DateRangeFilter<TData> | NumberFilter<TData> | ValuesFilter<TData> | LazyValuesFilter<TData> | BooleanFilter<TData> | CustomFilter<TData>;
447
+ interface BaseFilter<TData = unknown> {
358
448
  field: string;
359
449
  title: string;
360
450
  defaultShowing?: boolean;
@@ -364,23 +454,23 @@ interface BaseFilter<TData = any> {
364
454
  data?: TData;
365
455
  onChange?: (value: any) => void;
366
456
  }
367
- interface TextFilter<TData = any> extends BaseFilter<TData> {
457
+ interface TextFilter<TData = unknown> extends BaseFilter<TData> {
368
458
  type: 'string';
369
459
  default?: string;
370
460
  }
371
- interface DateFilter<TData = any> extends BaseFilter<TData> {
461
+ interface DateFilter<TData = unknown> extends BaseFilter<TData> {
372
462
  type: 'date';
373
463
  default?: Date | string;
374
464
  minDate?: string | number | Date;
375
465
  maxDate?: string | number | Date;
376
466
  }
377
- interface DateTimeFilter<TData = any> extends BaseFilter<TData> {
467
+ interface DateTimeFilter<TData = unknown> extends BaseFilter<TData> {
378
468
  type: 'datetime';
379
469
  default?: Date | string;
380
470
  minDate?: string | number | Date;
381
471
  maxDate?: string | number | Date;
382
472
  }
383
- interface DateRangeFilter<TData = any> extends BaseFilter<TData> {
473
+ interface DateRangeFilter<TData = unknown> extends BaseFilter<TData> {
384
474
  type: 'daterange';
385
475
  enableTime?: boolean;
386
476
  minDate?: string | number | Date;
@@ -390,11 +480,11 @@ interface DateRangeFilter<TData = any> extends BaseFilter<TData> {
390
480
  to?: Date | string;
391
481
  };
392
482
  }
393
- interface NumberFilter<TData = any> extends BaseFilter<TData> {
483
+ interface NumberFilter<TData = unknown> extends BaseFilter<TData> {
394
484
  type: 'number';
395
485
  default?: number;
396
486
  }
397
- interface ValuesFilter<TData = any> extends BaseFilter<TData> {
487
+ interface ValuesFilter<TData = unknown> extends BaseFilter<TData> {
398
488
  type: 'values';
399
489
  option: {
400
490
  valueField: string;
@@ -404,7 +494,7 @@ interface ValuesFilter<TData = any> extends BaseFilter<TData> {
404
494
  };
405
495
  default?: string | string[];
406
496
  }
407
- interface LazyValuesFilter<TData = any> extends BaseFilter<TData> {
497
+ interface LazyValuesFilter<TData = unknown> extends BaseFilter<TData> {
408
498
  type: 'lazy-values';
409
499
  option: {
410
500
  valueField: string;
@@ -414,7 +504,7 @@ interface LazyValuesFilter<TData = any> extends BaseFilter<TData> {
414
504
  };
415
505
  default?: string | string[];
416
506
  }
417
- interface BooleanFilter<TData = any> extends BaseFilter<TData> {
507
+ interface BooleanFilter<TData = unknown> extends BaseFilter<TData> {
418
508
  type: 'boolean';
419
509
  option?: {
420
510
  displayOnTrue?: string;
@@ -422,7 +512,7 @@ interface BooleanFilter<TData = any> extends BaseFilter<TData> {
422
512
  };
423
513
  default?: boolean;
424
514
  }
425
- interface CustomFilter<TData = any> extends BaseFilter<TData> {
515
+ interface CustomFilter<TData = unknown> extends BaseFilter<TData> {
426
516
  type: 'custom';
427
517
  filterDef?: TemplateRef<any>;
428
518
  default?: any;
@@ -442,30 +532,6 @@ interface TableFilterRegister {
442
532
  };
443
533
  }
444
534
 
445
- interface SdTableCommandOption<T = any> {
446
- align?: 'left' | 'right';
447
- commands?: SdTableCommand<T>[];
448
- }
449
- type SdTableCommand<T = any> = SdTableCommandNormal<T> | SdTableCommandChildren<T>;
450
- interface SdTableCommandNormal<T = any> {
451
- color?: Color;
452
- icon?: string | ((rowData: T) => string);
453
- fontSet?: SdIconSet;
454
- title?: string | ((rowData: T) => string);
455
- disabled?: boolean | ((rowData: T) => boolean);
456
- hidden?: boolean | ((rowData: T) => boolean | Promise<boolean>);
457
- click: (rowData: T) => void;
458
- htmlTemplate?: (rowData: T) => string;
459
- }
460
- interface SdTableCommandChildren<T = any> {
461
- icon?: string | ((rowData: T) => string);
462
- fontSet?: SdIconSet;
463
- title?: string | ((rowData: T) => string);
464
- disabled?: boolean | ((rowData: T) => boolean);
465
- hidden?: boolean | ((rowData: T) => boolean | Promise<boolean>);
466
- children: SdTableCommandNormal<T>[];
467
- }
468
-
469
535
  interface TableOptionConfig {
470
536
  visible?: boolean;
471
537
  resizable?: boolean;
@@ -619,14 +685,15 @@ interface SdTableOptionSelector<T = any> {
619
685
  *
620
686
  * - Default (false): selection bị mất khi data items được re-fetch (server-side) hoặc
621
687
  * item references thay đổi. Action bar chỉ hiển thị số item selected ở page hiện tại.
622
- * - Enabled (true): table giữ map nội bộ selectedItems theo `meta.id` (hash của data).
688
+ * - Enabled (true): table giữ map nội bộ selectedItems theo `meta.id`.
623
689
  * Sau mỗi #render, restore `isSelected` cho item nào id đã có trong map.
624
690
  * `selectedTableItems()` trả về TOÀN BỘ item đã chọn xuyên trang (kể cả off-page),
625
691
  * nên action bar + callback `click(items)` nhận đầy đủ data đang được chọn.
626
692
  *
627
- * Lưu ý: matching dựa trên `Utilities.hash(data)` hai item cùng data shape sẽ
628
- * trùng id (mong muốn). Nếu data timestamp/random field thay đổi giữa các lần fetch,
629
- * id sẽ khác selection không restore được.
693
+ * ⚠️ Matching dựa trên `meta.id`. Không khai báo `option.rowKey` thì id được sinh theo
694
+ * IDENTITY của object data sống qua filter/sort/paging phía client, nhưng KHÔNG sống
695
+ * qua một lần fetch mới của server (object mới → id mới). Với `type: 'server'`, HÃY
696
+ * khai báo `option.rowKey` trỏ vào field định danh của dòng.
630
697
  */
631
698
  preserveSelection?: boolean;
632
699
  }
@@ -819,6 +886,18 @@ interface SdTableBaseOption<T = any> {
819
886
  * ví dụ các option có hỗ trợ cache/config theo key.
820
887
  */
821
888
  key?: string;
889
+ /**
890
+ * Field định danh của MỘT DÒNG (hỗ trợ dot-notation, vd `'id'` hoặc `'user.id'`).
891
+ *
892
+ * Table dùng giá trị này làm `SdTableItem.meta.id` — khoá cho `trackBy` của mat-table,
893
+ * cho `preserveSelection`, cho trạng thái bung của tree và cho các `data-autoid` theo dòng.
894
+ *
895
+ * Không truyền thì table tự sinh id theo IDENTITY của object data (ổn định trong suốt
896
+ * vòng đời object, nhưng KHÔNG sống sót qua một lần fetch mới của server). Vì vậy hãy
897
+ * khai báo `rowKey` khi dùng `preserveSelection`, `tree` với `type: 'server'`, hoặc khi
898
+ * cần autoId theo dòng ổn định cho E2E.
899
+ */
900
+ rowKey?: string;
822
901
  /**
823
902
  * Cấu hình hiển thị/phục hồi config của table.
824
903
  * Xem thêm kiểu chi tiết tại `TableOptionConfig`.
@@ -981,7 +1060,7 @@ interface SdTableServerOption<T = any> extends SdTableBaseOption<T> {
981
1060
  declare class ExternalFilterComponent {
982
1061
  #private;
983
1062
  autoIdInput: _angular_core.InputSignal<string | null | undefined>;
984
- filter: _angular_core.InputSignal<SdTableOptionFilter<any> | undefined>;
1063
+ filter: _angular_core.InputSignal<SdTableOptionFilter<unknown> | undefined>;
985
1064
  externalFilters: _angular_core.InputSignal<SdTableExternalFilter[] | null | undefined>;
986
1065
  filterRegister: _angular_core.InputSignal<TableFilterRegister | undefined>;
987
1066
  externalFilter: _angular_core.WritableSignal<Record<string, any>>;
@@ -1018,7 +1097,7 @@ declare class ExternalFilterComponent {
1018
1097
  */
1019
1098
  declare class MobileFilterComponent {
1020
1099
  autoIdInput: _angular_core.InputSignal<string | null | undefined>;
1021
- filter: _angular_core.InputSignal<SdTableOptionFilter<any> | undefined>;
1100
+ filter: _angular_core.InputSignal<SdTableOptionFilter<unknown> | undefined>;
1022
1101
  externalFilters: _angular_core.InputSignal<SdTableExternalFilter[] | null | undefined>;
1023
1102
  columns: _angular_core.InputSignal<SdTableColumn[] | null | undefined>;
1024
1103
  filterDefs: _angular_core.InputSignal<readonly SdTableFilterDefDirective[] | null | undefined>;
@@ -1055,6 +1134,11 @@ declare class ConfigComponent {
1055
1134
  close: () => void;
1056
1135
  onSave: () => void;
1057
1136
  onReset: () => Promise<void>;
1137
+ /**
1138
+ * Cột đang tắt hiển thị thì tiêu đề / độ rộng / cố định / giới hạn ký tự đều vô nghĩa —
1139
+ * khoá chúng lại để row nói rõ trạng thái, chỉ chừa ô "Hiển thị" để bật lại.
1140
+ */
1141
+ isRowDisabled: (item: ConfiguredColumn) => boolean;
1058
1142
  dropTable(event: any): void;
1059
1143
  handleMouseDown(): void;
1060
1144
  handleMouseUp(): void;
@@ -1136,7 +1220,22 @@ interface ISdTableConfiguration {
1136
1220
  }
1137
1221
  declare const SD_TABLE_CONFIGURATION: InjectionToken<ISdTableConfiguration>;
1138
1222
 
1139
- declare class MatPaginatorIntlCro extends MatPaginatorIntl {
1223
+ /**
1224
+ * Cầu nối giữa `SdGroupPipe` (nơi group header được sinh ra) và `SdTable`.
1225
+ *
1226
+ * why: pipe dựng header nhưng KHÔNG biết method của component, còn component thì không
1227
+ * giữ mảng output của pipe. Host là một object DUY NHẤT, ổn định do component sở hữu:
1228
+ * pipe đổ header vào `headers` để component sync lại selection state sau này, và mượn
1229
+ * `toggleExpand`/`toggleSelect` để gắn vào template context.
1230
+ */
1231
+ interface SdGroupHeaderHost<T = any> {
1232
+ /** Sink các group header của lần transform gần nhất. Pipe clear + fill lại mỗi lần. */
1233
+ headers: SdTableItem<T>[];
1234
+ toggleExpand: (header: SdTableItem<T>) => void;
1235
+ toggleSelect: (header: SdTableItem<T>) => void;
1236
+ }
1237
+
1238
+ declare class SdTablePaginatorIntl extends MatPaginatorIntl {
1140
1239
  #private;
1141
1240
  firstPageLabel: string;
1142
1241
  lastPageLabel: string;
@@ -1144,8 +1243,8 @@ declare class MatPaginatorIntlCro extends MatPaginatorIntl {
1144
1243
  nextPageLabel: string;
1145
1244
  previousPageLabel: string;
1146
1245
  getRangeLabel: (page: number, pageSize: number, length: number) => string;
1147
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatPaginatorIntlCro, never>;
1148
- static ɵprov: _angular_core.ɵɵInjectableDeclaration<MatPaginatorIntlCro>;
1246
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTablePaginatorIntl, never>;
1247
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<SdTablePaginatorIntl>;
1149
1248
  }
1150
1249
  declare class SdTable<T = unknown> implements AfterViewInit, OnDestroy {
1151
1250
  #private;
@@ -1164,6 +1263,8 @@ declare class SdTable<T = unknown> implements AfterViewInit, OnDestroy {
1164
1263
  sdSubInformation: _angular_core.Signal<SdTableExpandDefDirective<any> | undefined>;
1165
1264
  sdGroupDef: _angular_core.Signal<SdTableGroupDefDirective<any> | undefined>;
1166
1265
  sdCellDefs: _angular_core.Signal<readonly SdTableCellDefDirective<any>[]>;
1266
+ /** Nội dung tuỳ chọn cho ô header của cột command (mặc định ô này để trống). */
1267
+ sdCommandHeaderDef: _angular_core.Signal<SdTableCommandHeaderDefDirective | undefined>;
1167
1268
  sdFooterDefs: _angular_core.Signal<readonly SdMaterialFooterDefDirective<any>[]>;
1168
1269
  sdFilterDefs: _angular_core.Signal<readonly SdTableFilterDefDirective[]>;
1169
1270
  sdTitleDefs: _angular_core.Signal<readonly SdTableTitleDefDirective<any>[]>;
@@ -1178,6 +1279,25 @@ declare class SdTable<T = unknown> implements AfterViewInit, OnDestroy {
1178
1279
  total: _angular_core.WritableSignal<number | undefined>;
1179
1280
  loading: _angular_core.WritableSignal<boolean>;
1180
1281
  isSelectAll: _angular_core.WritableSignal<boolean>;
1282
+ /**
1283
+ * Checkbox "chọn tất cả" ở header có hiển thị không.
1284
+ *
1285
+ * why: trước đây là `_items | selectionVisibleSelectAll: … | async` — pipe `async`
1286
+ * với `await setTimeout(500)` bên trong. Sleep đó CHE một vấn đề thứ tự
1287
+ * change-detection: pipe đọc `meta.selector.actions`, mảng chỉ được `SdSelectionVisiblePipe`
1288
+ * ghi khi cell BODY render, mà CDK dựng header TRƯỚC body → pass đầu luôn đọc ra rỗng.
1289
+ * Hệ quả: checkbox hiện trễ 500ms, và vì `transform` là `async` nên MỖI lần re-eval lại
1290
+ * trả một Promise mới + đặt thêm một timer không ai dọn. Computed tự tính từ
1291
+ * `items()` + `selector` nên không phụ thuộc pipe nào chạy trước → bỏ hẳn timer.
1292
+ */
1293
+ visibleSelectAll: _angular_core.Signal<boolean>;
1294
+ /**
1295
+ * Danh sách command của row, memoize theo option.
1296
+ * why: template cũ bind `_tableOption.command?.commands || _tableOption.commands || []`
1297
+ * — nhánh `[]` cấp phát mảng MỚI mỗi CD pass và đẩy vào `input()` của `desktop-command`,
1298
+ * làm child OnPush bị đánh dấu dirty mỗi pass cho từng dòng.
1299
+ */
1300
+ rowCommands: _angular_core.Signal<SdTableCommand<T>[]>;
1181
1301
  isFiltered: _angular_core.WritableSignal<boolean>;
1182
1302
  requireFiltered: _angular_core.WritableSignal<boolean>;
1183
1303
  filterRegister: TableFilterRegister;
@@ -1187,7 +1307,7 @@ declare class SdTable<T = unknown> implements AfterViewInit, OnDestroy {
1187
1307
  cacheValues: Record<string, unknown[]>;
1188
1308
  treeRevision: _angular_core.WritableSignal<number>;
1189
1309
  exporting: _angular_core.WritableSignal<boolean>;
1190
- exportTitle: _angular_core.WritableSignal<string>;
1310
+ exportTitle: _angular_core.Signal<string>;
1191
1311
  tableConfiguration: ISdTableConfiguration | null;
1192
1312
  constructor();
1193
1313
  ngAfterViewInit(): void;
@@ -1211,6 +1331,14 @@ declare class SdTable<T = unknown> implements AfterViewInit, OnDestroy {
1211
1331
  /** Toggle select-all cho 1 group: set isSelected cho mọi selectable child, sync state. */
1212
1332
  onSelectGroup: (header: SdTableItem<T>, checked: boolean) => void;
1213
1333
  groupExpandState: Map<string, boolean>;
1334
+ /**
1335
+ * Cầu nối tới SdGroupPipe (arg 4) — object DUY NHẤT, tạo một lần.
1336
+ * why: pipe sinh group header nhưng component mới là nơi biết selection đổi. Pipe đổ
1337
+ * header vào `headers` để `#syncGroupSelectionState` cập nhật `meta.group.isSelected` /
1338
+ * `indeterminate`, thay cho việc template gọi `isGroupAllSelected()`/`isGroupIndeterminate()`
1339
+ * (duyệt toàn bộ children) ở MỖI CD pass.
1340
+ */
1341
+ readonly groupHost: SdGroupHeaderHost<T>;
1214
1342
  /** Toggle expand/collapse cho 1 group (chỉ ý nghĩa khi option.group.collapsible). */
1215
1343
  toggleGroupExpand: (header: SdTableItem<T>) => void;
1216
1344
  /**
@@ -1225,7 +1353,21 @@ declare class SdTable<T = unknown> implements AfterViewInit, OnDestroy {
1225
1353
  * Span TOÀN BỘ width data row vì group row chỉ có 1 cell.
1226
1354
  */
1227
1355
  sdGroupColspan: _angular_core.Signal<number>;
1228
- /** Build context object truyền vào SdTableGroupDefDirective template. */
1356
+ /**
1357
+ * Context truyền vào template `sdTableGroupDef`.
1358
+ *
1359
+ * why: bản cũ dựng object MỚI (kèm `items.map(i => i.data)` mới và 2 lần duyệt children
1360
+ * qua `isGroupAllSelected`/`isGroupIndeterminate`) ở MỖI CD pass, cho MỖI group row —
1361
+ * `ngTemplateOutlet` thấy context đổi reference nên phải dựng lại embedded view. Giờ
1362
+ * context được `SdGroupPipe` precompute và cache trên `meta.group`; ở đây chỉ đọc ra
1363
+ * (fallback `??=` cho header không do pipe sinh) nên reference ổn định qua các pass.
1364
+ *
1365
+ * why: 3 field selection/expand thì phải làm TƯƠI mỗi lần đọc — `SdGroupPipe` dựng context
1366
+ * lúc header được sinh ra, thời điểm đó `selector.selectable` của children vẫn còn là mặc
1367
+ * định `false` (chỉ `SdSelectionVisiblePipe` ở cell BODY mới đặt đúng, mà CDK dựng header
1368
+ * trước body). Cache lại giá trị tính ở thời điểm đó là khoá cứng `isSelected = false`.
1369
+ * Mutate TẠI CHỖ để `ngTemplateOutlet` vẫn thấy cùng một reference và không dựng lại view.
1370
+ */
1229
1371
  groupContext: (header: SdTableItem<T>) => SdTableGroupDefContext<T>;
1230
1372
  rowStyle: (row: SdTableItem<T>, index?: number) => Record<string, string> | null;
1231
1373
  clearFilter: () => void;
@@ -1241,8 +1383,8 @@ declare class SdTable<T = unknown> implements AfterViewInit, OnDestroy {
1241
1383
  reorderSortPredicate: (index: number, drag: CdkDrag<SdTableItem<T>>, drop: CdkDropList<SdTableItem<T>[]>) => boolean;
1242
1384
  onReorderDrop(event: CdkDragDrop<SdTableItem<T>[]>): void;
1243
1385
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTable<any>, never>;
1244
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdTable<any>, "sd-table", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "option": { "alias": "option"; "required": true; "isSignal": true; }; }, {}, ["sdSubInformation", "sdGroupDef", "sdCellDefs", "sdFooterDefs", "sdFilterDefs", "sdTitleDefs"], ["[sdTableTop]"], true, never>;
1386
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdTable<any>, "sd-table", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "option": { "alias": "option"; "required": true; "isSignal": true; }; }, {}, ["sdSubInformation", "sdGroupDef", "sdCellDefs", "sdCommandHeaderDef", "sdFooterDefs", "sdFilterDefs", "sdTitleDefs"], ["[sdTableTop]"], true, never>;
1245
1387
  }
1246
1388
 
1247
- export { MatPaginatorIntlCro, SD_TABLE_CONFIGURATION, SdConvertToPagingReq, SdMaterialFooterDefDirective, SdTable, SdTableCellDefDirective, SdTableExpandDefDirective, SdTableFilterDefDirective, SdTableGroupDefDirective, SdTableTitleDefDirective };
1248
- export type { ISdTableConfiguration, SdTableColumn, SdTableColumnChildren, SdTableColumnLazyValues, SdTableColumnNormal, SdTableColumnTransformFunc, SdTableColumnValues, SdTableCommand, SdTableCommandChildren, SdTableCommandNormal, SdTableCommandOption, SdTableDisplay, SdTableExternalFilter, SdTableFilterRequest, SdTableGroupDefContext, SdTableItem, SdTableMeta, SdTableOption, SdTableOptionFilter, SdTableOptionTree, SdTableQuickFilter, TableFilterConfiguration, TableFilterRegister, TableFilterValue, TableOptionTreeLazy, TableOptionTreeStatic };
1389
+ export { SD_TABLE_CONFIGURATION, SdConvertToPagingReq, SdMaterialFooterDefDirective, SdTable, SdTableCellDefDirective, SdTableCommandHeaderDefDirective, SdTableExpandDefDirective, SdTableFilterDefDirective, SdTableGroupDefDirective, SdTablePaginatorIntl, SdTableTitleDefDirective };
1390
+ export type { ISdTableConfiguration, SdTableColumn, SdTableColumnAnyRow, SdTableColumnChildren, SdTableColumnLazyValues, SdTableColumnNormal, SdTableColumnTransformFunc, SdTableColumnValues, SdTableCommand, SdTableCommandChildren, SdTableCommandNormal, SdTableCommandOption, SdTableDisplay, SdTableExternalFilter, SdTableFilterRequest, SdTableGroupDefContext, SdTableItem, SdTableMeta, SdTableOption, SdTableOptionFilter, SdTableOptionTree, SdTableQuickFilter, TableFilterConfiguration, TableFilterRegister, TableFilterValue, TableOptionTreeLazy, TableOptionTreeStatic };