@sd-angular/core 19.0.0-beta.95 → 19.0.0-beta.97

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 (107) hide show
  1. package/README.md +8 -9
  2. package/components/badge/src/badge.component.d.ts +3 -4
  3. package/components/button/src/button.component.d.ts +2 -2
  4. package/components/document-builder/src/components/header-footer-builder/header-footer-builder.component.d.ts +2 -2
  5. package/components/document-builder/src/document-builder.model.d.ts +6 -2
  6. package/components/editor/src/editor.component.d.ts +8 -0
  7. package/components/editor/src/models/image-upload.plugin.model.d.ts +33 -0
  8. package/components/editor/src/plugins/image-upload/utils/style.utils.d.ts +1 -0
  9. package/components/index.d.ts +0 -2
  10. package/components/modal/src/modal.component.d.ts +1 -2
  11. package/components/section/src/section.component.d.ts +1 -2
  12. package/components/table/index.d.ts +1 -0
  13. package/components/table/src/components/column-filter/column-filter.component.d.ts +3 -3
  14. package/components/table/src/models/index.d.ts +1 -0
  15. package/components/table/src/models/table-item.model.d.ts +10 -0
  16. package/components/table/src/models/table-option-style.model.d.ts +6 -1
  17. package/components/table/src/models/table-option-tree.model.d.ts +12 -0
  18. package/components/table/src/models/table-option.model.d.ts +6 -0
  19. package/components/table/src/pipes/index.d.ts +1 -0
  20. package/components/table/src/pipes/sd-tree.pipe.d.ts +9 -0
  21. package/components/table/src/services/tree/tree.util.d.ts +14 -0
  22. package/components/table/src/table.component.d.ts +3 -0
  23. package/fesm2022/sd-angular-core-components-document-builder.mjs +9 -4
  24. package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
  25. package/fesm2022/sd-angular-core-components-editor.mjs +222 -97
  26. package/fesm2022/sd-angular-core-components-editor.mjs.map +1 -1
  27. package/fesm2022/sd-angular-core-components-form-generic.mjs +4 -4
  28. package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
  29. package/fesm2022/sd-angular-core-components-tab-router.mjs +80 -33
  30. package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
  31. package/fesm2022/sd-angular-core-components-table.mjs +325 -41
  32. package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
  33. package/fesm2022/sd-angular-core-components.mjs +0 -2
  34. package/fesm2022/sd-angular-core-components.mjs.map +1 -1
  35. package/fesm2022/sd-angular-core-forms-input.mjs +20 -5
  36. package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
  37. package/fesm2022/sd-angular-core-i18n.mjs +35 -0
  38. package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
  39. package/fesm2022/sd-angular-core-models.mjs +1 -4
  40. package/fesm2022/sd-angular-core-models.mjs.map +1 -1
  41. package/fesm2022/sd-angular-core-modules-layout.mjs +172 -37
  42. package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
  43. package/fesm2022/sd-angular-core-services-notify.mjs +21 -21
  44. package/fesm2022/sd-angular-core-services-notify.mjs.map +1 -1
  45. package/fesm2022/sd-angular-core-utilities-extensions.mjs +29 -819
  46. package/fesm2022/sd-angular-core-utilities-extensions.mjs.map +1 -1
  47. package/fesm2022/sd-angular-core-utilities-models.mjs +36 -136
  48. package/fesm2022/sd-angular-core-utilities-models.mjs.map +1 -1
  49. package/forms/autocomplete/src/autocomplete.component.d.ts +1 -2
  50. package/forms/chip/src/chip.component.d.ts +1 -2
  51. package/forms/chip-calendar/src/chip-calendar.component.d.ts +1 -2
  52. package/forms/date/src/date.component.d.ts +1 -2
  53. package/forms/date-range/src/date-range.component.d.ts +1 -2
  54. package/forms/datetime/src/datetime.component.d.ts +1 -2
  55. package/forms/input/src/input.component.d.ts +1 -2
  56. package/forms/input-number/src/input-number.component.d.ts +1 -2
  57. package/forms/select/src/select.component.d.ts +5 -5
  58. package/forms/textarea/src/textarea.component.d.ts +1 -2
  59. package/i18n/src/en.d.ts +6 -0
  60. package/models/src/language.model.d.ts +2 -4
  61. package/modules/layout/components/sidebar-v1/components/sidebar/sidebar.component.d.ts +8 -1
  62. package/modules/layout/configurations/layout.configuration.d.ts +8 -0
  63. package/modules/layout/services/storage/storage.service.d.ts +2 -0
  64. package/package.json +68 -79
  65. package/sd-angular-core-19.0.0-beta.97.tgz +0 -0
  66. package/services/notify/index.d.ts +1 -1
  67. package/services/notify/src/components/toast/toast.component.d.ts +3 -3
  68. package/services/notify/src/components/toast-container.component.d.ts +3 -4
  69. package/services/notify/src/notify.model.d.ts +1 -1
  70. package/services/notify/src/notify.service.d.ts +5 -5
  71. package/utilities/extensions/src/array.extension.d.ts +1 -7
  72. package/utilities/extensions/src/color.extension.d.ts +5 -20
  73. package/utilities/extensions/src/date.extension.d.ts +1 -18
  74. package/utilities/extensions/src/number.extension.d.ts +1 -10
  75. package/utilities/extensions/src/string.extension.d.ts +30 -4
  76. package/utilities/extensions/src/utility.extension.d.ts +6 -0
  77. package/utilities/models/src/color.model.d.ts +4 -1
  78. package/utilities/models/src/empty.model.d.ts +3 -0
  79. package/utilities/models/src/filter.model.d.ts +12 -24
  80. package/utilities/models/src/maybe-async.model.d.ts +10 -4
  81. package/utilities/models/src/nested-key-of.model.d.ts +4 -5
  82. package/utilities/models/src/operator.model.d.ts +9 -4
  83. package/utilities/models/src/order.model.d.ts +4 -5
  84. package/utilities/models/src/paging.model.d.ts +8 -16
  85. package/utilities/models/src/pattern.model.d.ts +13 -0
  86. package/utilities/models/src/size.model.d.ts +4 -1
  87. package/components/anchor-v2/index.d.ts +0 -1
  88. package/components/anchor-v2/src/components/anchor-item-v2/anchor-item-v2.component.d.ts +0 -12
  89. package/components/anchor-v2/src/components/anchor-v2/anchor-v2.component.d.ts +0 -19
  90. package/components/anchor-v2/src/components/anchor-vertical-v2/anchor-vertical-list-v2.component.d.ts +0 -16
  91. package/components/anchor-v2/src/components/index.d.ts +0 -2
  92. package/components/anchor-v2/src/index.d.ts +0 -2
  93. package/components/anchor-v2/src/models/index.d.ts +0 -1
  94. package/components/anchor-v2/src/models/sd-anchor-v2.model.d.ts +0 -7
  95. package/components/workflow/index.d.ts +0 -2
  96. package/components/workflow/src/configurations/index.d.ts +0 -1
  97. package/components/workflow/src/configurations/workflow.configuration.d.ts +0 -10
  98. package/fesm2022/sd-angular-core-components-anchor-v2.mjs +0 -151
  99. package/fesm2022/sd-angular-core-components-anchor-v2.mjs.map +0 -1
  100. package/fesm2022/sd-angular-core-components-workflow.mjs +0 -17
  101. package/fesm2022/sd-angular-core-components-workflow.mjs.map +0 -1
  102. package/fesm2022/sd-angular-core-services-firebase.mjs +0 -38
  103. package/fesm2022/sd-angular-core-services-firebase.mjs.map +0 -1
  104. package/sd-angular-core-19.0.0-beta.95.tgz +0 -0
  105. package/services/firebase/index.d.ts +0 -2
  106. package/services/firebase/src/firebase.model.d.ts +0 -8
  107. package/services/firebase/src/firebase.service.d.ts +0 -14
package/README.md CHANGED
@@ -189,7 +189,7 @@ import { SdButton } from '@sd-angular/core/components/button';
189
189
  | Input | Type | Default | Description |
190
190
  |---|---|---|---|
191
191
  | `type` | `'fill' \| 'light' \| 'outline' \| 'link'` | `'light'` | Kiểu nút |
192
- | `color` | `SdColor` | `'secondary'` | Màu sắc |
192
+ | `color` | `Color` | `'secondary'` | Màu sắc |
193
193
  | `size` | `'sm' \| 'md' \| 'lg'` | `'sm'` | Kích thước |
194
194
  | `title` | `string` | — | Nhãn nút |
195
195
  | `prefixIcon` | `string` | — | Icon Material trước text |
@@ -221,10 +221,10 @@ import { SdBadge } from '@sd-angular/core/components/badge';
221
221
  | Input | Type | Default | Description |
222
222
  |---|---|---|---|
223
223
  | `type` | `'tag' \| 'round' \| 'icon'` | `'icon'` | Kiểu badge |
224
- | `color` | `SdColor` | `'secondary'` | Màu sắc |
224
+ | `color` | `Color` | `'secondary'` | Màu sắc |
225
225
  | `title` | `string \| number` | — | Nội dung hiển thị |
226
226
  | `icon` | `string` | — | Icon Material |
227
- | `size` | `SdSize` | `'sm'` | Kích thước |
227
+ | `size` | `Size` | `'sm'` | Kích thước |
228
228
  | `tooltip` | `string` | — | Tooltip |
229
229
 
230
230
  Shorthand color inputs (boolean): `primary`, `secondary`, `success`, `info`, `warning`, `error`.
@@ -250,7 +250,7 @@ import { SdSection } from '@sd-angular/core/components/section';
250
250
  | `title` | `string` | *required* | Tiêu đề section |
251
251
  | `subTitle` | `string` | — | Tiêu đề phụ |
252
252
  | `icon` | `string` | — | Icon Material |
253
- | `iconColor` | `SdColor` | `'primary'` | Màu icon |
253
+ | `iconColor` | `Color` | `'primary'` | Màu icon |
254
254
  | `collapsable` | `boolean` | `false` | Cho phép thu gọn |
255
255
  | `collapsed` | `boolean` | `false` | Trạng thái ban đầu thu gọn |
256
256
  | `hideHeader` | `boolean` | `false` | Ẩn phần header |
@@ -278,7 +278,7 @@ import { SdModal } from '@sd-angular/core/components/modal';
278
278
  | Input | Type | Default | Description |
279
279
  |---|---|---|---|
280
280
  | `title` | `string` | — | Tiêu đề modal |
281
- | `color` | `SdColor` | `'primary'` | Màu header |
281
+ | `color` | `Color` | `'primary'` | Màu header |
282
282
  | `width` | `'sx' \| 'sm' \| 'md' \| 'lg' \| string` | `'md'` | Độ rộng (md = 60vw) |
283
283
  | `height` | `string` | `'auto'` | Chiều cao |
284
284
  | `view` | `'dialog' \| 'bottom-sheet'` | auto | Tự động bottom-sheet trên mobile |
@@ -406,7 +406,6 @@ import { SdAvatar } from '@sd-angular/core/components/avatar';
406
406
  | `SdHistory` | `@sd-angular/core/components/history` | Lịch sử thay đổi |
407
407
  | `SdImportExcel` | `@sd-angular/core/components/import-excel` | Wizard import Excel |
408
408
  | `SdQueryBuilder` | `@sd-angular/core/components/query-builder` | Visual query builder |
409
- | `SdWorkflow` | `@sd-angular/core/components/workflow` | Workflow builder |
410
409
  | `SdCodeEditor` | `@sd-angular/core/components/code-editor` | Code editor (PrismJS) |
411
410
  | `SdMiniEditor` | `@sd-angular/core/components/mini-editor` | Rich text editor nhỏ |
412
411
  | `SdDocumentBuilder` | `@sd-angular/core/components/document-builder` | Document builder |
@@ -654,7 +653,7 @@ export * from './src/my-component.component';
654
653
  // my-component.component.ts
655
654
  import { ChangeDetectionStrategy, Component, input } from '@angular/core';
656
655
  import { SdBaseSecureComponent } from '@sd-angular/core/components/base';
657
- import { SdColor } from '@sd-angular/core/utilities';
656
+ import { Color } from '@sd-angular/core/utilities';
658
657
 
659
658
  @Component({
660
659
  selector: 'sd-my-component',
@@ -665,7 +664,7 @@ import { SdColor } from '@sd-angular/core/utilities';
665
664
  imports: [],
666
665
  })
667
666
  export class SdMyComponent extends SdBaseSecureComponent {
668
- color = input<SdColor, SdColor | undefined | null>('primary', {
667
+ color = input<Color, Color | undefined | null>('primary', {
669
668
  transform: (value) => value || 'primary',
670
669
  });
671
670
 
@@ -691,7 +690,7 @@ export * from '@sd-angular/core/components/my-component';
691
690
  | Base class | Extend `SdBaseSecureComponent` cho component có permission |
692
691
  | Change detection | Luôn dùng `ChangeDetectionStrategy.OnPush` |
693
692
  | Standalone | Luôn `standalone: true` |
694
- | Colors | Dùng `SdColor` type, không hardcode màu |
693
+ | Colors | Dùng `Color` type, không hardcode màu |
695
694
 
696
695
  ### Build
697
696
 
@@ -1,12 +1,11 @@
1
1
  import { EventEmitter } from '@angular/core';
2
- import { SdColor, SdSize } from '@sd-angular/core/utilities/models';
3
2
  import { MaterialIconFontSet } from '@sd-angular/core/utilities/models';
4
3
  import * as i0 from "@angular/core";
5
4
  export type SdBadgeType = 'tag' | 'round' | 'icon';
6
5
  export declare class SdBadge {
7
6
  defaultIcon: string;
8
7
  type: import("@angular/core").InputSignalWithTransform<SdBadgeType, SdBadgeType | null | undefined>;
9
- color: import("@angular/core").InputSignalWithTransform<SdColor, SdColor | null | undefined>;
8
+ color: import("@angular/core").InputSignalWithTransform<import("@sdcorejs/utils/models").Color, import("@sdcorejs/utils/models").Color | null | undefined>;
10
9
  primary: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
11
10
  secondary: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
12
11
  success: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
@@ -18,10 +17,10 @@ export declare class SdBadge {
18
17
  description: import("@angular/core").InputSignal<string | null | undefined>;
19
18
  tooltip: import("@angular/core").InputSignal<string | null | undefined>;
20
19
  icon: import("@angular/core").InputSignal<string | null | undefined>;
21
- size: import("@angular/core").InputSignalWithTransform<SdSize, SdSize | null | undefined>;
20
+ size: import("@angular/core").InputSignalWithTransform<import("@sdcorejs/utils/models").Size, import("@sdcorejs/utils/models").Size | null | undefined>;
22
21
  click: EventEmitter<Event>;
23
22
  onClick: (event: Event) => void;
24
- effectiveColor: import("@angular/core").Signal<SdColor>;
23
+ effectiveColor: import("@angular/core").Signal<import("@sdcorejs/utils/models").Color>;
25
24
  baseColorClasses: import("@angular/core").Signal<{
26
25
  'c-primary': boolean;
27
26
  'c-secondary': boolean;
@@ -1,6 +1,6 @@
1
1
  import { OnDestroy, OnInit } from '@angular/core';
2
2
  import { SdBaseSecureComponent } from '@sd-angular/core/components/base';
3
- import { MaterialIconFontSet, SdColor } from '@sd-angular/core/utilities/models';
3
+ import { MaterialIconFontSet } from '@sd-angular/core/utilities/models';
4
4
  import * as i0 from "@angular/core";
5
5
  export type SdButtonType = 'fill' | 'light' | 'outline' | 'link';
6
6
  export type SdButtonSize = 'sm' | 'md' | 'lg';
@@ -10,7 +10,7 @@ export declare class SdButton extends SdBaseSecureComponent implements OnInit, O
10
10
  private el;
11
11
  autoIdInput: import("@angular/core").InputSignal<string | null | undefined>;
12
12
  type: import("@angular/core").InputSignalWithTransform<SdButtonType, SdButtonType | null | undefined>;
13
- color: import("@angular/core").InputSignalWithTransform<SdColor, SdColor | null | undefined>;
13
+ color: import("@angular/core").InputSignalWithTransform<import("@sdcorejs/utils/models").Color, import("@sdcorejs/utils/models").Color | null | undefined>;
14
14
  size: import("@angular/core").InputSignalWithTransform<SdButtonSize, SdButtonSize | null | undefined>;
15
15
  fontSet: import("@angular/core").InputSignalWithTransform<MaterialIconFontSet, MaterialIconFontSet | null | undefined>;
16
16
  title: import("@angular/core").InputSignal<string | null | undefined>;
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from '@angular/core';
2
- import { I18nService } from '@sd-angular/core/i18n';
2
+ import { DocumentBuilderI18n } from '../../document-builder.model';
3
3
  import { ClassicEditor, EditorConfig } from 'ckeditor5';
4
4
  import * as i0 from "@angular/core";
5
5
  export declare class SdHeaderFooterBuilder {
@@ -8,7 +8,7 @@ export declare class SdHeaderFooterBuilder {
8
8
  set model(value: string | undefined | null);
9
9
  modelChange: EventEmitter<string>;
10
10
  config: EditorConfig & {
11
- _i18n?: I18nService;
11
+ _i18n?: DocumentBuilderI18n;
12
12
  };
13
13
  onReady(editor: ClassicEditor): void;
14
14
  static ɵfac: i0.ɵɵFactoryDeclaration<SdHeaderFooterBuilder, never>;
@@ -1,9 +1,13 @@
1
1
  import { EditorConfig, EventInfo, ModelDocumentSelection, ViewDataTransfer } from 'ckeditor5';
2
- import { I18nService } from '@sd-angular/core/i18n';
2
+ import { I18nParams } from '@sd-angular/core/i18n';
3
3
  import { CkCommentConfig } from './plugins/ck-comment/ck-comment.plugin.model';
4
+ /** Plain translator cho CKEditor plugin — tránh truyền thẳng I18nService (private fields mất `this` qua config). */
5
+ export interface DocumentBuilderI18n {
6
+ t(key: string, params?: I18nParams): string;
7
+ }
4
8
  export type DocumentBuilderOption = EditorConfig & {
5
9
  getOption?: () => SdDocumentBuilderOption;
6
- _i18n?: I18nService;
10
+ _i18n?: DocumentBuilderI18n;
7
11
  };
8
12
  export interface SdDocumentBuilderOption {
9
13
  onDropVariable?: (variable: SdDocumentBuilderVariable) => boolean | Promise<boolean | SdDocumentBuilderVariable>;
@@ -36,6 +36,14 @@ export declare class SdEditor {
36
36
  constructor();
37
37
  onReady: (editor: ClassicEditor) => void;
38
38
  focusEditor: () => void | undefined;
39
+ /**
40
+ * Xử lý tải lên các file và trả về nội dung dữ liệu cuối cùng.
41
+ * * @description
42
+ * - Đối với các file upload chế độ 'deferred' (chỉ xử lý khi submit), cần @ViewChild component và gọi hàm upload() này.
43
+ * - Hỗ trợ two-way binding.
44
+ * - Hàm hỗ trợ trả ra data cuối cùng.
45
+ * * @returns {Promise<string>} Nội dung cuối cùng được trích xuất từ sd-editor.
46
+ */
39
47
  upload: () => Promise<string>;
40
48
  static ɵfac: i0.ɵɵFactoryDeclaration<SdEditor, never>;
41
49
  static ɵcmp: i0.ɵɵComponentDeclaration<SdEditor, "sd-editor", never, { "option": { "alias": "option"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "maxHeight": { "alias": "maxHeight"; "required": false; "isSignal": true; }; "maxlength": { "alias": "maxlength"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "helperText": { "alias": "helperText"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "hideInlineError": { "alias": "hideInlineError"; "required": false; "isSignal": true; }; "inlineError": { "alias": "inlineError"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "validator": { "alias": "validator"; "required": false; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; "key": { "alias": "key"; "required": false; "isSignal": true; }; "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "valueModel": { "alias": "model"; "required": false; "isSignal": true; }; }, { "valueModel": "modelChange"; "sdChange": "sdChange"; "sdBlur": "sdBlur"; "sdFocus": "sdFocus"; }, never, never, true, never>;
@@ -8,11 +8,44 @@ export interface SdEditorImageUploadValidation {
8
8
  allowedFormats?: string[];
9
9
  }
10
10
  export interface SdEditorImageConfig {
11
+ /**
12
+ * Chế độ tải lên hình ảnh.
13
+ * 'immediate': Upload ngay khi chọn ảnh.
14
+ * 'deferred': Lưu tạm ảnh blob, khi submit thì viewChild component sd-editor rồi gọi upload() để tự động map lại src lấy từ uploadFn,
15
+ * @default 'deferred'
16
+ */
11
17
  uploadMode?: 'deferred' | 'immediate';
18
+ /**
19
+ * Hàm xử lý tải lên file
20
+ * Nếu thuộc tính này được khai báo, tính năng tải lên hình ảnh trong editor sẽ tự động được kích hoạt.
21
+ * @param files Danh sách các tệp (File) cần tải lên.
22
+ * @returns Promise chứa mảng thông tin chi tiết của các tệp sau khi tải lên thành công.
23
+ */
12
24
  uploadFn?: (files: File[]) => Promise<SdEditorUploadFileDetail[]>;
25
+ /**
26
+ * Validation hình ảnh trước khi tiến hành tải lên.
27
+ */
13
28
  validation?: SdEditorImageUploadValidation;
29
+ /**
30
+ * Số lượng luồng tải lên (API calls) tối đa được thực thi đồng thời.
31
+ * Ví dụ: Nếu có 10 API cần tải lên, hệ thống sẽ đưa vào hàng đợi và xử lý song song dựa trên giới hạn này để tránh nghẽn mạng và rateLimit phía BE.
32
+ * @default 2
33
+ */
14
34
  maxConcurrentUploads?: number;
35
+ /**
36
+ * Số lượng file được gom nhóm (batch) trong mỗi lần gọi hàm `uploadFn`.
37
+ * Nếu Backend hỗ trợ multi-file, có thể thiết lập số này lớn hơn để gửi nhiều file trong cùng một payload.
38
+ * Ví dụ: Nếu chọn 10 file và `batchSize = 5`, hệ thống sẽ chỉ gọi 2 API, mỗi lần gửi 5 file.
39
+ * * @default 2
40
+ */
15
41
  batchSize?: number;
42
+ /**
43
+ * Số lượng hình ảnh tối đa người dùng được phép chọn trong một lần thao tác.
44
+ */
16
45
  maxImagesPerSelection?: number;
46
+ /**
47
+ * Kích hoạt chế độ tải chậm (lazy load) cho hình ảnh để tối ưu hóa hiệu suất
48
+ * @default true
49
+ */
17
50
  lazyLoad?: boolean;
18
51
  }
@@ -1,2 +1,3 @@
1
1
  export declare const countTextLength: (content: string) => number;
2
+ export declare const imageInlineStylesToClasses: (html: string) => string;
2
3
  export declare const imageClassesToInlineStyles: (html: string) => string;
@@ -8,9 +8,7 @@ export * from '@sd-angular/core/components/table';
8
8
  export * from '@sd-angular/core/components/quick-action';
9
9
  export * from '@sd-angular/core/components/upload-file';
10
10
  export * from '@sd-angular/core/components/section';
11
- export * from '@sd-angular/core/components/workflow';
12
11
  export * from '@sd-angular/core/components/anchor';
13
- export * from '@sd-angular/core/components/anchor-v2';
14
12
  export * from '@sd-angular/core/components/query-builder';
15
13
  export * from '@sd-angular/core/components/import-excel';
16
14
  export * from '@sd-angular/core/components/document-builder';
@@ -1,5 +1,4 @@
1
1
  import { ElementRef, TemplateRef } from '@angular/core';
2
- import { SdColor } from '@sd-angular/core/utilities/models';
3
2
  import * as i0 from "@angular/core";
4
3
  export declare class SdModal {
5
4
  #private;
@@ -10,7 +9,7 @@ export declare class SdModal {
10
9
  readonly autoId: import("@angular/core").Signal<string | undefined>;
11
10
  readonly closeButtonAutoId: import("@angular/core").Signal<string | undefined>;
12
11
  title: import("@angular/core").InputSignalWithTransform<string, string | null | undefined>;
13
- color: import("@angular/core").InputSignalWithTransform<SdColor, SdColor | null | undefined>;
12
+ color: import("@angular/core").InputSignalWithTransform<import("@sdcorejs/utils/models").Color, import("@sdcorejs/utils/models").Color | null | undefined>;
14
13
  width: import("@angular/core").InputSignalWithTransform<string, string | null | undefined>;
15
14
  height: import("@angular/core").InputSignalWithTransform<string, string | null | undefined>;
16
15
  view: import("@angular/core").InputSignalWithTransform<"dialog" | "bottom-sheet" | undefined, "dialog" | "bottom-sheet" | null | undefined>;
@@ -1,12 +1,11 @@
1
1
  import { SdBaseSecureComponent } from '@sd-angular/core/components/base';
2
- import { SdColor } from '@sd-angular/core/utilities';
3
2
  import * as i0 from "@angular/core";
4
3
  export declare class SdSection extends SdBaseSecureComponent {
5
4
  #private;
6
5
  title: import("@angular/core").InputSignal<string | null | undefined>;
7
6
  subTitle: import("@angular/core").InputSignal<string | null | undefined>;
8
7
  icon: import("@angular/core").InputSignal<string | null | undefined>;
9
- iconColor: import("@angular/core").InputSignal<SdColor>;
8
+ iconColor: import("@angular/core").InputSignal<import("@sdcorejs/utils/models").Color>;
10
9
  collapsed: import("@angular/core").ModelSignal<boolean>;
11
10
  collapsable: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
12
11
  hideHeader: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
@@ -1,6 +1,7 @@
1
1
  export * from './src/directives/sd-table-cell-def.directive';
2
2
  export * from './src/directives/sd-table-expand-def.directive';
3
3
  export * from './src/directives/sd-table-filter-def.directive';
4
+ export * from './src/directives/sd-table-footer-def.directive';
4
5
  export * from './src/directives/sd-table-title-def.directive';
5
6
  export * from './src/table.component';
6
7
  export * from './src/services/table-filter/table-filter.model';
@@ -12,12 +12,12 @@ export declare class ColumnFilterComponent implements OnInit, OnDestroy {
12
12
  _value(value: any): void;
13
13
  inlineSymbol: string;
14
14
  set _inlineOperator(inlineOperator: SdOperator);
15
- inlineOperatorChange: EventEmitter<SdOperator>;
16
- operatorChange: EventEmitter<SdOperator>;
15
+ inlineOperatorChange: EventEmitter<import("@sdcorejs/utils/models").Operator>;
16
+ operatorChange: EventEmitter<import("@sdcorejs/utils/models").Operator>;
17
17
  columnFilter: Record<string, any>;
18
18
  set _columnFilter(columnFilter: Record<string, any>);
19
19
  operators: {
20
- value: SdOperator;
20
+ value: import("@sdcorejs/utils/models").Operator;
21
21
  symbol?: string;
22
22
  display: string;
23
23
  }[];
@@ -1,3 +1,4 @@
1
1
  export * from './table-option.model';
2
2
  export * from './table-column.model';
3
3
  export * from './table-command.model';
4
+ export * from './table-option-tree.model';
@@ -10,6 +10,15 @@ export interface SdTableMetaExpand {
10
10
  isExpanding?: boolean;
11
11
  data?: any;
12
12
  }
13
+ export interface SdTableMetaTree<T = any> {
14
+ level: number;
15
+ hasChildren: boolean;
16
+ isExpanded: boolean;
17
+ isExpanding?: boolean;
18
+ parentId?: string;
19
+ /** Cached formatted child SdTableItem[] — populated on first expand/format */
20
+ childItems?: SdTableItem<T>[];
21
+ }
13
22
  export interface SdTableDisplay {
14
23
  tooltip?: string;
15
24
  badge?: {
@@ -32,6 +41,7 @@ export interface SdTableMeta<T> {
32
41
  htmlTemplate?: string;
33
42
  items?: SdTableItem<T>[];
34
43
  };
44
+ tree?: SdTableMetaTree<T>;
35
45
  }
36
46
  export interface SdTableItem<T = any> {
37
47
  meta: SdTableMeta<T>;
@@ -1,6 +1,11 @@
1
+ export interface SdTableRowCssContext {
2
+ level: number;
3
+ hasChildren: boolean;
4
+ isExpanded: boolean;
5
+ }
1
6
  export interface SdTableOptionStyle<T = any> {
2
7
  shadow?: boolean;
3
8
  maxHeight?: string;
4
9
  minHeight?: string;
5
- rowCss?: (rowData: T) => Record<string, string>;
10
+ rowCss?: (rowData: T, index?: number, ctx?: SdTableRowCssContext) => Record<string, string>;
6
11
  }
@@ -0,0 +1,12 @@
1
+ export interface SdTableOptionTree<T = any> {
2
+ /** Key trên object row chứa mảng children. Mặc định: 'children' */
3
+ childrenKey?: string;
4
+ /** Giới hạn độ sâu cây. undefined = không giới hạn. */
5
+ maxDepth?: number;
6
+ /** false | true | number (mở tới cấp N) */
7
+ defaultExpanded?: boolean | number;
8
+ /** Lazy load khi row chưa có children embedded */
9
+ onExpandChildren?: (rowData: T) => Promise<T[]> | T[];
10
+ /** Pixel indent mỗi cấp. Mặc định: 20 */
11
+ indentSize?: number;
12
+ }
@@ -11,6 +11,7 @@ import { SdTableOptionReload } from './table-option-reload.model';
11
11
  import { SdTableOptionSelector } from './table-option-selector.model';
12
12
  import { SdTableOptionSort } from './table-option-sort.model';
13
13
  import { SdTableOptionStyle } from './table-option-style.model';
14
+ import { SdTableOptionTree } from './table-option-tree.model';
14
15
  export type SdTableOption<T = any> = SdTableLocalOption<T> | SdTableServerOption<T>;
15
16
  interface SdTableBaseOption<T = any> {
16
17
  /**
@@ -61,6 +62,11 @@ interface SdTableBaseOption<T = any> {
61
62
  * Xem thêm tại `SdTableOptionGroup`.
62
63
  */
63
64
  group?: SdTableOptionGroup<T>;
65
+ /**
66
+ * Cấu hình tree rows — render children inline dưới parent.
67
+ * Xem thêm tại `SdTableOptionTree`.
68
+ */
69
+ tree?: SdTableOptionTree<T>;
64
70
  /**
65
71
  * Cấu hình filter của table.
66
72
  * Xem thêm tại `SdTableOptionFilter` để biết filter inline, external filter,
@@ -1 +1,2 @@
1
1
  export * from './filter-values.pipe';
2
+ export * from './sd-tree.pipe';
@@ -0,0 +1,9 @@
1
+ import { PipeTransform } from '@angular/core';
2
+ import { SdTableOptionTree } from '../models/table-option-tree.model';
3
+ import { SdTableItem } from '../models/table-item.model';
4
+ import * as i0 from "@angular/core";
5
+ export declare class SdTreePipe implements PipeTransform {
6
+ transform(items: SdTableItem[], treeOption?: SdTableOptionTree, _revision?: number): SdTableItem[];
7
+ static ɵfac: i0.ɵɵFactoryDeclaration<SdTreePipe, never>;
8
+ static ɵpipe: i0.ɵɵPipeDeclaration<SdTreePipe, "sdTree", true>;
9
+ }
@@ -0,0 +1,14 @@
1
+ import { SdTableOptionTree } from '../../models/table-option-tree.model';
2
+ import { SdTableItem } from '../../models/table-item.model';
3
+ export declare const getChildrenKey: (option?: SdTableOptionTree) => string;
4
+ export declare const getChildrenFromData: <T>(data: T, option?: SdTableOptionTree) => T[];
5
+ export declare const resolveDefaultExpanded: (level: number, option?: SdTableOptionTree) => boolean;
6
+ export declare const resolveHasChildren: <T>(row: SdTableItem<T>, option?: SdTableOptionTree) => boolean;
7
+ export declare const hasLazyChildren: <T>(row: SdTableItem<T>, option?: SdTableOptionTree) => boolean;
8
+ export declare const flattenTree: <T>(roots: SdTableItem<T>[], option?: SdTableOptionTree, visited?: Set<string>) => SdTableItem<T>[];
9
+ /** Thu thập mọi SdTableItem đã format trong cây (kể cả node đang collapse). */
10
+ export declare const collectFormattedTreeRows: <T>(roots: SdTableItem<T>[]) => SdTableItem<T>[];
11
+ /** Flatten ALL nodes regardless of expand state — used for export */
12
+ export declare const flattenTreeAll: <T>(roots: SdTableItem<T>[], option?: SdTableOptionTree, visited?: Set<string>) => SdTableItem<T>[];
13
+ /** Flatten raw data tree for export (ignores expand state) */
14
+ export declare const flattenDataTree: <T>(roots: T[], option?: SdTableOptionTree, visited?: Set<unknown>) => T[];
@@ -70,6 +70,7 @@ export declare class SdTable<T = unknown> extends SdBaseSecureComponent implemen
70
70
  columnOperator: Record<string, SdOperator>;
71
71
  columnFilter?: Record<string, any>;
72
72
  cacheValues: Record<string, any[]>;
73
+ treeRevision: import("@angular/core").WritableSignal<number>;
73
74
  exporting: import("@angular/core").WritableSignal<boolean>;
74
75
  exportTitle: import("@angular/core").WritableSignal<string>;
75
76
  tableConfiguration: ISdTableConfiguration | null;
@@ -82,11 +83,13 @@ export declare class SdTable<T = unknown> extends SdBaseSecureComponent implemen
82
83
  exportExcel: (columns?: SdExcelColumn[]) => void;
83
84
  exportCSV: (columns?: SdExcelColumn[]) => void;
84
85
  exportCustom: () => void;
86
+ onTreeToggle: (row: SdTableItem<T>) => Promise<void>;
85
87
  onFilterChange: () => void;
86
88
  onExpand: (rowData: SdTableItem<T>) => Promise<void>;
87
89
  onSelect: (rowData: SdTableItem<T>) => void;
88
90
  onSelectAll: () => void;
89
91
  onClearSelection: (items?: SdTableItem<T>[]) => void;
92
+ rowStyle: (row: SdTableItem<T>, index?: number) => Record<string, string> | null;
90
93
  clearFilter: () => void;
91
94
  setFilter: (args: {
92
95
  columnFilter?: Record<string, any>;
@@ -66,10 +66,12 @@ class SdHeaderFooterBuilder {
66
66
  }
67
67
  }
68
68
  modelChange = new EventEmitter();
69
+ #editorI18n = {
70
+ t: (key, params) => this.#i18n.t(key, params),
71
+ };
69
72
  config = {
70
73
  licenseKey: 'GPL', // Hoặc key thương mại nếu có
71
- // Truyền i18n service xuống CKEditor plugin (ngoài DI tree) để dịch label
72
- _i18n: this.#i18n,
74
+ _i18n: this.#editorI18n,
73
75
  // 1. PLUGIN RÚT GỌN (Bỏ Table, List, PageBreak...)
74
76
  plugins: [
75
77
  Essentials,
@@ -4432,11 +4434,14 @@ class SdDocumentBuilder {
4432
4434
  #contentChangeSubject = new Subject();
4433
4435
  #idTimeOutScrollHeading = null;
4434
4436
  #headingElementsMap = new Map(); // Hash lưu trữ các heading
4437
+ // Wrapper giữ `this` của I18nService — CKEditor config không truyền được class instance có private fields.
4438
+ #editorI18n = {
4439
+ t: (key, params) => this.#i18n.t(key, params),
4440
+ };
4435
4441
  // Config
4436
4442
  config = {
4437
4443
  getOption: () => this.option,
4438
- // Truyền i18n service xuống CKEditor plugin (ngoài DI tree) để dịch label/error
4439
- _i18n: this.#i18n,
4444
+ _i18n: this.#editorI18n,
4440
4445
  licenseKey: 'GPL', // Hoặc key thương mại nếu có
4441
4446
  plugins: [
4442
4447
  FontSize,