@simplysm/angular 14.0.51 → 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 (134) hide show
  1. package/dist/data/sheet/sd-sheet.d.ts +9 -12
  2. package/dist/data/sheet/sd-sheet.d.ts.map +1 -1
  3. package/dist/data/sheet/sd-sheet.js +150 -168
  4. package/dist/data/sheet/types.d.ts +1 -0
  5. package/dist/data/sheet/types.d.ts.map +1 -1
  6. package/dist/data/sheet/useSheetCellStyling.d.ts +2 -2
  7. package/dist/data/sheet/useSheetCellStyling.d.ts.map +1 -1
  8. package/dist/data/sheet/useSheetCellStyling.js +20 -12
  9. package/dist/data/sheet/useSheetColumnFixing.d.ts +3 -8
  10. package/dist/data/sheet/useSheetColumnFixing.d.ts.map +1 -1
  11. package/dist/data/sheet/useSheetColumnFixing.js +19 -27
  12. package/dist/data/sheet/useSheetLayoutEngine.d.ts.map +1 -1
  13. package/dist/data/sheet/useSheetLayoutEngine.js +4 -1
  14. package/dist/layout/dock/sd-dock-container.d.ts.map +1 -1
  15. package/dist/layout/dock/sd-dock-container.js +3 -3
  16. package/package.json +7 -8
  17. package/src/data/sheet/sd-sheet.ts +39 -60
  18. package/src/data/sheet/types.ts +1 -0
  19. package/src/data/sheet/useSheetCellStyling.ts +19 -11
  20. package/src/data/sheet/useSheetColumnFixing.ts +21 -28
  21. package/src/data/sheet/useSheetLayoutEngine.ts +4 -1
  22. package/src/layout/dock/sd-dock-container.ts +1 -0
  23. package/README.md +0 -476
  24. package/docs/bootstrap/provide-sd-angular.md +0 -37
  25. package/docs/bootstrap/sd-angular-config-provider.md +0 -16
  26. package/docs/directives/sd-command-directive.md +0 -30
  27. package/docs/directives/sd-events.md +0 -25
  28. package/docs/directives/sd-intersection-directive.md +0 -36
  29. package/docs/directives/sd-invalid.md +0 -24
  30. package/docs/directives/sd-resize-directive.md +0 -42
  31. package/docs/directives/sd-ripple.md +0 -23
  32. package/docs/directives/sd-router-link.md +0 -38
  33. package/docs/directives/sd-show-effect.md +0 -18
  34. package/docs/directives/sd-typed-template.md +0 -69
  35. package/docs/features/sd-address-search-modal.md +0 -50
  36. package/docs/features/sd-permission-table.md +0 -20
  37. package/docs/features/sd-shared-data-components.md +0 -158
  38. package/docs/features/sd-tiptap-editor.md +0 -26
  39. package/docs/pipes/format-pipe.md +0 -41
  40. package/docs/plugins/sd-global-error-handler.md +0 -23
  41. package/docs/plugins/sd-option-event-plugin.md +0 -34
  42. package/docs/provider-types/sd-menu.md +0 -65
  43. package/docs/provider-types/sd-modal-content-def.md +0 -148
  44. package/docs/provider-types/sd-toast-content-def.md +0 -73
  45. package/docs/provider-types/shared-data-base.md +0 -59
  46. package/docs/providers/sd-activated-modal-provider.md +0 -34
  47. package/docs/providers/sd-app-structure-provider.md +0 -81
  48. package/docs/providers/sd-busy-provider.md +0 -18
  49. package/docs/providers/sd-file-dialog-provider.md +0 -40
  50. package/docs/providers/sd-local-storage-provider.md +0 -20
  51. package/docs/providers/sd-modal-provider.md +0 -67
  52. package/docs/providers/sd-navigate-window-provider.md +0 -18
  53. package/docs/providers/sd-print-provider.md +0 -25
  54. package/docs/providers/sd-service-client-factory-provider.md +0 -43
  55. package/docs/providers/sd-shared-data-provider.md +0 -64
  56. package/docs/providers/sd-system-config-provider.md +0 -46
  57. package/docs/providers/sd-system-log-provider.md +0 -18
  58. package/docs/providers/sd-theme-provider.md +0 -38
  59. package/docs/providers/sd-toast-provider.md +0 -65
  60. package/docs/recipes/_common-rules.md +0 -244
  61. package/docs/recipes/crud-detail/extension-a-edit-save.md +0 -230
  62. package/docs/recipes/crud-detail/extension-b-delete-restore.md +0 -142
  63. package/docs/recipes/crud-detail/extension-c-modal-view.md +0 -214
  64. package/docs/recipes/crud-detail/extension-d-control-view.md +0 -103
  65. package/docs/recipes/crud-detail/extension-e-auxiliary.md +0 -87
  66. package/docs/recipes/crud-detail/extension-f-complex-detail.md +0 -234
  67. package/docs/recipes/crud-detail.md +0 -353
  68. package/docs/recipes/crud-list/extension-a-inline-edit.md +0 -410
  69. package/docs/recipes/crud-list/extension-b-selection.md +0 -226
  70. package/docs/recipes/crud-list/extension-c-inline-delete.md +0 -87
  71. package/docs/recipes/crud-list/extension-d-select-modal.md +0 -207
  72. package/docs/recipes/crud-list/extension-e-readonly-modal.md +0 -165
  73. package/docs/recipes/crud-list/extension-f-modal-edit.md +0 -177
  74. package/docs/recipes/crud-list/extension-g-excel.md +0 -157
  75. package/docs/recipes/crud-list.md +0 -446
  76. package/docs/recipes/data-select-button.md +0 -412
  77. package/docs/recipes/page-modal-container.md +0 -260
  78. package/docs/styling/classes.md +0 -149
  79. package/docs/styling/mixins.md +0 -100
  80. package/docs/styling/themes.md +0 -35
  81. package/docs/styling/variables.md +0 -147
  82. package/docs/type-utilities/directive-input-signals.md +0 -232
  83. package/docs/ui-data/sd-list.md +0 -37
  84. package/docs/ui-data/sd-sheet.md +0 -227
  85. package/docs/ui-form/sd-additional-button.md +0 -26
  86. package/docs/ui-form/sd-anchor.md +0 -31
  87. package/docs/ui-form/sd-button.md +0 -105
  88. package/docs/ui-form/sd-checkbox-group.md +0 -39
  89. package/docs/ui-form/sd-checkbox.md +0 -81
  90. package/docs/ui-form/sd-date-range-picker.md +0 -27
  91. package/docs/ui-form/sd-form.md +0 -89
  92. package/docs/ui-form/sd-modal-select-button.md +0 -54
  93. package/docs/ui-form/sd-numpad.md +0 -26
  94. package/docs/ui-form/sd-range.md +0 -26
  95. package/docs/ui-form/sd-select.md +0 -68
  96. package/docs/ui-form/sd-shared-data-select.md +0 -52
  97. package/docs/ui-form/sd-state-preset.md +0 -37
  98. package/docs/ui-form/sd-switch.md +0 -27
  99. package/docs/ui-form/sd-textarea.md +0 -33
  100. package/docs/ui-form/sd-textfield.md +0 -145
  101. package/docs/ui-layout/sd-dock-container.md +0 -64
  102. package/docs/ui-layout/sd-dock.md +0 -37
  103. package/docs/ui-layout/sd-gap.md +0 -26
  104. package/docs/ui-layout/sd-kanban-board.md +0 -96
  105. package/docs/ui-layout/sd-kanban-lane.md +0 -34
  106. package/docs/ui-layout/sd-kanban.md +0 -29
  107. package/docs/ui-navigation/sd-collapse.md +0 -35
  108. package/docs/ui-navigation/sd-pagination.md +0 -26
  109. package/docs/ui-navigation/sd-sidebar-container.md +0 -49
  110. package/docs/ui-navigation/sd-sidebar-menu.md +0 -22
  111. package/docs/ui-navigation/sd-sidebar-user.md +0 -43
  112. package/docs/ui-navigation/sd-tab.md +0 -51
  113. package/docs/ui-navigation/sd-topbar-container.md +0 -97
  114. package/docs/ui-navigation/sd-topbar-menu.md +0 -23
  115. package/docs/ui-navigation/sd-topbar-user.md +0 -38
  116. package/docs/ui-navigation/sd-topbar.md +0 -30
  117. package/docs/ui-overlay/sd-busy-container.md +0 -69
  118. package/docs/ui-overlay/sd-confirm-modal.md +0 -30
  119. package/docs/ui-overlay/sd-dropdown.md +0 -40
  120. package/docs/ui-overlay/sd-modal.md +0 -34
  121. package/docs/ui-overlay/sd-prompt-modal.md +0 -30
  122. package/docs/ui-overlay/sd-toast.md +0 -35
  123. package/docs/ui-visual/sd-barcode.md +0 -36
  124. package/docs/ui-visual/sd-calendar.md +0 -34
  125. package/docs/ui-visual/sd-echarts.md +0 -32
  126. package/docs/ui-visual/sd-label.md +0 -24
  127. package/docs/ui-visual/sd-note.md +0 -23
  128. package/docs/ui-visual/sd-progress.md +0 -23
  129. package/docs/utils/inject-routing-signals.md +0 -161
  130. package/docs/utils/inject-sd-system-config-resource.md +0 -35
  131. package/docs/utils/mark.md +0 -43
  132. package/docs/utils/selection-managers.md +0 -96
  133. package/docs/utils/set-safe-style.md +0 -19
  134. package/docs/utils/setup-functions.md +0 -93
@@ -1,35 +0,0 @@
1
- # `SdToast`
2
-
3
- 토스트 개별 항목 컴포넌트. `SdToastProvider`에 의해 프로그래밍 방식으로 생성된다.
4
-
5
- ```typescript
6
- @Component({ selector: "sd-toast", ... })
7
- export class SdToast
8
- ```
9
-
10
- ## Members
11
-
12
- | Member | Kind | Type | Description |
13
- |--------|------|------|-------------|
14
- | `open` | model | `boolean` | 열림 상태 (기본값: `false`) |
15
- | `useProgress` | input | `boolean` | 진행률 바 표시 (기본값: `false`) |
16
- | `theme` | input | `SdToastTheme` | 색상 테마 (기본값: `"info"`) |
17
- | `progress` | model | `number` | 진행률 (0~100, 기본값: `0`) |
18
- | `message` | model | `string \| undefined` | 메시지 텍스트 |
19
-
20
- 직접 사용하는 대신 [`SdToastProvider`](../providers/sd-toast-provider.md)를 사용한다.
21
-
22
- ## Related Types
23
-
24
- ### `SdToastContainer`
25
-
26
- ```typescript
27
- @Component({ selector: "sd-toast-container", ... })
28
- export class SdToastContainer
29
- ```
30
-
31
- 토스트 컨테이너. `SdToastProvider`에 의해 자동 생성된다.
32
-
33
- | Member | Kind | Type | Description |
34
- |--------|------|------|-------------|
35
- | `overlap` | input | `boolean` | 중복 표시 방지 (기본값: `false`) |
@@ -1,36 +0,0 @@
1
- # `SdBarcode`
2
-
3
- 바코드 생성 컴포넌트. bwip-js 라이브러리를 사용하여 SVG 바코드를 렌더링한다.
4
-
5
- ```typescript
6
- @Component({ selector: "sd-barcode", ... })
7
- export class SdBarcode
8
- ```
9
-
10
- ## Members
11
-
12
- | Member | Kind | Type | Description |
13
- |--------|------|------|-------------|
14
- | `type` | input (required) | `BarcodeType` | 바코드 종류 |
15
- | `value` | input | `string \| undefined` | 바코드에 인코딩할 텍스트 |
16
-
17
- ## Related Types
18
-
19
- ### `BarcodeType`
20
-
21
- bwip-js가 지원하는 바코드 형식 문자열 union type. 주요 값:
22
-
23
- - `"code128"` — Code 128
24
- - `"code39"` — Code 39
25
- - `"ean13"` — EAN-13
26
- - `"qrcode"` — QR Code
27
- - `"datamatrix"` — Data Matrix
28
-
29
- (전체 목록은 bwip-js 문서 참조)
30
-
31
- ## Usage
32
-
33
- ```html
34
- <sd-barcode [type]="'code128'" [value]="item.barcode" />
35
- <sd-barcode [type]="'qrcode'" [value]="item.qrUrl" />
36
- ```
@@ -1,34 +0,0 @@
1
- # `SdCalendar`
2
-
3
- 월별 달력 컴포넌트. `items`를 날짜 기준으로 분류하여 각 날짜 셀에 표시한다.
4
-
5
- ```typescript
6
- @Component({ selector: "sd-calendar", ... })
7
- export class SdCalendar<T>
8
- ```
9
-
10
- ## Members
11
-
12
- | Member | Kind | Type | Description |
13
- |--------|------|------|-------------|
14
- | `items` | input (required) | `T[]` | 표시할 항목 배열 |
15
- | `getItemDateFn` | input (required) | `(item: T, index: number) => DateOnly` | 각 항목의 날짜를 반환하는 함수 |
16
- | `yearMonth` | input | `DateOnly` | 표시할 연월 (기본값: 현재 월의 1일) |
17
- | `weekStartDay` | input | `number` | 주 시작 요일 (0=일, 1=월, 기본값: `0`) |
18
- | `minDaysInFirstWeek` | input | `number` | 첫 주 최소 날짜 수 (기본값: `1`) |
19
-
20
- 콘텐츠 템플릿: `ng-template[itemOf]`로 날짜별 항목을 렌더링한다 (`SdItemOfTemplateContext<T>` 타입).
21
-
22
- ## Usage
23
-
24
- ```html
25
- <sd-calendar
26
- [items]="schedules()"
27
- [getItemDateFn]="getScheduleDate"
28
- [(yearMonth)]="currentMonth"
29
- >
30
- <ng-template itemOf let-item>
31
- <div class="tx-sm">{{ item.title }}</div>
32
- </ng-template>
33
- </sd-calendar>
34
- ```
@@ -1,32 +0,0 @@
1
- # `SdEcharts`
2
-
3
- Apache ECharts 차트 래퍼 컴포넌트. 호스트 요소의 크기 변경을 감지하여 자동으로 차트를 리사이즈한다.
4
-
5
- ```typescript
6
- @Component({ selector: "sd-echarts", ... })
7
- export class SdEcharts
8
- ```
9
-
10
- ## Members
11
-
12
- | Member | Kind | Type | Description |
13
- |--------|------|------|-------------|
14
- | `option` | input (required) | `echarts.EChartsOption` | ECharts 옵션 객체 |
15
- | `notMerge` | input | `boolean` | `setOption` 호출 시 전체 교체 여부 (기본값: `false`) |
16
- | `loading` | input | `boolean` | 로딩 오버레이 표시 (기본값: `false`) |
17
-
18
- SVG 렌더러를 사용하며 (`renderer: "svg"`), `afterNextRender`에서 초기화된다.
19
-
20
- ## Usage
21
-
22
- ```html
23
- <sd-echarts [option]="chartOption()" style="height: 300px" />
24
- ```
25
-
26
- ```typescript
27
- chartOption = computed<echarts.EChartsOption>(() => ({
28
- xAxis: { type: "category", data: this.labels() },
29
- yAxis: { type: "value" },
30
- series: [{ type: "bar", data: this.values() }],
31
- }));
32
- ```
@@ -1,24 +0,0 @@
1
- # `SdLabel`
2
-
3
- 인라인 라벨 컴포넌트. 테마 색상 또는 커스텀 배경색을 적용한다.
4
-
5
- ```typescript
6
- @Component({ selector: "sd-label", ... })
7
- export class SdLabel
8
- ```
9
-
10
- ## Members
11
-
12
- | Member | Kind | Type | Description |
13
- |--------|------|------|-------------|
14
- | `theme` | input | `"primary" \| "secondary" \| "info" \| "success" \| "warning" \| "danger" \| "gray" \| "blue-gray" \| undefined` | 색상 테마 (미지정 시 `gray-darker`) |
15
- | `color` | input | `string \| undefined` | 커스텀 배경색 (CSS 색상값) |
16
- | `clickable` | input | `boolean` | 클릭 가능 여부 (기본값: `false`) |
17
-
18
- ## Usage
19
-
20
- ```html
21
- <sd-label [theme]="'success'">완료</sd-label>
22
- <sd-label [theme]="'danger'">오류</sd-label>
23
- <sd-label [color]="'#ff6600'">커스텀</sd-label>
24
- ```
@@ -1,23 +0,0 @@
1
- # `SdNote`
2
-
3
- 알림 메시지 블록 컴포넌트. 배경 색상으로 중요도를 표현한다.
4
-
5
- ```typescript
6
- @Component({ selector: "sd-note", ... })
7
- export class SdNote
8
- ```
9
-
10
- ## Members
11
-
12
- | Member | Kind | Type | Description |
13
- |--------|------|------|-------------|
14
- | `theme` | input | `"primary" \| "secondary" \| "info" \| "success" \| "warning" \| "danger" \| "gray" \| "blue-gray" \| undefined` | 색상 테마 |
15
- | `size` | input | `"sm" \| "lg" \| undefined` | 크기 |
16
- | `inset` | input | `boolean` | 인셋 스타일 (기본값: `false`) |
17
-
18
- ## Usage
19
-
20
- ```html
21
- <sd-note [theme]="'warning'">저장하지 않은 변경사항이 있습니다.</sd-note>
22
- <sd-note [theme]="'info'">Ctrl+S로 저장할 수 있습니다.</sd-note>
23
- ```
@@ -1,23 +0,0 @@
1
- # `SdProgress`
2
-
3
- 진행률 바 컴포넌트. `value`(0~1 범위)에 따라 바 너비를 계산하고 퍼센트를 표시한다.
4
-
5
- ```typescript
6
- @Component({ selector: "sd-progress", ... })
7
- export class SdProgress
8
- ```
9
-
10
- ## Members
11
-
12
- | Member | Kind | Type | Description |
13
- |--------|------|------|-------------|
14
- | `value` | input (required) | `number` | 진행률 (0~1 범위) |
15
- | `theme` | input (required) | `"primary" \| "secondary" \| "info" \| "success" \| "warning" \| "danger" \| "gray" \| "blue-gray"` | 색상 테마 |
16
- | `inset` | input | `boolean` | 인셋 스타일 (기본값: `false`) |
17
- | `size` | input | `"sm" \| "lg" \| undefined` | 크기 |
18
-
19
- ## Usage
20
-
21
- ```html
22
- <sd-progress [value]="progress() / 100" [theme]="'primary'" />
23
- ```
@@ -1,161 +0,0 @@
1
- # 라우팅 Signal 함수들
2
-
3
- 라우터 상태를 signal로 반환하는 inject 함수 모음. 생성자/필드 이니셜라이저에서 호출한다.
4
-
5
- ## `injectCurrentPageCodeSignal`
6
-
7
- 현재 활성 라우트의 경로 세그먼트를 `.`으로 연결한 코드 signal. `ActivatedRoute`가 없으면 undefined 반환.
8
-
9
- ```typescript
10
- function injectCurrentPageCodeSignal(): Signal<string> | undefined
11
- ```
12
-
13
- ### 사용 패턴
14
-
15
- `injectViewTypeSignal()`과 `injectViewTitleSignal()` 내부에서 사용된다. 일반적으로 직접 사용할 필요 없이 `injectViewTitleSignal()`을 사용하면 된다.
16
-
17
- ## `injectFullPageCodeSignal`
18
-
19
- 전체 URL 기반 페이지 코드 signal. `NavigationEnd` 이벤트를 구독하여 URL에서 코드를 추출한다.
20
-
21
- ```typescript
22
- function injectFullPageCodeSignal(): Signal<string>
23
- ```
24
-
25
- ### 사용 패턴
26
-
27
- `injectViewTypeSignal()`과 `injectViewTitleSignal()` 내부에서 사용된다. 일반적으로 직접 사용할 필요 없이 `injectViewTitleSignal()`을 사용하면 된다.
28
-
29
- ## `injectViewTitleSignal`
30
-
31
- 현재 뷰의 타이틀 signal. 모달이면 모달 타이틀, 페이지이면 `SdAppStructureProvider`에서 조회.
32
-
33
- ```typescript
34
- function injectViewTitleSignal(): Signal<string>
35
- ```
36
-
37
- ### 사용 패턴
38
-
39
- ```typescript
40
- protected readonly viewTitle = injectViewTitleSignal();
41
- ```
42
-
43
- ```html
44
- <sd-topbar>
45
- <h4>{{ viewTitle() }}</h4>
46
- </sd-topbar>
47
- ```
48
-
49
- **실사용 예:**
50
- - [crud-list.md §3 최소 뼈대](../recipes/crud-list.md#3-최소-뼈대-조회-전용-page) — topbar 제목
51
- - [crud-detail.md §3 최소 뼈대](../recipes/crud-detail.md#3-최소-뼈대-읽기-전용-상세-폼) — topbar 제목
52
-
53
- ## `injectViewTypeSignal`
54
-
55
- 현재 뷰의 타입 signal. 모달/페이지/컨트롤 중 하나를 반환한다.
56
-
57
- ```typescript
58
- function injectViewTypeSignal(): Signal<SdViewType>
59
- ```
60
-
61
- ### 내부 판정 로직
62
-
63
- - `SdActivatedModalProvider`가 inject되면 `"modal"`
64
- - `ActivatedRoute.component`의 `reflectComponentType().selector`가 호스트 tagName과 일치하고 `fullPageCode() === currPageCode?.()`이면 `"page"`
65
- - 그 외 `"control"`
66
-
67
- ### 호출 시점 제약
68
-
69
- Angular `inject()`는 injection context(생성자 실행 중 또는 필드 초기화 시점) 안에서만 유효하므로, `computed` 콜백이나 `effect` 안에서 호출하면 **`NG0203` 런타임 에러**가 발생한다.
70
-
71
- ```typescript
72
- // OK — 필드 이니셜라이저
73
- protected readonly viewType = injectViewTypeSignal();
74
-
75
- // NG0203 — computed 내부
76
- protected readonly viewType = computed(() => injectViewTypeSignal()());
77
- ```
78
-
79
- ### 수동 오버라이드 패턴
80
-
81
- 일반적으로 자동 판정으로 충분하다. 수동 오버라이드가 필요한 특수 상황(예: 특정 페이지 안에 자기 자신을 모달처럼 보이게 하고 싶은 경우)에는:
82
-
83
- ```typescript
84
- override = input<SdViewType>();
85
- private readonly _autoViewType = injectViewTypeSignal();
86
- protected readonly viewType = computed(() => this.override() ?? this._autoViewType());
87
- ```
88
-
89
- > 이 오버라이드는 추상화 복원을 부추기므로 **기본은 자동 판정으로 쓰기**를 권장한다. 상세: [page-modal-container.md §5 뷰 타입 결정](../recipes/page-modal-container.md#5-뷰-타입-결정)
90
-
91
- **실사용 예:**
92
- - [crud-list.md §3 최소 뼈대](../recipes/crud-list.md#3-최소-뼈대-조회-전용-page) — 뷰 타입 기반 topbar 조건부 렌더
93
- - [crud-list.md §8 확장 D: 선택 모달 전환](../recipes/crud-list.md#8-확장-d-선택-모달-전환) — modal 뷰 분기
94
- - [crud-detail.md §7 확장 C: modal 뷰](../recipes/crud-detail.md#7-확장-c-modal-뷰) — modal 뷰 분기
95
- - [crud-detail.md §8 확장 D: control 뷰](../recipes/crud-detail.md#8-확장-d-control-뷰) — control 뷰 분기
96
- - [page-modal-container.md §5 뷰 타입 결정](../recipes/page-modal-container.md#5-뷰-타입-결정) — 판정 규칙 + 수동 오버라이드
97
-
98
- ## `injectPermsSignal`
99
-
100
- 앱 구조(`SdAppStructureProvider`)에서 지정된 뷰 코드와 키 배열에 대한 권한을 조회하는 signal. 생성자/필드 이니셜라이저에서 호출한다.
101
-
102
- ```typescript
103
- function injectPermsSignal<K extends string>(viewCodes: string[], keys: K[]): Signal<K[]>
104
- ```
105
-
106
- | Parameter | Type | Description |
107
- |-----------|------|-------------|
108
- | `viewCodes` | `string[]` | 조회할 뷰 코드 배열 (예: `["sales.customer"]`) |
109
- | `keys` | `K[]` | 권한 키 배열 (예: `["use", "edit"]`) |
110
- | **반환** | `Signal<K[]>` | 현재 사용자가 보유한 권한 키 배열 |
111
-
112
- ### 사용 패턴
113
-
114
- ```typescript
115
- protected readonly perms = injectPermsSignal(["{도메인}.{viewCode}"], ["use", "edit"]);
116
- protected readonly canEdit = computed(() => this.perms().includes("edit"));
117
- ```
118
-
119
- ```html
120
- @if (!perms().includes("use")) {
121
- <div class="fill tx-theme-gray-light p-xxl tx-center">
122
- <br />
123
- <ng-icon [svg]="tablerAlertTriangle" [size]="'5em'" />
124
- <br />
125
- <br />
126
- '{{ viewTitle() }}'에 대한 사용권한이 없습니다. 시스템 관리자에게 문의하세요.
127
- </div>
128
- }
129
- ```
130
-
131
- **실사용 예:**
132
- - [crud-list.md §3 최소 뼈대](../recipes/crud-list.md#3-최소-뼈대-조회-전용-page) — 권한 기반 조건부 렌더
133
- - [crud-detail.md §3 최소 뼈대](../recipes/crud-detail.md#3-최소-뼈대-읽기-전용-상세-폼) — 권한 기반 조건부 렌더
134
-
135
- ## `getMenuRouterLinkOption`
136
-
137
- 메뉴에서 라우터 링크 옵션을 추출한다.
138
-
139
- ```typescript
140
- function getMenuRouterLinkOption(
141
- menu: SdMenu,
142
- ): { link: string; queryParams: Record<string, string> | undefined } | undefined
143
- ```
144
-
145
- ## `getIsMenuSelected`
146
-
147
- 메뉴가 현재 선택된 상태인지 확인한다.
148
-
149
- ```typescript
150
- function getIsMenuSelected(
151
- menu: SdMenu,
152
- fullPageCode: string | undefined,
153
- customFn?: (menu: SdMenu) => boolean,
154
- ): boolean
155
- ```
156
-
157
- | Parameter | Type | Description |
158
- |-----------|------|-------------|
159
- | `menu` | `SdMenu` | 메뉴 항목 |
160
- | `fullPageCode` | `string \| undefined` | 현재 페이지 코드 |
161
- | `customFn` | `((menu) => boolean) \| undefined` | 커스텀 비교 함수 |
@@ -1,35 +0,0 @@
1
- # `injectSdSystemConfigResource`
2
-
3
- 컴포넌트 태그명 기반 키로 시스템 설정을 읽고 쓰는 resource 래퍼. 생성자에서 호출한다.
4
-
5
- ```typescript
6
- function injectSdSystemConfigResource<T>(options: {
7
- key: Signal<string | undefined>;
8
- }): {
9
- value: Signal<T | undefined>;
10
- isLoading: Signal<boolean>;
11
- status: Signal<ResourceStatus>;
12
- hasValue: () => boolean;
13
- reload: () => void;
14
- set(value: T | undefined): void;
15
- update(fn: (prev: T | undefined) => T | undefined): void;
16
- }
17
- ```
18
-
19
- ## Parameters
20
-
21
- | Param | Type | Description |
22
- |-------|------|-------------|
23
- | `options.key` | `Signal<string \| undefined>` | 설정 키 signal. undefined이면 로딩 안 함 |
24
-
25
- ## Returns
26
-
27
- | Field | Type | Description |
28
- |-------|------|-------------|
29
- | `value` | `Signal<T \| undefined>` | 설정 값 signal |
30
- | `isLoading` | `Signal<boolean>` | 로딩 중 여부 |
31
- | `status` | `Signal<ResourceStatus>` | resource 상태 |
32
- | `hasValue()` | `() => boolean` | 값 존재 여부 |
33
- | `reload()` | `() => void` | 강제 재로딩 |
34
- | `set(value)` | `(T \| undefined) => void` | 값 설정 + 즉시 signal 업데이트 + 비동기 영속화 |
35
- | `update(fn)` | `((prev) => T \| undefined) => void` | 값 업데이트 + 즉시 signal 업데이트 + 비동기 영속화 |
@@ -1,43 +0,0 @@
1
- # `mark`
2
-
3
- WritableSignal의 변경 알림을 수동으로 트리거한다. 배열/객체의 내부 변경(mutation) 후 consumer에게 변경을 알릴 때 사용. shallow copy로 새 참조를 생성하여 signal을 업데이트한다.
4
-
5
- ```typescript
6
- function mark(sig: WritableSignal<any>): void
7
- ```
8
-
9
- ## Parameters
10
-
11
- | Param | Type | Description |
12
- |-------|------|-------------|
13
- | `sig` | `WritableSignal<any>` | 대상 signal. 배열이면 `[...v]`, 객체이면 `{...v}`로 shallow copy하여 update |
14
-
15
- ## 역할
16
-
17
- - **OnPush 템플릿 재렌더링**: shallow copy로 새 참조를 생성하여 Angular의 변경 감지를 트리거한다
18
- - **computed/effect 의존성 갱신**: signal 참조가 갱신되어 의존하는 computed·effect가 재실행된다
19
-
20
- ## Usage
21
-
22
- ```typescript
23
- // 배열 내부 mutation 후 mark → UI 갱신
24
- items()[0].name = "new";
25
- mark(items); // items signal이 [...items()] 로 갱신됨
26
-
27
- // 객체 내부 mutation 후 mark → effect 재실행
28
- filter().searchText = "abc";
29
- mark(filter); // filter signal이 {...filter()} 로 갱신됨
30
- ```
31
-
32
- ## 주의사항
33
-
34
- > **"저장 감지"가 아니다.** `obj.equal`이 deep equal로 snapshot과 현재 값을 비교하므로, `item.name = "new"` 같은 mutation은 `mark` 없이도 `diffs()` / `onSubmit()`의 snapshot 비교에서 감지된다.
35
-
36
- - Chrome 61 호환성(`Proxy` 폴리필 불가)으로 signal 자동 notify가 불가하여 명시적 `mark` 호출이 필요
37
- - `mark`는 **UI에 변경을 반영**하기 위한 것이지, 데이터 변경 자체를 감지하는 메커니즘이 아니다
38
-
39
- **실사용 예:**
40
- - [crud-list.md §5 확장 A: inline 편집/저장](../recipes/crud-list.md#5-확장-a-inline-편집저장) — items 배열 mutation 후 mark
41
- - [crud-list.md §6 확장 B: 선택 기능](../recipes/crud-list.md#6-확장-b-선택-기능--선택-삭제복구) — selectedItems 변경 후 mark
42
- - [crud-detail.md §5 확장 A: 편집/저장](../recipes/crud-detail.md#5-확장-a-편집저장) — data 객체 mutation 후 mark
43
- - [crud-detail.md §10 확장 F: 복합 상세](../recipes/crud-detail.md#10-확장-f-복합-상세-내부-sd-sheet) — 하위 컬렉션 mutation 후 mark
@@ -1,96 +0,0 @@
1
- # Selection Managers
2
-
3
- 선택/정렬/트리 확장을 관리하는 composable 함수 모음. `inject()` 없이 Signal 입력만으로 동작한다.
4
-
5
- ## `useSelectionManager`
6
-
7
- 선택 관리 composable. single/multi 모드를 지원한다. `trackByFn`이 반환하는 key를 기준으로 `obj.equal`(deep equal) 비교를 수행하므로, 같은 key의 다른 reference item도 `isSelected` true로 복원된다.
8
-
9
- ```typescript
10
- function useSelectionManager<T>(options: {
11
- displayItems: Signal<T[]>;
12
- selectedItems: WritableSignal<T[]>;
13
- selectMode: Signal<"single" | "multi" | undefined>;
14
- getItemSelectableFn: Signal<((item: T) => boolean | string) | undefined>;
15
- trackByFn: Signal<(item: T, index: number) => unknown>;
16
- }): {
17
- hasSelectable: Signal<boolean>;
18
- isAllSelected: Signal<boolean>;
19
- getSelectable(item: T): true | string | undefined;
20
- getCanChangeFn(item: T): () => boolean;
21
- select(item: T): void;
22
- deselect(item: T): void;
23
- toggle(item: T): void;
24
- toggleAll(): void;
25
- isSelected(item: T): boolean;
26
- }
27
- ```
28
-
29
- ### Returns
30
-
31
- | Return | Type | Description |
32
- |--------|------|-------------|
33
- | `hasSelectable` | `Signal<boolean>` | selectMode가 설정되어 있는지 여부 |
34
- | `isAllSelected` | `Signal<boolean>` | 모든 선택 가능 항목이 선택되었는지 |
35
- | `getSelectable(item)` | `true \| string \| undefined` | 선택 가능 여부. string은 불가 사유 |
36
- | `getCanChangeFn(item)` | `() => boolean` | 선택 변경 가능 여부 함수 |
37
- | `select(item)` | `void` | 항목 선택 (single이면 교체) |
38
- | `deselect(item)` | `void` | 항목 선택 해제 |
39
- | `toggle(item)` | `void` | 항목 토글 |
40
- | `toggleAll()` | `void` | 전체 선택/해제 토글 |
41
- | `isSelected(item)` | `boolean` | 선택 여부 |
42
-
43
- ## `useSortingManager`
44
-
45
- 정렬 관리 composable.
46
-
47
- ```typescript
48
- function useSortingManager(options: {
49
- sorts: WritableSignal<SortingDef[]>;
50
- }): {
51
- defMap: Signal<Map<string, { indexText?: string; desc: boolean }>>;
52
- toggle(key: string, multiple: boolean): void;
53
- sort<T>(items: T[]): T[];
54
- }
55
- ```
56
-
57
- ### Returns
58
-
59
- | Return | Type | Description |
60
- |--------|------|-------------|
61
- | `defMap` | `Signal<Map<string, ...>>` | 키별 정렬 정의 (인덱스 텍스트, 방향) |
62
- | `toggle(key, multiple)` | `void` | 정렬 토글. `multiple=true`면 멀티 소트, `false`면 단일 소트. 3단계: asc → desc → 없음 |
63
- | `sort(items)` | `T[]` | 정렬 적용. 원본 배열은 변경하지 않음 |
64
-
65
- ## `useExpandingManager`
66
-
67
- 트리 확장/축소 관리 composable.
68
-
69
- ```typescript
70
- function useExpandingManager<T>(binding: {
71
- items: Signal<T[]>;
72
- expandedItems: WritableSignal<T[]>;
73
- getChildrenFn: Signal<((item: T, index: number) => T[] | undefined) | undefined>;
74
- sort: (items: T[]) => T[];
75
- }): {
76
- displayItems: Signal<T[]>;
77
- hasExpandable: Signal<boolean>;
78
- isAllExpanded: Signal<boolean>;
79
- toggle(item: T): void;
80
- toggleAll(): void;
81
- isVisible(item: T): boolean;
82
- def(item: T): ExpandItemDef<T>;
83
- }
84
- ```
85
-
86
- ### Returns
87
-
88
- | Return | Type | Description |
89
- |--------|------|-------------|
90
- | `displayItems` | `Signal<T[]>` | 트리를 평탄화한 전체 항목 (숨김 포함) |
91
- | `hasExpandable` | `Signal<boolean>` | 확장 가능한 항목 존재 여부 |
92
- | `isAllExpanded` | `Signal<boolean>` | 모든 확장 가능 항목이 펼쳐졌는지 |
93
- | `toggle(item)` | `void` | 항목 확장/축소 토글 |
94
- | `toggleAll()` | `void` | 전체 확장/축소 토글 |
95
- | `isVisible(item)` | `boolean` | 부모 체인이 모두 펼쳐져 항목이 보이는지 |
96
- | `def(item)` | `ExpandItemDef<T>` | 항목의 트리 정의 |
@@ -1,19 +0,0 @@
1
- # `setSafeStyle`
2
-
3
- Renderer2를 사용하여 여러 CSS 스타일을 일괄 적용한다.
4
-
5
- ```typescript
6
- function setSafeStyle(
7
- renderer: Renderer2,
8
- el: HTMLElement,
9
- style: Partial<CSSStyleDeclaration>,
10
- ): void
11
- ```
12
-
13
- ## Parameters
14
-
15
- | Param | Type | Description |
16
- |-------|------|-------------|
17
- | `renderer` | `Renderer2` | Angular Renderer2 인스턴스 |
18
- | `el` | `HTMLElement` | 스타일 적용 대상 요소 |
19
- | `style` | `Partial<CSSStyleDeclaration>` | 적용할 CSS 스타일 객체 |
@@ -1,93 +0,0 @@
1
- # Setup Functions
2
-
3
- 생성자에서 호출하는 설정 함수들. `inject()`, `effect()`, `DestroyRef.onDestroy()`를 사용하여 수명주기를 관리한다.
4
-
5
- ## `setupBgTheme`
6
-
7
- body 배경 테마 색상을 설정한다. 파괴 시 자동 복원.
8
-
9
- ```typescript
10
- function setupBgTheme(options?: {
11
- theme?: "primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray";
12
- lightness?: "lightest" | "lighter";
13
- }): void
14
- ```
15
-
16
- ## `setupRipple`
17
-
18
- 호스트 요소에 리플 효과를 설정한다. pointer 이벤트 기반.
19
-
20
- ```typescript
21
- function setupRipple(enableFn?: () => boolean): void
22
- ```
23
-
24
- ## `setupRevealOnShow`
25
-
26
- 뷰포트 진입 시 reveal 애니메이션을 설정한다. IntersectionObserver 사용.
27
-
28
- ```typescript
29
- function setupRevealOnShow(optFn?: () => {
30
- type?: "l2r" | "t2b";
31
- enabled?: boolean;
32
- }): void
33
- ```
34
-
35
- ## `setupInvalid`
36
-
37
- 유효성 검증 표시기를 설정한다. 빨간 점 indicator + hidden input으로 구현.
38
-
39
- ```typescript
40
- function setupInvalid(getInvalidMessage: () => string): void
41
- ```
42
-
43
- 빈 문자열이면 유효, 비어있지 않으면 무효.
44
-
45
- ## `setupModelHook`
46
-
47
- model signal의 `set`/`update`를 가드 함수로 래핑한다. 가드 함수가 `false`를 반환하면 값 변경을 차단.
48
-
49
- ```typescript
50
- function setupModelHook<T, S extends WritableSignal<T>>(
51
- model: S,
52
- canFn: Signal<(item: T) => boolean | Promise<boolean>>,
53
- ): void
54
- ```
55
-
56
- ## `setupCanDeactivate`
57
-
58
- 모달 또는 라우트에 canDeactivate 가드를 설정한다.
59
-
60
- ```typescript
61
- function setupCanDeactivate(fn: () => boolean): void
62
- ```
63
-
64
- - 모달 내부이면 `SdActivatedModalProvider.canDeactivateFn`에 설정
65
- - 라우트 내부이면 `routeConfig.canDeactivate`에 추가
66
- - control 뷰에서는 라우트도 모달도 아니므로 아무 동작 하지 않음
67
-
68
- ### 사용 패턴
69
-
70
- #### 기본 패턴 (편집 이탈 방지)
71
-
72
- ```typescript
73
- setupCanDeactivate(() => this._checkIgnoreChanges());
74
- ```
75
-
76
- `_checkIgnoreChanges()`가 `false`를 반환하면 이탈이 차단된다 (confirm 대화상자로 사용자 확인).
77
-
78
- #### 뷰 타입별 분기 패턴
79
-
80
- modal 뷰를 추가 지원할 때, 모달에서는 취소 버튼으로 제어하므로 항상 이탈을 허용한다:
81
-
82
- ```typescript
83
- setupCanDeactivate(() => this.viewType() === "modal" || this._checkIgnoreChanges());
84
- ```
85
-
86
- - **모달 뷰**: `true` → 항상 이탈 허용 (모달 자체 취소 버튼으로 제어)
87
- - **페이지 뷰**: `_checkIgnoreChanges()` → confirm 결과로 제어
88
- - **control 뷰**: setupCanDeactivate 내부에서 아무 동작 하지 않음 (라우트도 모달도 아님)
89
-
90
- **실사용 예:**
91
- - [crud-list.md §5 확장 A: inline 편집/저장](../recipes/crud-list.md#5-확장-a-inline-편집저장) — 기본 패턴
92
- - [crud-detail.md §5 확장 A: 편집/저장](../recipes/crud-detail.md#5-확장-a-편집저장) — 기본 패턴
93
- - [crud-detail.md §7 확장 C: modal 뷰](../recipes/crud-detail.md#7-확장-c-modal-뷰) — 뷰 타입별 분기 패턴