@simplysm/sd-claude 14.0.42 → 14.0.43

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 (67) hide show
  1. package/claude/references/sd-simplysm14/angular/docs/directives.md +74 -3
  2. package/claude/references/sd-simplysm14/angular/docs/features.md +64 -14
  3. package/claude/references/sd-simplysm14/angular/docs/plugins.md +2 -90
  4. package/claude/references/sd-simplysm14/angular/docs/providers.md +2 -2
  5. package/claude/references/sd-simplysm14/angular/docs/type-utilities.md +1 -2
  6. package/claude/references/sd-simplysm14/angular/docs/ui-data.md +103 -23
  7. package/claude/references/sd-simplysm14/angular/docs/ui-form.md +173 -28
  8. package/claude/references/sd-simplysm14/angular/docs/ui-layout.md +19 -4
  9. package/claude/references/sd-simplysm14/angular/docs/ui-navigation.md +20 -2
  10. package/claude/references/sd-simplysm14/angular/docs/ui-overlay.md +23 -14
  11. package/claude/references/sd-simplysm14/angular/docs/ui-visual.md +15 -7
  12. package/claude/references/sd-simplysm14/angular/docs/utils.md +1 -1
  13. package/claude/references/sd-simplysm14/angular/usage.md +16 -15
  14. package/claude/references/sd-simplysm14/capacitor-plugin-auto-update/usage.md +1 -1
  15. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/file-operations.md +154 -0
  16. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/permissions.md +84 -0
  17. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/storage-paths.md +107 -0
  18. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/docs/types.md +83 -0
  19. package/claude/references/sd-simplysm14/capacitor-plugin-file-system/usage.md +83 -128
  20. package/claude/references/sd-simplysm14/capacitor-plugin-usb-storage/usage.md +99 -1
  21. package/claude/references/sd-simplysm14/core-node/docs/child-process.md +182 -0
  22. package/claude/references/sd-simplysm14/core-node/docs/features.md +1 -1
  23. package/claude/references/sd-simplysm14/core-node/docs/file-system.md +509 -0
  24. package/claude/references/sd-simplysm14/core-node/docs/file-watching.md +139 -0
  25. package/claude/references/sd-simplysm14/core-node/docs/logging.md +180 -0
  26. package/claude/references/sd-simplysm14/core-node/docs/path.md +176 -0
  27. package/claude/references/sd-simplysm14/core-node/docs/worker-threads.md +334 -0
  28. package/claude/references/sd-simplysm14/core-node/usage.md +192 -96
  29. package/claude/references/sd-simplysm14/excel/docs/core-classes.md +33 -14
  30. package/claude/references/sd-simplysm14/excel/usage.md +47 -45
  31. package/claude/references/sd-simplysm14/lint/usage.md +3 -2
  32. package/claude/references/sd-simplysm14/orm-common/docs/queryable-executable.md +30 -35
  33. package/claude/references/sd-simplysm14/orm-common/usage.md +9 -8
  34. package/claude/references/sd-simplysm14/sd-claude/docs/assets.md +43 -34
  35. package/claude/references/sd-simplysm14/sd-claude/docs/cli.md +1 -1
  36. package/claude/references/sd-simplysm14/sd-claude/docs/hooks.md +20 -2
  37. package/claude/references/sd-simplysm14/sd-claude/docs/scripts.md +5 -18
  38. package/claude/references/sd-simplysm14/sd-claude/usage.md +6 -5
  39. package/claude/references/sd-simplysm14/sd-cli/usage.md +176 -1
  40. package/claude/references/sd-simplysm14/service-client/usage.md +126 -61
  41. package/claude/references/sd-simplysm14/service-common/usage.md +28 -28
  42. package/claude/references/sd-simplysm14/storage/usage.md +123 -30
  43. package/claude/references/sd-testing.md +100 -4
  44. package/claude/rules/sd-claude-rules.md +19 -4
  45. package/claude/sd-check-write.py +1 -1
  46. package/claude/skills/sd-check/SKILL.md +7 -4
  47. package/claude/skills/sd-claude-docs/SKILL.md +7 -4
  48. package/claude/skills/sd-claude-docs/references/package-doc-gen.md +30 -7
  49. package/claude/skills/sd-commit/SKILL.md +2 -0
  50. package/claude/skills/sd-debug/SKILL.md +1 -1
  51. package/claude/skills/sd-deliverable/SKILL.md +2 -0
  52. package/claude/skills/sd-dev/SKILL.md +1 -1
  53. package/claude/skills/sd-doc-extract/SKILL.md +2 -0
  54. package/claude/{references/sd-debug.md → skills/sd-inner-debug/SKILL.md} +16 -20
  55. package/claude/{references/sd-review.md → skills/sd-inner-review/SKILL.md} +9 -4
  56. package/claude/skills/sd-issue/SKILL.md +2 -0
  57. package/claude/skills/sd-outlook/SKILL.md +2 -0
  58. package/claude/skills/sd-plan/SKILL.md +1 -1
  59. package/claude/skills/sd-prompt/SKILL.md +2 -2
  60. package/claude/skills/sd-refactor/SKILL.md +2 -2
  61. package/claude/skills/sd-review/SKILL.md +1 -1
  62. package/claude/skills/sd-tdd/SKILL.md +7 -7
  63. package/claude/skills/sd-use/SKILL.md +2 -0
  64. package/claude/skills/sd-wbs/SKILL.md +41 -18
  65. package/package.json +1 -1
  66. /package/claude/{rules → references}/sd-simplysm14.md +0 -0
  67. /package/claude/{references → rules}/sd-clarify.md +0 -0
@@ -9,19 +9,29 @@
9
9
  ```typescript
10
10
  @Component({ selector: "sd-button" })
11
11
  class SdButton {
12
+ type = input<"button" | "submit">("button");
13
+ theme = input<"primary" | "secondary" | "info" | ... | "link" | "link-primary" | ... | "link-rev">();
12
14
  inline = input(false, { transform: booleanAttribute });
13
15
  inset = input(false, { transform: booleanAttribute });
16
+ size = input<"sm" | "lg">();
14
17
  disabled = input(false, { transform: booleanAttribute });
18
+ buttonStyle = input<string>();
19
+ buttonClass = input<string>();
15
20
  }
16
21
  ```
17
22
 
18
23
  | Input | Type | Default | Description |
19
24
  |-------|------|---------|-------------|
25
+ | `type` | `"button" \| "submit"` | `"button"` | 버튼 HTML 타입 |
26
+ | `theme` | `string \| undefined` | `undefined` | 테마 (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) |
20
27
  | `inline` | `boolean` | `false` | 인라인 표시 |
21
28
  | `inset` | `boolean` | `false` | 테두리 없는 삽입 스타일 |
29
+ | `size` | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
22
30
  | `disabled` | `boolean` | `false` | 비활성화 |
31
+ | `buttonStyle` | `string \| undefined` | `undefined` | 버튼 인라인 스타일 |
32
+ | `buttonClass` | `string \| undefined` | `undefined` | 버튼 CSS 클래스 |
23
33
 
24
- 호스트 속성: `data-sd-theme`, `data-sd-size`, `data-sd-disabled`
34
+ 호스트 속성: `data-sd-theme`, `data-sd-inline`, `data-sd-size`, `data-sd-inset`, `data-sd-disabled`
25
35
 
26
36
  ### `SdAnchor`
27
37
 
@@ -31,9 +41,15 @@ class SdButton {
31
41
  @Component({ selector: "sd-anchor" })
32
42
  class SdAnchor {
33
43
  disabled = input(false, { transform: booleanAttribute });
44
+ theme = input<"primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray">("primary");
34
45
  }
35
46
  ```
36
47
 
48
+ | Input | Type | Default | Description |
49
+ |-------|------|---------|-------------|
50
+ | `disabled` | `boolean` | `false` | 비활성화 |
51
+ | `theme` | `string` | `"primary"` | 테마 색상 |
52
+
37
53
  ### `SdAdditionalButton`
38
54
 
39
55
  추가 동작 버튼. 드롭다운 포함.
@@ -41,6 +57,7 @@ class SdAnchor {
41
57
  ```typescript
42
58
  @Component({ selector: "sd-additional-button" })
43
59
  class SdAdditionalButton {
60
+ size = input<"sm" | "lg">();
44
61
  inset = input(false, { transform: booleanAttribute });
45
62
  }
46
63
  ```
@@ -51,28 +68,32 @@ class SdAdditionalButton {
51
68
 
52
69
  ```typescript
53
70
  @Component({ selector: "sd-modal-select-button" })
54
- class SdModalSelectButton<T> {
71
+ class SdModalSelectButton<T extends object, K, M extends keyof SelectModeValue<K>> {
55
72
  modal = input.required<SdSelectModalInfo<SdSelectModal<T>>>();
56
- value = model<SelectModeValue<any>[any]>();
73
+ value = model<SelectModeValue<K>[M]>();
74
+ selectedItems = model<T[]>([]);
57
75
  disabled = input(false, { transform: booleanAttribute });
58
76
  required = input(false, { transform: booleanAttribute });
59
77
  inset = input(false, { transform: booleanAttribute });
60
- selectMode = input<"single" | "multi">("single");
61
- searchIcon = input(tablerSearch);
78
+ size = input<"sm" | "lg">();
79
+ selectMode = input<M>("single" as M);
62
80
  modalOptions = input<SdModalOptions>();
81
+ searchIcon = input(tablerSearch);
63
82
  }
64
83
  ```
65
84
 
66
85
  | Input | Type | Default | Description |
67
86
  |-------|------|---------|-------------|
68
87
  | `modal` | `SdSelectModalInfo<...>` | required | 모달 정보 |
69
- | `value` | `any` | - | 선택된 값 (two-way) |
88
+ | `value` | `SelectModeValue<K>[M]` | - | 선택된 값 (two-way) |
89
+ | `selectedItems` | `T[]` | `[]` | 선택된 항목 객체 배열 (two-way) |
70
90
  | `disabled` | `boolean` | `false` | 비활성화 |
71
91
  | `required` | `boolean` | `false` | 필수 (지우기 버튼 숨김) |
72
92
  | `inset` | `boolean` | `false` | 삽입 스타일 |
73
- | `selectMode` | `"single" \| "multi"` | `"single"` | 선택 모드 |
93
+ | `size` | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
94
+ | `selectMode` | `M` | `"single"` | 선택 모드 |
95
+ | `modalOptions` | `SdModalOptions \| undefined` | `undefined` | 모달 옵션 |
74
96
  | `searchIcon` | `string` | `tablerSearch` | 검색 아이콘 |
75
- | `modalOptions` | `SdModalOptions \| undefined` | - | 모달 옵션 |
76
97
 
77
98
  ## Inputs
78
99
 
@@ -83,20 +104,30 @@ class SdModalSelectButton<T> {
83
104
  ```typescript
84
105
  @Component({ selector: "sd-textfield" })
85
106
  class SdTextfield<K extends keyof SdTextfieldTypes> {
107
+ value = model<SdTextfieldTypes[K]>();
86
108
  type = input.required<K>();
87
- value = model<SdTextfieldTypes[K] | undefined>();
109
+ placeholder = input<string>();
110
+ title = input<string>();
111
+ inputStyle = input<string>();
112
+ inputClass = input<string>();
88
113
  disabled = input(false, { transform: booleanAttribute });
89
114
  readonly = input(false, { transform: booleanAttribute });
90
115
  required = input(false, { transform: booleanAttribute });
91
- useNumberComma = input(true, { transform: booleanAttribute });
92
- inline = input(false, { transform: booleanAttribute });
93
- inset = input(false, { transform: booleanAttribute });
94
- placeholder = input<string>();
95
- format = input<string>();
96
116
  min = input<SdTextfieldTypes[K]>();
97
117
  max = input<SdTextfieldTypes[K]>();
118
+ minlength = input<number>();
119
+ maxlength = input<number>();
120
+ pattern = input<string>();
121
+ validatorFn = input<(value: SdTextfieldTypes[K] | undefined) => string | undefined>();
122
+ format = input<string>();
98
123
  step = input<number>();
124
+ autocomplete = input<string>();
125
+ useNumberComma = input(true, { transform: booleanAttribute });
126
+ minDigits = input<number>();
127
+ inline = input(false, { transform: booleanAttribute });
128
+ inset = input(false, { transform: booleanAttribute });
99
129
  size = input<"sm" | "lg">();
130
+ theme = input<string>();
100
131
  }
101
132
  ```
102
133
 
@@ -104,13 +135,28 @@ class SdTextfield<K extends keyof SdTextfieldTypes> {
104
135
  |-------|------|---------|-------------|
105
136
  | `type` | `keyof SdTextfieldTypes` | required | 입력 타입 (number, text, password, color, email, format, date, month, year, datetime, datetime-sec, time, time-sec) |
106
137
  | `value` | `SdTextfieldTypes[K] \| undefined` | - | 값 (two-way) |
138
+ | `placeholder` | `string \| undefined` | `undefined` | 플레이스홀더 |
139
+ | `title` | `string \| undefined` | `undefined` | title 속성 (없으면 placeholder 사용) |
140
+ | `inputStyle` | `string \| undefined` | `undefined` | input 인라인 스타일 |
141
+ | `inputClass` | `string \| undefined` | `undefined` | input CSS 클래스 |
107
142
  | `disabled` | `boolean` | `false` | 비활성화 |
108
143
  | `readonly` | `boolean` | `false` | 읽기 전용 |
109
144
  | `required` | `boolean` | `false` | 필수 |
145
+ | `min` | `SdTextfieldTypes[K] \| undefined` | `undefined` | 최소값 |
146
+ | `max` | `SdTextfieldTypes[K] \| undefined` | `undefined` | 최대값 |
147
+ | `minlength` | `number \| undefined` | `undefined` | 최소 길이 |
148
+ | `maxlength` | `number \| undefined` | `undefined` | 최대 길이 |
149
+ | `pattern` | `string \| undefined` | `undefined` | 입력 패턴 (정규식) |
150
+ | `validatorFn` | `((value) => string \| undefined) \| undefined` | `undefined` | 커스텀 유효성 검증 함수 (에러 메시지 반환) |
151
+ | `format` | `string \| undefined` | `undefined` | format 타입에서 사용할 포맷 문자열 |
152
+ | `step` | `number \| undefined` | `undefined` | 증감 단위 |
153
+ | `autocomplete` | `string \| undefined` | `undefined` | autocomplete 속성 |
110
154
  | `useNumberComma` | `boolean` | `true` | number 타입에서 천 단위 쉼표 사용 |
155
+ | `minDigits` | `number \| undefined` | `undefined` | number 타입 최소 자릿수 |
111
156
  | `inline` | `boolean` | `false` | 인라인 표시 |
112
157
  | `inset` | `boolean` | `false` | 삽입 스타일 |
113
- | `format` | `string \| undefined` | - | format 타입에서 사용할 포맷 문자열 |
158
+ | `size` | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
159
+ | `theme` | `string \| undefined` | `undefined` | 테마 |
114
160
 
115
161
  ### `SdTextarea`
116
162
 
@@ -120,11 +166,19 @@ class SdTextfield<K extends keyof SdTextfieldTypes> {
120
166
  @Component({ selector: "sd-textarea" })
121
167
  class SdTextarea {
122
168
  value = model<string>();
169
+ placeholder = input<string>();
170
+ title = input<string>();
171
+ minRows = input<number>(1);
123
172
  disabled = input(false, { transform: booleanAttribute });
124
173
  readonly = input(false, { transform: booleanAttribute });
125
174
  required = input(false, { transform: booleanAttribute });
126
175
  inline = input(false, { transform: booleanAttribute });
127
176
  inset = input(false, { transform: booleanAttribute });
177
+ size = input<"sm" | "lg">();
178
+ validatorFn = input<(value: string | undefined) => string | undefined>();
179
+ theme = input<string>();
180
+ inputStyle = input<string>();
181
+ inputClass = input<string>();
128
182
  }
129
183
  ```
130
184
 
@@ -135,14 +189,30 @@ class SdTextarea {
135
189
  ```typescript
136
190
  @Component({ selector: "sd-numpad" })
137
191
  class SdNumpad {
138
- value = model<number | undefined>();
192
+ placeholder = input<string>();
193
+ value = model<number>();
139
194
  required = input(false, { transform: booleanAttribute });
140
195
  inputDisabled = input(false, { transform: booleanAttribute });
141
196
  useEnterButton = input(false, { transform: booleanAttribute });
142
197
  useMinusButton = input(false, { transform: booleanAttribute });
198
+
199
+ enterButtonClick = output();
143
200
  }
144
201
  ```
145
202
 
203
+ | Input | Type | Default | Description |
204
+ |-------|------|---------|-------------|
205
+ | `placeholder` | `string \| undefined` | `undefined` | 플레이스홀더 |
206
+ | `value` | `number \| undefined` | - | 값 (two-way) |
207
+ | `required` | `boolean` | `false` | 필수 |
208
+ | `inputDisabled` | `boolean` | `false` | 입력 필드 비활성화 |
209
+ | `useEnterButton` | `boolean` | `false` | 엔터 버튼 표시 |
210
+ | `useMinusButton` | `boolean` | `false` | 마이너스 버튼 표시 |
211
+
212
+ | Output | Type | Description |
213
+ |--------|------|-------------|
214
+ | `enterButtonClick` | `void` | 엔터 버튼 클릭 시 발생 |
215
+
146
216
  ### `SdRange`
147
217
 
148
218
  범위 슬라이더 컴포넌트.
@@ -151,8 +221,9 @@ class SdNumpad {
151
221
  @Component({ selector: "sd-range" })
152
222
  class SdRange<K extends keyof SdTextfieldTypes> {
153
223
  type = input.required<K>();
154
- from = model<SdTextfieldTypes[K] | undefined>();
155
- to = model<SdTextfieldTypes[K] | undefined>();
224
+ from = model<SdTextfieldTypes[K]>();
225
+ to = model<SdTextfieldTypes[K]>();
226
+ inputStyle = input<string>();
156
227
  required = input(false, { transform: booleanAttribute });
157
228
  disabled = input(false, { transform: booleanAttribute });
158
229
  }
@@ -165,12 +236,20 @@ class SdRange<K extends keyof SdTextfieldTypes> {
165
236
  ```typescript
166
237
  @Component({ selector: "sd-date-range-picker" })
167
238
  class SdDateRangePicker {
168
- from = model<DateOnly | undefined>();
169
- to = model<DateOnly | undefined>();
239
+ periodType = model<"일" | "월" | "범위">("범위");
240
+ from = model<DateOnly>();
241
+ to = model<DateOnly>();
170
242
  required = input(false, { transform: booleanAttribute });
171
243
  }
172
244
  ```
173
245
 
246
+ | Input | Type | Default | Description |
247
+ |-------|------|---------|-------------|
248
+ | `periodType` | `"일" \| "월" \| "범위"` | `"범위"` | 기간 선택 타입 (two-way) |
249
+ | `from` | `DateOnly \| undefined` | - | 시작일 (two-way) |
250
+ | `to` | `DateOnly \| undefined` | - | 종료일 (two-way) |
251
+ | `required` | `boolean` | `false` | 필수 |
252
+
174
253
  ## Choice
175
254
 
176
255
  ### `SdStatePreset`
@@ -181,9 +260,17 @@ class SdDateRangePicker {
181
260
  @Component({ selector: "sd-state-preset" })
182
261
  class SdStatePreset {
183
262
  key = input.required<string>();
263
+ state = model<any>();
264
+ size = input<"sm" | "lg">();
184
265
  }
185
266
  ```
186
267
 
268
+ | Input | Type | Default | Description |
269
+ |-------|------|---------|-------------|
270
+ | `key` | `string` | required | 프리셋 저장 키 |
271
+ | `state` | `any` | - | 상태 데이터 (two-way) |
272
+ | `size` | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
273
+
187
274
  ### `SdStatePresetDef`
188
275
 
189
276
  ```typescript
@@ -208,22 +295,30 @@ interface SdStatePresetDef {
208
295
  @Component({ selector: "sd-checkbox" })
209
296
  class SdCheckbox {
210
297
  value = model(false);
298
+ canChangeFn = input<(item: boolean) => boolean | Promise<boolean>>(() => true);
211
299
  icon = input(tablerCheck);
212
300
  radio = input(false, { transform: booleanAttribute });
213
301
  disabled = input(false, { transform: booleanAttribute });
302
+ size = input<"sm" | "lg">();
214
303
  inline = input(false, { transform: booleanAttribute });
215
304
  inset = input(false, { transform: booleanAttribute });
305
+ theme = input<"primary" | "secondary" | ...>();
306
+ contentStyle = input<string>();
216
307
  }
217
308
  ```
218
309
 
219
310
  | Input | Type | Default | Description |
220
311
  |-------|------|---------|-------------|
221
312
  | `value` | `boolean` | `false` | 체크 여부 (two-way) |
313
+ | `canChangeFn` | `(item: boolean) => boolean \| Promise<boolean>` | `() => true` | 값 변경 가능 여부 함수 |
222
314
  | `icon` | `string` | `tablerCheck` | 체크 아이콘 |
223
315
  | `radio` | `boolean` | `false` | 라디오 버튼 스타일 |
224
316
  | `disabled` | `boolean` | `false` | 비활성화 |
317
+ | `size` | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
225
318
  | `inline` | `boolean` | `false` | 인라인 표시 |
226
319
  | `inset` | `boolean` | `false` | 삽입 스타일 |
320
+ | `theme` | `string \| undefined` | `undefined` | 테마 색상 |
321
+ | `contentStyle` | `string \| undefined` | `undefined` | 컨텐츠 인라인 스타일 |
227
322
 
228
323
  ### `SdSwitch`
229
324
 
@@ -233,9 +328,12 @@ class SdCheckbox {
233
328
  @Component({ selector: "sd-switch" })
234
329
  class SdSwitch {
235
330
  value = model(false);
331
+ canChangeFn = input<(item: boolean) => boolean | Promise<boolean>>(() => true);
236
332
  disabled = input(false, { transform: booleanAttribute });
237
333
  inline = input(false, { transform: booleanAttribute });
238
334
  inset = input(false, { transform: booleanAttribute });
335
+ size = input<"sm" | "lg">();
336
+ theme = input<string>();
239
337
  }
240
338
  ```
241
339
 
@@ -276,36 +374,71 @@ class SdTiptapEditor {
276
374
  disabled = input(false, { transform: booleanAttribute });
277
375
  readonly = input(false, { transform: booleanAttribute });
278
376
  required = input(false, { transform: booleanAttribute });
377
+ placeholder = input<string>();
378
+ validatorFn = input<(value: string | undefined) => string | undefined>();
379
+ extensions = input<AnyExtension[]>();
279
380
  }
280
381
  ```
281
382
 
383
+ | Input | Type | Default | Description |
384
+ |-------|------|---------|-------------|
385
+ | `value` | `string \| undefined` | - | HTML 콘텐츠 (two-way) |
386
+ | `disabled` | `boolean` | `false` | 비활성화 |
387
+ | `readonly` | `boolean` | `false` | 읽기 전용 |
388
+ | `required` | `boolean` | `false` | 필수 |
389
+ | `placeholder` | `string \| undefined` | `undefined` | 플레이스홀더 |
390
+ | `validatorFn` | `((value) => string \| undefined) \| undefined` | `undefined` | 커스텀 유효성 검증 함수 |
391
+ | `extensions` | `AnyExtension[] \| undefined` | `undefined` | 추가 TipTap 확장 |
392
+
282
393
  ## Select
283
394
 
284
395
  ### `SdSelect`
285
396
 
286
- 드롭다운 선택 컴포넌트. single/multi/multi-with-header 모드를 지원한다.
397
+ 드롭다운 선택 컴포넌트. single/multi 모드를 지원한다.
287
398
 
288
399
  ```typescript
289
400
  @Component({ selector: "sd-select" })
290
401
  class SdSelect<T, M extends keyof SelectModeValue<T>> {
291
- value = model<SelectModeValue<T>[M]>();
292
402
  selectMode = input("single" as M);
403
+ value = model<SelectModeValue<any>[M]>();
404
+ placeholder = input<string>();
293
405
  disabled = input(false, { transform: booleanAttribute });
294
406
  inline = input(false, { transform: booleanAttribute });
295
407
  inset = input(false, { transform: booleanAttribute });
408
+ size = input<"sm" | "lg">();
296
409
  required = input(false, { transform: booleanAttribute });
297
410
  hideSelectAll = input(false, { transform: booleanAttribute });
298
- size = input<"sm" | "lg">();
411
+ multiSelectionDisplayDirection = input<"vertical">();
412
+ items = input<T[]>();
413
+ getChildrenFn = input<(item: T) => T[] | undefined>();
414
+ contentClass = input<string>();
415
+ contentStyle = input<string>();
299
416
  }
300
417
  ```
301
418
 
419
+ | Input | Type | Default | Description |
420
+ |-------|------|---------|-------------|
421
+ | `selectMode` | `M` | `"single"` | 선택 모드 |
422
+ | `value` | `SelectModeValue<any>[M]` | - | 선택된 값 (two-way) |
423
+ | `placeholder` | `string \| undefined` | `undefined` | 플레이스홀더 |
424
+ | `disabled` | `boolean` | `false` | 비활성화 |
425
+ | `inline` | `boolean` | `false` | 인라인 표시 |
426
+ | `inset` | `boolean` | `false` | 삽입 스타일 |
427
+ | `size` | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
428
+ | `required` | `boolean` | `false` | 필수 |
429
+ | `hideSelectAll` | `boolean` | `false` | multi 모드에서 전체 선택 숨김 |
430
+ | `multiSelectionDisplayDirection` | `"vertical" \| undefined` | `undefined` | multi 모드 표시 방향 |
431
+ | `items` | `T[] \| undefined` | `undefined` | 항목 배열 (selectMode가 "multi"일 때 내부 목록 렌더링용) |
432
+ | `getChildrenFn` | `((item) => T[] \| undefined) \| undefined` | `undefined` | 트리 구조 자식 함수 |
433
+ | `contentClass` | `string \| undefined` | `undefined` | 컨텐츠 CSS 클래스 |
434
+ | `contentStyle` | `string \| undefined` | `undefined` | 컨텐츠 인라인 스타일 |
435
+
302
436
  ### `SelectModeValue`
303
437
 
304
438
  ```typescript
305
439
  type SelectModeValue<T> = {
306
- single: T | undefined;
307
440
  multi: T[];
308
- "multi-with-header": T[];
441
+ single: T;
309
442
  }
310
443
  ```
311
444
 
@@ -335,11 +468,23 @@ class SdSelectButton<T> { }
335
468
 
336
469
  ### `SdForm`
337
470
 
338
- 폼 래퍼 컴포넌트. submit 이벤트 처리, 유효성 검증, busy 관리.
471
+ 폼 래퍼 컴포넌트. `<form>` 태그를 렌더링하며 submit 이벤트 처리 유효성 검증을 수행한다.
339
472
 
340
473
  ```typescript
341
474
  @Component({ selector: "sd-form" })
342
- class SdForm { }
475
+ class SdForm {
476
+ formSubmit = output<SubmitEvent>();
477
+ formInvalid = output();
478
+
479
+ requestSubmit(): void;
480
+ }
343
481
  ```
344
482
 
345
- `<form>` 태그를 렌더링하며 submit 이벤트를 처리한다.
483
+ | Output | Type | Description |
484
+ |--------|------|-------------|
485
+ | `formSubmit` | `SubmitEvent` | 유효성 검증 통과 시 발생 |
486
+ | `formInvalid` | `void` | 유효성 검증 실패 시 발생 (`reportValidity()` 호출 후) |
487
+
488
+ | Method | Description |
489
+ |--------|-------------|
490
+ | `requestSubmit()` | 프로그래밍 방식으로 submit 트리거 |
@@ -16,12 +16,16 @@ class SdDockContainer { }
16
16
  ```typescript
17
17
  @Component({ selector: "sd-dock" })
18
18
  class SdDock {
19
+ key = input<string>();
20
+ position = input<"top" | "bottom" | "right" | "left">("top");
19
21
  resizable = input(false, { transform: booleanAttribute });
20
22
  }
21
23
  ```
22
24
 
23
25
  | Input | Type | Default | Description |
24
26
  |-------|------|---------|-------------|
27
+ | `key` | `string \| undefined` | `undefined` | 리사이즈 설정 저장 키 |
28
+ | `position` | `"top" \| "bottom" \| "right" \| "left"` | `"top"` | 도킹 위치 |
25
29
  | `resizable` | `boolean` | `false` | 크기 조절 가능 여부 |
26
30
 
27
31
  ## `SdGap`
@@ -39,11 +43,16 @@ class SdGap { }
39
43
 
40
44
  ```typescript
41
45
  @Component({ selector: "sd-kanban-board" })
42
- class SdKanbanBoard {
43
- drop = output<SdKanbanBoardDropInfo>();
46
+ class SdKanbanBoard<L, T> {
47
+ selectedValues = model<T[]>([]);
48
+ drop = output<SdKanbanBoardDropInfo<L, T>>();
44
49
  }
45
50
  ```
46
51
 
52
+ | Input | Type | Default | Description |
53
+ |-------|------|---------|-------------|
54
+ | `selectedValues` | `T[]` | `[]` | 선택된 칸반 아이템 값 배열 (two-way) |
55
+
47
56
  ### `SdKanbanBoardDropInfo`
48
57
 
49
58
  ```typescript
@@ -94,16 +103,20 @@ interface SdKanbanDropTarget<L, T> {
94
103
 
95
104
  ```typescript
96
105
  @Component({ selector: "sd-kanban" })
97
- class SdKanban {
106
+ class SdKanban<L, T> {
107
+ value = input<T>();
98
108
  selectable = input(false, { transform: booleanAttribute });
99
109
  draggable = input(false, { transform: booleanAttribute });
110
+ contentClass = input<string>();
100
111
  }
101
112
  ```
102
113
 
103
114
  | Input | Type | Default | Description |
104
115
  |-------|------|---------|-------------|
116
+ | `value` | `T \| undefined` | `undefined` | 칸반 아이템의 값 |
105
117
  | `selectable` | `boolean` | `false` | 선택 가능 여부 |
106
118
  | `draggable` | `boolean` | `false` | 드래그 가능 여부 |
119
+ | `contentClass` | `string \| undefined` | `undefined` | 컨텐츠 CSS 클래스 |
107
120
 
108
121
  ## `SdKanbanLane`
109
122
 
@@ -111,10 +124,11 @@ class SdKanban {
111
124
 
112
125
  ```typescript
113
126
  @Component({ selector: "sd-kanban-lane" })
114
- class SdKanbanLane {
127
+ class SdKanbanLane<L, T> {
115
128
  busy = input(false, { transform: booleanAttribute });
116
129
  useCollapse = input(false, { transform: booleanAttribute });
117
130
  collapse = model(false);
131
+ value = input<L>();
118
132
  }
119
133
  ```
120
134
 
@@ -123,3 +137,4 @@ class SdKanbanLane {
123
137
  | `busy` | `boolean` | `false` | busy 상태 |
124
138
  | `useCollapse` | `boolean` | `false` | 접기 기능 사용 |
125
139
  | `collapse` | `boolean` | `false` | 접힘 상태 (two-way) |
140
+ | `value` | `L \| undefined` | `undefined` | 레인의 값 |
@@ -105,9 +105,19 @@ class SdSidebar { }
105
105
 
106
106
  ```typescript
107
107
  @Component({ selector: "sd-sidebar-menu" })
108
- class SdSidebarMenu { }
108
+ class SdSidebarMenu {
109
+ menus = input<SdMenu[]>([]);
110
+ layout = input<"accordion" | "flat">();
111
+ getMenuIsSelectedFn = input<(menu: SdMenu) => boolean>();
112
+ }
109
113
  ```
110
114
 
115
+ | Input | Type | Default | Description |
116
+ |-------|------|---------|-------------|
117
+ | `menus` | `SdMenu[]` | `[]` | 메뉴 항목 |
118
+ | `layout` | `"accordion" \| "flat" \| undefined` | `undefined` | 레이아웃 모드 |
119
+ | `getMenuIsSelectedFn` | `((menu) => boolean) \| undefined` | `undefined` | 커스텀 메뉴 선택 여부 함수 |
120
+
111
121
  ### `SdSidebarUser`
112
122
 
113
123
  사이드바 사용자 영역 컴포넌트.
@@ -162,9 +172,17 @@ class SdTopbar { }
162
172
 
163
173
  ```typescript
164
174
  @Component({ selector: "sd-topbar-menu" })
165
- class SdTopbarMenu { }
175
+ class SdTopbarMenu {
176
+ menus = input<SdMenu[]>([]);
177
+ getMenuIsSelectedFn = input<(menu: SdMenu) => boolean>();
178
+ }
166
179
  ```
167
180
 
181
+ | Input | Type | Default | Description |
182
+ |-------|------|---------|-------------|
183
+ | `menus` | `SdMenu[]` | `[]` | 메뉴 항목 |
184
+ | `getMenuIsSelectedFn` | `((menu) => boolean) \| undefined` | `undefined` | 커스텀 메뉴 선택 여부 함수 |
185
+
168
186
  ### `SdTopbarUser`
169
187
 
170
188
  탑바 사용자 영역 컴포넌트.
@@ -38,22 +38,25 @@ class SdDropdownPopup { }
38
38
  @Component({ selector: "sd-modal" })
39
39
  class SdModal {
40
40
  open = model(false);
41
+ key = input<string | undefined>(undefined);
41
42
  title = input("");
42
43
  hideHeader = input(false);
43
44
  hideCloseButton = input(false);
45
+ headerStyle = input<string | undefined>(undefined);
44
46
  useCloseByBackdrop = input(true);
45
47
  useCloseByEscapeKey = input(true);
46
48
  float = input(false);
47
49
  fill = input(false);
48
50
  resizable = input(false);
49
51
  movable = input(false);
50
- position = input<"bottom-right" | "top-right">();
51
- minHeightPx = input<number>();
52
- minWidthPx = input<number>();
53
- heightPx = input<number>();
54
- widthPx = input<number>();
55
- headerStyle = input<string>();
56
- noFirstControlFocusing = input(false);
52
+ position = input<"bottom-right" | "top-right" | undefined>(undefined);
53
+ minHeightPx = input<number | undefined>(undefined);
54
+ minWidthPx = input<number | undefined>(undefined);
55
+ heightPx = input<number | undefined>(undefined);
56
+ widthPx = input<number | undefined>(undefined);
57
+ actionTplRef = input<TemplateRef<any> | undefined>(undefined);
58
+
59
+ closeRequest = output<void>();
57
60
  }
58
61
  ```
59
62
 
@@ -70,7 +73,11 @@ class SdModal {
70
73
  | `resizable` | `boolean` | `false` | 크기 조절 가능 |
71
74
  | `movable` | `boolean` | `false` | 이동 가능 |
72
75
  | `position` | `"bottom-right" \| "top-right"` | - | 위치 프리셋 |
73
- | `noFirstControlFocusing` | `boolean` | `false` | 자동 포커스 비활성화 |
76
+ | `actionTplRef` | `TemplateRef<any> \| undefined` | `undefined` | 헤더 액션 영역 템플릿 (SdModalProvider에서 설정) |
77
+
78
+ | Output | Type | Description |
79
+ |--------|------|-------------|
80
+ | `closeRequest` | `void` | 배경 클릭, ESC 키, 닫기 버튼으로 닫기 요청 시 발생 |
74
81
 
75
82
  ### `SdPromptModal`
76
83
 
@@ -109,9 +116,9 @@ class SdConfirmModal implements SdModalContentDef<boolean> {
109
116
  class SdToast {
110
117
  open = model(false);
111
118
  useProgress = input(false, { transform: booleanAttribute });
119
+ theme = input<SdToastTheme>("info");
112
120
  progress = model(0);
113
- theme = input<SdToastTheme>();
114
- message = signal<string>("");
121
+ message = model<string | undefined>(undefined);
115
122
  }
116
123
  ```
117
124
 
@@ -136,13 +143,15 @@ busy 표시 컨테이너 컴포넌트. spinner/bar/cube 3가지 타입을 지원
136
143
  @Component({ selector: "sd-busy-container" })
137
144
  class SdBusyContainer {
138
145
  busy = input(false, { transform: booleanAttribute });
139
- type = input<SdBusyType>("bar");
140
- message = input<string>();
146
+ message = input<string | undefined>(undefined);
147
+ type = input<SdBusyType | undefined>(undefined);
148
+ progressPercent = input<number | undefined>(undefined);
141
149
  }
142
150
  ```
143
151
 
144
152
  | Input | Type | Default | Description |
145
153
  |-------|------|---------|-------------|
146
154
  | `busy` | `boolean` | `false` | busy 상태 |
147
- | `type` | `SdBusyType` | `"bar"` | 표시 유형 (spinner, bar, cube) |
148
- | `message` | `string \| undefined` | - | busy 메시지 |
155
+ | `message` | `string \| undefined` | `undefined` | busy 메시지 |
156
+ | `type` | `SdBusyType \| undefined` | `undefined` | 표시 유형 (spinner, bar, cube). undefined이면 부모의 SdBusyProvider.type 사용 |
157
+ | `progressPercent` | `number \| undefined` | `undefined` | 진행률 (0-100). 설정 시 progress bar로 표시 |
@@ -7,15 +7,19 @@
7
7
  ```typescript
8
8
  @Component({ selector: "sd-label" })
9
9
  class SdLabel {
10
+ theme = input<"primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray">();
11
+ color = input<string>();
10
12
  clickable = input(false, { transform: booleanAttribute });
11
13
  }
12
14
  ```
13
15
 
14
16
  | Input | Type | Default | Description |
15
17
  |-------|------|---------|-------------|
18
+ | `theme` | `string \| undefined` | `undefined` | 테마 색상 |
19
+ | `color` | `string \| undefined` | `undefined` | 커스텀 CSS 색상 |
16
20
  | `clickable` | `boolean` | `false` | 클릭 가능 여부 |
17
21
 
18
- 호스트 속성: `data-sd-theme` (primary, secondary, info, success, warning, danger, gray, blue-gray)
22
+ 호스트 속성: `data-sd-theme`
19
23
 
20
24
  ## `SdNote`
21
25
 
@@ -24,12 +28,16 @@ class SdLabel {
24
28
  ```typescript
25
29
  @Component({ selector: "sd-note" })
26
30
  class SdNote {
31
+ theme = input<"primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray">();
32
+ size = input<"sm" | "lg">();
27
33
  inset = input(false, { transform: booleanAttribute });
28
34
  }
29
35
  ```
30
36
 
31
37
  | Input | Type | Default | Description |
32
38
  |-------|------|---------|-------------|
39
+ | `theme` | `string \| undefined` | `undefined` | 테마 색상 |
40
+ | `size` | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
33
41
  | `inset` | `boolean` | `false` | 삽입 스타일 (테두리 없음) |
34
42
 
35
43
  호스트 속성: `data-sd-theme`
@@ -41,17 +49,19 @@ class SdNote {
41
49
  ```typescript
42
50
  @Component({ selector: "sd-progress" })
43
51
  class SdProgress {
52
+ inset = input(false, { transform: booleanAttribute });
53
+ size = input<"sm" | "lg">();
44
54
  theme = input.required<"primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray">();
45
55
  value = input.required<number>();
46
- inset = input(false, { transform: booleanAttribute });
47
56
  }
48
57
  ```
49
58
 
50
59
  | Input | Type | Default | Description |
51
60
  |-------|------|---------|-------------|
61
+ | `inset` | `boolean` | `false` | 삽입 스타일 |
62
+ | `size` | `"sm" \| "lg" \| undefined` | `undefined` | 크기 |
52
63
  | `theme` | `string` | required | 테마 색상 |
53
64
  | `value` | `number` | required | 진행률 (0-100) |
54
- | `inset` | `boolean` | `false` | 삽입 스타일 |
55
65
 
56
66
  ## `SdCalendar`
57
67
 
@@ -84,16 +94,14 @@ class SdCalendar<T> {
84
94
  @Component({ selector: "sd-barcode" })
85
95
  class SdBarcode {
86
96
  type = input.required<BarcodeType>();
87
- value = input.required<string>();
88
- scale = input(2);
97
+ value = input<string>();
89
98
  }
90
99
  ```
91
100
 
92
101
  | Input | Type | Default | Description |
93
102
  |-------|------|---------|-------------|
94
103
  | `type` | `BarcodeType` | required | 바코드 타입 |
95
- | `value` | `string` | required | 바코드 |
96
- | `scale` | `number` | `2` | 렌더링 스케일 |
104
+ | `value` | `string \| undefined` | `undefined` | 바코드 값. 빈 문자열이거나 undefined이면 빈 출력 |
97
105
 
98
106
  ### `BarcodeType`
99
107