@simplysm/angular 14.0.19 → 14.0.21
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/dist/core/provideSdAngular.js +1 -1
- package/dist/core/providers/sd-activated-modal.provider.d.ts +13 -0
- package/dist/core/providers/sd-activated-modal.provider.d.ts.map +1 -0
- package/dist/core/providers/sd-activated-modal.provider.js +15 -0
- package/dist/core/providers/sd-app-structure.provider.d.ts +3 -64
- package/dist/core/providers/sd-app-structure.provider.d.ts.map +1 -1
- package/dist/core/providers/sd-app-structure.provider.js +1 -252
- package/dist/core/providers/sd-app-structure.types.d.ts +52 -0
- package/dist/core/providers/sd-app-structure.types.d.ts.map +1 -0
- package/dist/core/providers/sd-app-structure.types.js +1 -0
- package/dist/core/providers/sd-app-structure.utils.d.ts +13 -0
- package/dist/core/providers/sd-app-structure.utils.d.ts.map +1 -0
- package/dist/core/providers/sd-app-structure.utils.js +250 -0
- package/dist/{ui/overlay/busy → core/providers}/sd-busy.provider.d.ts +1 -1
- package/dist/core/providers/sd-busy.provider.d.ts.map +1 -0
- package/dist/{ui/overlay/busy → core/providers}/sd-busy.provider.js +1 -1
- package/dist/core/providers/sd-print.provider.js +1 -1
- package/dist/core/providers/sd-service-client-factory.provider.js +1 -1
- package/dist/{ui/overlay/toast → core/providers}/sd-toast.provider.d.ts +1 -1
- package/dist/core/providers/sd-toast.provider.d.ts.map +1 -0
- package/dist/{ui/overlay/toast → core/providers}/sd-toast.provider.js +3 -3
- package/dist/core/types/select-modal-output-result.d.ts +8 -0
- package/dist/core/types/select-modal-output-result.d.ts.map +1 -0
- package/dist/core/types/select-modal-output-result.js +1 -0
- package/dist/core/utils/setups/setupCanDeactivate.js +1 -1
- package/dist/core/utils/useViewTitleSignal.js +1 -1
- package/dist/core/utils/useViewTypeSignal.js +1 -1
- package/dist/features/base/sd-base-container.control.js +1 -1
- package/dist/features/data-view/sd-data-detail.control.js +1 -1
- package/dist/features/data-view/sd-data-sheet.control.d.ts +24 -37
- package/dist/features/data-view/sd-data-sheet.control.d.ts.map +1 -1
- package/dist/features/data-view/sd-data-sheet.control.js +98 -152
- package/dist/features/data-view/sd-data-sheet.types.d.ts +17 -0
- package/dist/features/data-view/sd-data-sheet.types.d.ts.map +1 -0
- package/dist/features/data-view/sd-data-sheet.types.js +1 -0
- package/dist/{core/utils/setups → features/data-view}/setupCloserWhenSingleSelectionChange.d.ts +1 -1
- package/dist/features/data-view/setupCloserWhenSingleSelectionChange.d.ts.map +1 -0
- package/dist/features/data-view/useDataSheetExcelManager.d.ts +14 -0
- package/dist/features/data-view/useDataSheetExcelManager.d.ts.map +1 -0
- package/dist/features/data-view/useDataSheetExcelManager.js +31 -0
- package/dist/features/data-view/useDataSheetFilterManager.d.ts +13 -0
- package/dist/features/data-view/useDataSheetFilterManager.d.ts.map +1 -0
- package/dist/features/data-view/useDataSheetFilterManager.js +22 -0
- package/dist/features/data-view/useDataSheetInlineEditManager.d.ts +26 -0
- package/dist/features/data-view/useDataSheetInlineEditManager.d.ts.map +1 -0
- package/dist/features/data-view/useDataSheetInlineEditManager.js +54 -0
- package/dist/features/data-view/useDataSheetModalEditManager.d.ts +19 -0
- package/dist/features/data-view/useDataSheetModalEditManager.d.ts.map +1 -0
- package/dist/features/data-view/useDataSheetModalEditManager.js +44 -0
- package/dist/features/data-view/useDataSheetRefreshManager.d.ts +25 -0
- package/dist/features/data-view/useDataSheetRefreshManager.d.ts.map +1 -0
- package/dist/features/data-view/useDataSheetRefreshManager.js +50 -0
- package/dist/features/permission-table/sd-permission-table.control.d.ts +1 -1
- package/dist/features/permission-table/sd-permission-table.control.d.ts.map +1 -1
- package/dist/index.d.ts +12 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -5
- package/dist/ui/data/sheet/sd-sheet.control.d.ts +22 -30
- package/dist/ui/data/sheet/sd-sheet.control.d.ts.map +1 -1
- package/dist/ui/data/sheet/sd-sheet.control.js +52 -210
- package/dist/ui/data/sheet/useSheetCellStyling.d.ts +22 -0
- package/dist/ui/data/sheet/useSheetCellStyling.d.ts.map +1 -0
- package/dist/ui/data/sheet/useSheetCellStyling.js +95 -0
- package/dist/ui/data/sheet/useSheetColumnResizing.d.ts +17 -0
- package/dist/ui/data/sheet/useSheetColumnResizing.d.ts.map +1 -0
- package/dist/ui/data/sheet/useSheetColumnResizing.js +65 -0
- package/dist/ui/data/sheet/useSheetDisplayPipeline.d.ts +24 -0
- package/dist/ui/data/sheet/useSheetDisplayPipeline.d.ts.map +1 -0
- package/dist/ui/data/sheet/useSheetDisplayPipeline.js +52 -0
- package/dist/ui/form/button/sd-modal-select-button.control.d.ts +1 -7
- package/dist/ui/form/button/sd-modal-select-button.control.d.ts.map +1 -1
- package/dist/ui/form/button/sd-modal-select-button.control.js +1 -1
- package/dist/ui/form/choice/sd-state-preset.control.js +1 -1
- package/dist/ui/navigation/menu-utils.d.ts +2 -7
- package/dist/ui/navigation/menu-utils.d.ts.map +1 -1
- package/dist/ui/overlay/busy/sd-busy-container.control.d.ts +1 -1
- package/dist/ui/overlay/busy/sd-busy-container.control.d.ts.map +1 -1
- package/dist/ui/overlay/busy/sd-busy-container.control.js +1 -1
- package/dist/ui/overlay/modal/sd-modal.control.js +1 -1
- package/dist/ui/overlay/modal/sd-modal.provider.d.ts +0 -10
- package/dist/ui/overlay/modal/sd-modal.provider.d.ts.map +1 -1
- package/dist/ui/overlay/modal/sd-modal.provider.js +1 -13
- package/dist/ui/overlay/toast/sd-toast.control.d.ts +1 -1
- package/dist/ui/overlay/toast/sd-toast.control.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/core/provideSdAngular.ts +1 -1
- package/src/core/providers/sd-activated-modal.provider.ts +12 -0
- package/src/core/providers/sd-app-structure.provider.ts +2 -405
- package/src/core/providers/sd-app-structure.types.ts +60 -0
- package/src/core/providers/sd-app-structure.utils.ts +350 -0
- package/src/{ui/overlay/busy → core/providers}/sd-busy.provider.ts +1 -1
- package/src/core/providers/sd-print.provider.ts +1 -1
- package/src/core/providers/sd-service-client-factory.provider.ts +1 -1
- package/src/{ui/overlay/toast → core/providers}/sd-toast.provider.ts +4 -4
- package/src/core/types/select-modal-output-result.ts +7 -0
- package/src/core/utils/setups/setupCanDeactivate.ts +1 -1
- package/src/core/utils/useViewTitleSignal.ts +1 -1
- package/src/core/utils/useViewTypeSignal.ts +1 -1
- package/src/features/base/sd-base-container.control.ts +1 -1
- package/src/features/data-view/sd-data-detail.control.ts +1 -1
- package/src/features/data-view/sd-data-sheet.control.ts +117 -216
- package/src/features/data-view/sd-data-sheet.types.ts +18 -0
- package/src/{core/utils/setups → features/data-view}/setupCloserWhenSingleSelectionChange.ts +1 -1
- package/src/features/data-view/useDataSheetExcelManager.ts +57 -0
- package/src/features/data-view/useDataSheetFilterManager.ts +30 -0
- package/src/features/data-view/useDataSheetInlineEditManager.ts +89 -0
- package/src/features/data-view/useDataSheetModalEditManager.ts +76 -0
- package/src/features/data-view/useDataSheetRefreshManager.ts +90 -0
- package/src/features/permission-table/sd-permission-table.control.ts +1 -1
- package/src/index.ts +17 -11
- package/src/ui/data/sheet/sd-sheet.control.ts +50 -238
- package/src/ui/data/sheet/useSheetCellStyling.ts +113 -0
- package/src/ui/data/sheet/useSheetColumnResizing.ts +92 -0
- package/src/ui/data/sheet/useSheetDisplayPipeline.ts +64 -0
- package/src/ui/form/button/sd-modal-select-button.control.ts +1 -8
- package/src/ui/form/choice/sd-state-preset.control.ts +1 -1
- package/src/ui/navigation/menu-utils.ts +3 -7
- package/src/ui/overlay/busy/sd-busy-container.control.ts +1 -1
- package/src/ui/overlay/modal/sd-modal.control.ts +1 -1
- package/src/ui/overlay/modal/sd-modal.provider.ts +1 -10
- package/src/ui/overlay/toast/sd-toast.control.ts +1 -1
- package/dist/core/utils/setups/setupCloserWhenSingleSelectionChange.d.ts.map +0 -1
- package/dist/ui/overlay/busy/sd-busy.provider.d.ts.map +0 -1
- package/dist/ui/overlay/toast/sd-toast.provider.d.ts.map +0 -1
- /package/dist/{core/utils/setups → features/data-view}/setupCloserWhenSingleSelectionChange.js +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type OutputEmitterRef,
|
|
3
|
+
type Signal,
|
|
4
|
+
type WritableSignal,
|
|
5
|
+
inject,
|
|
6
|
+
} from "@angular/core";
|
|
7
|
+
import { SdToastProvider } from "../../core/providers/sd-toast.provider";
|
|
8
|
+
import { withBusy } from "../../core/utils/withBusy";
|
|
9
|
+
import type { ISelectModalOutputResult } from "../../core/types/select-modal-output-result";
|
|
10
|
+
|
|
11
|
+
export function useDataSheetModalEditManager<TItem, TKey>(options: {
|
|
12
|
+
busyCount: WritableSignal<number>;
|
|
13
|
+
canEdit: () => boolean;
|
|
14
|
+
selectedItemKeys: Signal<TKey[]>;
|
|
15
|
+
selectedItems: Signal<TItem[]>;
|
|
16
|
+
close: OutputEmitterRef<ISelectModalOutputResult<TItem>>;
|
|
17
|
+
refresh: () => Promise<void>;
|
|
18
|
+
getEditItemFn: () =>
|
|
19
|
+
| ((item?: TItem) => Promise<boolean | undefined> | boolean | undefined)
|
|
20
|
+
| undefined;
|
|
21
|
+
getToggleDeleteItemsFn: () =>
|
|
22
|
+
| ((del: boolean) => Promise<boolean>)
|
|
23
|
+
| undefined;
|
|
24
|
+
errorMessageFn: (err: unknown) => string;
|
|
25
|
+
}) {
|
|
26
|
+
const sdToast = inject(SdToastProvider);
|
|
27
|
+
|
|
28
|
+
async function doEditItem(item?: TItem): Promise<void> {
|
|
29
|
+
const editItemFn = options.getEditItemFn();
|
|
30
|
+
if (!editItemFn) return;
|
|
31
|
+
|
|
32
|
+
const result = await editItemFn(item);
|
|
33
|
+
if (!result) return;
|
|
34
|
+
|
|
35
|
+
await withBusy(options.busyCount, () =>
|
|
36
|
+
sdToast.try(async () => {
|
|
37
|
+
await options.refresh();
|
|
38
|
+
}),
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function doToggleDeleteItems(del: boolean): Promise<void> {
|
|
43
|
+
if (!options.canEdit()) return;
|
|
44
|
+
const toggleDeleteItemsFn = options.getToggleDeleteItemsFn();
|
|
45
|
+
if (!toggleDeleteItemsFn) return;
|
|
46
|
+
|
|
47
|
+
await withBusy(options.busyCount, () =>
|
|
48
|
+
sdToast.try(
|
|
49
|
+
async () => {
|
|
50
|
+
const result = await toggleDeleteItemsFn(del);
|
|
51
|
+
if (!result) return;
|
|
52
|
+
|
|
53
|
+
await options.refresh();
|
|
54
|
+
sdToast.success(`${del ? "삭제" : "복구"} 되었습니다.`);
|
|
55
|
+
},
|
|
56
|
+
(err) => options.errorMessageFn(err),
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function doModalConfirm(): void {
|
|
62
|
+
options.close.emit({
|
|
63
|
+
selectedItemKeys: options.selectedItemKeys(),
|
|
64
|
+
selectedItems: options.selectedItems(),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function doModalCancel(): void {
|
|
69
|
+
options.close.emit({
|
|
70
|
+
selectedItemKeys: [],
|
|
71
|
+
selectedItems: [],
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { doEditItem, doToggleDeleteItems, doModalConfirm, doModalCancel };
|
|
76
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { type Signal, type WritableSignal, effect, inject } from "@angular/core";
|
|
2
|
+
import { type ArrayOneWayDiffResult, obj } from "@simplysm/core-common";
|
|
3
|
+
import { SdToastProvider } from "../../core/providers/sd-toast.provider";
|
|
4
|
+
import { SdSharedDataProvider } from "../../core/providers/sd-shared-data.provider";
|
|
5
|
+
import { withBusy } from "../../core/utils/withBusy";
|
|
6
|
+
import type { ISdDataSheetSearchResult } from "./sd-data-sheet.types";
|
|
7
|
+
|
|
8
|
+
export function useDataSheetRefreshManager<
|
|
9
|
+
TItem,
|
|
10
|
+
TKey extends string | number | undefined,
|
|
11
|
+
>(options: {
|
|
12
|
+
busyCount: WritableSignal<number>;
|
|
13
|
+
initialized: WritableSignal<boolean>;
|
|
14
|
+
canUse: () => boolean;
|
|
15
|
+
items: WritableSignal<TItem[]>;
|
|
16
|
+
selectedItems: WritableSignal<TItem[]>;
|
|
17
|
+
pageLength: WritableSignal<number>;
|
|
18
|
+
summaryData: WritableSignal<Partial<TItem>>;
|
|
19
|
+
page: Signal<number>;
|
|
20
|
+
lastFilter: Signal<unknown>;
|
|
21
|
+
sortingDefs: Signal<unknown[]>;
|
|
22
|
+
getItemInfoFn: (item: TItem) => { key: TKey };
|
|
23
|
+
search: (
|
|
24
|
+
usePagination: boolean,
|
|
25
|
+
) => Promise<ISdDataSheetSearchResult<TItem>> | ISdDataSheetSearchResult<TItem>;
|
|
26
|
+
prepareRefreshEffect?: () => void;
|
|
27
|
+
getDiffsExcludes: () => string[] | undefined;
|
|
28
|
+
}) {
|
|
29
|
+
const sdToast = inject(SdToastProvider);
|
|
30
|
+
const sdSharedData = inject(SdSharedDataProvider);
|
|
31
|
+
let itemsSnapshot: TItem[] = [];
|
|
32
|
+
|
|
33
|
+
async function refresh(): Promise<void> {
|
|
34
|
+
const result = await options.search(true);
|
|
35
|
+
options.items.set(result.items);
|
|
36
|
+
itemsSnapshot = obj.clone(result.items);
|
|
37
|
+
|
|
38
|
+
options.pageLength.set(result.pageLength ?? 0);
|
|
39
|
+
options.summaryData.set(result.summary ?? {});
|
|
40
|
+
|
|
41
|
+
const selectedKeySet = new Set(
|
|
42
|
+
options.selectedItems().map((sel) => options.getItemInfoFn(sel).key),
|
|
43
|
+
);
|
|
44
|
+
options.selectedItems.set(
|
|
45
|
+
options.items().filter((item) => selectedKeySet.has(options.getItemInfoFn(item).key)),
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getDiffs(): ArrayOneWayDiffResult<TItem>[] {
|
|
50
|
+
const diffsExcludes = options.getDiffsExcludes();
|
|
51
|
+
return options
|
|
52
|
+
.items()
|
|
53
|
+
.oneWayDiffs(
|
|
54
|
+
itemsSnapshot,
|
|
55
|
+
(item) => options.getItemInfoFn(item).key,
|
|
56
|
+
diffsExcludes ? { excludes: diffsExcludes } : undefined,
|
|
57
|
+
)
|
|
58
|
+
.filter((d) => d.type !== "same");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
effect((onCleanup) => {
|
|
62
|
+
options.page();
|
|
63
|
+
options.lastFilter();
|
|
64
|
+
options.sortingDefs();
|
|
65
|
+
options.prepareRefreshEffect?.();
|
|
66
|
+
|
|
67
|
+
let cancelled = false;
|
|
68
|
+
onCleanup(() => {
|
|
69
|
+
cancelled = true;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
queueMicrotask(async () => {
|
|
73
|
+
if (cancelled) return;
|
|
74
|
+
if (!options.canUse()) {
|
|
75
|
+
options.initialized.set(true);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await withBusy(options.busyCount, () =>
|
|
80
|
+
sdToast.try(async () => {
|
|
81
|
+
await sdSharedData.wait();
|
|
82
|
+
await refresh();
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
options.initialized.set(true);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return { refresh, getDiffs };
|
|
90
|
+
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
ViewEncapsulation,
|
|
11
11
|
} from "@angular/core";
|
|
12
12
|
import { obj } from "@simplysm/core-common";
|
|
13
|
-
import type { ISdPermission } from "../../core/providers/sd-app-structure.
|
|
13
|
+
import type { ISdPermission } from "../../core/providers/sd-app-structure.types";
|
|
14
14
|
import { SdCheckboxControl } from "../../ui/form/checkbox/sd-checkbox.control";
|
|
15
15
|
import { SdCollapseIconControl } from "../../ui/navigation/collapse/sd-collapse-icon.control";
|
|
16
16
|
import { SdTypedTemplateDirective } from "../../core/directives/sd-typed-template.directive";
|
package/src/index.ts
CHANGED
|
@@ -32,14 +32,16 @@ export { SdAngularConfigProvider } from "./core/providers/sd-angular-config.prov
|
|
|
32
32
|
export { SdSystemLogProvider } from "./core/providers/sd-system-log.provider";
|
|
33
33
|
export {
|
|
34
34
|
SdAppStructureProvider,
|
|
35
|
-
SdAppStructureUtils,
|
|
36
35
|
usePermsSignal,
|
|
37
|
-
type TSdAppStructureItem,
|
|
38
|
-
type ISdMenu,
|
|
39
|
-
type ISdFlatMenu,
|
|
40
|
-
type ISdPermission,
|
|
41
|
-
type ISdFlatPermission,
|
|
42
36
|
} from "./core/providers/sd-app-structure.provider";
|
|
37
|
+
export { SdAppStructureUtils } from "./core/providers/sd-app-structure.utils";
|
|
38
|
+
export type {
|
|
39
|
+
TSdAppStructureItem,
|
|
40
|
+
ISdMenu,
|
|
41
|
+
ISdFlatMenu,
|
|
42
|
+
ISdPermission,
|
|
43
|
+
ISdFlatPermission,
|
|
44
|
+
} from "./core/providers/sd-app-structure.types";
|
|
43
45
|
export { SdFileDialogProvider } from "./core/providers/sd-file-dialog.provider";
|
|
44
46
|
export { SdLocalStorageProvider } from "./core/providers/sd-local-storage.provider";
|
|
45
47
|
export { SdSystemConfigProvider } from "./core/providers/sd-system-config.provider";
|
|
@@ -58,7 +60,7 @@ export { useViewTitleSignal } from "./core/utils/useViewTitleSignal";
|
|
|
58
60
|
export { useViewTypeSignal, type TSdViewType } from "./core/utils/useViewTypeSignal";
|
|
59
61
|
export { setupCanDeactivate } from "./core/utils/setups/setupCanDeactivate";
|
|
60
62
|
export { setupCumulateSelectedKeys } from "./core/utils/setups/setupCumulateSelectedKeys";
|
|
61
|
-
export { setupCloserWhenSingleSelectionChange } from "./
|
|
63
|
+
export { setupCloserWhenSingleSelectionChange } from "./features/data-view/setupCloserWhenSingleSelectionChange";
|
|
62
64
|
export {
|
|
63
65
|
useExpandingManager,
|
|
64
66
|
type IExpandItemDef,
|
|
@@ -100,6 +102,7 @@ export {
|
|
|
100
102
|
export { SdSharedDataSelectControl } from "./features/shared-data/sd-shared-data-select.control";
|
|
101
103
|
export { SdSharedDataSelectButtonControl } from "./features/shared-data/sd-shared-data-select-button.control";
|
|
102
104
|
export { SdSharedDataSelectListControl } from "./features/shared-data/sd-shared-data-select-list.control";
|
|
105
|
+
export { matchesSearchText } from "./features/shared-data/matchesSearchText";
|
|
103
106
|
|
|
104
107
|
// ui/layout
|
|
105
108
|
export { SdDockContainerControl } from "./ui/layout/dock/sd-dock-container.control";
|
|
@@ -125,9 +128,9 @@ export { SdAdditionalButtonControl } from "./ui/form/button/sd-additional-button
|
|
|
125
128
|
export {
|
|
126
129
|
SdModalSelectButtonControl,
|
|
127
130
|
type ISdSelectModal,
|
|
128
|
-
type ISelectModalOutputResult,
|
|
129
131
|
type TSdSelectModalInfo,
|
|
130
132
|
} from "./ui/form/button/sd-modal-select-button.control";
|
|
133
|
+
export type { ISelectModalOutputResult } from "./core/types/select-modal-output-result";
|
|
131
134
|
|
|
132
135
|
// ui/form/input
|
|
133
136
|
export { SdTextfieldControl } from "./ui/form/input/sd-textfield.control";
|
|
@@ -170,6 +173,9 @@ export { SdTabItemControl } from "./ui/navigation/tab/sd-tab-item.control";
|
|
|
170
173
|
export { SdTabviewControl } from "./ui/navigation/tab/sd-tabview.control";
|
|
171
174
|
export { SdTabviewItemControl } from "./ui/navigation/tab/sd-tabview-item.control";
|
|
172
175
|
|
|
176
|
+
// ui/navigation/menu
|
|
177
|
+
export { getMenuRouterLinkOption, getIsMenuSelected } from "./ui/navigation/menu-utils";
|
|
178
|
+
|
|
173
179
|
// ui/navigation/pagination
|
|
174
180
|
export { SdPaginationControl } from "./ui/navigation/pagination/sd-pagination.control";
|
|
175
181
|
|
|
@@ -223,11 +229,11 @@ export { SdDropdownPopupControl } from "./ui/overlay/dropdown/sd-dropdown-popup.
|
|
|
223
229
|
export { SdModalControl } from "./ui/overlay/modal/sd-modal.control";
|
|
224
230
|
export {
|
|
225
231
|
SdModalProvider,
|
|
226
|
-
SdActivatedModalProvider,
|
|
227
232
|
type ISdModal,
|
|
228
233
|
type ISdModalInfo,
|
|
229
234
|
type ISdModalOptions,
|
|
230
235
|
} from "./ui/overlay/modal/sd-modal.provider";
|
|
236
|
+
export { SdActivatedModalProvider } from "./core/providers/sd-activated-modal.provider";
|
|
231
237
|
export { SdPromptModalControl } from "./ui/overlay/modal/sd-prompt-modal.control";
|
|
232
238
|
export { SdConfirmModalControl } from "./ui/overlay/modal/sd-confirm-modal.control";
|
|
233
239
|
|
|
@@ -240,14 +246,14 @@ export {
|
|
|
240
246
|
type TSdToastTheme,
|
|
241
247
|
type ISdToast,
|
|
242
248
|
type ISdToastInput,
|
|
243
|
-
} from "./
|
|
249
|
+
} from "./core/providers/sd-toast.provider";
|
|
244
250
|
|
|
245
251
|
// ui/overlay/busy
|
|
246
252
|
export { SdBusyContainerControl } from "./ui/overlay/busy/sd-busy-container.control";
|
|
247
253
|
export {
|
|
248
254
|
SdBusyProvider,
|
|
249
255
|
type TSdBusyType,
|
|
250
|
-
} from "./
|
|
256
|
+
} from "./core/providers/sd-busy.provider";
|
|
251
257
|
|
|
252
258
|
// core/providers (integration)
|
|
253
259
|
export {
|
|
@@ -4,12 +4,10 @@ import {
|
|
|
4
4
|
Component,
|
|
5
5
|
computed,
|
|
6
6
|
contentChildren,
|
|
7
|
-
DestroyRef,
|
|
8
7
|
inject,
|
|
9
8
|
input,
|
|
10
9
|
model,
|
|
11
10
|
output,
|
|
12
|
-
signal,
|
|
13
11
|
ViewEncapsulation,
|
|
14
12
|
} from "@angular/core";
|
|
15
13
|
import { NgTemplateOutlet } from "@angular/common";
|
|
@@ -29,12 +27,10 @@ import { useSheetLayoutEngine } from "./useSheetLayoutEngine";
|
|
|
29
27
|
import { useSheetColumnFixing } from "./useSheetColumnFixing";
|
|
30
28
|
import { useSelectionManager } from "../../../core/utils/useSelectionManager";
|
|
31
29
|
import { useSortingManager, type ISortingDef } from "../../../core/utils/useSortingManager";
|
|
32
|
-
import { useExpandingManager } from "../../../core/utils/useExpandingManager";
|
|
33
30
|
import { SdPaginationControl } from "../../navigation/pagination/sd-pagination.control";
|
|
34
31
|
import { SdAnchorControl } from "../../form/button/sd-anchor.control";
|
|
35
32
|
import { SdButtonControl } from "../../form/button/sd-button.control";
|
|
36
33
|
import type {
|
|
37
|
-
ISdSheetColumnDef,
|
|
38
34
|
ISdSheetCellKeydownEventParam,
|
|
39
35
|
ISdSheetConfig,
|
|
40
36
|
ISdSheetHeaderDef,
|
|
@@ -43,6 +39,9 @@ import type {
|
|
|
43
39
|
import { useSdSystemConfigResource } from "../../../core/utils/useSdSystemConfigResource";
|
|
44
40
|
import { useSheetDomAccessor } from "./useSheetDomAccessor";
|
|
45
41
|
import { useSheetCellAgent } from "./useSheetCellAgent";
|
|
42
|
+
import { useSheetColumnResizing } from "./useSheetColumnResizing";
|
|
43
|
+
import { useSheetDisplayPipeline } from "./useSheetDisplayPipeline";
|
|
44
|
+
import { useSheetCellStyling } from "./useSheetCellStyling";
|
|
46
45
|
import { SdModalProvider } from "../../overlay/modal/sd-modal.provider";
|
|
47
46
|
import { SdSheetConfigModal } from "./sd-sheet-config.modal";
|
|
48
47
|
|
|
@@ -370,29 +369,26 @@ export class SdSheetControl<T> {
|
|
|
370
369
|
|
|
371
370
|
// Injected providers
|
|
372
371
|
private readonly _modalProvider = inject(SdModalProvider);
|
|
373
|
-
private readonly _destroyRef = inject(DestroyRef);
|
|
374
372
|
|
|
375
373
|
// DOM accessor & cell agent
|
|
376
374
|
domAccessor = useSheetDomAccessor();
|
|
377
375
|
cellAgent = useSheetCellAgent({ domAccessor: this.domAccessor });
|
|
378
376
|
|
|
379
|
-
constructor() {
|
|
380
|
-
this._destroyRef.onDestroy(() => {
|
|
381
|
-
this._resizingCleanup?.();
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// Resizing state
|
|
386
|
-
_isResizing = signal(false);
|
|
387
|
-
_resizeIndicatorLeft = signal(0);
|
|
388
|
-
private _lastResizeEndTimeStamp = 0;
|
|
389
|
-
private _resizingCleanup: (() => void) | null = null;
|
|
390
|
-
|
|
391
377
|
// Config resource
|
|
392
378
|
private readonly _configResource = useSdSystemConfigResource<ISdSheetConfig>({
|
|
393
379
|
key: this.key,
|
|
394
380
|
});
|
|
395
381
|
|
|
382
|
+
// Resizing composable
|
|
383
|
+
private readonly _resizing = useSheetColumnResizing({
|
|
384
|
+
domAccessor: this.domAccessor,
|
|
385
|
+
configResource: this._configResource,
|
|
386
|
+
});
|
|
387
|
+
_isResizing = this._resizing.isResizing;
|
|
388
|
+
_resizeIndicatorLeft = this._resizing.indicatorLeft;
|
|
389
|
+
onResizerMousedown = this._resizing.onMousedown;
|
|
390
|
+
onResizerDblClick = this._resizing.onDblClick;
|
|
391
|
+
|
|
396
392
|
// Layout engine
|
|
397
393
|
layout = useSheetLayoutEngine({
|
|
398
394
|
columnControls: this.columnControls,
|
|
@@ -409,67 +405,36 @@ export class SdSheetControl<T> {
|
|
|
409
405
|
sorts: this.sorts,
|
|
410
406
|
});
|
|
411
407
|
|
|
412
|
-
//
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
// Icons
|
|
422
|
-
icons = {
|
|
423
|
-
tablerArrowUp,
|
|
424
|
-
tablerArrowDown,
|
|
425
|
-
tablerChevronRight,
|
|
426
|
-
tablerChevronDown,
|
|
427
|
-
tablerChevronsRight,
|
|
428
|
-
tablerChevronsDown,
|
|
429
|
-
tablerSettings,
|
|
430
|
-
};
|
|
431
|
-
|
|
432
|
-
// Sorted items
|
|
433
|
-
private readonly _sortedItems = computed(() => {
|
|
434
|
-
const items = this.items();
|
|
435
|
-
if (this.useAutoSort()) {
|
|
436
|
-
return this.sorting.sort(items);
|
|
437
|
-
}
|
|
438
|
-
return items;
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
// Paged items (root-level only)
|
|
442
|
-
private readonly _pagedItems = computed(() => {
|
|
443
|
-
const items = this._sortedItems();
|
|
444
|
-
const perPage = this.itemsPerPage();
|
|
445
|
-
if (perPage <= 0) return items;
|
|
446
|
-
const page = this.currentPage();
|
|
447
|
-
const start = page * perPage;
|
|
448
|
-
return items.slice(start, start + perPage);
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
// Expanding manager
|
|
452
|
-
expanding = useExpandingManager<T>({
|
|
453
|
-
items: this._pagedItems,
|
|
408
|
+
// Display pipeline (sort → page → expand → display)
|
|
409
|
+
private readonly _pipeline = useSheetDisplayPipeline<T>({
|
|
410
|
+
items: this.items,
|
|
411
|
+
useAutoSort: this.useAutoSort,
|
|
412
|
+
sortItems: (items) => this.sorting.sort(items),
|
|
413
|
+
itemsPerPage: this.itemsPerPage,
|
|
414
|
+
currentPage: this.currentPage,
|
|
415
|
+
totalPageCount: this.totalPageCount,
|
|
454
416
|
expandedItems: this.expandedItems,
|
|
455
417
|
getChildrenFn: this.getChildrenFn,
|
|
456
|
-
sort: (items) => {
|
|
457
|
-
if (this.useAutoSort()) {
|
|
458
|
-
return this.sorting.sort(items);
|
|
459
|
-
}
|
|
460
|
-
return items;
|
|
461
|
-
},
|
|
462
418
|
});
|
|
419
|
+
effectivePageCount = this._pipeline.effectivePageCount;
|
|
420
|
+
expanding = this._pipeline.expanding;
|
|
421
|
+
displayItems = this._pipeline.displayItems;
|
|
463
422
|
|
|
464
|
-
//
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
423
|
+
// Cell styling composable
|
|
424
|
+
private readonly _styling = useSheetCellStyling<T>({
|
|
425
|
+
columnDefs: this.layout.columnDefs,
|
|
426
|
+
fixedLeftMap: this.fixing.fixedLeftMap,
|
|
427
|
+
getItemCellStyleFn: this.getItemCellStyleFn,
|
|
428
|
+
getItemCellClassFn: this.getItemCellClassFn,
|
|
429
|
+
getChildrenFn: this.getChildrenFn,
|
|
430
|
+
expandingDef: (item) => this.expanding.def(item),
|
|
431
|
+
isCellEditMode: (addr) => this.cellAgent.isCellEditMode(addr),
|
|
472
432
|
});
|
|
433
|
+
getHeaderCellStyle = this._styling.getHeaderCellStyle;
|
|
434
|
+
getCellStyle = this._styling.getCellStyle;
|
|
435
|
+
getFixedCellStyle = this._styling.getFixedCellStyle;
|
|
436
|
+
getCellStyleWithIndent = this._styling.getCellStyleWithIndent;
|
|
437
|
+
getDataCellClass = this._styling.getDataCellClass;
|
|
473
438
|
|
|
474
439
|
// Selection manager
|
|
475
440
|
selection = useSelectionManager<T>({
|
|
@@ -479,6 +444,17 @@ export class SdSheetControl<T> {
|
|
|
479
444
|
getItemSelectableFn: this.getItemSelectableFn,
|
|
480
445
|
});
|
|
481
446
|
|
|
447
|
+
// Icons
|
|
448
|
+
icons = {
|
|
449
|
+
tablerArrowUp,
|
|
450
|
+
tablerArrowDown,
|
|
451
|
+
tablerChevronRight,
|
|
452
|
+
tablerChevronDown,
|
|
453
|
+
tablerChevronsRight,
|
|
454
|
+
tablerChevronsDown,
|
|
455
|
+
tablerSettings,
|
|
456
|
+
};
|
|
457
|
+
|
|
482
458
|
private readonly _columnControlMap = computed(() => {
|
|
483
459
|
const map = new Map<string, SdSheetColumnDirective>();
|
|
484
460
|
for (const col of this.columnControls()) {
|
|
@@ -497,51 +473,6 @@ export class SdSheetControl<T> {
|
|
|
497
473
|
return col?.summaryTplRef() ?? null;
|
|
498
474
|
}
|
|
499
475
|
|
|
500
|
-
// Pre-computed column styles: header/footer (fixed z-index:3)
|
|
501
|
-
private readonly _headerColumnStyles = computed(() => {
|
|
502
|
-
const map = new Map<string, string | null>();
|
|
503
|
-
for (const colDef of this.layout.columnDefs()) {
|
|
504
|
-
const parts: string[] = [];
|
|
505
|
-
const colStyle = this._getColDefStyle(colDef);
|
|
506
|
-
if (colStyle != null) parts.push(colStyle);
|
|
507
|
-
const fixedStyle = this._getFixedStyle(colDef, 3, "var(--theme-secondary-lightest)");
|
|
508
|
-
if (fixedStyle != null) parts.push(fixedStyle);
|
|
509
|
-
map.set(colDef.key, parts.length > 0 ? parts.join("; ") : null);
|
|
510
|
-
}
|
|
511
|
-
return map;
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
// Pre-computed column styles: body (fixed z-index:1)
|
|
515
|
-
private readonly _dataColumnBaseStyles = computed(() => {
|
|
516
|
-
const map = new Map<string, string | null>();
|
|
517
|
-
for (const colDef of this.layout.columnDefs()) {
|
|
518
|
-
const parts: string[] = [];
|
|
519
|
-
const colStyle = this._getColDefStyle(colDef);
|
|
520
|
-
if (colStyle != null) parts.push(colStyle);
|
|
521
|
-
const fixedStyle = this._getFixedStyle(colDef);
|
|
522
|
-
if (fixedStyle != null) parts.push(fixedStyle);
|
|
523
|
-
map.set(colDef.key, parts.length > 0 ? parts.join("; ") : null);
|
|
524
|
-
}
|
|
525
|
-
return map;
|
|
526
|
-
});
|
|
527
|
-
|
|
528
|
-
getHeaderCellStyle(cell: ISdSheetHeaderDef) {
|
|
529
|
-
if (cell.colDef == null) return null;
|
|
530
|
-
return this._headerColumnStyles().get(cell.colDef.key) ?? null;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
getCellStyle(item: T, colDef: ISdSheetColumnDef) {
|
|
534
|
-
const baseStyle = this._dataColumnBaseStyles().get(colDef.key) ?? null;
|
|
535
|
-
const styleFn = this.getItemCellStyleFn();
|
|
536
|
-
const customStyle = styleFn != null ? styleFn(item, colDef.key) : undefined;
|
|
537
|
-
if (baseStyle != null && customStyle != null) return `${baseStyle}; ${customStyle}`;
|
|
538
|
-
return customStyle ?? baseStyle ?? null;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
getFixedCellStyle(colDef: ISdSheetColumnDef) {
|
|
542
|
-
return this._getFixedStyle(colDef, 3);
|
|
543
|
-
}
|
|
544
|
-
|
|
545
476
|
getSelectableTooltip(item: T): string | null {
|
|
546
477
|
const result = this.selection.getSelectable(item);
|
|
547
478
|
if (typeof result === "string") return result;
|
|
@@ -572,7 +503,7 @@ export class SdSheetControl<T> {
|
|
|
572
503
|
}
|
|
573
504
|
|
|
574
505
|
onHeaderClick(event: MouseEvent, cell: ISdSheetHeaderDef): void {
|
|
575
|
-
if (event.timeStamp - this.
|
|
506
|
+
if (event.timeStamp - this._resizing.lastResizeEndTimeStamp() < 50) return;
|
|
576
507
|
if (cell.colDef == null) return;
|
|
577
508
|
if (cell.colDef.disableSorting) return;
|
|
578
509
|
this.sorting.toggle(cell.colDef.key, event.shiftKey);
|
|
@@ -582,22 +513,6 @@ export class SdSheetControl<T> {
|
|
|
582
513
|
return this.sorting.defMap().get(key) ?? null;
|
|
583
514
|
}
|
|
584
515
|
|
|
585
|
-
getCellStyleWithIndent(item: T, colDef: ISdSheetColumnDef, colIdx: number) {
|
|
586
|
-
const parts: string[] = [];
|
|
587
|
-
const cellStyle = this.getCellStyle(item, colDef);
|
|
588
|
-
if (cellStyle != null) {
|
|
589
|
-
parts.push(cellStyle);
|
|
590
|
-
}
|
|
591
|
-
// Add indent for tree depth on first data column
|
|
592
|
-
if (colIdx === 0 && this.getChildrenFn() != null) {
|
|
593
|
-
const itemDef = this.getItemDef(item);
|
|
594
|
-
if (itemDef.depth > 0) {
|
|
595
|
-
parts.push(`padding-left: calc(var(--gap-default) + ${itemDef.depth}em)`);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
return parts.length > 0 ? parts.join("; ") : null;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
516
|
getItemDef(item: T) {
|
|
602
517
|
return this.expanding.def(item);
|
|
603
518
|
}
|
|
@@ -628,41 +543,6 @@ export class SdSheetControl<T> {
|
|
|
628
543
|
return sortDef.desc ? "descending" : "ascending";
|
|
629
544
|
}
|
|
630
545
|
|
|
631
|
-
private _getColDefStyle(colDef: { width: string | undefined; collapse: boolean }): string | null {
|
|
632
|
-
if (colDef.collapse) {
|
|
633
|
-
return "padding: 0; width: 0; min-width: 0; max-width: 0; overflow: hidden; border: none";
|
|
634
|
-
}
|
|
635
|
-
if (colDef.width != null) {
|
|
636
|
-
return `width: ${colDef.width}; min-width: ${colDef.width}; max-width: ${colDef.width}`;
|
|
637
|
-
}
|
|
638
|
-
return null;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
private _getFixedStyle(
|
|
642
|
-
colDef: ISdSheetColumnDef,
|
|
643
|
-
zIndex: number = 1,
|
|
644
|
-
background: string = "var(--control-color)",
|
|
645
|
-
): string | null {
|
|
646
|
-
const fixedLeftMap = this.fixing.fixedLeftMap();
|
|
647
|
-
const leftValue = fixedLeftMap.get(colDef.key);
|
|
648
|
-
if (leftValue == null) return null;
|
|
649
|
-
|
|
650
|
-
return `position: sticky; left: ${leftValue}px; z-index: ${zIndex}; background: ${background}`;
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
getDataCellClass(item: T, colDef: ISdSheetColumnDef, r: number, c: number): string | null {
|
|
654
|
-
const parts: string[] = [];
|
|
655
|
-
const classFn = this.getItemCellClassFn();
|
|
656
|
-
const customClass = classFn != null ? classFn(item, colDef.key) : undefined;
|
|
657
|
-
if (customClass != null) {
|
|
658
|
-
parts.push(customClass);
|
|
659
|
-
}
|
|
660
|
-
if (this.cellAgent.isCellEditMode({ r, c })) {
|
|
661
|
-
parts.push("_edit-mode");
|
|
662
|
-
}
|
|
663
|
-
return parts.length > 0 ? parts.join(" ") : null;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
546
|
async onKeydownCapture(event: Event): Promise<void> {
|
|
667
547
|
await this.cellAgent.handleKeydownCapture(event as KeyboardEvent);
|
|
668
548
|
}
|
|
@@ -699,74 +579,6 @@ export class SdSheetControl<T> {
|
|
|
699
579
|
}
|
|
700
580
|
}
|
|
701
581
|
|
|
702
|
-
// --- Resizing ---
|
|
703
|
-
|
|
704
|
-
onResizerMousedown(event: MouseEvent, colDef: ISdSheetColumnDef): void {
|
|
705
|
-
event.preventDefault();
|
|
706
|
-
event.stopPropagation();
|
|
707
|
-
|
|
708
|
-
const container = this.domAccessor.getContainer();
|
|
709
|
-
const startX = event.clientX;
|
|
710
|
-
const th = (event.target as HTMLElement).parentElement as HTMLElement;
|
|
711
|
-
const startWidth = th.offsetWidth;
|
|
712
|
-
|
|
713
|
-
this._isResizing.set(true);
|
|
714
|
-
this._resizeIndicatorLeft.set(
|
|
715
|
-
th.offsetLeft + th.offsetWidth - container.scrollLeft,
|
|
716
|
-
);
|
|
717
|
-
|
|
718
|
-
const onMouseMove = (e: MouseEvent) => {
|
|
719
|
-
const deltaX = e.clientX - startX;
|
|
720
|
-
const newWidth = Math.max(startWidth + deltaX, 5);
|
|
721
|
-
this._resizeIndicatorLeft.set(
|
|
722
|
-
th.offsetLeft + newWidth - container.scrollLeft,
|
|
723
|
-
);
|
|
724
|
-
};
|
|
725
|
-
|
|
726
|
-
const onMouseUp = (e: MouseEvent) => {
|
|
727
|
-
document.removeEventListener("mousemove", onMouseMove);
|
|
728
|
-
document.removeEventListener("mouseup", onMouseUp);
|
|
729
|
-
this._resizingCleanup = null;
|
|
730
|
-
|
|
731
|
-
const deltaX = e.clientX - startX;
|
|
732
|
-
const newWidth = Math.max(startWidth + deltaX, 5);
|
|
733
|
-
|
|
734
|
-
this._isResizing.set(false);
|
|
735
|
-
this._saveColumnConfig(colDef.key, { width: `${newWidth}px` });
|
|
736
|
-
|
|
737
|
-
this._lastResizeEndTimeStamp = e.timeStamp;
|
|
738
|
-
};
|
|
739
|
-
|
|
740
|
-
document.addEventListener("mousemove", onMouseMove);
|
|
741
|
-
document.addEventListener("mouseup", onMouseUp);
|
|
742
|
-
this._resizingCleanup = () => {
|
|
743
|
-
document.removeEventListener("mousemove", onMouseMove);
|
|
744
|
-
document.removeEventListener("mouseup", onMouseUp);
|
|
745
|
-
};
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
onResizerDblClick(event: MouseEvent, colDef: ISdSheetColumnDef): void {
|
|
749
|
-
event.preventDefault();
|
|
750
|
-
event.stopPropagation();
|
|
751
|
-
|
|
752
|
-
// Remove the width from config to reset to column definition default
|
|
753
|
-
const current = this._configResource.value() ?? { columnRecord: {} };
|
|
754
|
-
const columnRecord = { ...current.columnRecord };
|
|
755
|
-
const colConfig = { ...columnRecord[colDef.key] };
|
|
756
|
-
delete colConfig.width;
|
|
757
|
-
columnRecord[colDef.key] = colConfig;
|
|
758
|
-
this._configResource.set({ ...current, columnRecord });
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
private _saveColumnConfig(
|
|
762
|
-
colKey: string,
|
|
763
|
-
changes: Partial<ISdSheetConfig["columnRecord"][string]>,
|
|
764
|
-
): void {
|
|
765
|
-
const current = this._configResource.value() ?? { columnRecord: {} };
|
|
766
|
-
const columnRecord = { ...current.columnRecord };
|
|
767
|
-
columnRecord[colKey] = { ...columnRecord[colKey], ...changes };
|
|
768
|
-
this._configResource.set({ ...current, columnRecord });
|
|
769
|
-
}
|
|
770
582
|
}
|
|
771
583
|
|
|
772
584
|
// Re-export ISortingDef from useSortingManager for convenience
|