@simplysm/angular 14.0.49 → 14.0.52

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 (50) hide show
  1. package/dist/controls/select/sd-select.js +3 -3
  2. package/dist/data/sheet/sd-sheet.d.ts +9 -12
  3. package/dist/data/sheet/sd-sheet.d.ts.map +1 -1
  4. package/dist/data/sheet/sd-sheet.js +150 -168
  5. package/dist/data/sheet/types.d.ts +1 -0
  6. package/dist/data/sheet/types.d.ts.map +1 -1
  7. package/dist/data/sheet/useSheetCellStyling.d.ts +2 -2
  8. package/dist/data/sheet/useSheetCellStyling.d.ts.map +1 -1
  9. package/dist/data/sheet/useSheetCellStyling.js +20 -12
  10. package/dist/data/sheet/useSheetColumnFixing.d.ts +3 -8
  11. package/dist/data/sheet/useSheetColumnFixing.d.ts.map +1 -1
  12. package/dist/data/sheet/useSheetColumnFixing.js +19 -27
  13. package/dist/data/sheet/useSheetLayoutEngine.d.ts.map +1 -1
  14. package/dist/data/sheet/useSheetLayoutEngine.js +4 -1
  15. package/dist/layout/dock/sd-dock-container.d.ts.map +1 -1
  16. package/dist/layout/dock/sd-dock-container.js +4 -4
  17. package/package.json +7 -8
  18. package/src/controls/select/sd-select.ts +3 -3
  19. package/src/core/modal/sd-modal.provider.ts +1 -1
  20. package/src/core/modal/sd-modal.ts +1 -1
  21. package/src/core/routing/menu-utils.ts +1 -1
  22. package/src/core/shared-data/sd-shared-data.provider.ts +7 -7
  23. package/src/data/shared-data/sd-shared-data-select.ts +2 -2
  24. package/src/data/sheet/sd-sheet.ts +39 -60
  25. package/src/data/sheet/types.ts +1 -0
  26. package/src/data/sheet/useSheetCellStyling.ts +19 -11
  27. package/src/data/sheet/useSheetColumnFixing.ts +21 -28
  28. package/src/data/sheet/useSheetLayoutEngine.ts +4 -1
  29. package/src/layout/dock/sd-dock-container.ts +2 -1
  30. package/README.md +0 -467
  31. package/docs/bootstrap.md +0 -38
  32. package/docs/directives.md +0 -236
  33. package/docs/features.md +0 -154
  34. package/docs/pipes.md +0 -32
  35. package/docs/plugins.md +0 -37
  36. package/docs/provider-types.md +0 -283
  37. package/docs/providers.md +0 -379
  38. package/docs/recipes/crud-detail.md +0 -875
  39. package/docs/recipes/crud-list.md +0 -1037
  40. package/docs/recipes/data-select-button.md +0 -318
  41. package/docs/recipes/page-modal-container.md +0 -178
  42. package/docs/styling.md +0 -222
  43. package/docs/type-utilities.md +0 -250
  44. package/docs/ui-data.md +0 -333
  45. package/docs/ui-form.md +0 -502
  46. package/docs/ui-layout.md +0 -140
  47. package/docs/ui-navigation.md +0 -303
  48. package/docs/ui-overlay.md +0 -157
  49. package/docs/ui-visual.md +0 -127
  50. package/docs/utils.md +0 -244
@@ -17,6 +17,7 @@ export interface SdSheetHeaderDef {
17
17
  rowspan: number;
18
18
  isLastRow: boolean;
19
19
  colDef: SdSheetColumnDef | undefined;
20
+ colIndex: number;
20
21
  }
21
22
  export interface SdSheetConfig {
22
23
  columnRecord: Record<string, {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/data/sheet/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;CACtC;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAClB,MAAM,EACN;QACE,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CACF,CAAC;CACH;AAED,MAAM,WAAW,4BAA4B,CAAC,CAAC;IAC7C,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,4BAA4B,CAAC,CAAC;IAC7C,IAAI,EAAE,CAAC,CAAC;IACR,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,aAAa,CAAC;CACtB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/data/sheet/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACrC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAClB,MAAM,EACN;QACE,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CACF,CAAC;CACH;AAED,MAAM,WAAW,4BAA4B,CAAC,CAAC;IAC7C,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,4BAA4B,CAAC,CAAC;IAC7C,IAAI,EAAE,CAAC,CAAC;IACR,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,aAAa,CAAC;CACtB"}
@@ -3,7 +3,7 @@ import type { SdSheetColumnDef, SdSheetHeaderDef } from "./types";
3
3
  import type { ExpandItemDef } from "../../core/selection/useExpandingManager";
4
4
  export declare function useSheetCellStyling<T>(options: {
5
5
  columnDefs: Signal<SdSheetColumnDef[]>;
6
- fixedLeftMap: Signal<Map<string, number>>;
6
+ fixedLeftMap: Signal<Map<number, number>>;
7
7
  getItemCellStyleFn: Signal<((item: T, colKey: string) => string | undefined) | undefined>;
8
8
  getItemCellClassFn: Signal<((item: T, colKey: string) => string) | undefined>;
9
9
  getChildrenFn: Signal<((item: T, index: number) => T[] | undefined) | undefined>;
@@ -15,7 +15,7 @@ export declare function useSheetCellStyling<T>(options: {
15
15
  }): {
16
16
  getHeaderCellStyle: (cell: SdSheetHeaderDef) => string | null;
17
17
  getCellStyle: (item: T, colDef: SdSheetColumnDef) => string | null;
18
- getFixedCellStyle: (colDef: SdSheetColumnDef) => string | null;
18
+ getFixedCellStyle: (colIdx: number) => string | null;
19
19
  getCellStyleWithIndent: (item: T, colDef: SdSheetColumnDef, colIdx: number) => string | null;
20
20
  getDataCellClass: (item: T, colDef: SdSheetColumnDef, r: number, c: number) => string | null;
21
21
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useSheetCellStyling.d.ts","sourceRoot":"","sources":["../../../src/data/sheet/useSheetCellStyling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAE9E,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE;IAC9C,UAAU,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACvC,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;IAC1F,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC;IAC9E,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC,EAAE,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;IACjF,YAAY,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC;IAC5C,cAAc,EAAE,CAAC,IAAI,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;CAC7D;+BA4CmC,gBAAgB,KAAG,MAAM,GAAG,IAAI;yBAStC,CAAC,UAAU,gBAAgB,KAAG,MAAM,GAAG,IAAI;gCAQpC,gBAAgB,KAAG,MAAM,GAAG,IAAI;mCAI7B,CAAC,UAAU,gBAAgB,UAAU,MAAM,KAAG,MAAM,GAAG,IAAI;6BAejE,CAAC,UAAU,gBAAgB,KAAK,MAAM,KAAK,MAAM,KAAG,MAAM,GAAG,IAAI;EAoBlG"}
1
+ {"version":3,"file":"useSheetCellStyling.d.ts","sourceRoot":"","sources":["../../../src/data/sheet/useSheetCellStyling.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAE9E,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE;IAC9C,UAAU,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACvC,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;IAC1F,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC;IAC9E,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC,EAAE,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC;IACjF,YAAY,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC;IAC5C,cAAc,EAAE,CAAC,IAAI,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;CAC7D;+BAoDmC,gBAAgB,KAAG,MAAM,GAAG,IAAI;yBAStC,CAAC,UAAU,gBAAgB,KAAG,MAAM,GAAG,IAAI;gCAQpC,MAAM,KAAG,MAAM,GAAG,IAAI;mCAInB,CAAC,UAAU,gBAAgB,UAAU,MAAM,KAAG,MAAM,GAAG,IAAI;6BAejE,CAAC,UAAU,gBAAgB,KAAK,MAAM,KAAK,MAAM,KAAG,MAAM,GAAG,IAAI;EAoBlG"}
@@ -9,36 +9,44 @@ export function useSheetCellStyling(options) {
9
9
  }
10
10
  return null;
11
11
  }
12
- function getFixedStyle(colDef) {
13
- const leftValue = options.fixedLeftMap().get(colDef.key);
12
+ function getFixedLeftStyle(colIdx) {
13
+ const leftValue = options.fixedLeftMap().get(colIdx);
14
14
  if (leftValue == null)
15
15
  return null;
16
16
  return `left: ${leftValue}px`;
17
17
  }
18
18
  const headerColumnStyles = computed(() => {
19
19
  const map = new Map();
20
- for (const colDef of options.columnDefs()) {
20
+ const defs = options.columnDefs();
21
+ for (let i = 0; i < defs.length; i++) {
22
+ const colDef = defs[i];
21
23
  const parts = [];
22
24
  const colStyle = getColDefStyle(colDef);
23
25
  if (colStyle != null)
24
26
  parts.push(colStyle);
25
- const fixedStyle = getFixedStyle(colDef);
26
- if (fixedStyle != null)
27
- parts.push(fixedStyle);
27
+ if (colDef.fixed) {
28
+ const fixedStyle = getFixedLeftStyle(i);
29
+ if (fixedStyle != null)
30
+ parts.push(fixedStyle);
31
+ }
28
32
  map.set(colDef.key, parts.length > 0 ? parts.join("; ") : null);
29
33
  }
30
34
  return map;
31
35
  }, ...(ngDevMode ? [{ debugName: "headerColumnStyles" }] : /* istanbul ignore next */ []));
32
36
  const dataColumnBaseStyles = computed(() => {
33
37
  const map = new Map();
34
- for (const colDef of options.columnDefs()) {
38
+ const defs = options.columnDefs();
39
+ for (let i = 0; i < defs.length; i++) {
40
+ const colDef = defs[i];
35
41
  const parts = [];
36
42
  const colStyle = getColDefStyle(colDef);
37
43
  if (colStyle != null)
38
44
  parts.push(colStyle);
39
- const fixedStyle = getFixedStyle(colDef);
40
- if (fixedStyle != null)
41
- parts.push(fixedStyle);
45
+ if (colDef.fixed) {
46
+ const fixedStyle = getFixedLeftStyle(i);
47
+ if (fixedStyle != null)
48
+ parts.push(fixedStyle);
49
+ }
42
50
  map.set(colDef.key, parts.length > 0 ? parts.join("; ") : null);
43
51
  }
44
52
  return map;
@@ -62,8 +70,8 @@ export function useSheetCellStyling(options) {
62
70
  return `${baseStyle}; ${customStyle}`;
63
71
  return customStyle ?? baseStyle ?? null;
64
72
  }
65
- function getFixedCellStyle(colDef) {
66
- return getFixedStyle(colDef);
73
+ function getFixedCellStyle(colIdx) {
74
+ return getFixedLeftStyle(colIdx);
67
75
  }
68
76
  function getCellStyleWithIndent(item, colDef, colIdx) {
69
77
  const parts = [];
@@ -1,15 +1,10 @@
1
1
  import { type Signal } from "@angular/core";
2
2
  import type { SdSheetColumnDef } from "./types";
3
- /**
4
- * Fixed column의 left offset을 계산한다.
5
- *
6
- * **주의:** fixed column의 `width`는 반드시 px 단위여야 정확한 offset이 계산된다.
7
- * em, rem, % 등 non-px 단위의 width는 offset 누적에 반영되지 않는다 (0으로 처리).
8
- */
9
3
  export declare function useSheetColumnFixing(options: {
10
4
  columnDefs: Signal<SdSheetColumnDef[]>;
5
+ cellWidths: Signal<Map<number, number>>;
6
+ hasExpandable: Signal<boolean>;
11
7
  }): {
12
- fixedLeftMap: Signal<Map<string, number>>;
13
- hasFixed: Signal<boolean>;
8
+ fixedLeftMap: Signal<Map<number, number>>;
14
9
  };
15
10
  //# sourceMappingURL=useSheetColumnFixing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSheetColumnFixing.d.ts","sourceRoot":"","sources":["../../../src/data/sheet/useSheetColumnFixing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,UAAU,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;CACxC;;;EA+BA"}
1
+ {"version":3,"file":"useSheetColumnFixing.d.ts","sourceRoot":"","sources":["../../../src/data/sheet/useSheetColumnFixing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,UAAU,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACvC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;CAChC;;EA4BA"}
@@ -1,35 +1,27 @@
1
1
  import { computed } from "@angular/core";
2
- /**
3
- * Fixed column의 left offset을 계산한다.
4
- *
5
- * **주의:** fixed column의 `width`는 반드시 px 단위여야 정확한 offset이 계산된다.
6
- * em, rem, % 등 non-px 단위의 width는 offset 누적에 반영되지 않는다 (0으로 처리).
7
- */
8
2
  export function useSheetColumnFixing(options) {
9
3
  const fixedLeftMap = computed(() => {
10
- const map = new Map();
11
- let accumulatedLeft = 0;
12
- for (const colDef of options.columnDefs()) {
13
- if (!colDef.fixed)
14
- continue;
15
- if (colDef.collapse)
16
- continue;
17
- map.set(colDef.key, accumulatedLeft);
18
- const width = colDef.width;
19
- if (width != null && width.endsWith("px")) {
20
- const px = parseFloat(width);
21
- if (!Number.isNaN(px)) {
22
- accumulatedLeft += px;
23
- }
4
+ const widths = options.cellWidths();
5
+ const fixedIndices = [];
6
+ if (options.hasExpandable()) {
7
+ fixedIndices.push(-2, -1);
8
+ }
9
+ else {
10
+ fixedIndices.push(-1);
11
+ }
12
+ const defs = options.columnDefs();
13
+ for (let i = 0; i < defs.length; i++) {
14
+ if (defs[i].fixed && !defs[i].collapse) {
15
+ fixedIndices.push(i);
24
16
  }
25
17
  }
18
+ const map = new Map();
19
+ let accLeft = 0;
20
+ for (const idx of fixedIndices) {
21
+ map.set(idx, accLeft);
22
+ accLeft += widths.get(idx) ?? 0;
23
+ }
26
24
  return map;
27
25
  }, ...(ngDevMode ? [{ debugName: "fixedLeftMap" }] : /* istanbul ignore next */ []));
28
- const hasFixed = computed(() => {
29
- return fixedLeftMap().size > 0;
30
- }, ...(ngDevMode ? [{ debugName: "hasFixed" }] : /* istanbul ignore next */ []));
31
- return {
32
- fixedLeftMap,
33
- hasFixed,
34
- };
26
+ return { fixedLeftMap };
35
27
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useSheetLayoutEngine.d.ts","sourceRoot":"","sources":["../../../src/data/sheet/useSheetLayoutEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEjF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,cAAc,EAAE,MAAM,CAAC,SAAS,aAAa,EAAE,CAAC,CAAC;IACjD,MAAM,EAAE,MAAM,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;CAC3C;;;;;;EA0IA"}
1
+ {"version":3,"file":"useSheetLayoutEngine.d.ts","sourceRoot":"","sources":["../../../src/data/sheet/useSheetLayoutEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEjF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,cAAc,EAAE,MAAM,CAAC,SAAS,aAAa,EAAE,CAAC,CAAC;IACjD,MAAM,EAAE,MAAM,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;CAC3C;;;;;;EA6IA"}
@@ -46,7 +46,8 @@ export function useSheetLayoutEngine(options) {
46
46
  }
47
47
  // Track the header array of the first column in each cell span per row
48
48
  const spanStartHeaders = new Array(depth);
49
- for (const colDef of cols) {
49
+ for (let colIdx = 0; colIdx < cols.length; colIdx++) {
50
+ const colDef = cols[colIdx];
50
51
  const headers = Array.isArray(colDef.header)
51
52
  ? colDef.header
52
53
  : [colDef.header];
@@ -61,6 +62,7 @@ export function useSheetLayoutEngine(options) {
61
62
  rowspan,
62
63
  isLastRow: true,
63
64
  colDef,
65
+ colIndex: colIdx,
64
66
  });
65
67
  spanStartHeaders[row] = headers;
66
68
  break;
@@ -108,6 +110,7 @@ export function useSheetLayoutEngine(options) {
108
110
  rowspan: 1,
109
111
  isLastRow,
110
112
  colDef: isLastRow ? colDef : undefined,
113
+ colIndex: colIdx,
111
114
  });
112
115
  spanStartHeaders[row] = headers;
113
116
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sd-dock-container.d.ts","sourceRoot":"","sources":["../../../src/layout/dock/sd-dock-container.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,UAAU,EAIX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;;AAEnC,qBAyBa,eAAe;IAC1B,YAAY,oDAA2B;IAEvC,YAAY,6DAET;IAEH,YAAY,0DAAmB;;yCAPpB,eAAe;2CAAf,eAAe;CA8D3B"}
1
+ {"version":3,"file":"sd-dock-container.d.ts","sourceRoot":"","sources":["../../../src/layout/dock/sd-dock-container.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,UAAU,EAIX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;;AAEnC,qBA0Ba,eAAe;IAC1B,YAAY,oDAA2B;IAEvC,YAAY,6DAET;IAEH,YAAY,0DAAmB;;yCAPpB,eAAe;2CAAf,eAAe;CA8D3B"}
@@ -81,16 +81,16 @@ export class SdDockContainer {
81
81
  i0.ɵɵdomElementEnd();
82
82
  } if (rf & 2) {
83
83
  i0.ɵɵclassMap(i0.ɵɵpureFunction1(3, _c2, ctx.contentClass()).filter(i0.ɵɵarrowFunction(2, arrowFn0, ctx)).join(" "));
84
- } }, styles: ["sd-dock-container {\n display: block;\n height: 100%;\n}\nsd-dock-container > ._content {\n position: relative;\n height: 100%;\n}"], encapsulation: 2, changeDetection: 0 });
84
+ } }, styles: ["sd-dock-container {\n display: block;\n height: 100%;\n overflow: auto;\n}\nsd-dock-container > ._content {\n position: relative;\n height: 100%;\n}"], encapsulation: 2, changeDetection: 0 });
85
85
  }
86
86
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SdDockContainer, [{
87
87
  type: Component,
88
88
  args: [{ selector: "sd-dock-container", changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, standalone: true, imports: [], template: `
89
- <div #content [class]="['_content', contentClass()].filter(v => v != null).join(' ')">
89
+ <div #content [class]="['_content', contentClass()].filter((v) => v != null).join(' ')">
90
90
  <ng-content />
91
91
  </div>
92
- `, styles: ["sd-dock-container {\n display: block;\n height: 100%;\n}\nsd-dock-container > ._content {\n position: relative;\n height: 100%;\n}"] }]
92
+ `, styles: ["sd-dock-container {\n display: block;\n height: 100%;\n overflow: auto;\n}\nsd-dock-container > ._content {\n position: relative;\n height: 100%;\n}"] }]
93
93
  }], () => [], { dockControls: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdDock), { isSignal: true }] }], contentElRef: [{ type: i0.ViewChild, args: ["content", { ...{
94
94
  read: ElementRef,
95
95
  }, isSignal: true }] }], contentClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentClass", required: false }] }] }); })();
96
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SdDockContainer, { className: "SdDockContainer", filePath: "packages/angular/src/layout/dock/sd-dock-container.ts", lineNumber: 38 }); })();
96
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SdDockContainer, { className: "SdDockContainer", filePath: "packages/angular/src/layout/dock/sd-dock-container.ts", lineNumber: 39 }); })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/angular",
3
- "version": "14.0.49",
3
+ "version": "14.0.52",
4
4
  "description": "심플리즘 패키지 - Angular",
5
5
  "author": "심플리즘",
6
6
  "license": "Apache-2.0",
@@ -16,8 +16,7 @@
16
16
  "files": [
17
17
  "dist",
18
18
  "src",
19
- "scss",
20
- "docs"
19
+ "scss"
21
20
  ],
22
21
  "sideEffects": [
23
22
  "./src/index.ts",
@@ -45,16 +44,16 @@
45
44
  "@tiptap/extension-text-style": "^3.22.4",
46
45
  "@tiptap/extension-underline": "^3.22.4",
47
46
  "@tiptap/starter-kit": "^3.22.4",
48
- "bwip-js": "^4.9.2",
47
+ "bwip-js": "^4.10.1",
49
48
  "echarts": "^6.0.0",
50
49
  "html-to-image": "^1.11.13",
51
50
  "jspdf": "^4.2.1",
52
51
  "rxjs": "^7.8.2",
53
52
  "tabbable": "^6.4.0",
54
- "@simplysm/core-browser": "14.0.49",
55
- "@simplysm/core-common": "14.0.49",
56
- "@simplysm/service-client": "14.0.49",
57
- "@simplysm/service-common": "14.0.49"
53
+ "@simplysm/core-browser": "14.0.52",
54
+ "@simplysm/core-common": "14.0.52",
55
+ "@simplysm/service-client": "14.0.52",
56
+ "@simplysm/service-common": "14.0.52"
58
57
  },
59
58
  "devDependencies": {
60
59
  "@angular/compiler": "^21.2.9",
@@ -372,12 +372,12 @@ export class SdSelect<M extends "single" | "multi", T> {
372
372
  const currentValue = this.value();
373
373
 
374
374
  if (this.selectMode() === "multi") {
375
- const arr = currentValue as T[] | undefined;
376
- if (arr == null || arr.length === 0) {
375
+ if (!Array.isArray(currentValue) || currentValue.length === 0) {
377
376
  this._selectedItemContentHTML.set(undefined);
378
377
  return;
379
378
  }
380
379
 
380
+ const arr: T[] = currentValue;
381
381
  const selectedItems = untracked(() => items.filter((item) => arr.includes(item.value())));
382
382
 
383
383
  const isVertical = this.multiSelectionDisplayDirection() === "vertical";
@@ -429,7 +429,7 @@ export class SdSelect<M extends "single" | "multi", T> {
429
429
  this.value.set(itemValue);
430
430
  } else {
431
431
  this.value.update((v) => {
432
- const arr = (v as T[] | undefined) ?? [];
432
+ const arr: T[] = Array.isArray(v) ? v : [];
433
433
  if (arr.includes(itemValue as T)) {
434
434
  return arr.filter((item) => item !== itemValue);
435
435
  } else {
@@ -112,7 +112,7 @@ export class SdModalProvider {
112
112
  }
113
113
 
114
114
  // 4. setInput으로 inputs 바인딩
115
- for (const [key, value] of Object.entries(modal.inputs as Record<string, unknown>)) {
115
+ for (const [key, value] of Object.entries(modal.inputs)) {
116
116
  contentRef.setInput(key, value);
117
117
  }
118
118
 
@@ -514,7 +514,7 @@ export class SdModal {
514
514
  private async _restoreConfig(k: string): Promise<void> {
515
515
  if (this._sdSystemConfig == null) return;
516
516
 
517
- const config = (await this._sdSystemConfig.getAsync(`sd-modal.${k}` as any)) as
517
+ const config = (await this._sdSystemConfig.getAsync(`sd-modal.${k}`)) as
518
518
  | Record<string, string | undefined>
519
519
  | undefined;
520
520
  if (config == null) return;
@@ -15,7 +15,7 @@ export function getMenuRouterLinkOption(
15
15
  const qp =
16
16
  q == null
17
17
  ? undefined
18
- : (Object.fromEntries(new URLSearchParams(q)) as Record<string, string>);
18
+ : Object.fromEntries(new URLSearchParams(q));
19
19
 
20
20
  return {
21
21
  link: "/home/" + n,
@@ -50,7 +50,7 @@ export abstract class SdSharedDataProvider<T extends Record<string, SharedDataBa
50
50
  abstract initialize(): void;
51
51
 
52
52
  register<K extends string & keyof T>(name: K, info: SharedDataInfo<T[K]>): void {
53
- const existing = this._entries.get(name as string);
53
+ const existing = this._entries.get(name);
54
54
  if (existing != null) {
55
55
  // 기존 리스너 키 초기화 + generation 증가로 이전 이벤트 무시
56
56
  if (existing.listenerKey != null) {
@@ -75,7 +75,7 @@ export abstract class SdSharedDataProvider<T extends Record<string, SharedDataBa
75
75
  },
76
76
  };
77
77
 
78
- this._entries.set(name as string, {
78
+ this._entries.set(name, {
79
79
  info,
80
80
  itemsSignal,
81
81
  handle,
@@ -87,14 +87,14 @@ export abstract class SdSharedDataProvider<T extends Record<string, SharedDataBa
87
87
  }
88
88
 
89
89
  getHandle<K extends string & keyof T>(name: K): SharedDataHandle<T[K]> {
90
- const entry = this._entries.get(name as string);
90
+ const entry = this._entries.get(name);
91
91
  if (entry == null) {
92
- throw new Error(`등록되지 않은 공유 데이터: ${name as string}`);
92
+ throw new Error(`등록되지 않은 공유 데이터: ${name}`);
93
93
  }
94
94
 
95
95
  if (entry.needsReload && !entry.isLoading) {
96
96
  entry.needsReload = false;
97
- this._loadAndListen(name as string, entry);
97
+ this._loadAndListen(name, entry);
98
98
  }
99
99
 
100
100
  return entry.handle;
@@ -104,9 +104,9 @@ export abstract class SdSharedDataProvider<T extends Record<string, SharedDataBa
104
104
  name: K,
105
105
  changeKeys?: (string | number)[],
106
106
  ): Promise<void> {
107
- const entry = this._entries.get(name as string);
107
+ const entry = this._entries.get(name);
108
108
  if (entry == null) {
109
- throw new Error(`등록되지 않은 공유 데이터: ${name as string}`);
109
+ throw new Error(`등록되지 않은 공유 데이터: ${name}`);
110
110
  }
111
111
 
112
112
  const client = this._sdServiceClientFactory.get(entry.info.serviceKey);
@@ -247,7 +247,7 @@ export class SdSharedDataSelect<
247
247
  }
248
248
 
249
249
  if (hasParent && parentMap != null) {
250
- const children = parentMap.get(key as TItem["__valueKey"]) ?? [];
250
+ const children = parentMap.get(key) ?? [];
251
251
  for (let i = 0; i < children.length; i++) {
252
252
  if (check(children[i], i)) {
253
253
  cache.set(key, true);
@@ -331,7 +331,7 @@ export class SdSharedDataSelect<
331
331
 
332
332
  getChildren = (item: SharedDataBase<string | number>): TItem[] => {
333
333
  return (
334
- this._sortedChildrenMap()?.get(item.__valueKey as TItem["__valueKey"]) ??
334
+ this._sortedChildrenMap()?.get(item.__valueKey) ??
335
335
  []
336
336
  );
337
337
  };
@@ -4,13 +4,11 @@ import {
4
4
  Component,
5
5
  computed,
6
6
  contentChildren,
7
- effect,
8
7
  inject,
9
8
  input,
10
9
  model,
11
10
  output,
12
11
  signal,
13
- untracked,
14
12
  ViewEncapsulation,
15
13
  } from "@angular/core";
16
14
  import { NgTemplateOutlet } from "@angular/common";
@@ -106,8 +104,8 @@ import { SdEvents } from "../../core/events/sd-events";
106
104
  layout.headerFeatureRowSpan() > 1 ? layout.headerFeatureRowSpan() : null
107
105
  "
108
106
  [attr.data-c]="_fc"
109
- [style.left.px]="featureFixedLeftMap().get(_fc)"
110
- (sdResize)="onFeatureCellResize($event, _fc)"
107
+ [style.left.px]="fixing.fixedLeftMap().get(_fc)"
108
+ (sdResize)="onFixedCellResize($event, _fc)"
111
109
  >
112
110
  @if (selection.hasSelectable() && selectMode() === "multi") {
113
111
  <sd-checkbox
@@ -125,8 +123,8 @@ import { SdEvents } from "../../core/events/sd-events";
125
123
  layout.headerFeatureRowSpan() > 1 ? layout.headerFeatureRowSpan() : null
126
124
  "
127
125
  [attr.data-c]="-1"
128
- [style.left.px]="featureFixedLeftMap().get(-1)"
129
- (sdResize)="onFeatureCellResize($event, -1)"
126
+ [style.left.px]="fixing.fixedLeftMap().get(-1)"
127
+ (sdResize)="onFixedCellResize($event, -1)"
130
128
  >
131
129
  <ng-icon
132
130
  [svg]="icons.tablerCaretRight"
@@ -137,16 +135,16 @@ import { SdEvents } from "../../core/events/sd-events";
137
135
  </th>
138
136
  }
139
137
  }
140
- @for (cell of row; track $index; let c = $index) {
138
+ @for (cell of row; track $index) {
141
139
  @if (!cell.isLastRow) {
142
140
  <th
143
141
  [class._fixed]="cell.colDef?.fixed"
144
142
  [attr.colspan]="cell.colspan > 1 ? cell.colspan : null"
145
143
  [attr.rowspan]="cell.rowspan > 1 ? cell.rowspan : null"
146
- [attr.data-c]="c"
144
+ [attr.data-c]="cell.colIndex"
147
145
  [attr.title]="cell.text"
148
146
  [style.left.px]="
149
- cell.colDef?.fixed ? fixing.fixedLeftMap().get(cell.colDef!.key) : null
147
+ cell.colDef?.fixed ? fixing.fixedLeftMap().get(cell.colIndex) : null
150
148
  "
151
149
  >
152
150
  <div class="_p-sheet">
@@ -160,10 +158,11 @@ import { SdEvents } from "../../core/events/sd-events";
160
158
  [class._sort]="cell.colDef && !cell.colDef.disableSorting"
161
159
  [attr.colspan]="cell.colspan > 1 ? cell.colspan : null"
162
160
  [attr.rowspan]="cell.rowspan > 1 ? cell.rowspan : null"
163
- [attr.data-c]="c"
161
+ [attr.data-c]="cell.colIndex"
164
162
  [attr.title]="cell.colDef?.tooltip ?? cell.text"
165
163
  [class.help]="cell.colDef?.tooltip"
166
164
  [style]="getHeaderCellStyle(cell)"
165
+ (sdResize)="onFixedCellResize($event, cell.colIndex)"
167
166
  (click)="onHeaderClick($event, cell)"
168
167
  >
169
168
  <div class="_headerContent flex-row">
@@ -206,15 +205,22 @@ import { SdEvents } from "../../core/events/sd-events";
206
205
  }
207
206
  @if (layout.hasSummary()) {
208
207
  <tr class="_summary-row">
209
- <th class="_fixed _feature-cell"></th>
208
+ @let _sfc = expanding.hasExpandable() ? -2 : -1;
209
+ <th
210
+ class="_fixed _feature-cell"
211
+ [style.left.px]="fixing.fixedLeftMap().get(_sfc)"
212
+ ></th>
210
213
  @if (expanding.hasExpandable()) {
211
- <th class="_fixed _feature-cell"></th>
214
+ <th
215
+ class="_fixed _feature-cell"
216
+ [style.left.px]="fixing.fixedLeftMap().get(-1)"
217
+ ></th>
212
218
  }
213
219
  @for (colDef of layout.columnDefs(); track colDef.key; let c = $index) {
214
220
  <th
215
221
  [class._fixed]="colDef.fixed"
216
222
  [attr.data-c]="c"
217
- [style.left.px]="colDef.fixed ? fixing.fixedLeftMap().get(colDef.key) : null"
223
+ [style.left.px]="colDef.fixed ? fixing.fixedLeftMap().get(c) : null"
218
224
  >
219
225
  @if (getColumnSummaryTpl(colDef.key); as tpl) {
220
226
  <ng-template [ngTemplateOutlet]="tpl" />
@@ -236,7 +242,7 @@ import { SdEvents } from "../../core/events/sd-events";
236
242
  class="_fixed _feature-cell"
237
243
  [attr.data-r]="rowIdx"
238
244
  [attr.data-c]="_fc"
239
- [style.left.px]="featureFixedLeftMap().get(_fc)"
245
+ [style.left.px]="fixing.fixedLeftMap().get(_fc)"
240
246
  >
241
247
  @if (selectMode() === "multi") {
242
248
  @let _selectable = selection.getSelectable(item);
@@ -268,7 +274,7 @@ import { SdEvents } from "../../core/events/sd-events";
268
274
  class="_fixed _feature-cell"
269
275
  [attr.data-r]="rowIdx"
270
276
  [attr.data-c]="-1"
271
- [style.left.px]="featureFixedLeftMap().get(-1)"
277
+ [style.left.px]="fixing.fixedLeftMap().get(-1)"
272
278
  >
273
279
  @let itemDef = getItemDef(item);
274
280
  @if (itemDef.depth > 0) {
@@ -580,7 +586,6 @@ export class SdSheet<T> {
580
586
  getItemCellClassFn = input<(item: T, colKey: string) => string>();
581
587
  getItemCellStyleFn = input<(item: T, colKey: string) => string | undefined>();
582
588
  hideConfigBar = input(false, { transform: booleanAttribute });
583
- cumulativeSelection = input(false, { transform: booleanAttribute });
584
589
 
585
590
  // Outputs
586
591
  itemKeydown = output<SdSheetItemKeydownEventParam<T>>();
@@ -594,6 +599,10 @@ export class SdSheet<T> {
594
599
 
595
600
  // Content query
596
601
  columnControls = contentChildren(SdSheetColumn);
602
+ columnControlsInput = input<readonly SdSheetColumn[]>();
603
+ private readonly _effectiveColumnControls = computed(
604
+ () => this.columnControlsInput() ?? this.columnControls(),
605
+ );
597
606
 
598
607
  // Injected providers
599
608
  private readonly _sdModal = inject(SdModalProvider);
@@ -619,32 +628,10 @@ export class SdSheet<T> {
619
628
 
620
629
  // Layout engine
621
630
  layout = useSheetLayoutEngine({
622
- columnControls: this.columnControls,
631
+ columnControls: this._effectiveColumnControls,
623
632
  config: computed(() => this._configResource.value()),
624
633
  });
625
634
 
626
- // Column fixing
627
- fixing = useSheetColumnFixing({
628
- columnDefs: this.layout.columnDefs,
629
- });
630
-
631
- // Feature cell fixing (select/expand columns)
632
- private readonly _featureCellWidths = signal(new Map<number, number>());
633
-
634
- featureFixedLeftMap = computed(() => {
635
- const map = new Map<number, number>();
636
- const widths = this._featureCellWidths();
637
- const hasExpand = this.expanding.hasExpandable();
638
-
639
- if (hasExpand) {
640
- map.set(-2, 0);
641
- map.set(-1, widths.get(-2) ?? 0);
642
- } else {
643
- map.set(-1, 0);
644
- }
645
- return map;
646
- });
647
-
648
635
  // Sorting manager
649
636
  sorting = useSortingManager({
650
637
  sorts: this.sorts,
@@ -665,6 +652,15 @@ export class SdSheet<T> {
665
652
  expanding = this._pipeline.expanding;
666
653
  displayItems = this._pipeline.displayItems;
667
654
 
655
+ // Column fixing (DOM 측정 기반 통합 fixedLeftMap)
656
+ private readonly _fixedCellWidths = signal(new Map<number, number>());
657
+
658
+ fixing = useSheetColumnFixing({
659
+ columnDefs: this.layout.columnDefs,
660
+ cellWidths: this._fixedCellWidths,
661
+ hasExpandable: this.expanding.hasExpandable,
662
+ });
663
+
668
664
  // Cell styling composable
669
665
  private readonly _styling = useSheetCellStyling<T>({
670
666
  columnDefs: this.layout.columnDefs,
@@ -702,23 +698,6 @@ export class SdSheet<T> {
702
698
  trackByFn: this.trackByFn,
703
699
  });
704
700
 
705
- // cumulativeSelection=false면 items 변경 시 selectedItems를 초기화한다.
706
- // 첫 실행(초기 마운트)은 skip하여 소비자가 넘긴 초기 selectedItems 값을 보존한다.
707
- private _resetOnItemsChangeSkipFirst = true;
708
- private readonly _resetOnItemsChange = effect(() => {
709
- this.items(); // track only items
710
- if (this._resetOnItemsChangeSkipFirst) {
711
- this._resetOnItemsChangeSkipFirst = false;
712
- return;
713
- }
714
- untracked(() => {
715
- if (this.cumulativeSelection()) return;
716
- if (this.selectedItems().length > 0) {
717
- this.selectedItems.set([]);
718
- }
719
- });
720
- });
721
-
722
701
  // Icons
723
702
  icons = {
724
703
  tablerSettings,
@@ -731,7 +710,7 @@ export class SdSheet<T> {
731
710
 
732
711
  private readonly _columnControlMap = computed(() => {
733
712
  const map = new Map<string, SdSheetColumn>();
734
- for (const col of this.columnControls()) {
713
+ for (const col of this._effectiveColumnControls()) {
735
714
  map.set(col.key(), col);
736
715
  }
737
716
  return map;
@@ -845,10 +824,10 @@ export class SdSheet<T> {
845
824
  this._selectRowIndicator.redraw();
846
825
  }
847
826
 
848
- onFeatureCellResize(event: SdResizeEvent, key: number): void {
827
+ onFixedCellResize(event: SdResizeEvent, key: number): void {
849
828
  if (!event.widthChanged) return;
850
829
  const width = event.target.offsetWidth;
851
- this._featureCellWidths.update((m) => {
830
+ this._fixedCellWidths.update((m) => {
852
831
  const newMap = new Map(m);
853
832
  newMap.set(key, width);
854
833
  return newMap;
@@ -923,7 +902,7 @@ export class SdSheet<T> {
923
902
  type: SdSheetConfigModal,
924
903
  inputs: {
925
904
  sheetKey: this.key()!,
926
- controls: this.columnControls(),
905
+ controls: this._effectiveColumnControls(),
927
906
  config: this._configResource.value(),
928
907
  },
929
908
  });