@simplysm/angular 14.0.48 → 14.0.51

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 (144) hide show
  1. package/README.md +234 -226
  2. package/dist/controls/select/sd-select.js +3 -3
  3. package/dist/index.d.ts +0 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +0 -2
  6. package/dist/layout/dock/sd-dock-container.js +1 -1
  7. package/dist/styles.css +9 -0
  8. package/docs/bootstrap/provide-sd-angular.md +37 -0
  9. package/docs/bootstrap/sd-angular-config-provider.md +16 -0
  10. package/docs/directives/sd-command-directive.md +30 -0
  11. package/docs/directives/sd-events.md +25 -0
  12. package/docs/directives/sd-intersection-directive.md +36 -0
  13. package/docs/directives/sd-invalid.md +24 -0
  14. package/docs/directives/sd-resize-directive.md +42 -0
  15. package/docs/directives/sd-ripple.md +23 -0
  16. package/docs/directives/sd-router-link.md +38 -0
  17. package/docs/directives/sd-show-effect.md +18 -0
  18. package/docs/directives/sd-typed-template.md +69 -0
  19. package/docs/features/sd-address-search-modal.md +50 -0
  20. package/docs/features/sd-permission-table.md +20 -0
  21. package/docs/features/sd-shared-data-components.md +158 -0
  22. package/docs/features/sd-tiptap-editor.md +26 -0
  23. package/docs/{pipes.md → pipes/format-pipe.md} +14 -5
  24. package/docs/plugins/sd-global-error-handler.md +23 -0
  25. package/docs/{plugins.md → plugins/sd-option-event-plugin.md} +9 -12
  26. package/docs/provider-types/sd-menu.md +65 -0
  27. package/docs/provider-types/sd-modal-content-def.md +148 -0
  28. package/docs/provider-types/sd-toast-content-def.md +73 -0
  29. package/docs/provider-types/shared-data-base.md +59 -0
  30. package/docs/providers/sd-activated-modal-provider.md +34 -0
  31. package/docs/providers/sd-app-structure-provider.md +81 -0
  32. package/docs/providers/sd-busy-provider.md +18 -0
  33. package/docs/providers/sd-file-dialog-provider.md +40 -0
  34. package/docs/providers/sd-local-storage-provider.md +20 -0
  35. package/docs/providers/sd-modal-provider.md +67 -0
  36. package/docs/providers/sd-navigate-window-provider.md +18 -0
  37. package/docs/providers/sd-print-provider.md +25 -0
  38. package/docs/providers/sd-service-client-factory-provider.md +43 -0
  39. package/docs/providers/sd-shared-data-provider.md +64 -0
  40. package/docs/providers/sd-system-config-provider.md +46 -0
  41. package/docs/providers/sd-system-log-provider.md +18 -0
  42. package/docs/providers/sd-theme-provider.md +38 -0
  43. package/docs/providers/sd-toast-provider.md +65 -0
  44. package/docs/recipes/_common-rules.md +244 -0
  45. package/docs/recipes/crud-detail/extension-a-edit-save.md +230 -0
  46. package/docs/recipes/crud-detail/extension-b-delete-restore.md +142 -0
  47. package/docs/recipes/crud-detail/extension-c-modal-view.md +214 -0
  48. package/docs/recipes/crud-detail/extension-d-control-view.md +103 -0
  49. package/docs/recipes/crud-detail/extension-e-auxiliary.md +87 -0
  50. package/docs/recipes/crud-detail/extension-f-complex-detail.md +234 -0
  51. package/docs/recipes/crud-detail.md +215 -722
  52. package/docs/recipes/crud-list/extension-a-inline-edit.md +410 -0
  53. package/docs/recipes/crud-list/extension-b-selection.md +226 -0
  54. package/docs/recipes/crud-list/extension-c-inline-delete.md +87 -0
  55. package/docs/recipes/crud-list/extension-d-select-modal.md +207 -0
  56. package/docs/recipes/crud-list/extension-e-readonly-modal.md +165 -0
  57. package/docs/recipes/crud-list/extension-f-modal-edit.md +177 -0
  58. package/docs/recipes/crud-list/extension-g-excel.md +157 -0
  59. package/docs/recipes/crud-list.md +293 -626
  60. package/docs/recipes/data-select-button.md +194 -101
  61. package/docs/recipes/page-modal-container.md +168 -86
  62. package/docs/styling/classes.md +149 -0
  63. package/docs/styling/mixins.md +100 -0
  64. package/docs/styling/themes.md +35 -0
  65. package/docs/styling/variables.md +147 -0
  66. package/docs/{type-utilities.md → type-utilities/directive-input-signals.md} +17 -35
  67. package/docs/ui-data/sd-list.md +37 -0
  68. package/docs/ui-data/sd-sheet.md +227 -0
  69. package/docs/ui-form/sd-additional-button.md +26 -0
  70. package/docs/ui-form/sd-anchor.md +31 -0
  71. package/docs/ui-form/sd-button.md +105 -0
  72. package/docs/ui-form/sd-checkbox-group.md +39 -0
  73. package/docs/ui-form/sd-checkbox.md +81 -0
  74. package/docs/ui-form/sd-date-range-picker.md +27 -0
  75. package/docs/ui-form/sd-form.md +89 -0
  76. package/docs/ui-form/sd-modal-select-button.md +54 -0
  77. package/docs/ui-form/sd-numpad.md +26 -0
  78. package/docs/ui-form/sd-range.md +26 -0
  79. package/docs/ui-form/sd-select.md +68 -0
  80. package/docs/ui-form/sd-shared-data-select.md +52 -0
  81. package/docs/ui-form/sd-state-preset.md +37 -0
  82. package/docs/ui-form/sd-switch.md +27 -0
  83. package/docs/ui-form/sd-textarea.md +33 -0
  84. package/docs/ui-form/sd-textfield.md +145 -0
  85. package/docs/ui-layout/sd-dock-container.md +64 -0
  86. package/docs/ui-layout/sd-dock.md +37 -0
  87. package/docs/ui-layout/sd-gap.md +26 -0
  88. package/docs/{ui-layout.md → ui-layout/sd-kanban-board.md} +41 -85
  89. package/docs/ui-layout/sd-kanban-lane.md +34 -0
  90. package/docs/ui-layout/sd-kanban.md +29 -0
  91. package/docs/ui-navigation/sd-collapse.md +35 -0
  92. package/docs/ui-navigation/sd-pagination.md +26 -0
  93. package/docs/ui-navigation/sd-sidebar-container.md +49 -0
  94. package/docs/ui-navigation/sd-sidebar-menu.md +22 -0
  95. package/docs/ui-navigation/sd-sidebar-user.md +43 -0
  96. package/docs/ui-navigation/sd-tab.md +51 -0
  97. package/docs/ui-navigation/sd-topbar-container.md +97 -0
  98. package/docs/ui-navigation/sd-topbar-menu.md +23 -0
  99. package/docs/ui-navigation/sd-topbar-user.md +38 -0
  100. package/docs/ui-navigation/sd-topbar.md +30 -0
  101. package/docs/ui-overlay/sd-busy-container.md +69 -0
  102. package/docs/ui-overlay/sd-confirm-modal.md +30 -0
  103. package/docs/ui-overlay/sd-dropdown.md +40 -0
  104. package/docs/ui-overlay/sd-modal.md +34 -0
  105. package/docs/ui-overlay/sd-prompt-modal.md +30 -0
  106. package/docs/ui-overlay/sd-toast.md +35 -0
  107. package/docs/ui-visual/sd-barcode.md +36 -0
  108. package/docs/ui-visual/sd-calendar.md +34 -0
  109. package/docs/ui-visual/sd-echarts.md +32 -0
  110. package/docs/ui-visual/sd-label.md +24 -0
  111. package/docs/ui-visual/sd-note.md +23 -0
  112. package/docs/ui-visual/sd-progress.md +23 -0
  113. package/docs/utils/inject-routing-signals.md +161 -0
  114. package/docs/utils/inject-sd-system-config-resource.md +35 -0
  115. package/docs/utils/mark.md +43 -0
  116. package/docs/utils/selection-managers.md +96 -0
  117. package/docs/utils/set-safe-style.md +19 -0
  118. package/docs/utils/setup-functions.md +93 -0
  119. package/package.json +7 -7
  120. package/scss/commons/_styles.scss +12 -0
  121. package/src/controls/select/sd-select.ts +3 -3
  122. package/src/core/modal/sd-modal.provider.ts +1 -1
  123. package/src/core/modal/sd-modal.ts +1 -1
  124. package/src/core/routing/menu-utils.ts +1 -1
  125. package/src/core/shared-data/sd-shared-data.provider.ts +7 -7
  126. package/src/data/shared-data/sd-shared-data-select.ts +2 -2
  127. package/src/index.ts +0 -3
  128. package/src/layout/dock/sd-dock-container.ts +1 -1
  129. package/dist/data/getOrmDataEditToastErrorMessage.d.ts +0 -2
  130. package/dist/data/getOrmDataEditToastErrorMessage.d.ts.map +0 -1
  131. package/dist/data/getOrmDataEditToastErrorMessage.js +0 -8
  132. package/docs/bootstrap.md +0 -38
  133. package/docs/directives.md +0 -236
  134. package/docs/features.md +0 -169
  135. package/docs/provider-types.md +0 -283
  136. package/docs/providers.md +0 -379
  137. package/docs/styling.md +0 -222
  138. package/docs/ui-data.md +0 -333
  139. package/docs/ui-form.md +0 -502
  140. package/docs/ui-navigation.md +0 -273
  141. package/docs/ui-overlay.md +0 -157
  142. package/docs/ui-visual.md +0 -127
  143. package/docs/utils.md +0 -244
  144. package/src/data/getOrmDataEditToastErrorMessage.ts +0 -10
@@ -0,0 +1,43 @@
1
+ # `SdSidebarUser`
2
+
3
+ 사이드바 하단 사용자 영역 컴포넌트. 사용자 정보를 표시하고, 선택적으로 드롭다운 메뉴를 제공한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-sidebar-user", ... })
7
+ export class SdSidebarUser
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `userMenu` | input | `SdSidebarUserMenu \| undefined` | 사용자 메뉴 정보. `title`이 있으면 메뉴 버튼 표시 |
15
+
16
+ ## Related Types
17
+
18
+ ### `SdSidebarUserMenu`
19
+
20
+ ```typescript
21
+ interface SdSidebarUserMenu {
22
+ title: string;
23
+ menus: {
24
+ title: string;
25
+ onClick: () => void;
26
+ }[];
27
+ }
28
+ ```
29
+
30
+ | Field | Type | Description |
31
+ |-------|------|-------------|
32
+ | `title` | `string` | 메뉴 버튼 라벨 |
33
+ | `menus` | `{ title: string; onClick: () => void }[]` | 드롭다운 메뉴 항목 목록 |
34
+
35
+ ## Usage
36
+
37
+ ```html
38
+ <sd-sidebar-user
39
+ [userMenu]="{ title: '홍길동', menus: [{ title: '로그아웃', onClick: logout }] }"
40
+ >
41
+ <span>홍길동</span>
42
+ </sd-sidebar-user>
43
+ ```
@@ -0,0 +1,51 @@
1
+ # `SdTab`
2
+
3
+ 탭 컨테이너 컴포넌트. 선택된 값을 `value` model로 보관한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-tab" })
7
+ class SdTab<T> {
8
+ value = model<T>();
9
+ }
10
+ ```
11
+
12
+ > **CRITICAL — 역할 범위**
13
+ > `sd-tab`/`sd-tab-item`은 **상단의 탭 선택 UI만** 담당한다. 내부 뷰(패널) 전환 기능은 **없다**.
14
+ > `sd-tab-item`의 `<ng-content>`는 **탭 라벨 전용**이다. 이 안에 시트/폼/상세 등 뷰 콘텐츠를 넣지 않는다.
15
+ > 뷰 콘텐츠는 `sd-tab` **바깥**에서 선택된 `value`를 기준으로 `@if` / `@switch`로 제어한다.
16
+
17
+ ## Members
18
+
19
+ | Member | Kind | Type | Description |
20
+ |--------|------|------|-------------|
21
+ | `value` | model | `T \| undefined` | 선택된 탭 값 (two-way) |
22
+
23
+ ## Related Types
24
+
25
+ ### `SdTabItem`
26
+
27
+ 탭 항목 컴포넌트. 자신의 `value`가 부모 `SdTab.value`와 같으면 선택 상태가 된다.
28
+
29
+ ```typescript
30
+ @Component({ selector: "sd-tab-item" })
31
+ class SdTabItem<T> {
32
+ value = input.required<T>();
33
+ }
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ ```html
39
+ <!-- ✅ 올바른 사용: 탭은 선택 UI, 뷰는 @if로 제어 -->
40
+ <sd-tab [(value)]="tab">
41
+ <sd-tab-item [value]="'list'">목록</sd-tab-item>
42
+ <sd-tab-item [value]="'detail'">상세</sd-tab-item>
43
+ </sd-tab>
44
+
45
+ @if (tab() === "list") {
46
+ <sd-sheet ...></sd-sheet>
47
+ }
48
+ @if (tab() === "detail") {
49
+ <app-detail ...></app-detail>
50
+ }
51
+ ```
@@ -0,0 +1,97 @@
1
+ # `SdTopbarContainer`
2
+
3
+ 탑바 컨테이너.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-topbar-container" })
7
+ class SdTopbarContainer { }
8
+ ```
9
+
10
+ ## Related Types
11
+
12
+ ### `SdTopbar`
13
+
14
+ 탑바 컴포넌트.
15
+
16
+ ```typescript
17
+ @Component({ selector: "sd-topbar" })
18
+ class SdTopbar { }
19
+ ```
20
+
21
+ ### `SdTopbarMenu`
22
+
23
+ 탑바 메뉴 항목.
24
+
25
+ ```typescript
26
+ @Component({ selector: "sd-topbar-menu" })
27
+ class SdTopbarMenu {
28
+ menus = input<SdMenu[]>([]);
29
+ getMenuIsSelectedFn = input<(menu: SdMenu) => boolean>();
30
+ }
31
+ ```
32
+
33
+ | Input | Type | Default | Description |
34
+ |-------|------|---------|-------------|
35
+ | `menus` | `SdMenu[]` | `[]` | 메뉴 항목 |
36
+ | `getMenuIsSelectedFn` | `((menu) => boolean) \| undefined` | `undefined` | 커스텀 메뉴 선택 여부 함수 |
37
+
38
+ ### `SdTopbarUser`
39
+
40
+ 탑바 사용자 영역 컴포넌트.
41
+
42
+ ```typescript
43
+ @Component({ selector: "sd-topbar-user" })
44
+ class SdTopbarUser {
45
+ menus = input.required<SdTopbarUserMenu[]>();
46
+ }
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ ### topbar 내부 슬롯 활용
52
+
53
+ ```html
54
+ <sd-topbar-container>
55
+ @if (viewType() === "page") {
56
+ <sd-topbar>
57
+ <h4>{{ viewTitle() }}</h4>
58
+ <sd-button [size]="'sm'" [theme]="'link-info'" (click)="onRefreshButtonClick()">
59
+ <ng-icon [svg]="icons.tablerRefresh" />
60
+ 새로고침
61
+ <small>(Ctrl+Alt+L)</small>
62
+ </sd-button>
63
+ </sd-topbar>
64
+ }
65
+ <!-- 메인 콘텐츠 -->
66
+ </sd-topbar-container>
67
+ ```
68
+
69
+ 페이지/모달/control 뷰에서 **재사용**되는 화면은 topbar를 page 뷰에서만 렌더한다. `@if (viewType() === "page")` 조건을 사용한다.
70
+
71
+ ### 실사용 예
72
+
73
+ - [crud-list.md §3 최소 뼈대: 조회 전용 page](../recipes/crud-list.md#3-최소-뼈대-조회-전용-page) — topbar + 새로고침 버튼 + 단축키 힌트
74
+ - [crud-list.md §5 확장 A: inline 편집/저장](../recipes/crud-list.md#5-확장-a-inline-편집저장) — topbar 내 저장·등록 버튼 추가
75
+ - [crud-list.md §11 확장 G: 엑셀 업로드/다운로드](../recipes/crud-list.md#11-확장-g-엑셀-업로드다운로드) — topbar 내 엑셀 버튼 추가
76
+ - [crud-detail.md §3 최소 뼈대: 읽기 전용 상세 폼](../recipes/crud-detail.md#3-최소-뼈대-읽기-전용-상세-폼) — topbar 조건 없이 렌더 (page 뷰 전용)
77
+ - [crud-detail.md §5 확장 A: 편집/저장](../recipes/crud-detail.md#5-확장-a-편집저장) — topbar 내 저장 버튼 추가
78
+ - [crud-detail.md §7 확장 C: modal 뷰](../recipes/crud-detail.md#7-확장-c-modal-뷰) — `@if (viewType() === "page")` 조건부 렌더
79
+
80
+ ## `SdPagination`
81
+
82
+ 페이지네이션 컴포넌트.
83
+
84
+ ```typescript
85
+ @Component({ selector: "sd-pagination" })
86
+ class SdPagination {
87
+ currentPage = model(0);
88
+ totalPageCount = input(0, { transform: numberAttribute });
89
+ visiblePageCount = input(10, { transform: numberAttribute });
90
+ }
91
+ ```
92
+
93
+ | Input | Type | Default | Description |
94
+ |-------|------|---------|-------------|
95
+ | `currentPage` | `number` | `0` | 현재 페이지 (0-based, two-way) |
96
+ | `totalPageCount` | `number` | `0` | 총 페이지 수 |
97
+ | `visiblePageCount` | `number` | `10` | 한 번에 표시할 페이지 수 |
@@ -0,0 +1,23 @@
1
+ # `SdTopbarMenu`
2
+
3
+ 탑바 메뉴 컴포넌트. `SdMenu[]` 트리를 드롭다운 방식으로 렌더링한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-topbar-menu", ... })
7
+ export class SdTopbarMenu
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `menus` | input | `SdMenu[]` | 메뉴 트리 (기본값: `[]`) |
15
+ | `getMenuIsSelectedFn` | input | `(menu: SdMenu) => boolean \| undefined` | 메뉴 선택 여부 커스텀 함수 |
16
+
17
+ ## Usage
18
+
19
+ ```html
20
+ <sd-topbar>
21
+ <sd-topbar-menu [menus]="sdAppStructure.usableMenus()" />
22
+ </sd-topbar>
23
+ ```
@@ -0,0 +1,38 @@
1
+ # `SdTopbarUser`
2
+
3
+ 탑바 사용자 영역 컴포넌트. 사용자 이름을 버튼으로 표시하고, 클릭 시 드롭다운 메뉴를 제공한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-topbar-user", ... })
7
+ export class SdTopbarUser
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `menus` | input (required) | `SdTopbarUserMenu[]` | 드롭다운 메뉴 항목 목록 |
15
+
16
+ ## Related Types
17
+
18
+ ### `SdTopbarUserMenu`
19
+
20
+ ```typescript
21
+ interface SdTopbarUserMenu {
22
+ title: string;
23
+ onClick: () => void;
24
+ }
25
+ ```
26
+
27
+ | Field | Type | Description |
28
+ |-------|------|-------------|
29
+ | `title` | `string` | 메뉴 항목 텍스트 |
30
+ | `onClick` | `() => void` | 클릭 핸들러 |
31
+
32
+ ## Usage
33
+
34
+ ```html
35
+ <sd-topbar-user [menus]="[{ title: '내 정보', onClick: goToProfile }, { title: '로그아웃', onClick: logout }]">
36
+ 홍길동
37
+ </sd-topbar-user>
38
+ ```
@@ -0,0 +1,30 @@
1
+ # `SdTopbar`
2
+
3
+ 탑바 컴포넌트. `SdTopbarContainer` 내부에서 사용하며, 사이드바 토글 버튼과 콘텐츠 슬롯을 제공한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-topbar", ... })
7
+ export class SdTopbar
8
+ ```
9
+
10
+ `SdSidebarContainer`가 상위에 있으면 자동으로 사이드바 토글 버튼을 표시한다.
11
+
12
+ ### 실사용 예
13
+
14
+ - [crud-list.md §3 최소 뼈대: 조회 전용 page](../recipes/crud-list.md#3-최소-뼈대-조회-전용-page) — `<h4>` 타이틀 + 새로고침 버튼 + `<small>` 단축키 힌트
15
+ - [crud-list.md §5 확장 A: inline 편집/저장](../recipes/crud-list.md#5-확장-a-inline-편집저장) — 저장·등록 버튼 추가
16
+ - [crud-detail.md §3 최소 뼈대: 읽기 전용 상세 폼](../recipes/crud-detail.md#3-최소-뼈대-읽기-전용-상세-폼) — `<h4>` 타이틀 + 새로고침 버튼
17
+ - [crud-detail.md §7 확장 C: modal 뷰](../recipes/crud-detail.md#7-확장-c-modal-뷰) — `@if (viewType() === "page")` 조건부 렌더
18
+
19
+ ## Usage
20
+
21
+ ```html
22
+ <sd-topbar-container>
23
+ <sd-topbar>
24
+ <h1>앱 타이틀</h1>
25
+ <sd-topbar-menu [menus]="menus()" />
26
+ <sd-topbar-user [menus]="userMenus()" />
27
+ </sd-topbar>
28
+ ...
29
+ </sd-topbar-container>
30
+ ```
@@ -0,0 +1,69 @@
1
+ # `SdBusyContainer`
2
+
3
+ busy 상태(로딩 중) 표시 컨테이너 컴포넌트. `busy` 입력이 `true`일 때 스크린 오버레이와 인디케이터를 표시한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-busy-container", ... })
7
+ export class SdBusyContainer
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `busy` | input | `boolean` | busy 상태 (기본값: `false`) |
15
+ | `type` | input | `SdBusyType` | 인디케이터 유형. 미지정 시 `SdBusyProvider.type()` 값 사용 |
16
+
17
+ 글로벌 busy 표시는 [`SdBusyProvider`](../providers/sd-busy-provider.md)를 통해 관리한다.
18
+
19
+ ## Usage
20
+
21
+ ```html
22
+ <!-- 컴포넌트 로컬 busy -->
23
+ <sd-busy-container [busy]="busyCount() > 0">
24
+ <!-- 콘텐츠 -->
25
+ </sd-busy-container>
26
+ ```
27
+
28
+ ### busyCount 카운트 패턴
29
+
30
+ 비동기 작업마다 카운트를 증감하여 동시 요청을 안전하게 처리한다:
31
+
32
+ ```typescript
33
+ busyCount = signal(0);
34
+
35
+ async _refresh(): Promise<void> {
36
+ this.busyCount.update((v) => v + 1);
37
+ await this._sdToast.try(async () => {
38
+ // ... 비동기 작업
39
+ });
40
+ this.busyCount.update((v) => v - 1);
41
+ }
42
+ ```
43
+
44
+ ```html
45
+ <sd-busy-container [busy]="busyCount() > 0">
46
+ ```
47
+
48
+ ### busyMessage 선택적 패턴
49
+
50
+ 긴 작업(엑셀 업로드 등) 시에만 사용. 기본적으로는 메시지 없이 인디케이터만 표시한다:
51
+
52
+ ```typescript
53
+ busyMessage = signal<string | undefined>(undefined);
54
+
55
+ // 긴 작업 시
56
+ this.busyMessage.set("엑셀 업로드 중...");
57
+ // ... 작업 완료 후
58
+ this.busyMessage.set(undefined);
59
+ ```
60
+
61
+ ```html
62
+ <sd-busy-container [busy]="busyCount() > 0" [message]="busyMessage()">
63
+ ```
64
+
65
+ ### 실사용 예
66
+
67
+ - [crud-list.md §3 최소 뼈대: 조회 전용 page](../recipes/crud-list.md#3-최소-뼈대-조회-전용-page) — busyCount 기본 패턴
68
+ - [crud-list.md §11 확장 G: 엑셀 업로드/다운로드](../recipes/crud-list.md#11-확장-g-엑셀-업로드다운로드) — busyMessage 패턴
69
+ - [crud-detail.md §3 최소 뼈대: 읽기 전용 상세 폼](../recipes/crud-detail.md#3-최소-뼈대-읽기-전용-상세-폼) — busyCount 기본 패턴
@@ -0,0 +1,30 @@
1
+ # `SdConfirmModal`
2
+
3
+ 범용 확인 모달. `SdModalContentDef<boolean>`을 구현한다.
4
+ 메시지를 표시하고 확인/취소한다. 확인 시 `true` 반환, 취소 시 `undefined` 반환.
5
+
6
+ ```typescript
7
+ @Component({ selector: "sd-confirm-modal", ... })
8
+ export class SdConfirmModal implements SdModalContentDef<boolean>
9
+ ```
10
+
11
+ ## Members
12
+
13
+ | Member | Kind | Type | Description |
14
+ |--------|------|------|-------------|
15
+ | `message` | input (required) | `string` | 표시할 메시지 (HTML 허용) |
16
+ | `initialized` | property | `Signal<boolean>` | 항상 `true` (SdModalContentDef 요구사항) |
17
+ | `close` | output | `boolean \| undefined` | 확인: `true`, 취소: `undefined` |
18
+
19
+ ## Usage
20
+
21
+ ```typescript
22
+ const confirmed = await this._sdModal.showAsync({
23
+ title: "삭제 확인",
24
+ type: SdConfirmModal,
25
+ inputs: { message: "정말 삭제하시겠습니까?" },
26
+ });
27
+ if (confirmed) {
28
+ await this._delete();
29
+ }
30
+ ```
@@ -0,0 +1,40 @@
1
+ # `SdDropdown`
2
+
3
+ 드롭다운 트리거 컴포넌트. 클릭 또는 키보드로 `SdDropdownPopup`을 열고 닫는다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-dropdown", ... })
7
+ export class SdDropdown
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `open` | model | `boolean` | 팝업 열림 상태 (기본값: `false`) |
15
+ | `disabled` | input | `boolean` | 비활성화 (기본값: `false`) |
16
+
17
+ ## Related Types
18
+
19
+ ### `SdDropdownPopup`
20
+
21
+ ```typescript
22
+ @Component({ selector: "sd-dropdown-popup", ... })
23
+ export class SdDropdownPopup
24
+ ```
25
+
26
+ 드롭다운 팝업 영역. `SdDropdown` 내부에서만 사용한다.
27
+
28
+ ## Usage
29
+
30
+ ```html
31
+ <sd-dropdown>
32
+ <sd-button>메뉴 열기</sd-button>
33
+ <sd-dropdown-popup>
34
+ <sd-list>
35
+ <sd-list-item (click)="onAction1()">동작 1</sd-list-item>
36
+ <sd-list-item (click)="onAction2()">동작 2</sd-list-item>
37
+ </sd-list>
38
+ </sd-dropdown-popup>
39
+ </sd-dropdown>
40
+ ```
@@ -0,0 +1,34 @@
1
+ # `SdModal`
2
+
3
+ 모달 래퍼 컴포넌트. `SdModalProvider.showAsync()`에 의해 프로그래밍 방식으로 생성된다. 직접 템플릿에 배치하지 않는다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-modal", ... })
7
+ export class SdModal
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `open` | model | `boolean` | 열림 상태 (기본값: `false`) |
15
+ | `key` | input | `string \| undefined` | 설정 저장 키 (크기/위치 저장) |
16
+ | `title` | input | `string` | 모달 제목 (기본값: `""`) |
17
+ | `hideHeader` | input | `boolean` | 헤더 숨김 (기본값: `false`) |
18
+ | `hideCloseButton` | input | `boolean` | 닫기 버튼 숨김 (기본값: `false`) |
19
+ | `headerStyle` | input | `string \| undefined` | 헤더 인라인 스타일 |
20
+ | `useCloseByBackdrop` | input | `boolean` | 배경 클릭으로 닫기 (기본값: `true`) |
21
+ | `useCloseByEscapeKey` | input | `boolean` | ESC 키로 닫기 (기본값: `true`) |
22
+ | `float` | input | `boolean` | 플로팅 모달 (backdrop 없음) (기본값: `false`) |
23
+ | `fill` | input | `boolean` | 전체 화면 채우기 (기본값: `false`) |
24
+ | `resizable` | input | `boolean` | 크기 조절 가능 (기본값: `false`) |
25
+ | `movable` | input | `boolean` | 이동 가능 (기본값: `false`) |
26
+ | `position` | input | `"bottom-right" \| "top-right" \| undefined` | 초기 위치 |
27
+ | `minHeightPx` | input | `number \| undefined` | 최소 높이 |
28
+ | `minWidthPx` | input | `number \| undefined` | 최소 너비 |
29
+ | `heightPx` | input | `number \| undefined` | 초기 높이 |
30
+ | `widthPx` | input | `number \| undefined` | 초기 너비 |
31
+ | `actionTplRef` | input | `TemplateRef<any> \| undefined` | 헤더 액션 영역 템플릿 |
32
+ | `closeRequest` | output | `void` | 닫기 요청 (배경 클릭, ESC, X 버튼) |
33
+
34
+ 모달 컴포넌트를 직접 사용하는 대신 [`SdModalProvider`](../providers/sd-modal-provider.md)를 사용한다.
@@ -0,0 +1,30 @@
1
+ # `SdPromptModal`
2
+
3
+ 범용 프롬프트 입력 모달. `SdModalContentDef<string>`을 구현한다.
4
+ 메시지를 표시하고 텍스트 입력 후 확인/취소한다. 확인 시 입력값 반환, 취소 시 `undefined` 반환.
5
+
6
+ ```typescript
7
+ @Component({ selector: "sd-prompt-modal", ... })
8
+ export class SdPromptModal implements SdModalContentDef<string>
9
+ ```
10
+
11
+ ## Members
12
+
13
+ | Member | Kind | Type | Description |
14
+ |--------|------|------|-------------|
15
+ | `message` | input (required) | `string` | 표시할 메시지 (HTML 허용) |
16
+ | `initialized` | property | `Signal<boolean>` | 항상 `true` (SdModalContentDef 요구사항) |
17
+ | `close` | output | `string \| undefined` | 확인: 입력값, 취소: `undefined` |
18
+
19
+ ## Usage
20
+
21
+ ```typescript
22
+ const name = await this._sdModal.showAsync({
23
+ title: "이름 입력",
24
+ type: SdPromptModal,
25
+ inputs: { message: "새 항목의 이름을 입력하세요." },
26
+ });
27
+ if (name != null) {
28
+ // 입력한 이름 사용
29
+ }
30
+ ```
@@ -0,0 +1,35 @@
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`) |
@@ -0,0 +1,36 @@
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
+ ```
@@ -0,0 +1,34 @@
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
+ ```
@@ -0,0 +1,32 @@
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
+ ```
@@ -0,0 +1,24 @@
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
+ ```
@@ -0,0 +1,23 @@
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
+ ```