@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,105 @@
1
+ # `SdButton`
2
+
3
+ 버튼 컴포넌트.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-button" })
7
+ class SdButton {
8
+ type = input<"button" | "submit">("button");
9
+ theme = input<"primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray" | "link" | "link-primary" | "link-secondary" | "link-info" | "link-success" | "link-warning" | "link-danger" | "link-gray" | "link-blue-gray" | "link-rev">();
10
+ inline = input(false, { transform: booleanAttribute });
11
+ inset = input(false, { transform: booleanAttribute });
12
+ size = input<"sm" | "lg">();
13
+ disabled = input(false, { transform: booleanAttribute });
14
+ buttonStyle = input<string>();
15
+ buttonClass = input<string>();
16
+ }
17
+ ```
18
+
19
+ ## Members
20
+
21
+ | Member | Kind | Type | Default | Description |
22
+ |--------|------|------|---------|-------------|
23
+ | `type` | input | `"button" \| "submit"` | `"button"` | 버튼 HTML 타입 |
24
+ | `theme` | input | `string \| undefined` | `undefined` | 테마 색상 |
25
+ | `inline` | input | `boolean` | `false` | 인라인 표시 |
26
+ | `inset` | input | `boolean` | `false` | 테두리 없는 삽입 스타일 |
27
+ | `size` | input | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
28
+ | `disabled` | input | `boolean` | `false` | 비활성화 |
29
+ | `buttonStyle` | input | `string \| undefined` | `undefined` | 버튼 인라인 스타일 |
30
+ | `buttonClass` | input | `string \| undefined` | `undefined` | 버튼 CSS 클래스 |
31
+
32
+ **스타일 적용**: 시각적 스타일은 내부 `<button>`에 적용되므로 `buttonClass`/`buttonStyle`을 사용한다. 호스트(`<sd-button>`)에 직접 `class`/`style`을 줘도 버튼 외형은 변경되지 않는다.
33
+
34
+ ### 실사용 예
35
+
36
+ - [crud-list.md §3 최소 뼈대: 조회 전용 page](../recipes/crud-list.md#3-최소-뼈대-조회-전용-page) — 새로고침 버튼 (link-info theme)
37
+ - [crud-list.md §5 확장 A: inline 편집/저장](../recipes/crud-list.md#5-확장-a-inline-편집저장) — 저장·등록 버튼 (type="submit", primary theme)
38
+ - [crud-list.md §11 확장 G: 엑셀 업로드/다운로드](../recipes/crud-list.md#11-확장-g-엑셀-업로드다운로드) — 엑셀 업로드·다운로드 버튼
39
+ - [crud-detail.md §3 최소 뼈대: 읽기 전용 상세 폼](../recipes/crud-detail.md#3-최소-뼈대-읽기-전용-상세-폼) — 새로고침 버튼
40
+ - [crud-detail.md §5 확장 A: 편집/저장](../recipes/crud-detail.md#5-확장-a-편집저장) — 저장 버튼 (type="submit")
41
+ - [crud-detail.md §6 확장 B: 삭제/복구 토글](../recipes/crud-detail.md#6-확장-b-삭제복구-토글) — 삭제·복구 버튼 (danger/warning theme)
42
+ - [crud-detail.md §7 확장 C: modal 뷰](../recipes/crud-detail.md#7-확장-c-modal-뷰) — modal 하단 바 확인·취소 버튼
43
+ - [crud-detail.md §8 확장 D: control 뷰](../recipes/crud-detail.md#8-확장-d-control-뷰) — control 상단 바 버튼
44
+
45
+ ## Related Types
46
+
47
+ ### `SdAnchor`
48
+
49
+ 앵커(인라인 버튼) 컴포넌트. 텍스트 내 클릭 가능 요소.
50
+
51
+ ```typescript
52
+ @Component({ selector: "sd-anchor" })
53
+ class SdAnchor {
54
+ disabled = input(false, { transform: booleanAttribute });
55
+ theme = input<"primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray">("primary");
56
+ }
57
+ ```
58
+
59
+ | Input | Type | Default | Description |
60
+ |-------|------|---------|-------------|
61
+ | `disabled` | `boolean` | `false` | 비활성화 |
62
+ | `theme` | `string` | `"primary"` | 테마 색상 |
63
+
64
+ ### `SdAdditionalButton`
65
+
66
+ 추가 동작 버튼. 드롭다운 포함.
67
+
68
+ ```typescript
69
+ @Component({ selector: "sd-additional-button" })
70
+ class SdAdditionalButton {
71
+ size = input<"sm" | "lg">();
72
+ inset = input(false, { transform: booleanAttribute });
73
+ }
74
+ ```
75
+
76
+ ### `SdModalSelectButton`
77
+
78
+ 모달을 열어 선택하는 버튼 컴포넌트.
79
+
80
+ ```typescript
81
+ @Component({ selector: "sd-modal-select-button" })
82
+ class SdModalSelectButton<T extends object, K, M extends keyof SelectModeValue<K>> {
83
+ modal = input.required<SdSelectModalInfo<SdSelectModal<T>>>();
84
+ value = model<SelectModeValue<K>[M]>();
85
+ selectedItems = model<T[]>([]);
86
+ disabled = input(false, { transform: booleanAttribute });
87
+ required = input(false, { transform: booleanAttribute });
88
+ inset = input(false, { transform: booleanAttribute });
89
+ size = input<"sm" | "lg">();
90
+ selectMode = input<M>("single" as M);
91
+ modalOptions = input<SdModalOptions>();
92
+ searchIcon = input(tablerSearch);
93
+ }
94
+ ```
95
+
96
+ | Input | Type | Default | Description |
97
+ |-------|------|---------|-------------|
98
+ | `modal` | `SdSelectModalInfo<...>` | required | 모달 정보 |
99
+ | `value` | `SelectModeValue<K>[M]` | - | 선택된 값 (two-way) |
100
+ | `selectedItems` | `T[]` | `[]` | 선택된 항목 객체 배열 (two-way) |
101
+ | `disabled` | `boolean` | `false` | 비활성화 |
102
+ | `required` | `boolean` | `false` | 필수 (지우기 버튼 숨김) |
103
+ | `inset` | `boolean` | `false` | 삽입 스타일 |
104
+ | `size` | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
105
+ | `selectMode` | `M` | `"single"` | 선택 모드 |
@@ -0,0 +1,39 @@
1
+ # `SdCheckboxGroup`
2
+
3
+ 체크박스 그룹 컴포넌트. `SdCheckboxGroupItem`과 함께 사용하여 다중 선택을 관리한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-checkbox-group", ... })
7
+ export class SdCheckboxGroup<T>
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `value` | model | `T[]` | 선택된 값 배열 (기본값: `[]`) |
15
+ | `disabled` | input | `boolean` | 비활성화 (기본값: `false`) |
16
+
17
+ ## Related Types
18
+
19
+ ### `SdCheckboxGroupItem`
20
+
21
+ ```typescript
22
+ @Component({ selector: "sd-checkbox-group-item", ... })
23
+ export class SdCheckboxGroupItem<T>
24
+ ```
25
+
26
+ | Member | Kind | Type | Description |
27
+ |--------|------|------|-------------|
28
+ | `value` | input (required) | `T` | 이 항목의 값 |
29
+ | `inline` | input | `boolean` | 인라인 표시 (기본값: `false`) |
30
+
31
+ ## Usage
32
+
33
+ ```html
34
+ <sd-checkbox-group [(value)]="selectedRoles">
35
+ <sd-checkbox-group-item [value]="'admin'">관리자</sd-checkbox-group-item>
36
+ <sd-checkbox-group-item [value]="'user'">사용자</sd-checkbox-group-item>
37
+ <sd-checkbox-group-item [value]="'viewer'">조회</sd-checkbox-group-item>
38
+ </sd-checkbox-group>
39
+ ```
@@ -0,0 +1,81 @@
1
+ # `SdCheckbox`
2
+
3
+ 체크박스 컴포넌트.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-checkbox" })
7
+ class SdCheckbox {
8
+ value = model(false);
9
+ canChangeFn = input<(item: boolean) => boolean | Promise<boolean>>(() => true);
10
+ icon = input(tablerCheck);
11
+ radio = input(false, { transform: booleanAttribute });
12
+ disabled = input(false, { transform: booleanAttribute });
13
+ size = input<"sm" | "lg">();
14
+ inline = input(false, { transform: booleanAttribute });
15
+ inset = input(false, { transform: booleanAttribute });
16
+ theme = input<"primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray">();
17
+ contentStyle = input<string>();
18
+ }
19
+ ```
20
+
21
+ ## Members
22
+
23
+ | Member | Kind | Type | Default | Description |
24
+ |--------|------|------|---------|-------------|
25
+ | `value` | model | `boolean` | `false` | 체크 여부 (two-way) |
26
+ | `canChangeFn` | input | `(item: boolean) => boolean \| Promise<boolean>` | `() => true` | 값 변경 가능 여부 함수 |
27
+ | `icon` | input | `string` | `tablerCheck` | 체크 아이콘 |
28
+ | `radio` | input | `boolean` | `false` | 라디오 버튼 스타일 |
29
+ | `disabled` | input | `boolean` | `false` | 비활성화 |
30
+ | `size` | input | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
31
+ | `inline` | input | `boolean` | `false` | 인라인 표시 |
32
+ | `inset` | input | `boolean` | `false` | 삽입 스타일 |
33
+ | `theme` | input | `string \| undefined` | `undefined` | 테마 색상 |
34
+ | `contentStyle` | input | `string \| undefined` | `undefined` | 라벨 텍스트 인라인 스타일 |
35
+
36
+ ### 실사용 예
37
+
38
+ - [crud-list.md §5 확장 A: inline 편집/저장](../recipes/crud-list.md#5-확장-a-inline-편집저장) — 필터 영역 "삭제항목 포함" 체크박스
39
+
40
+ ## Related Types
41
+
42
+ ### `SdSwitch`
43
+
44
+ 스위치 토글 컴포넌트.
45
+
46
+ ```typescript
47
+ @Component({ selector: "sd-switch" })
48
+ class SdSwitch {
49
+ value = model(false);
50
+ canChangeFn = input<(item: boolean) => boolean | Promise<boolean>>(() => true);
51
+ disabled = input(false, { transform: booleanAttribute });
52
+ inline = input(false, { transform: booleanAttribute });
53
+ inset = input(false, { transform: booleanAttribute });
54
+ size = input<"sm" | "lg">();
55
+ theme = input<string>();
56
+ }
57
+ ```
58
+
59
+ ### `SdCheckboxGroup`
60
+
61
+ 체크박스 그룹 컴포넌트.
62
+
63
+ ```typescript
64
+ @Component({ selector: "sd-checkbox-group" })
65
+ class SdCheckboxGroup<T> {
66
+ value = model<T[]>([]);
67
+ disabled = input(false, { transform: booleanAttribute });
68
+ }
69
+ ```
70
+
71
+ ### `SdCheckboxGroupItem`
72
+
73
+ 체크박스 그룹 항목.
74
+
75
+ ```typescript
76
+ @Component({ selector: "sd-checkbox-group-item" })
77
+ class SdCheckboxGroupItem<T> {
78
+ value = input.required<T>();
79
+ inline = input(false, { transform: booleanAttribute });
80
+ }
81
+ ```
@@ -0,0 +1,27 @@
1
+ # `SdDateRangePicker`
2
+
3
+ 날짜 범위 선택 컴포넌트. 기간 유형(`일`/`월`/`범위`)을 선택하고 `from`/`to` 날짜를 입력한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-date-range-picker", ... })
7
+ export class SdDateRangePicker
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `periodType` | model | `"일" \| "월" \| "범위"` | 기간 유형 (기본값: `"범위"`) |
15
+ | `from` | model | `DateOnly \| undefined` | 시작 날짜 |
16
+ | `to` | model | `DateOnly \| undefined` | 종료 날짜 |
17
+ | `required` | input | `boolean` | 필수 여부 (기본값: `false`) |
18
+
19
+ ## Usage
20
+
21
+ ```html
22
+ <sd-date-range-picker
23
+ [(periodType)]="searchPeriodType"
24
+ [(from)]="searchFrom"
25
+ [(to)]="searchTo"
26
+ />
27
+ ```
@@ -0,0 +1,89 @@
1
+ # `SdForm`
2
+
3
+ 폼 래퍼 컴포넌트. `<form>` 태그를 렌더링하며 submit 이벤트 처리 및 유효성 검증을 수행한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-form" })
7
+ class SdForm {
8
+ formSubmit = output<SubmitEvent>();
9
+ formInvalid = output();
10
+
11
+ requestSubmit(): void;
12
+ }
13
+ ```
14
+
15
+ ## Members
16
+
17
+ | Member | Kind | Type | Description |
18
+ |--------|------|------|-------------|
19
+ | `formSubmit` | output | `SubmitEvent` | 유효성 검증 통과 시 발생 |
20
+ | `formInvalid` | output | `void` | 유효성 검증 실패 시 발생 (`reportValidity()` 호출 후) |
21
+ | `requestSubmit()` | method | `() => void` | 프로그래밍 방식으로 submit 트리거 |
22
+
23
+ ## Usage
24
+
25
+ ```html
26
+ <sd-form #formCtrl (formSubmit)="onSubmit($event)">
27
+ <sd-textfield [type]="'text'" [(value)]="name" [required]="true" />
28
+ <sd-button [type]="'submit'">저장</sd-button>
29
+ </sd-form>
30
+ ```
31
+
32
+ 프로그래밍 방식 저장:
33
+
34
+ ```typescript
35
+ const formCtrl = viewChild.required<SdForm>('formCtrl');
36
+
37
+ onSave(): void {
38
+ this.formCtrl().requestSubmit();
39
+ }
40
+ ```
41
+
42
+ ### 실사용 예
43
+
44
+ - [crud-list.md §3 최소 뼈대: 조회 전용 page](../recipes/crud-list.md#3-최소-뼈대-조회-전용-page) — 필터 폼 래퍼 (formSubmit으로 검색 트리거)
45
+ - [crud-list.md §5 확장 A: inline 편집/저장](../recipes/crud-list.md#5-확장-a-inline-편집저장) — 편집 폼 래퍼 (#formCtrl + requestSubmit)
46
+ - [crud-detail.md §3 최소 뼈대: 읽기 전용 상세 폼](../recipes/crud-detail.md#3-최소-뼈대-읽기-전용-상세-폼) — 읽기 전용 필드 배치 컨테이너
47
+ - [crud-detail.md §5 확장 A: 편집/저장](../recipes/crud-detail.md#5-확장-a-편집저장) — 편집 폼 래퍼 (formSubmit + #formCtrl + requestSubmit)
48
+
49
+ ## Related Types
50
+
51
+ ### `SdStatePreset`
52
+
53
+ 상태 프리셋 저장/불러오기 컴포넌트.
54
+
55
+ ```typescript
56
+ @Component({ selector: "sd-state-preset" })
57
+ class SdStatePreset {
58
+ key = input.required<string>();
59
+ state = model<any>();
60
+ size = input<"sm" | "lg">();
61
+ }
62
+ ```
63
+
64
+ ### `SdTiptapEditor`
65
+
66
+ TipTap 기반 리치 텍스트 에디터.
67
+
68
+ ```typescript
69
+ @Component({ selector: "sd-tiptap-editor" })
70
+ class SdTiptapEditor {
71
+ value = model<string>();
72
+ disabled = input(false, { transform: booleanAttribute });
73
+ readonly = input(false, { transform: booleanAttribute });
74
+ required = input(false, { transform: booleanAttribute });
75
+ placeholder = input<string>();
76
+ validatorFn = input<(value: string | undefined) => string | undefined>();
77
+ extensions = input<AnyExtension[]>();
78
+ }
79
+ ```
80
+
81
+ | Input | Type | Default | Description |
82
+ |-------|------|---------|-------------|
83
+ | `value` | `string \| undefined` | - | HTML 콘텐츠 (two-way) |
84
+ | `disabled` | `boolean` | `false` | 비활성화 |
85
+ | `readonly` | `boolean` | `false` | 읽기 전용 |
86
+ | `required` | `boolean` | `false` | 필수 |
87
+ | `placeholder` | `string \| undefined` | `undefined` | 플레이스홀더 |
88
+ | `validatorFn` | `((value) => string \| undefined) \| undefined` | `undefined` | 커스텀 유효성 검증 함수 |
89
+ | `extensions` | `AnyExtension[] \| undefined` | `undefined` | 추가 TipTap 확장 |
@@ -0,0 +1,54 @@
1
+ # `SdModalSelectButton`
2
+
3
+ 모달을 열어 항목을 선택하는 버튼 컴포넌트. 선택된 값은 `value`와 `selectedItems` model로 관리된다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-modal-select-button", ... })
7
+ export class SdModalSelectButton<T extends object, K, M extends keyof SelectModeValue<K> = keyof SelectModeValue<K>>
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `modal` | input (required) | `SdSelectModalInfo<SdSelectModal<T>>` | 모달 정보 |
15
+ | `value` | model | `SelectModeValue<K>[M] \| undefined` | 선택된 키 값 |
16
+ | `selectedItems` | model | `T[]` | 선택된 항목 배열 (기본값: `[]`) |
17
+ | `disabled` | input | `boolean` | 비활성화 여부 (기본값: `false`) |
18
+ | `required` | input | `boolean` | 필수 여부 (기본값: `false`) |
19
+ | `inset` | input | `boolean` | 인셋 스타일 (기본값: `false`) |
20
+ | `size` | input | `"sm" \| "lg" \| undefined` | 크기 |
21
+ | `selectMode` | input | `M` | 선택 모드 (기본값: `"single"`) |
22
+ | `modalOptions` | input | `SdModalOptions \| undefined` | 모달 옵션 |
23
+ | `searchIcon` | input | `string` | 검색 버튼 아이콘 SVG (기본값: `tablerSearch`) |
24
+
25
+ ## Related Types
26
+
27
+ ### `SdSelectModal<T>`
28
+
29
+ ```typescript
30
+ interface SdSelectModal<T> extends SdModalContentDef<SelectModalOutputResult<T>> {
31
+ selectMode: InputSignal<"single" | "multi" | undefined>;
32
+ selectedItemKeys: InputSignal<any[]>;
33
+ }
34
+ ```
35
+
36
+ ### `SdSelectModalInfo<T>`
37
+
38
+ ```typescript
39
+ type SdSelectModalInfo<T extends SdSelectModal<any>> = SdModalInfo<T, "selectMode" | "selectedItemKeys">
40
+ ```
41
+
42
+ `selectMode`, `selectedItemKeys`를 제외한 나머지 inputs만 전달하면 된다.
43
+
44
+ ## Usage
45
+
46
+ ```html
47
+ <sd-modal-select-button
48
+ [modal]="{ title: '고객 선택', type: CustomerSelectModal, inputs: {} }"
49
+ [(value)]="selectedCustomerId"
50
+ [(selectedItems)]="selectedCustomers"
51
+ >
52
+ {{ selectedCustomers()[0]?.name }}
53
+ </sd-modal-select-button>
54
+ ```
@@ -0,0 +1,26 @@
1
+ # `SdNumpad`
2
+
3
+ 숫자 패드 입력 컴포넌트. 버튼을 클릭하여 숫자를 입력한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-numpad", ... })
7
+ export class SdNumpad
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `value` | model | `number \| undefined` | 숫자 값 |
15
+ | `placeholder` | input | `string \| undefined` | 플레이스홀더 |
16
+ | `required` | input | `boolean` | 필수 여부 (기본값: `false`) |
17
+ | `inputDisabled` | input | `boolean` | 상단 텍스트 입력 비활성화 (기본값: `false`) |
18
+ | `useEnterButton` | input | `boolean` | 확인 버튼 표시 (기본값: `false`) |
19
+ | `useMinusButton` | input | `boolean` | 부호 반전 버튼 표시 (기본값: `false`) |
20
+ | `enterButtonClick` | output | `void` | 확인 버튼 클릭 이벤트 |
21
+
22
+ ## Usage
23
+
24
+ ```html
25
+ <sd-numpad [(value)]="quantity" [useEnterButton]="true" (enterButtonClick)="onConfirm()" />
26
+ ```
@@ -0,0 +1,26 @@
1
+ # `SdRange`
2
+
3
+ 범위 입력 컴포넌트. `from`/`to` 두 개의 `SdTextfield`를 나란히 배치한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-range", ... })
7
+ export class SdRange<K extends keyof SdTextfieldTypes>
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `type` | input (required) | `K` | 텍스트필드 타입 (`SdTextfieldTypes`의 키) |
15
+ | `from` | model | `SdTextfieldTypes[K] \| undefined` | 시작 값 |
16
+ | `to` | model | `SdTextfieldTypes[K] \| undefined` | 종료 값 |
17
+ | `inputStyle` | input | `string \| undefined` | 인라인 스타일 |
18
+ | `required` | input | `boolean` | 필수 여부 (기본값: `false`) |
19
+ | `disabled` | input | `boolean` | 비활성화 (기본값: `false`) |
20
+
21
+ ## Usage
22
+
23
+ ```html
24
+ <sd-range [type]="'date'" [(from)]="startDate" [(to)]="endDate" />
25
+ <sd-range [type]="'number'" [(from)]="minValue" [(to)]="maxValue" />
26
+ ```
@@ -0,0 +1,68 @@
1
+ # `SdSelect`
2
+
3
+ 드롭다운 선택 컴포넌트. single/multi 모드를 지원한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-select" })
7
+ class SdSelect<T, M extends keyof SelectModeValue<T>> {
8
+ selectMode = input("single" as M);
9
+ value = model<SelectModeValue<any>[M]>();
10
+ placeholder = input<string>();
11
+ disabled = input(false, { transform: booleanAttribute });
12
+ inline = input(false, { transform: booleanAttribute });
13
+ inset = input(false, { transform: booleanAttribute });
14
+ size = input<"sm" | "lg">();
15
+ required = input(false, { transform: booleanAttribute });
16
+ hideSelectAll = input(false, { transform: booleanAttribute });
17
+ multiSelectionDisplayDirection = input<"vertical">();
18
+ items = input<T[]>();
19
+ getChildrenFn = input<(item: T) => T[] | undefined>();
20
+ contentClass = input<string>();
21
+ contentStyle = input<string>();
22
+ }
23
+ ```
24
+
25
+ ## Members
26
+
27
+ | Member | Kind | Type | Default | Description |
28
+ |--------|------|------|---------|-------------|
29
+ | `selectMode` | input | `M` | `"single"` | 선택 모드 |
30
+ | `value` | model | `SelectModeValue<any>[M]` | - | 선택된 값 (two-way) |
31
+ | `placeholder` | input | `string \| undefined` | `undefined` | 플레이스홀더 |
32
+ | `disabled` | input | `boolean` | `false` | 비활성화 |
33
+ | `inline` | input | `boolean` | `false` | 인라인 표시 |
34
+ | `inset` | input | `boolean` | `false` | 삽입 스타일 |
35
+ | `size` | input | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
36
+ | `required` | input | `boolean` | `false` | 필수 |
37
+ | `hideSelectAll` | input | `boolean` | `false` | multi 모드에서 전체 선택 숨김 |
38
+ | `multiSelectionDisplayDirection` | input | `"vertical" \| undefined` | `undefined` | multi 모드 표시 방향 |
39
+ | `items` | input | `T[] \| undefined` | `undefined` | 항목 배열 |
40
+ | `getChildrenFn` | input | `((item) => T[] \| undefined) \| undefined` | `undefined` | 트리 구조 자식 함수 |
41
+ | `contentClass` | input | `string \| undefined` | `undefined` | 트리거 영역 CSS 클래스 |
42
+ | `contentStyle` | input | `string \| undefined` | `undefined` | 트리거 영역 인라인 스타일 |
43
+
44
+ **스타일 적용**: `contentClass`/`contentStyle`은 트리거 영역(선택값 텍스트와 드롭다운 화살표가 함께 놓인 박스)에만 적용된다.
45
+
46
+ ## Related Types
47
+
48
+ ### `SdSelectItem`
49
+
50
+ 드롭다운 선택 항목.
51
+
52
+ ```typescript
53
+ @Component({ selector: "sd-select-item" })
54
+ class SdSelectItem<T> {
55
+ value = input.required<T>();
56
+ disabled = input(false, { transform: booleanAttribute });
57
+ hidden = input(false, { transform: booleanAttribute });
58
+ }
59
+ ```
60
+
61
+ ### `SdSelectButton`
62
+
63
+ 버튼 스타일 선택 컴포넌트.
64
+
65
+ ```typescript
66
+ @Component({ selector: "sd-select-button" })
67
+ class SdSelectButton<T> { }
68
+ ```
@@ -0,0 +1,52 @@
1
+ # `SdSharedDataSelect`
2
+
3
+ 공유 데이터 드롭다운 선택 컴포넌트. 검색 기능 포함. 상세 API는 [features/sd-shared-data-components.md](../features/sd-shared-data-components.md#sdshareddataselect)를 참조한다.
4
+
5
+ ## 시트 셀 내 사용 패턴
6
+
7
+ 시트 셀 안에서 사용할 때 `[inset]="true" [size]="'sm'"`을 반드시 지정한다.
8
+
9
+ ```html
10
+ <sd-sheet-column [header]="'거래처'" [key]="'vendorId'">
11
+ <ng-template [cell]="items()" let-item let-edit="edit">
12
+ <sd-shared-data-select
13
+ [items]="sharedVendors()"
14
+ [inset]="true"
15
+ [size]="'sm'"
16
+ [disabled]="!canEdit()"
17
+ [readonly]="!edit"
18
+ [(value)]="item.vendorId"
19
+ (valueChange)="mark(items)"
20
+ >
21
+ <ng-template [itemOf]="sharedVendors()">
22
+ <div class="flex-row gap-sm">
23
+ <div>{{ item.__searchText }}</div>
24
+ </div>
25
+ </ng-template>
26
+ </sd-shared-data-select>
27
+ </ng-template>
28
+ </sd-sheet-column>
29
+ ```
30
+
31
+ ## 일반 form 내 사용 패턴
32
+
33
+ ```html
34
+ <sd-shared-data-select
35
+ [items]="sharedVendors()"
36
+ [(value)]="data().vendorId"
37
+ (valueChange)="mark(data)"
38
+ >
39
+ <ng-template [itemOf]="sharedVendors()">
40
+ <div class="flex-row gap-sm">
41
+ <div>{{ item.__searchText }}</div>
42
+ </div>
43
+ </ng-template>
44
+ </sd-shared-data-select>
45
+ ```
46
+
47
+ `<ng-template [itemOf]>` 패턴으로 드롭다운 항목의 표시 형식을 커스터마이징한다.
48
+
49
+ ### 실사용 예
50
+
51
+ - [crud-list.md §5 확장 A: inline 편집/저장](../recipes/crud-list.md#5-확장-a-inline-편집저장) — 시트 셀 내 공유 데이터 선택
52
+ - [crud-detail.md §9 확장 E: 보조 기능 영역](../recipes/crud-detail.md#9-확장-e-보조-기능-영역) — 보조 form 셀렉터
@@ -0,0 +1,37 @@
1
+ # `SdStatePreset`
2
+
3
+ 화면 상태(검색 조건 등)를 로컬 스토리지에 저장하고 불러오는 프리셋 컴포넌트.
4
+ `SdSystemConfigProvider`를 통해 설정 키 기반으로 저장한다.
5
+
6
+ ```typescript
7
+ @Component({ selector: "sd-state-preset", ... })
8
+ export class SdStatePreset
9
+ ```
10
+
11
+ ## Members
12
+
13
+ | Member | Kind | Type | Description |
14
+ |--------|------|------|-------------|
15
+ | `key` | input (required) | `string` | 저장 키 (`SdSystemConfigProvider` 기반) |
16
+ | `state` | model | `any` | 현재 상태 객체. 프리셋 클릭 시 해당 프리셋의 상태로 업데이트됨 |
17
+ | `size` | input | `"sm" \| "lg" \| undefined` | 크기 |
18
+
19
+ ## Related Types
20
+
21
+ ### `SdStatePresetDef`
22
+
23
+ ```typescript
24
+ interface SdStatePresetDef {
25
+ name: string;
26
+ state: any;
27
+ }
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```html
33
+ <sd-state-preset [key]="'order-list-search'" [(state)]="searchState" />
34
+ ```
35
+
36
+ > 프리셋 아이콘 클릭 → 이름 입력 모달 → 현재 `state`를 해당 이름으로 저장.
37
+ > 저장된 프리셋 클릭 → `state`가 해당 프리셋의 값으로 업데이트됨.
@@ -0,0 +1,27 @@
1
+ # `SdSwitch`
2
+
3
+ 토글 스위치 컴포넌트. `value` model로 on/off 상태를 관리한다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-switch", ... })
7
+ export class SdSwitch
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `value` | model | `boolean` | on/off 상태 (기본값: `false`) |
15
+ | `canChangeFn` | input | `(item: boolean) => boolean \| Promise<boolean>` | 변경 가드 함수 (기본값: 항상 `true`) |
16
+ | `disabled` | input | `boolean` | 비활성화 (기본값: `false`) |
17
+ | `inline` | input | `boolean` | 인라인 표시 (기본값: `false`) |
18
+ | `inset` | input | `boolean` | 인셋 스타일 (기본값: `false`) |
19
+ | `size` | input | `"sm" \| "lg" \| undefined` | 크기 |
20
+ | `theme` | input | `"primary" \| "secondary" \| "info" \| "success" \| "warning" \| "danger" \| "gray" \| "blue-gray" \| undefined` | 색상 테마 |
21
+
22
+ ## Usage
23
+
24
+ ```html
25
+ <sd-switch [(value)]="isActive" [theme]="'primary'" />
26
+ <sd-switch [(value)]="isEnabled" [canChangeFn]="canChangeActiveAsync" />
27
+ ```
@@ -0,0 +1,33 @@
1
+ # `SdTextarea`
2
+
3
+ 멀티라인 텍스트 입력 컴포넌트. 내용에 따라 행 수가 자동으로 늘어난다.
4
+
5
+ ```typescript
6
+ @Component({ selector: "sd-textarea", ... })
7
+ export class SdTextarea
8
+ ```
9
+
10
+ ## Members
11
+
12
+ | Member | Kind | Type | Description |
13
+ |--------|------|------|-------------|
14
+ | `value` | model | `string \| undefined` | 입력 값 |
15
+ | `placeholder` | input | `string \| undefined` | 플레이스홀더 텍스트 |
16
+ | `title` | input | `string \| undefined` | 툴팁 |
17
+ | `minRows` | input | `number` | 최소 행 수 (기본값: `1`) |
18
+ | `disabled` | input | `boolean` | 비활성화 (기본값: `false`) |
19
+ | `readonly` | input | `boolean` | 읽기 전용 (기본값: `false`) |
20
+ | `required` | input | `boolean` | 필수 여부 (기본값: `false`) |
21
+ | `inline` | input | `boolean` | 인라인 표시 (기본값: `false`) |
22
+ | `inset` | input | `boolean` | 인셋 스타일 (기본값: `false`) |
23
+ | `size` | input | `"sm" \| "lg" \| undefined` | 크기 |
24
+ | `validatorFn` | input | `(value: string \| undefined) => string \| undefined` | 커스텀 유효성 검사 함수 |
25
+ | `theme` | input | `"primary" \| "secondary" \| "info" \| "success" \| "warning" \| "danger" \| "gray" \| "blue-gray" \| undefined` | 배경 테마 |
26
+ | `inputStyle` | input | `string \| undefined` | 인라인 스타일 |
27
+ | `inputClass` | input | `string \| undefined` | 추가 CSS 클래스 |
28
+
29
+ ## Usage
30
+
31
+ ```html
32
+ <sd-textarea [(value)]="description" [placeholder]="'설명을 입력하세요'" [minRows]="3" />
33
+ ```