@sd-angular/core 19.0.31 → 19.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/scss/core/_read-state-panel.scss +57 -0
- package/components/data-state/index.d.ts +1 -0
- package/components/data-state/src/data-state.component.d.ts +41 -0
- package/components/import-excel/src/import-excel.component.d.ts +23 -1
- package/components/index.d.ts +1 -0
- package/components/quick-action/src/quick-action.component.d.ts +3 -1
- package/components/table/src/components/selector-action/selector-action.component.d.ts +12 -0
- package/components/table/src/models/table-option-selector.model.d.ts +2 -0
- package/components/table/src/table.component.d.ts +10 -1
- package/components/upload-file/src/upload-file.component.d.ts +5 -1
- package/fesm2022/sd-angular-core-components-badge.mjs +2 -2
- package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-button.mjs +2 -2
- package/fesm2022/sd-angular-core-components-button.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-data-state.mjs +72 -0
- package/fesm2022/sd-angular-core-components-data-state.mjs.map +1 -0
- package/fesm2022/sd-angular-core-components-form-generic.mjs +14 -14
- package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-import-excel.mjs +67 -18
- package/fesm2022/sd-angular-core-components-import-excel.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-inform.mjs +6 -6
- package/fesm2022/sd-angular-core-components-inform.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-query-bar.mjs +3 -3
- package/fesm2022/sd-angular-core-components-query-bar.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-query-builder.mjs +1 -1
- package/fesm2022/sd-angular-core-components-query-builder.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-quick-action.mjs +4 -2
- package/fesm2022/sd-angular-core-components-quick-action.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-stepper.mjs +2 -2
- package/fesm2022/sd-angular-core-components-stepper.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-table.mjs +125 -31
- package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-tree.mjs +1 -1
- package/fesm2022/sd-angular-core-components-tree.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-upload-file.mjs +20 -6
- package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components.mjs +1 -0
- package/fesm2022/sd-angular-core-components.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs +247 -59
- package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date-range.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-date.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-datetime.mjs +2 -2
- package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-select.mjs +290 -67
- package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
- package/fesm2022/sd-angular-core-i18n.mjs +160 -0
- package/fesm2022/sd-angular-core-i18n.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-layout.mjs +756 -15
- package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
- package/fesm2022/sd-angular-core-utilities-read-state.mjs +87 -0
- package/fesm2022/sd-angular-core-utilities-read-state.mjs.map +1 -0
- package/fesm2022/sd-angular-core-utilities.mjs +1 -0
- package/fesm2022/sd-angular-core-utilities.mjs.map +1 -1
- package/forms/autocomplete/src/autocomplete.component.d.ts +13 -2
- package/forms/select/src/select.component.d.ts +11 -1
- package/i18n/src/en.d.ts +32 -0
- package/modules/layout/components/layout-main/layout-main.component.d.ts +1 -1
- package/modules/layout/components/sidebar-mobile-v1/components/sidebar/sidebar.component.d.ts +2 -2
- package/modules/layout/components/sidebar-mobile-v1/main.component.d.ts +2 -2
- package/modules/layout/components/sidebar-v2/components/sidebar/sidebar.component.d.ts +56 -0
- package/modules/layout/components/sidebar-v2/components/user/user.component.d.ts +22 -0
- package/modules/layout/components/sidebar-v2/main.component.d.ts +25 -0
- package/modules/layout/configurations/layout.configuration.d.ts +5 -1
- package/modules/layout/services/layout.service.d.ts +2 -2
- package/package.json +9 -1
- package/utilities/index.d.ts +1 -0
- package/utilities/read-state/index.d.ts +1 -0
- package/utilities/read-state/src/read-state.d.ts +37 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { signal, TemplateRef } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
/** VALUE errors take precedence; otherwise SEARCH errors, then the active SEARCH channel. */
|
|
4
|
+
function combineReadStates(value, search) {
|
|
5
|
+
const current = value.status === 'error' ? value : search.status !== 'idle' ? search : value;
|
|
6
|
+
return Object.freeze({ ...current, channels: Object.freeze({ VALUE: value, SEARCH: search }) });
|
|
7
|
+
}
|
|
8
|
+
/** @internal Request guard shared by controls. Context is checked even before Angular effects run. */
|
|
9
|
+
class SdReadChannel {
|
|
10
|
+
operation;
|
|
11
|
+
changed;
|
|
12
|
+
#state;
|
|
13
|
+
state;
|
|
14
|
+
#revision = 0;
|
|
15
|
+
#valid = () => true;
|
|
16
|
+
constructor(operation, changed) {
|
|
17
|
+
this.operation = operation;
|
|
18
|
+
this.changed = changed;
|
|
19
|
+
this.#state = signal(Object.freeze({ status: 'idle', operation }));
|
|
20
|
+
this.state = this.#state.asReadonly();
|
|
21
|
+
}
|
|
22
|
+
begin(valid = () => true) {
|
|
23
|
+
this.#valid = valid;
|
|
24
|
+
const revision = ++this.#revision;
|
|
25
|
+
this.#set({ status: 'loading', operation: this.operation });
|
|
26
|
+
return revision;
|
|
27
|
+
}
|
|
28
|
+
isCurrent(revision) {
|
|
29
|
+
return revision === this.#revision && this.#valid();
|
|
30
|
+
}
|
|
31
|
+
succeed(revision, count) {
|
|
32
|
+
if (!this.isCurrent(revision))
|
|
33
|
+
return false;
|
|
34
|
+
this.#set({ status: count ? 'ready' : 'empty', operation: this.operation });
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
fail(revision, error) {
|
|
38
|
+
if (!this.isCurrent(revision))
|
|
39
|
+
return false;
|
|
40
|
+
this.#set({ status: 'error', operation: this.operation, error });
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
invalidate() {
|
|
44
|
+
++this.#revision;
|
|
45
|
+
this.#valid = () => true;
|
|
46
|
+
if (this.state().status !== 'idle')
|
|
47
|
+
this.#set({ status: 'idle', operation: this.operation });
|
|
48
|
+
}
|
|
49
|
+
#set(state) {
|
|
50
|
+
const snapshot = Object.freeze(state);
|
|
51
|
+
this.#state.set(snapshot);
|
|
52
|
+
this.changed?.(snapshot);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @internal Copy request-owned data, including Dates. Unlike ObjectUtilities.clone,
|
|
57
|
+
* Dates must be copied too; structuredClone cannot retain table column callbacks.
|
|
58
|
+
*/
|
|
59
|
+
function cloneReadRequest(value, seen = new WeakMap()) {
|
|
60
|
+
if (value === null || typeof value !== 'object')
|
|
61
|
+
return value;
|
|
62
|
+
// why: TemplateRef là handle thuộc Angular view, không phải dữ liệu request có thể sao chép.
|
|
63
|
+
if (value instanceof TemplateRef)
|
|
64
|
+
return value;
|
|
65
|
+
if (seen.has(value))
|
|
66
|
+
return seen.get(value);
|
|
67
|
+
if (value instanceof Date)
|
|
68
|
+
return new Date(value.getTime());
|
|
69
|
+
const copy = (Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value)));
|
|
70
|
+
seen.set(value, copy);
|
|
71
|
+
for (const key of Object.keys(value)) {
|
|
72
|
+
Object.defineProperty(copy, key, {
|
|
73
|
+
value: cloneReadRequest(value[key], seen),
|
|
74
|
+
enumerable: true,
|
|
75
|
+
writable: true,
|
|
76
|
+
configurable: true,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return copy;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Generated bundle index. Do not edit.
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
export { SdReadChannel, cloneReadRequest, combineReadStates };
|
|
87
|
+
//# sourceMappingURL=sd-angular-core-utilities-read-state.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sd-angular-core-utilities-read-state.mjs","sources":["../../../projects/sd-angular/utilities/read-state/src/read-state.ts","../../../projects/sd-angular/utilities/read-state/sd-angular-core-utilities-read-state.ts"],"sourcesContent":["import { TemplateRef, signal } from '@angular/core';\n\nexport type SdReadOperation = 'TABLE' | 'VALUE' | 'SEARCH';\nexport type SdReadStatus = 'idle' | 'loading' | 'ready' | 'empty' | 'error';\n\n/** An accepted read result. Only an error snapshot contains the original exception. */\nexport type SdReadState = Readonly<\n { status: Exclude<SdReadStatus, 'error'>; operation: SdReadOperation } | { status: 'error'; operation: SdReadOperation; error: unknown }\n>;\n\nexport type SdSearchReadState = SdReadState & {\n readonly channels: Readonly<{ VALUE: SdReadState; SEARCH: SdReadState }>;\n};\n\n/** VALUE errors take precedence; otherwise SEARCH errors, then the active SEARCH channel. */\nexport function combineReadStates(value: SdReadState, search: SdReadState): SdSearchReadState {\n const current = value.status === 'error' ? value : search.status !== 'idle' ? search : value;\n return Object.freeze({ ...current, channels: Object.freeze({ VALUE: value, SEARCH: search }) });\n}\n\n/** @internal Request guard shared by controls. Context is checked even before Angular effects run. */\nexport class SdReadChannel {\n readonly #state;\n readonly state;\n #revision = 0;\n #valid = () => true;\n\n constructor(\n readonly operation: SdReadOperation,\n private readonly changed?: (state: SdReadState) => void\n ) {\n this.#state = signal<SdReadState>(Object.freeze({ status: 'idle', operation }));\n this.state = this.#state.asReadonly();\n }\n\n begin(valid: () => boolean = () => true): number {\n this.#valid = valid;\n const revision = ++this.#revision;\n this.#set({ status: 'loading', operation: this.operation });\n return revision;\n }\n\n isCurrent(revision: number): boolean {\n return revision === this.#revision && this.#valid();\n }\n\n succeed(revision: number, count: number): boolean {\n if (!this.isCurrent(revision)) return false;\n this.#set({ status: count ? 'ready' : 'empty', operation: this.operation });\n return true;\n }\n\n fail(revision: number, error: unknown): boolean {\n if (!this.isCurrent(revision)) return false;\n this.#set({ status: 'error', operation: this.operation, error });\n return true;\n }\n\n invalidate(): void {\n ++this.#revision;\n this.#valid = () => true;\n if (this.state().status !== 'idle') this.#set({ status: 'idle', operation: this.operation });\n }\n\n #set(state: SdReadState): void {\n const snapshot = Object.freeze(state);\n this.#state.set(snapshot);\n this.changed?.(snapshot);\n }\n}\n\n/**\n * @internal Copy request-owned data, including Dates. Unlike ObjectUtilities.clone,\n * Dates must be copied too; structuredClone cannot retain table column callbacks.\n */\nexport function cloneReadRequest<T>(value: T, seen = new WeakMap<object, unknown>()): T {\n if (value === null || typeof value !== 'object') return value;\n // why: TemplateRef là handle thuộc Angular view, không phải dữ liệu request có thể sao chép.\n if (value instanceof TemplateRef) return value;\n if (seen.has(value)) return seen.get(value) as T;\n if (value instanceof Date) return new Date(value.getTime()) as T;\n const copy = (Array.isArray(value) ? [] : Object.create(Object.getPrototypeOf(value))) as T;\n seen.set(value, copy);\n for (const key of Object.keys(value)) {\n Object.defineProperty(copy, key, {\n value: cloneReadRequest((value as Record<string, unknown>)[key], seen),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n return copy;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from '@sd-angular/core/utilities/extensions';
|
|
2
2
|
export * from '@sd-angular/core/utilities/models';
|
|
3
3
|
export * from '@sd-angular/core/utilities/data-state';
|
|
4
|
+
export * from '@sd-angular/core/utilities/read-state';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-utilities.mjs","sources":["../../../projects/sd-angular/utilities/sd-angular-core-utilities.ts"],"sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sd-angular-core-utilities.mjs","sources":["../../../projects/sd-angular/utilities/sd-angular-core-utilities.ts"],"sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;AAAA;;AAEG"}
|
|
@@ -3,6 +3,8 @@ import { FormControl, FormGroup, FormGroupDirective, NgForm } from '@angular/for
|
|
|
3
3
|
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
|
|
4
4
|
import { ErrorStateMatcher } from '@angular/material/core';
|
|
5
5
|
import { MatFormFieldAppearance } from '@angular/material/form-field';
|
|
6
|
+
import { SdDataStateTemplateDirective } from '@sd-angular/core/components/data-state';
|
|
7
|
+
import { SdSearchReadState } from '@sd-angular/core/utilities/read-state';
|
|
6
8
|
import { SdItemDefDefDirective, SdViewDefDirective } from '@sd-angular/core/forms/directives';
|
|
7
9
|
import { SdCustomValidator, SdFormControl, SdSearch, SdSelectionData, SdViewed, SdViewedInput } from '@sd-angular/core/forms/models';
|
|
8
10
|
import { Size } from '@sdcorejs/utils/models';
|
|
@@ -46,6 +48,11 @@ export declare class SdAutocomplete<T = any> implements OnInit, OnDestroy, After
|
|
|
46
48
|
hyperlink: import("@angular/core").InputSignal<string | null | undefined>;
|
|
47
49
|
items: import("@angular/core").InputSignal<SdSearch<T> | T[] | null | undefined>;
|
|
48
50
|
hideInlineError: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
51
|
+
readonly hideReadError: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
52
|
+
readonly dataStateTemplate: import("@angular/core").Signal<SdDataStateTemplateDirective | undefined>;
|
|
53
|
+
readonly sdReadStateChange: import("@angular/core").OutputEmitterRef<SdSearchReadState>;
|
|
54
|
+
readonly readState: import("@angular/core").Signal<SdSearchReadState>;
|
|
55
|
+
readonly hasSearched: import("@angular/core").WritableSignal<boolean>;
|
|
49
56
|
addable: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
50
57
|
required: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
51
58
|
disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
@@ -91,7 +98,9 @@ export declare class SdAutocomplete<T = any> implements OnInit, OnDestroy, After
|
|
|
91
98
|
ngOnDestroy(): void;
|
|
92
99
|
onSelect: (item: T) => void;
|
|
93
100
|
onFocus: () => void;
|
|
94
|
-
onBlur: () => void;
|
|
101
|
+
onBlur: (event?: FocusEvent) => void;
|
|
102
|
+
protected focusReadRetry: (event: KeyboardEvent) => void;
|
|
103
|
+
protected onReadRegionKeydown: (event: KeyboardEvent) => void;
|
|
95
104
|
onClick: () => void;
|
|
96
105
|
blur: () => void;
|
|
97
106
|
focus: () => void;
|
|
@@ -100,7 +109,9 @@ export declare class SdAutocomplete<T = any> implements OnInit, OnDestroy, After
|
|
|
100
109
|
clear: ($event?: any) => void;
|
|
101
110
|
onAdd: ($event: Event) => void;
|
|
102
111
|
reValidate: () => void;
|
|
112
|
+
/** Retry bypasses text debounce/distinctness while using the original loader and request snapshot. */
|
|
113
|
+
retryRead: () => void;
|
|
103
114
|
static ɵfac: i0.ɵɵFactoryDeclaration<SdAutocomplete<any>, never>;
|
|
104
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<SdAutocomplete<any>, "sd-autocomplete", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "helperText": { "alias": "helperText"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "valueField": { "alias": "valueField"; "required": false; "isSignal": true; }; "displayField": { "alias": "displayField"; "required": false; "isSignal": true; }; "disabledField": { "alias": "disabledField"; "required": false; "isSignal": true; }; "limit": { "alias": "limit"; "required": false; "isSignal": true; }; "cacheChecksum": { "alias": "cacheChecksum"; "required": false; "isSignal": true; }; "hyperlink": { "alias": "hyperlink"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "hideInlineError": { "alias": "hideInlineError"; "required": false; "isSignal": true; }; "addable": { "alias": "addable"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "viewed": { "alias": "viewed"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "validator": { "alias": "validator"; "required": false; "isSignal": true; }; "inlineError": { "alias": "inlineError"; "required": false; "isSignal": true; }; "appearanceInput": { "alias": "appearance"; "required": false; "isSignal": true; }; "valueModel": { "alias": "model"; "required": false; "isSignal": true; }; }, { "valueModel": "modelChange"; "sdChange": "sdChange"; "sdSelection": "sdSelection"; "sdAdd": "sdAdd"; }, ["sdLabelTemplate", "sdValueTemplate", "itemDef", "sdViewDef"], ["[sdLabel]"], true, never>;
|
|
115
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SdAutocomplete<any>, "sd-autocomplete", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "helperText": { "alias": "helperText"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "valueField": { "alias": "valueField"; "required": false; "isSignal": true; }; "displayField": { "alias": "displayField"; "required": false; "isSignal": true; }; "disabledField": { "alias": "disabledField"; "required": false; "isSignal": true; }; "limit": { "alias": "limit"; "required": false; "isSignal": true; }; "cacheChecksum": { "alias": "cacheChecksum"; "required": false; "isSignal": true; }; "hyperlink": { "alias": "hyperlink"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "hideInlineError": { "alias": "hideInlineError"; "required": false; "isSignal": true; }; "hideReadError": { "alias": "hideReadError"; "required": false; "isSignal": true; }; "addable": { "alias": "addable"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "viewed": { "alias": "viewed"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "validator": { "alias": "validator"; "required": false; "isSignal": true; }; "inlineError": { "alias": "inlineError"; "required": false; "isSignal": true; }; "appearanceInput": { "alias": "appearance"; "required": false; "isSignal": true; }; "valueModel": { "alias": "model"; "required": false; "isSignal": true; }; }, { "sdReadStateChange": "sdReadStateChange"; "valueModel": "modelChange"; "sdChange": "sdChange"; "sdSelection": "sdSelection"; "sdAdd": "sdAdd"; }, ["sdLabelTemplate", "sdValueTemplate", "itemDef", "sdViewDef", "dataStateTemplate"], ["[sdLabel]"], true, never>;
|
|
105
116
|
}
|
|
106
117
|
export {};
|
|
@@ -4,6 +4,8 @@ import { FormControl, FormGroup } from '@angular/forms';
|
|
|
4
4
|
import { FloatLabelType, MatFormFieldAppearance } from '@angular/material/form-field';
|
|
5
5
|
import { MatInput } from '@angular/material/input';
|
|
6
6
|
import { MatSelect, MatSelectChange } from '@angular/material/select';
|
|
7
|
+
import { SdDataStateTemplateDirective } from '@sd-angular/core/components/data-state';
|
|
8
|
+
import { SdSearchReadState } from '@sd-angular/core/utilities/read-state';
|
|
7
9
|
import { SdItemDefDefDirective, SdViewDefDirective } from '@sd-angular/core/forms/directives';
|
|
8
10
|
import { SdCustomValidator, SdFormControl, SdSearch, SdSelectionData, SdViewed, SdViewedInput } from '@sd-angular/core/forms/models';
|
|
9
11
|
import { Size } from '@sdcorejs/utils/models';
|
|
@@ -57,6 +59,10 @@ export declare class SdSelect<T extends object | string | number = Record<string
|
|
|
57
59
|
hyperlink: import("@angular/core").InputSignal<string | null | undefined>;
|
|
58
60
|
minWidthPanel: import("@angular/core").InputSignalWithTransform<string | number, string | number | null | undefined>;
|
|
59
61
|
hideInlineError: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
62
|
+
readonly hideReadError: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
63
|
+
readonly dataStateTemplate: Signal<SdDataStateTemplateDirective | undefined>;
|
|
64
|
+
readonly sdReadStateChange: import("@angular/core").OutputEmitterRef<SdSearchReadState>;
|
|
65
|
+
readonly readState: Signal<SdSearchReadState>;
|
|
60
66
|
required: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
61
67
|
disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
62
68
|
/** Display mode: `false` edit · `true` static view · `'inline'` view + click-to-edit (bare editor). */
|
|
@@ -131,6 +137,10 @@ export declare class SdSelect<T extends object | string | number = Record<string
|
|
|
131
137
|
updatePanelWidth: () => void;
|
|
132
138
|
constructor();
|
|
133
139
|
ngOnInit(): void;
|
|
140
|
+
protected focusReadRetry: (event: KeyboardEvent) => void;
|
|
141
|
+
protected onReadRegionKeydown: (event: KeyboardEvent) => void;
|
|
142
|
+
/** Retry the error selected by readState; VALUE and SEARCH retain separate snapshots. */
|
|
143
|
+
retryRead: () => Promise<void>;
|
|
134
144
|
onSelectionChange: (change: MatSelectChange) => void;
|
|
135
145
|
/**
|
|
136
146
|
* Toggle "Chọn tất cả" theo scope hiện tại (items enabled khớp search):
|
|
@@ -148,5 +158,5 @@ export declare class SdSelect<T extends object | string | number = Record<string
|
|
|
148
158
|
open: () => void;
|
|
149
159
|
onOpenedChange: (isOpened: boolean) => void;
|
|
150
160
|
static ɵfac: i0.ɵɵFactoryDeclaration<SdSelect<any>, never>;
|
|
151
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<SdSelect<any>, "sd-select", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "helperText": { "alias": "helperText"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "valueField": { "alias": "valueField"; "required": false; "isSignal": true; }; "displayField": { "alias": "displayField"; "required": false; "isSignal": true; }; "disabledField": { "alias": "disabledField"; "required": false; "isSignal": true; }; "cacheChecksum": { "alias": "cacheChecksum"; "required": false; "isSignal": true; }; "limit": { "alias": "limit"; "required": false; "isSignal": true; }; "hyperlink": { "alias": "hyperlink"; "required": false; "isSignal": true; }; "minWidthPanel": { "alias": "minWidthPanel"; "required": false; "isSignal": true; }; "hideInlineError": { "alias": "hideInlineError"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "viewed": { "alias": "viewed"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "showSelectAll": { "alias": "showSelectAll"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "validator": { "alias": "validator"; "required": false; "isSignal": true; }; "inlineError": { "alias": "inlineError"; "required": false; "isSignal": true; }; "appearanceInput": { "alias": "appearance"; "required": false; "isSignal": true; }; "floatLabel": { "alias": "floatLabel"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "valueModel": { "alias": "model"; "required": false; "isSignal": true; }; }, { "valueModel": "modelChange"; "sdChange": "sdChange"; "sdSelection": "sdSelection"; }, ["sdLabelTemplate", "sdValueTemplate", "sdSelectedTemplate", "itemDef", "sdViewDef", "footerActions"], ["[sdLabel]"], true, never>;
|
|
161
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SdSelect<any>, "sd-select", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "form": { "alias": "form"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "helperText": { "alias": "helperText"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "valueField": { "alias": "valueField"; "required": false; "isSignal": true; }; "displayField": { "alias": "displayField"; "required": false; "isSignal": true; }; "disabledField": { "alias": "disabledField"; "required": false; "isSignal": true; }; "cacheChecksum": { "alias": "cacheChecksum"; "required": false; "isSignal": true; }; "limit": { "alias": "limit"; "required": false; "isSignal": true; }; "hyperlink": { "alias": "hyperlink"; "required": false; "isSignal": true; }; "minWidthPanel": { "alias": "minWidthPanel"; "required": false; "isSignal": true; }; "hideInlineError": { "alias": "hideInlineError"; "required": false; "isSignal": true; }; "hideReadError": { "alias": "hideReadError"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "viewed": { "alias": "viewed"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "showSelectAll": { "alias": "showSelectAll"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "validator": { "alias": "validator"; "required": false; "isSignal": true; }; "inlineError": { "alias": "inlineError"; "required": false; "isSignal": true; }; "appearanceInput": { "alias": "appearance"; "required": false; "isSignal": true; }; "floatLabel": { "alias": "floatLabel"; "required": false; "isSignal": true; }; "items": { "alias": "items"; "required": false; "isSignal": true; }; "valueModel": { "alias": "model"; "required": false; "isSignal": true; }; }, { "sdReadStateChange": "sdReadStateChange"; "valueModel": "modelChange"; "sdChange": "sdChange"; "sdSelection": "sdSelection"; }, ["sdLabelTemplate", "sdValueTemplate", "sdSelectedTemplate", "itemDef", "sdViewDef", "footerActions", "dataStateTemplate"], ["[sdLabel]"], true, never>;
|
|
152
162
|
}
|
package/i18n/src/en.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export declare const EN_MESSAGES: {
|
|
2
|
+
readonly 'core.component.data-state.loading.title': "Loading";
|
|
3
|
+
readonly 'core.component.data-state.loading.message': "Please wait while the data is being loaded.";
|
|
4
|
+
readonly 'core.component.data-state.empty.title': "No data";
|
|
5
|
+
readonly 'core.component.data-state.empty.message': "There is no data to display yet.";
|
|
6
|
+
readonly 'core.component.data-state.error.title': "Unable to load data";
|
|
7
|
+
readonly 'core.component.data-state.error.message': "An error occurred. Please try again.";
|
|
8
|
+
readonly 'core.component.data-state.forbidden.title': "Access denied";
|
|
9
|
+
readonly 'core.component.data-state.forbidden.message': "You do not have permission to view this content.";
|
|
10
|
+
readonly 'core.component.data-state.retry': "Try again";
|
|
2
11
|
readonly 'core.common.cancel': "Cancel";
|
|
3
12
|
readonly 'core.common.close': "Close";
|
|
4
13
|
readonly 'core.common.reload': "Reload page";
|
|
@@ -114,6 +123,7 @@ export declare const EN_MESSAGES: {
|
|
|
114
123
|
readonly 'core.form.date-range.invalid-max': "End date is invalid (above limit)";
|
|
115
124
|
readonly 'core.form.date-range.from': "From";
|
|
116
125
|
readonly 'core.form.date-range.to': "to";
|
|
126
|
+
readonly 'core.form.date-range.clear': "Clear date range";
|
|
117
127
|
readonly 'core.form.datetime.required': "Please enter information";
|
|
118
128
|
readonly 'core.form.datetime.min-date': "Minimum date: {date}";
|
|
119
129
|
readonly 'core.form.datetime.max-date': "Maximum date: {date}";
|
|
@@ -139,6 +149,7 @@ export declare const EN_MESSAGES: {
|
|
|
139
149
|
readonly 'core.form.checkbox.unchecked': "No";
|
|
140
150
|
readonly 'core.form.select.required': "Please enter information";
|
|
141
151
|
readonly 'core.form.select.selectAll': "All";
|
|
152
|
+
readonly 'core.form.select.selected-count': "{count} items selected";
|
|
142
153
|
readonly 'core.form.textarea.required': "Please enter information";
|
|
143
154
|
readonly 'core.form.textarea.maxlength': "Maximum characters: {max}";
|
|
144
155
|
readonly 'core.form.textarea.invalid-pattern': "Invalid format";
|
|
@@ -280,6 +291,21 @@ export declare const EN_MESSAGES: {
|
|
|
280
291
|
readonly 'core.component.code-editor.copied': "Copied!";
|
|
281
292
|
readonly 'core.component.code-editor.copy': "Copy code";
|
|
282
293
|
readonly 'core.component.history.by': "By";
|
|
294
|
+
readonly 'core.component.import-excel.choose-hint': "Choose an .xlsx template file with up to {limit} rows.";
|
|
295
|
+
readonly 'core.component.import-excel.choose-file': "Choose Excel file";
|
|
296
|
+
readonly 'core.component.import-excel.template': "Download template";
|
|
297
|
+
readonly 'core.component.import-excel.row-count': "{count} data rows";
|
|
298
|
+
readonly 'core.component.import-excel.replace-file': "Replace file";
|
|
299
|
+
readonly 'core.component.import-excel.filter-all': "All";
|
|
300
|
+
readonly 'core.component.import-excel.filter-success': "Valid";
|
|
301
|
+
readonly 'core.component.import-excel.filter-warning': "Warnings";
|
|
302
|
+
readonly 'core.component.import-excel.filter-error': "Errors";
|
|
303
|
+
readonly 'core.component.import-excel.preview': "Excel data preview";
|
|
304
|
+
readonly 'core.component.import-excel.issue-count': "View {count} issues";
|
|
305
|
+
readonly 'core.component.import-excel.no-filter-results': "No matching rows";
|
|
306
|
+
readonly 'core.component.import-excel.no-filter-results-hint': "Try another filter or view all data.";
|
|
307
|
+
readonly 'core.component.import-excel.blocked-errors': "Fix {count} rows with errors before importing.";
|
|
308
|
+
readonly 'core.component.import-excel.submitted': "Data has been submitted for processing.";
|
|
283
309
|
readonly 'core.component.import-excel.title': "Import Excel data";
|
|
284
310
|
readonly 'core.component.import-excel.see-all': "See all";
|
|
285
311
|
readonly 'core.component.import-excel.valid-rows': "Valid rows";
|
|
@@ -406,9 +432,14 @@ export declare const EN_MESSAGES: {
|
|
|
406
432
|
readonly 'core.component.table.not-an-array': "Data is not an array";
|
|
407
433
|
readonly 'core.component.table.config.confirm-reset': "Confirm reset all settings to defaults";
|
|
408
434
|
readonly 'core.component.table.popup-export.select-columns': "Please select columns to export";
|
|
435
|
+
readonly 'core.component.table.selector-action.selected': "Selected {count}";
|
|
436
|
+
readonly 'core.component.table.selector-action.more': "More";
|
|
409
437
|
readonly 'core.component.table.selector-action.default-msg': "items selected";
|
|
410
438
|
readonly 'core.component.tab-router.too-many-tabs': "You have opened too many tabs.";
|
|
411
439
|
readonly 'core.component.upload-file.upload': "Upload file";
|
|
440
|
+
readonly 'core.component.upload-file.remove': "Remove file";
|
|
441
|
+
readonly 'core.component.upload-file.loading': "Uploading file";
|
|
442
|
+
readonly 'core.component.upload-file.choose-or-drop': "Choose a file or drag it here";
|
|
412
443
|
readonly 'core.component.upload-file.error-occurred': "An error occurred";
|
|
413
444
|
readonly 'core.component.upload-file.please-upload': "Please upload a file/image";
|
|
414
445
|
readonly 'core.component.upload-file.desc-format-and-size': "Format: {exts} and up to: {maxSize}MB";
|
|
@@ -429,6 +460,7 @@ export declare const EN_MESSAGES: {
|
|
|
429
460
|
readonly 'core.module.layout.user.change-password': "Change password";
|
|
430
461
|
readonly 'core.module.layout.user.logout': "Sign out";
|
|
431
462
|
readonly 'core.module.layout.sidebar.search': "Search";
|
|
463
|
+
readonly 'core.module.layout.sidebar.clear-search': "Clear search";
|
|
432
464
|
readonly 'core.module.layout.greeting.hello': "Hello, {name}";
|
|
433
465
|
readonly 'core.module.layout.weekday.0': "Sunday";
|
|
434
466
|
readonly 'core.module.layout.weekday.1': "Monday";
|
|
@@ -5,7 +5,7 @@ export declare class SdLayoutComponent {
|
|
|
5
5
|
menusInput: import("@angular/core").InputSignal<SdLayoutMenu[]>;
|
|
6
6
|
menus: import("@angular/core").Signal<SdLayoutMenu[]>;
|
|
7
7
|
userInfo: import("@angular/core").WritableSignal<import("@sd-angular/core/modules/layout").SdLayoutUserInfo | undefined>;
|
|
8
|
-
sidebar: import("@angular/core").WritableSignal<import("@sd-angular/core/modules/layout").
|
|
8
|
+
sidebar: import("@angular/core").WritableSignal<import("@sd-angular/core/modules/layout").ISdSidebarConfiguration | undefined>;
|
|
9
9
|
isMobileOrTablet: import("@angular/core").WritableSignal<boolean>;
|
|
10
10
|
static ɵfac: i0.ɵɵFactoryDeclaration<SdLayoutComponent, never>;
|
|
11
11
|
static ɵcmp: i0.ɵɵComponentDeclaration<SdLayoutComponent, "sd-layout", never, { "menusInput": { "alias": "menus"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
package/modules/layout/components/sidebar-mobile-v1/components/sidebar/sidebar.component.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Params } from '@angular/router';
|
|
2
|
-
import { SdLayoutUserInfo,
|
|
2
|
+
import { SdLayoutUserInfo, ISdSidebarConfiguration } from '../../../../configurations';
|
|
3
3
|
import { SdLayoutMenu } from '../../../../services';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
5
|
export declare class SidebarMobileOverlayComponent {
|
|
@@ -7,7 +7,7 @@ export declare class SidebarMobileOverlayComponent {
|
|
|
7
7
|
isShowSidebar: import("@angular/core").InputSignal<boolean>;
|
|
8
8
|
menus: import("@angular/core").InputSignal<SdLayoutMenu[]>;
|
|
9
9
|
userInfo: import("@angular/core").InputSignal<SdLayoutUserInfo>;
|
|
10
|
-
sidebar: import("@angular/core").InputSignal<
|
|
10
|
+
sidebar: import("@angular/core").InputSignal<ISdSidebarConfiguration>;
|
|
11
11
|
showSideBar: import("@angular/core").OutputEmitterRef<boolean | null>;
|
|
12
12
|
expandSideBar: import("@angular/core").OutputEmitterRef<void>;
|
|
13
13
|
popupUserMenuOpened: import("@angular/core").OutputEmitterRef<void>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { SdLayoutUserInfo,
|
|
1
|
+
import { SdLayoutUserInfo, ISdSidebarConfiguration } from '../../configurations';
|
|
2
2
|
import { SdLayoutMenu } from '../../services';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
export declare class SidebarMobileV1Component {
|
|
5
5
|
#private;
|
|
6
6
|
menus: import("@angular/core").InputSignal<SdLayoutMenu[]>;
|
|
7
7
|
userInfo: import("@angular/core").InputSignal<SdLayoutUserInfo>;
|
|
8
|
-
sidebar: import("@angular/core").InputSignal<
|
|
8
|
+
sidebar: import("@angular/core").InputSignal<ISdSidebarConfiguration>;
|
|
9
9
|
isShowSidebar: import("@angular/core").WritableSignal<boolean>;
|
|
10
10
|
titleMenuGroup: import("@angular/core").WritableSignal<string | undefined>;
|
|
11
11
|
constructor();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { NestedTreeControl } from '@angular/cdk/tree';
|
|
2
|
+
import { MatTreeNestedDataSource } from '@angular/material/tree';
|
|
3
|
+
import { Params } from '@angular/router';
|
|
4
|
+
import { SdLayoutUserInfo, SidebarConfigurationV2 } from '../../../../configurations';
|
|
5
|
+
import { SdLayoutChildrenMenu, SdLayoutMenu } from '../../../../services';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
export declare class SidebarV2PanelComponent {
|
|
8
|
+
#private;
|
|
9
|
+
isShowSidebar: import("@angular/core").InputSignal<boolean>;
|
|
10
|
+
menus: import("@angular/core").InputSignal<SdLayoutMenu[]>;
|
|
11
|
+
userInfo: import("@angular/core").InputSignal<SdLayoutUserInfo>;
|
|
12
|
+
sidebar: import("@angular/core").InputSignal<SidebarConfigurationV2>;
|
|
13
|
+
expandSideBar: import("@angular/core").OutputEmitterRef<void>;
|
|
14
|
+
popupUserMenuClosed: import("@angular/core").OutputEmitterRef<void>;
|
|
15
|
+
popupUserMenuOpened: import("@angular/core").OutputEmitterRef<void>;
|
|
16
|
+
showSideBar: import("@angular/core").OutputEmitterRef<boolean | null>;
|
|
17
|
+
screenHeight: number;
|
|
18
|
+
isMobileOrTablet: boolean;
|
|
19
|
+
isMenuLock: import("@angular/core").WritableSignal<boolean>;
|
|
20
|
+
currentPath: import("@angular/core").WritableSignal<string>;
|
|
21
|
+
searchText: import("@angular/core").WritableSignal<string>;
|
|
22
|
+
titleMenuGroup: import("@angular/core").WritableSignal<string | undefined>;
|
|
23
|
+
idMenuGroupActive: import("@angular/core").WritableSignal<string | undefined>;
|
|
24
|
+
menusByGroup: import("@angular/core").WritableSignal<SdLayoutMenu[]>;
|
|
25
|
+
pinnedMenuGroup: import("@angular/core").WritableSignal<SdLayoutChildrenMenu>;
|
|
26
|
+
totalMenuInMenusByGroup: import("@angular/core").Signal<number>;
|
|
27
|
+
pinnedNodeKeys: import("@angular/core").Signal<Set<string>>;
|
|
28
|
+
isPinnedMenuGroupActive: import("@angular/core").Signal<boolean>;
|
|
29
|
+
activeMenuPath: import("@angular/core").Signal<string | null>;
|
|
30
|
+
dataSource: MatTreeNestedDataSource<SdLayoutMenu>;
|
|
31
|
+
treeControl: NestedTreeControl<SdLayoutMenu, SdLayoutMenu>;
|
|
32
|
+
constructor();
|
|
33
|
+
hasChild: (_: number, node: SdLayoutMenu) => boolean;
|
|
34
|
+
onToggleMenuNode: (menu: SdLayoutMenu) => void;
|
|
35
|
+
isPinnedNode: (node: SdLayoutMenu) => boolean;
|
|
36
|
+
isHoveredNode: (node: SdLayoutMenu) => boolean;
|
|
37
|
+
expandPinnedGroup: () => void;
|
|
38
|
+
onTogglePin: (event: MouseEvent, node: SdLayoutMenu) => void;
|
|
39
|
+
toggleMenuLock(event: Event): void;
|
|
40
|
+
openHomePage: () => void;
|
|
41
|
+
onUserMenuClosed: () => void;
|
|
42
|
+
onUserMenuOpened: () => void;
|
|
43
|
+
navigate: (args: {
|
|
44
|
+
path: string;
|
|
45
|
+
queryParams: Params;
|
|
46
|
+
}) => void;
|
|
47
|
+
onFilterSearchText: (event: string) => void;
|
|
48
|
+
onClearSearchText: () => void;
|
|
49
|
+
expandMenuGroup: (menuGroupNode: SdLayoutMenu) => void;
|
|
50
|
+
onMouseOverMenuGroupNode: (event: MouseEvent, menuNode: SdLayoutMenu) => void;
|
|
51
|
+
onMouseLeaveMenuGroupNode: (event: MouseEvent, menuNode: SdLayoutMenu) => void;
|
|
52
|
+
onMouseOverMenuNode: (event: MouseEvent, menuItem: SdLayoutMenu) => void;
|
|
53
|
+
onMouseLeaveMenuNode: (event: MouseEvent, menuItem: SdLayoutMenu) => void;
|
|
54
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SidebarV2PanelComponent, never>;
|
|
55
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SidebarV2PanelComponent, "sd-sidebar-v2-panel", never, { "isShowSidebar": { "alias": "isShowSidebar"; "required": true; "isSignal": true; }; "menus": { "alias": "menus"; "required": true; "isSignal": true; }; "userInfo": { "alias": "userInfo"; "required": true; "isSignal": true; }; "sidebar": { "alias": "sidebar"; "required": true; "isSignal": true; }; }, { "expandSideBar": "expandSideBar"; "popupUserMenuClosed": "popupUserMenuClosed"; "popupUserMenuOpened": "popupUserMenuOpened"; "showSideBar": "showSideBar"; }, never, never, true, never>;
|
|
56
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SdLayoutUserInfo } from '../../../../configurations';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class SidebarV2UserComponent {
|
|
4
|
+
#private;
|
|
5
|
+
isMobileOrTablet: import("@angular/core").InputSignal<boolean>;
|
|
6
|
+
isMenuLock: import("@angular/core").InputSignal<boolean>;
|
|
7
|
+
isShowSidebar: import("@angular/core").InputSignal<boolean>;
|
|
8
|
+
userInfo: import("@angular/core").InputSignal<SdLayoutUserInfo>;
|
|
9
|
+
menuClosed: import("@angular/core").OutputEmitterRef<void>;
|
|
10
|
+
menuOpened: import("@angular/core").OutputEmitterRef<void>;
|
|
11
|
+
toggleMenuLock: import("@angular/core").OutputEmitterRef<Event>;
|
|
12
|
+
singoutLayoutConfig: () => void | Promise<void>;
|
|
13
|
+
changePasswordLayoutConfig: (() => void | Promise<void>) | undefined;
|
|
14
|
+
onMenuOpened: () => void;
|
|
15
|
+
onMenuClosed: () => void;
|
|
16
|
+
keepOpenWhenClickInsideMenu: (event: Event) => void;
|
|
17
|
+
logout: () => void;
|
|
18
|
+
changePassword: () => void;
|
|
19
|
+
onToggleMenuLock: (event: Event) => void;
|
|
20
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SidebarV2UserComponent, never>;
|
|
21
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SidebarV2UserComponent, "sd-sidebar-v2-user", never, { "isMobileOrTablet": { "alias": "isMobileOrTablet"; "required": false; "isSignal": true; }; "isMenuLock": { "alias": "isMenuLock"; "required": false; "isSignal": true; }; "isShowSidebar": { "alias": "isShowSidebar"; "required": false; "isSignal": true; }; "userInfo": { "alias": "userInfo"; "required": true; "isSignal": true; }; }, { "menuClosed": "menuClosed"; "menuOpened": "menuOpened"; "toggleMenuLock": "toggleMenuLock"; }, never, never, true, never>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { MatSidenav } from '@angular/material/sidenav';
|
|
2
|
+
import { SdLayoutUserInfo, SidebarConfigurationV2 } from '../../configurations';
|
|
3
|
+
import { SdLayoutMenu } from '../../services';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export declare class SidebarV2Component {
|
|
6
|
+
#private;
|
|
7
|
+
sidenav: import("@angular/core").Signal<MatSidenav>;
|
|
8
|
+
menus: import("@angular/core").InputSignal<SdLayoutMenu[]>;
|
|
9
|
+
userInfo: import("@angular/core").InputSignal<SdLayoutUserInfo>;
|
|
10
|
+
sidebar: import("@angular/core").InputSignal<SidebarConfigurationV2>;
|
|
11
|
+
isMobileOrTablet: import("@angular/core").WritableSignal<boolean>;
|
|
12
|
+
isMenuLock: import("@angular/core").WritableSignal<boolean>;
|
|
13
|
+
isShowSidebar: import("@angular/core").WritableSignal<boolean>;
|
|
14
|
+
onhover: import("@angular/core").WritableSignal<boolean>;
|
|
15
|
+
constructor();
|
|
16
|
+
openSidebar: () => void;
|
|
17
|
+
onPopupOfSideBarOpened: () => void;
|
|
18
|
+
onPopupOfSideBarClosed: () => void;
|
|
19
|
+
onExpandSideBar: () => void;
|
|
20
|
+
onMouseleaveSideBar: () => void;
|
|
21
|
+
onSidenavOpenedChange: (opened: boolean) => void;
|
|
22
|
+
onToggle: (data: boolean | null) => void;
|
|
23
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SidebarV2Component, never>;
|
|
24
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SidebarV2Component, "sd-sidebar-v2", never, { "menus": { "alias": "menus"; "required": false; "isSignal": true; }; "userInfo": { "alias": "userInfo"; "required": true; "isSignal": true; }; "sidebar": { "alias": "sidebar"; "required": true; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
25
|
+
}
|
|
@@ -30,7 +30,7 @@ export interface SdLayoutUserInfo {
|
|
|
30
30
|
*/
|
|
31
31
|
avatar?: string;
|
|
32
32
|
}
|
|
33
|
-
export type ISdSidebarConfiguration = SidebarConfigurationV1;
|
|
33
|
+
export type ISdSidebarConfiguration = SidebarConfigurationV1 | SidebarConfigurationV2;
|
|
34
34
|
export interface SidebarConfigurationV1 {
|
|
35
35
|
version: 1;
|
|
36
36
|
/**
|
|
@@ -64,4 +64,8 @@ export interface SidebarConfigurationV1 {
|
|
|
64
64
|
enabled?: boolean;
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
|
+
/** Opt in to the refreshed desktop sidebar while keeping the V1 configuration fields. */
|
|
68
|
+
export interface SidebarConfigurationV2 extends Omit<SidebarConfigurationV1, 'version'> {
|
|
69
|
+
version: 2;
|
|
70
|
+
}
|
|
67
71
|
export declare const SD_LAYOUT_CONFIGURATION: InjectionToken<ISdLayoutConfiguration>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { SdLayoutUserInfo } from '../configurations';
|
|
1
|
+
import { ISdSidebarConfiguration, SdLayoutUserInfo } from '../configurations';
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
export declare class SdLayoutService {
|
|
4
4
|
#private;
|
|
5
5
|
userInfo: import("@angular/core").WritableSignal<SdLayoutUserInfo | undefined>;
|
|
6
|
-
sidebar: import("@angular/core").WritableSignal<
|
|
6
|
+
sidebar: import("@angular/core").WritableSignal<ISdSidebarConfiguration | undefined>;
|
|
7
7
|
constructor();
|
|
8
8
|
static ɵfac: i0.ɵɵFactoryDeclaration<SdLayoutService, never>;
|
|
9
9
|
static ɵprov: i0.ɵɵInjectableDeclaration<SdLayoutService>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-angular/core",
|
|
3
|
-
"version": "19.0.
|
|
3
|
+
"version": "19.0.33",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": "^19.0.0 || ^20.0.0 || ^21.0.0",
|
|
6
6
|
"@angular/core": "^19.0.0 || ^20.0.0 || ^21.0.0",
|
|
@@ -116,6 +116,10 @@
|
|
|
116
116
|
"types": "./components/code-editor/index.d.ts",
|
|
117
117
|
"default": "./fesm2022/sd-angular-core-components-code-editor.mjs"
|
|
118
118
|
},
|
|
119
|
+
"./components/data-state": {
|
|
120
|
+
"types": "./components/data-state/index.d.ts",
|
|
121
|
+
"default": "./fesm2022/sd-angular-core-components-data-state.mjs"
|
|
122
|
+
},
|
|
119
123
|
"./components/document-builder": {
|
|
120
124
|
"types": "./components/document-builder/index.d.ts",
|
|
121
125
|
"default": "./fesm2022/sd-angular-core-components-document-builder.mjs"
|
|
@@ -355,6 +359,10 @@
|
|
|
355
359
|
"./utilities/models": {
|
|
356
360
|
"types": "./utilities/models/index.d.ts",
|
|
357
361
|
"default": "./fesm2022/sd-angular-core-utilities-models.mjs"
|
|
362
|
+
},
|
|
363
|
+
"./utilities/read-state": {
|
|
364
|
+
"types": "./utilities/read-state/index.d.ts",
|
|
365
|
+
"default": "./fesm2022/sd-angular-core-utilities-read-state.mjs"
|
|
358
366
|
}
|
|
359
367
|
}
|
|
360
368
|
}
|
package/utilities/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src/read-state';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type SdReadOperation = 'TABLE' | 'VALUE' | 'SEARCH';
|
|
2
|
+
export type SdReadStatus = 'idle' | 'loading' | 'ready' | 'empty' | 'error';
|
|
3
|
+
/** An accepted read result. Only an error snapshot contains the original exception. */
|
|
4
|
+
export type SdReadState = Readonly<{
|
|
5
|
+
status: Exclude<SdReadStatus, 'error'>;
|
|
6
|
+
operation: SdReadOperation;
|
|
7
|
+
} | {
|
|
8
|
+
status: 'error';
|
|
9
|
+
operation: SdReadOperation;
|
|
10
|
+
error: unknown;
|
|
11
|
+
}>;
|
|
12
|
+
export type SdSearchReadState = SdReadState & {
|
|
13
|
+
readonly channels: Readonly<{
|
|
14
|
+
VALUE: SdReadState;
|
|
15
|
+
SEARCH: SdReadState;
|
|
16
|
+
}>;
|
|
17
|
+
};
|
|
18
|
+
/** VALUE errors take precedence; otherwise SEARCH errors, then the active SEARCH channel. */
|
|
19
|
+
export declare function combineReadStates(value: SdReadState, search: SdReadState): SdSearchReadState;
|
|
20
|
+
/** @internal Request guard shared by controls. Context is checked even before Angular effects run. */
|
|
21
|
+
export declare class SdReadChannel {
|
|
22
|
+
#private;
|
|
23
|
+
readonly operation: SdReadOperation;
|
|
24
|
+
private readonly changed?;
|
|
25
|
+
readonly state: import("@angular/core").Signal<SdReadState>;
|
|
26
|
+
constructor(operation: SdReadOperation, changed?: ((state: SdReadState) => void) | undefined);
|
|
27
|
+
begin(valid?: () => boolean): number;
|
|
28
|
+
isCurrent(revision: number): boolean;
|
|
29
|
+
succeed(revision: number, count: number): boolean;
|
|
30
|
+
fail(revision: number, error: unknown): boolean;
|
|
31
|
+
invalidate(): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @internal Copy request-owned data, including Dates. Unlike ObjectUtilities.clone,
|
|
35
|
+
* Dates must be copied too; structuredClone cannot retain table column callbacks.
|
|
36
|
+
*/
|
|
37
|
+
export declare function cloneReadRequest<T>(value: T, seen?: WeakMap<object, unknown>): T;
|