@sd-angular/core 19.0.0-beta.96 → 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 (31) hide show
  1. package/components/document-builder/src/components/header-footer-builder/header-footer-builder.component.d.ts +2 -2
  2. package/components/document-builder/src/document-builder.model.d.ts +6 -2
  3. package/components/editor/src/editor.component.d.ts +8 -0
  4. package/components/editor/src/models/image-upload.plugin.model.d.ts +33 -0
  5. package/components/editor/src/plugins/image-upload/utils/style.utils.d.ts +1 -0
  6. package/components/table/index.d.ts +1 -0
  7. package/components/table/src/models/index.d.ts +1 -0
  8. package/components/table/src/models/table-item.model.d.ts +10 -0
  9. package/components/table/src/models/table-option-style.model.d.ts +6 -1
  10. package/components/table/src/models/table-option-tree.model.d.ts +12 -0
  11. package/components/table/src/models/table-option.model.d.ts +6 -0
  12. package/components/table/src/pipes/index.d.ts +1 -0
  13. package/components/table/src/pipes/sd-tree.pipe.d.ts +9 -0
  14. package/components/table/src/services/tree/tree.util.d.ts +14 -0
  15. package/components/table/src/table.component.d.ts +3 -0
  16. package/fesm2022/sd-angular-core-components-document-builder.mjs +9 -4
  17. package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
  18. package/fesm2022/sd-angular-core-components-editor.mjs +222 -97
  19. package/fesm2022/sd-angular-core-components-editor.mjs.map +1 -1
  20. package/fesm2022/sd-angular-core-components-tab-router.mjs +57 -15
  21. package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
  22. package/fesm2022/sd-angular-core-components-table.mjs +325 -41
  23. package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
  24. package/fesm2022/sd-angular-core-modules-layout.mjs +172 -37
  25. package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
  26. package/modules/layout/components/sidebar-v1/components/sidebar/sidebar.component.d.ts +8 -1
  27. package/modules/layout/configurations/layout.configuration.d.ts +8 -0
  28. package/modules/layout/services/storage/storage.service.d.ts +2 -0
  29. package/package.json +70 -70
  30. package/sd-angular-core-19.0.0-beta.97.tgz +0 -0
  31. package/sd-angular-core-19.0.0-beta.96.tgz +0 -0
@@ -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;
@@ -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';
@@ -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,