@simplysm/sd-claude 14.0.75 → 14.0.77
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.
- package/claude/output-styles/sd-tone.md +128 -0
- package/claude/references/sd-simplysm14/apis/angular/README.md +28 -89
- package/claude/references/sd-simplysm14/apis/angular/app-structure.md +75 -32
- package/claude/references/sd-simplysm14/apis/angular/buttons.md +65 -29
- package/claude/references/sd-simplysm14/apis/angular/crud.md +86 -21
- package/claude/references/sd-simplysm14/apis/angular/forms.md +168 -42
- package/claude/references/sd-simplysm14/apis/angular/infrastructure.md +200 -49
- package/claude/references/sd-simplysm14/apis/angular/kanban.md +64 -20
- package/claude/references/sd-simplysm14/apis/angular/layout.md +75 -30
- package/claude/references/sd-simplysm14/apis/angular/modal.md +92 -40
- package/claude/references/sd-simplysm14/apis/angular/routing.md +86 -25
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +72 -41
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +113 -21
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +108 -33
- package/claude/references/sd-simplysm14/apis/angular/toast.md +81 -30
- package/claude/references/sd-simplysm14/apis/angular/visual.md +140 -32
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +46 -43
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +59 -48
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +17 -7
- package/claude/references/sd-simplysm14/apis/core-common/README.md +43 -116
- package/claude/references/sd-simplysm14/apis/core-common/extensions.md +74 -109
- package/claude/references/sd-simplysm14/apis/core-common/features.md +40 -35
- package/claude/references/sd-simplysm14/apis/core-common/types.md +80 -106
- package/claude/references/sd-simplysm14/apis/core-common/utils.md +142 -111
- package/claude/references/sd-simplysm14/apis/core-node/README.md +7 -16
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +33 -38
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +25 -33
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +27 -38
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +32 -60
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +14 -45
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +35 -81
- package/claude/references/sd-simplysm14/apis/excel/README.md +178 -80
- package/claude/references/sd-simplysm14/apis/lint/README.md +5 -0
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +1 -1
- package/claude/references/sd-simplysm14/apis/sd-claude/README.md +28 -5
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +1 -1
- package/claude/references/sd-simplysm14/apis/service-client/README.md +57 -50
- package/claude/references/sd-simplysm14/apis/service-server/README.md +8 -15
- package/claude/references/sd-simplysm14/apis/service-server/auth.md +24 -16
- package/claude/references/sd-simplysm14/apis/service-server/builtin-services.md +55 -31
- package/claude/references/sd-simplysm14/apis/service-server/define-service.md +28 -44
- package/claude/references/sd-simplysm14/apis/service-server/internals.md +59 -18
- package/claude/references/sd-simplysm14/apis/service-server/server.md +37 -46
- package/claude/references/sd-simplysm14/manuals/client-component.md +3 -1
- package/claude/references/sd-simplysm14/manuals/logging.md +9 -8
- package/claude/rules/sd-base-rules.md +380 -217
- package/claude/settings.json +1 -0
- package/claude/skills/sd-commit/SKILL.md +31 -8
- package/claude/skills/sd-docs/SKILL.md +15 -10
- package/claude/skills/sd-docs/references/subagent-prompt.md +26 -8
- package/claude/skills/sd-impl/SKILL.md +1 -1
- package/claude/skills/sd-skill/references/skill-authoring.md +1 -1
- package/claude/skills/sd-spec/SKILL.md +22 -13
- package/claude/skills/sd-spec/references/spec-authoring.md +1 -1
- package/claude/skills/sd-unpack/SKILL.md +150 -26
- package/claude/skills/sd-unpack/scripts/handlers/__pycache__/_common.cpython-314.pyc +0 -0
- package/claude/skills/sd-unpack/scripts/handlers/__pycache__/eml_handler.cpython-314.pyc +0 -0
- package/claude/skills/sd-unpack/scripts/handlers/__pycache__/office_com.cpython-314.pyc +0 -0
- package/claude/skills/sd-unpack/scripts/handlers/__pycache__/pdf_handler.cpython-314.pyc +0 -0
- package/claude/skills/sd-unpack/scripts/handlers/_common.py +17 -2
- package/claude/skills/sd-unpack/scripts/handlers/eml_handler.py +100 -24
- package/claude/skills/sd-unpack/scripts/handlers/msg_handler.py +140 -27
- package/claude/skills/sd-unpack/scripts/handlers/office_com.py +698 -107
- package/claude/skills/sd-unpack/scripts/handlers/office_worker.py +34 -26
- package/claude/skills/sd-unpack/scripts/handlers/pdf_handler.py +130 -8
- package/package.json +1 -1
|
@@ -1,35 +1,100 @@
|
|
|
1
1
|
# @simplysm/angular — crud
|
|
2
2
|
|
|
3
|
-
CRUD 화면 골격.
|
|
3
|
+
CRUD 화면 골격. 공통 컨테이너(`SdBaseContainer`) + 리스트(`SdCrudList`) + 상세(`SdCrudDetail`) + 사용자 상태 프리셋(`SdStatePreset`).
|
|
4
4
|
|
|
5
|
-
## `<sd-base-container>`
|
|
5
|
+
## SdBaseContainer — `<sd-base-container>`
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```ts
|
|
8
|
+
ready = model(false);
|
|
9
|
+
initialized = input(false);
|
|
10
|
+
busyCount = model(0);
|
|
11
|
+
restricted = input(false);
|
|
12
|
+
viewType = input.required<SdViewType>(); // "page"|"modal"|"control" (routing.md)
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
// content slots: #topbarTpl #commandTpl #contentTpl #bottomCommandTpl
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- 모든 simplysm 화면의 기본 컨테이너. 진입 시 `SdSharedDataProvider.wait()` 후 `ready` true.
|
|
18
|
+
- `restricted=true` 면 권한 없음 안내 화면 표시(데이터 로드 스킵).
|
|
19
|
+
- `viewType` — 보통 `injectViewTypeSignal()` 결과 바인딩.
|
|
20
|
+
- 슬롯: `<ng-template #topbarTpl>` 상단 영역, `#commandTpl` 명령바, `#contentTpl` 본문, `#bottomCommandTpl` 하단.
|
|
21
|
+
|
|
22
|
+
## SdCrudList — `<sd-crud-list>`
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
class SdCrudList<TItem, TKey>
|
|
26
|
+
ready = model(false); initialized = input(false); busyCount = model(0);
|
|
27
|
+
restricted = input(false); readonly = input(false);
|
|
28
|
+
viewType = input.required<SdViewType>();
|
|
29
|
+
selectMode = input<"single"|"multi">();
|
|
30
|
+
key = input.required<string>(); // 시트/프리셋 key prefix
|
|
31
|
+
|
|
32
|
+
filterSubmit = output(); submit = output();
|
|
33
|
+
create = output(); delete = output<TItem[]>(); restore = output<TItem[]>();
|
|
34
|
+
|
|
35
|
+
items = input<TItem[]>([]);
|
|
36
|
+
selectedKeys = model<NonNullable<TKey>[]>([]);
|
|
37
|
+
currDeletedItems = input<TItem[]>([]); // 삭제됨 표시(취소선) 대상
|
|
38
|
+
|
|
39
|
+
currentPage = model(0); totalPageCount = input(0);
|
|
40
|
+
itemsPerPage = input(0); visiblePageCount = input(10);
|
|
41
|
+
sorts = model<SortingDef[]>([]);
|
|
42
|
+
trackByFn = input.required<(item) => TKey>();
|
|
43
|
+
|
|
44
|
+
// content slots: #commandTpl #filterTpl #toolTpl #bottomCommandTpl
|
|
45
|
+
// + 자식: <sd-sheet-column> 들
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- 표준 리스트 화면: 필터 영역 + 시트 + 페이지바 + 명령(저장/추가/삭제/복원).
|
|
49
|
+
- `filterSubmit` — 필터 폼 submit. 호출자가 데이터 fetch.
|
|
50
|
+
- `submit` — 명령바의 저장 버튼.
|
|
51
|
+
- `create`/`delete`/`restore` — 행 추가/선택 삭제/선택 복원.
|
|
52
|
+
- `currDeletedItems` — soft-delete 표시. 해당 행 셀에 취소선 자동.
|
|
53
|
+
- `readonly=true` 면 명령바·편집 차단.
|
|
54
|
+
- 모달로 띄워서 선택 picker 로도 동작: 모달 confirm 시 `SdActivatedModalProvider.contentComponent.close.emit({ selectedKeys })`.
|
|
55
|
+
- `key` — 자식 `<sd-sheet key>` 와 `SdStatePreset key` 가 이 값을 prefix 로 사용.
|
|
10
56
|
|
|
11
57
|
```html
|
|
12
|
-
<sd-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
58
|
+
<sd-crud-list [viewType]="viewType()" key="invoice" [trackByFn]="trackById"
|
|
59
|
+
[items]="items()" [(selectedKeys)]="sel" selectMode="multi"
|
|
60
|
+
(filterSubmit)="reload()" (create)="onCreate()" (delete)="onDelete($event)">
|
|
61
|
+
<ng-template #filterTpl>...필터 폼...</ng-template>
|
|
62
|
+
<sd-sheet-column key="no" header="번호" />
|
|
63
|
+
</sd-crud-list>
|
|
16
64
|
```
|
|
17
65
|
|
|
18
|
-
## `<sd-crud-
|
|
66
|
+
## SdCrudDetail — `<sd-crud-detail>`
|
|
19
67
|
|
|
20
|
-
|
|
68
|
+
```ts
|
|
69
|
+
ready = model(false); initialized = input(false); busyCount = model(0);
|
|
70
|
+
restricted = input(false); readonly = input(false);
|
|
71
|
+
viewType = input.required<SdViewType>();
|
|
72
|
+
submit = output();
|
|
21
73
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- 모달 컨텍스트면 confirm/cancel 핸들러 자동 (`onModalSelectionConfirmClick`/`onModalSelectionCancelClick`).
|
|
74
|
+
// content slots: #commandTpl #contentTpl #bottomCommandTpl
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- 상세 화면 골격. 내부에 `<sd-form>` 자동 배치. 저장 버튼 클릭 시 form submit → invalid 없으면 `submit` 발화.
|
|
78
|
+
|
|
79
|
+
## SdStatePreset — `<sd-state-preset>`
|
|
29
80
|
|
|
30
|
-
|
|
81
|
+
```ts
|
|
82
|
+
key = input.required<string>();
|
|
83
|
+
state = model<any>(); // 적용할 상태 객체 (필터 등)
|
|
84
|
+
size = input<"sm"|"lg">();
|
|
85
|
+
|
|
86
|
+
interface SdStatePresetDef { name: string; state: any; }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- 사용자가 현재 `state` 를 이름 붙여 저장/불러오기. `SdSystemConfigProvider` 키 `key` 로 `SdStatePresetDef[]` 저장.
|
|
90
|
+
- 별 아이콘 클릭 → 이름 입력(`SdPromptModal`) → 추가. 프리셋 클릭 → `state` 에 적용. 디스켓 아이콘 → 현재 state 덮어쓰기. X 아이콘 → 삭제.
|
|
91
|
+
|
|
92
|
+
```html
|
|
93
|
+
<sd-state-preset key="invoice-filter" [(state)]="filter" />
|
|
94
|
+
```
|
|
31
95
|
|
|
32
|
-
|
|
96
|
+
## 주의
|
|
33
97
|
|
|
34
|
-
-
|
|
35
|
-
-
|
|
98
|
+
- 모든 CRUD 컴포넌트의 `ready` 는 진입 후 데이터 준비 완료 시 true. 호출자가 `[ready]="ready()"` 로 자식 조건부 렌더링.
|
|
99
|
+
- `key` 는 한 클라이언트 내 고유해야 함. 시트 컬럼 설정·프리셋·기타 영구 상태가 이 키로 충돌 없이 저장됨.
|
|
100
|
+
- `SdCrudList` 의 selectMode 가 설정되었고 컨테이너가 모달 안에 있으면 자동으로 picker 모드로 동작.
|
|
@@ -1,74 +1,200 @@
|
|
|
1
1
|
# @simplysm/angular — forms
|
|
2
2
|
|
|
3
|
-
폼 컨테이너 + 입력 컨트롤. 모든 컨트롤은 `value` model 기반. native form validity API
|
|
3
|
+
폼 컨테이너 + 값 입력 컨트롤. 모든 입력 컨트롤은 `value` model 기반. native form validity API 활용.
|
|
4
4
|
|
|
5
|
-
## `<sd-form>`
|
|
5
|
+
## SdForm — `<sd-form>`
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
formSubmit = output<SubmitEvent>();
|
|
9
|
+
formInvalid = output();
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
- 내부에 native `<form>` 구성. 자식 `<sd-textfield required>` 등 native invalid 상태가 있으면 submit 막고 `formInvalid` 발화. 모두 valid 면 `formSubmit` 발화.
|
|
6
13
|
|
|
7
14
|
```html
|
|
8
|
-
<sd-form (formSubmit)="onSubmit(
|
|
9
|
-
<sd-textfield [type]="'text'" [(value)]="name" [required]="true" />
|
|
10
|
-
<sd-button [type]="'submit'">저장</sd-button>
|
|
11
|
-
</sd-form>
|
|
15
|
+
<sd-form (formSubmit)="onSubmit()"><sd-textfield type="text" required [(value)]="name"/></sd-form>
|
|
12
16
|
```
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
## SdTextfield — `<sd-textfield>`
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
class SdTextfield<K extends keyof SdTextfieldTypes>
|
|
22
|
+
value = model<SdTextfieldTypes[K]>();
|
|
23
|
+
type = input.required<K>();
|
|
24
|
+
placeholder = input<string>(); title = input<string>();
|
|
25
|
+
inputStyle = input<string>(); inputClass = input<string>();
|
|
26
|
+
disabled = input(false); readonly = input(false); required = input(false);
|
|
27
|
+
min/max = input<SdTextfieldTypes[K]>(); minlength/maxlength = input<number>();
|
|
28
|
+
pattern = input<string>();
|
|
29
|
+
validatorFn = input<(value) => string|undefined>();
|
|
30
|
+
format = input<string>(); step = input<number>(); autocomplete = input<string>();
|
|
31
|
+
useNumberComma = input(true); minDigits = input<number>();
|
|
32
|
+
inline = input(false); inset = input(false); size = input<"sm"|"lg">();
|
|
33
|
+
theme = input<"primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray">();
|
|
34
|
+
|
|
35
|
+
type SdTextfieldTypes = {
|
|
36
|
+
number: number; text: string; password: string; color: string; email: string;
|
|
37
|
+
format: string; date: DateOnly; month: DateOnly; year: DateOnly;
|
|
38
|
+
datetime: DateTime; "datetime-sec": DateTime; time: Time; "time-sec": Time;
|
|
39
|
+
}
|
|
40
|
+
const sdTextfieldTypes: (keyof SdTextfieldTypes)[]
|
|
41
|
+
```
|
|
17
42
|
|
|
18
|
-
|
|
43
|
+
- `type` — 위 13개 중 1개. 각 타입별 핸들러가 파싱/포맷/입력 제한 담당. `number` 는 콤마 표시, `date`/`month`/`year` 는 `DateOnly`, `datetime[-sec]` 는 `DateTime`, `time[-sec]` 는 `Time`, `format` 은 `format` 입력에 따른 자유 포맷.
|
|
44
|
+
- `value` — 양방향. 타입에 맞는 객체/숫자/문자열.
|
|
45
|
+
- `format` — `type=format` 또는 표시 포맷팅용. `XXX-XXXX` 같은 패턴(`X` 자리).
|
|
46
|
+
- `validatorFn` — 반환 문자열이 있으면 invalid 메시지로 표시. undefined 면 통과.
|
|
47
|
+
- `useNumberComma` — `type=number` 기본 true. 천 단위 콤마 표시.
|
|
48
|
+
- `minDigits` — `type=number` 정수부 자릿수(부족 시 0 패딩).
|
|
49
|
+
- `min`/`max`/`minlength`/`maxlength`/`pattern`/`required` — native 검증으로 위임.
|
|
50
|
+
- `inline`/`inset`/`size`/`theme` — 레이아웃 옵션. `inset` 은 sd-sheet/모달 셀 안에 박힌 룩.
|
|
51
|
+
- `readonly` — 편집 차단(포커스 가능). `disabled` — 포커스 불가.
|
|
19
52
|
|
|
20
53
|
```html
|
|
21
|
-
<sd-textfield
|
|
22
|
-
<sd-textfield
|
|
23
|
-
<sd-textfield [type]="'format'" [format]="'XXX-XXXX-XXXX'" [(value)]="phone" />
|
|
54
|
+
<sd-textfield type="number" [(value)]="qty" [min]="0" />
|
|
55
|
+
<sd-textfield type="date" [(value)]="dueDate" required />
|
|
24
56
|
```
|
|
25
57
|
|
|
26
|
-
|
|
58
|
+
## SdTextarea — `<sd-textarea>`
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
value = model<string>();
|
|
62
|
+
placeholder/title/inputStyle/inputClass = input<string>(); minRows = input<number>(1);
|
|
63
|
+
disabled/readonly/required/inline/inset = input(false);
|
|
64
|
+
size = input<"sm"|"lg">();
|
|
65
|
+
validatorFn = input<(v) => string|undefined>();
|
|
66
|
+
theme = input<...8 themes>();
|
|
67
|
+
```
|
|
27
68
|
|
|
28
|
-
|
|
69
|
+
- 멀티라인 입력. `minRows` 만큼 시작 높이 확보, 내용 늘면 자동 확장.
|
|
29
70
|
|
|
30
|
-
|
|
71
|
+
## SdNumpad — `<sd-numpad>`
|
|
31
72
|
|
|
32
|
-
|
|
73
|
+
```ts
|
|
74
|
+
value = model<number>(); placeholder = input<string>();
|
|
75
|
+
required = input(false); inputDisabled = input(false);
|
|
76
|
+
useEnterButton = input(false); useMinusButton = input(false);
|
|
77
|
+
enterButtonClick = output();
|
|
78
|
+
```
|
|
33
79
|
|
|
34
|
-
|
|
80
|
+
- 터치용 숫자 패드. `useEnterButton` true 면 엔터 키 노출, 클릭 시 `enterButtonClick` 발화. `useMinusButton` true 면 부호 토글 키 노출. `inputDisabled` true 면 상단 표시 영역의 직접 타이핑 차단(패드만 사용).
|
|
35
81
|
|
|
36
|
-
## `<sd-
|
|
82
|
+
## SdRange — `<sd-range>`
|
|
37
83
|
|
|
38
|
-
|
|
84
|
+
```ts
|
|
85
|
+
class SdRange<K extends keyof SdTextfieldTypes>
|
|
86
|
+
type = input.required<K>(); from = model<SdTextfieldTypes[K]>(); to = model<SdTextfieldTypes[K]>();
|
|
87
|
+
inputStyle = input<string>(); required = input(false); disabled = input(false);
|
|
88
|
+
```
|
|
39
89
|
|
|
40
|
-
|
|
90
|
+
- `SdTextfield` 2개를 `~` 로 묶은 범위 입력. `type` 은 `SdTextfield` 와 동일 키.
|
|
41
91
|
|
|
42
|
-
|
|
92
|
+
## SdDateRangePicker — `<sd-date-range-picker>`
|
|
43
93
|
|
|
44
|
-
|
|
94
|
+
```ts
|
|
95
|
+
periodType = model<"일"|"월"|"범위">("범위");
|
|
96
|
+
from = model<DateOnly>(); to = model<DateOnly>();
|
|
97
|
+
required = input(false);
|
|
98
|
+
```
|
|
45
99
|
|
|
46
|
-
`
|
|
47
|
-
- `"일"`: 단일 date 입력. `to`는 `from` 따라감.
|
|
48
|
-
- `"월"`: month 입력. `from`은 1일, `to`는 말일 자동 설정.
|
|
49
|
-
- `"범위"`: from~to date 양쪽 입력. from > to 시 to를 from으로 보정.
|
|
100
|
+
- `periodType` — `일`: 단일 날짜(`from`=`to`), `월`: 단일 월, `범위`: from/to 자유 범위. 사용자가 토글 가능.
|
|
50
101
|
|
|
51
|
-
##
|
|
102
|
+
## SdSelect — `<sd-select>`
|
|
52
103
|
|
|
53
|
-
```
|
|
54
|
-
<
|
|
55
|
-
|
|
104
|
+
```ts
|
|
105
|
+
class SdSelect<M extends "single"|"multi", T>
|
|
106
|
+
selectMode = input("single" as M);
|
|
107
|
+
value = model<SelectModeValue<any>[M]>(); // single → T, multi → T[]
|
|
108
|
+
placeholder = input<string>();
|
|
109
|
+
disabled/inline/inset/required = input(false); size = input<"sm"|"lg">();
|
|
110
|
+
hideSelectAll = input(false);
|
|
111
|
+
multiSelectionDisplayDirection = input<"vertical">();
|
|
112
|
+
items = input<T[]>(); trackByFn = input<(item, index) => unknown>((item) => item);
|
|
113
|
+
getChildrenFn = input<(item: T) => T[]|undefined>();
|
|
114
|
+
contentClass = input<string>(); contentStyle = input<string>();
|
|
115
|
+
dropdownOpen = model(false);
|
|
116
|
+
|
|
117
|
+
type SelectModeValue<T> = { multi: T[]; single: T };
|
|
56
118
|
```
|
|
57
119
|
|
|
58
|
-
|
|
120
|
+
- 드롭다운 셀렉트. `items` 를 직접 주거나, content projection 으로 `<sd-select-item>` 나열.
|
|
121
|
+
- `selectMode` — `single`: 단일 선택, `multi`: 체크박스 다중 선택(`hideSelectAll` false 면 전체 선택 옵션 노출).
|
|
122
|
+
- `getChildrenFn` — 트리형 선택지. 자식 있는 노드 펼침.
|
|
123
|
+
- `multiSelectionDisplayDirection` — multi 모드에서 선택값 표시 방향. `vertical` 만.
|
|
124
|
+
- `dropdownOpen` — 양방향. 외부에서 강제 열림 제어 가능.
|
|
125
|
+
- `<ng-content>` — 표시 영역 커스텀 템플릿 또는 `<sd-select-item>` 리스트.
|
|
59
126
|
|
|
60
|
-
##
|
|
127
|
+
## SdSelectItem — `<sd-select-item>`
|
|
61
128
|
|
|
62
|
-
```
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
129
|
+
```ts
|
|
130
|
+
class SdSelectItem<T> { value = input<T|undefined>(); disabled = input(false); hidden = input(false); }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
- `SdSelect` 자식. content projection 으로 표시할 옵션. `hidden` true 면 필터링 결과 등으로 숨김.
|
|
134
|
+
|
|
135
|
+
## SdSelectButton — `<sd-select-button>`
|
|
136
|
+
|
|
137
|
+
- `SdSelect` 트리거 버튼 슬롯. inputs 없음. `<sd-select>` 내부에 표시 영역 커스터마이즈 시 content projection 으로 사용.
|
|
138
|
+
|
|
139
|
+
## SdCheckbox — `<sd-checkbox>`
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
value = model(false);
|
|
143
|
+
canChangeFn = input<(item: boolean) => boolean|Promise<boolean>>(() => true);
|
|
144
|
+
icon = input(tablerCheck); radio = input(false);
|
|
145
|
+
disabled = input(false); size = input<"sm"|"lg">();
|
|
146
|
+
inline = input(false); inset = input(false);
|
|
147
|
+
theme = input<...8 themes>(); contentStyle = input<string>();
|
|
66
148
|
```
|
|
67
149
|
|
|
68
|
-
|
|
150
|
+
- `radio` true 면 라디오 룩(원형). false 면 체크박스(사각).
|
|
151
|
+
- `canChangeFn` — 변경 직전 호출, false 반환·Promise<false> 면 무시. 비동기 확인용.
|
|
152
|
+
- `icon` — 체크 상태 아이콘. 기본 `tablerCheck`.
|
|
153
|
+
|
|
154
|
+
## SdSwitch — `<sd-switch>`
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
value = model(false);
|
|
158
|
+
canChangeFn = input<(item) => boolean|Promise<boolean>>(() => true);
|
|
159
|
+
disabled = input(false); inline = input(false); inset = input(false);
|
|
160
|
+
size = input<"sm"|"lg">(); theme = input<...8 themes>();
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
- 토글 스위치. `SdCheckbox` 와 의미 같지만 룩만 슬라이더.
|
|
164
|
+
|
|
165
|
+
## SdCheckboxGroup — `<sd-checkbox-group>`
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
class SdCheckboxGroup<T> { value = model<T[]>([]); disabled = input(false); }
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- 자식 `<sd-checkbox-group-item>` 들을 묶어 `value` 배열로 관리.
|
|
172
|
+
|
|
173
|
+
## SdCheckboxGroupItem — `<sd-checkbox-group-item>`
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
class SdCheckboxGroupItem<T> { value = input.required<T>(); inline = input(false); }
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
- 그룹의 단일 옵션. `value` 가 그룹 배열에 있으면 체크 상태.
|
|
180
|
+
|
|
181
|
+
## SdDropdown — `<sd-dropdown>`
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
open = model(false); disabled = input(false);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
- 트리거 + 팝업 컨테이너. content projection 으로 트리거와 `<sd-dropdown-popup>` 을 함께 둠.
|
|
188
|
+
|
|
189
|
+
## SdDropdownPopup — `<sd-dropdown-popup>`
|
|
190
|
+
|
|
191
|
+
- `SdDropdown` 의 팝업 슬롯. inputs 없음. content projection 으로 내용 채움.
|
|
192
|
+
|
|
193
|
+
```html
|
|
194
|
+
<sd-dropdown [(open)]="open">트리거<sd-dropdown-popup>...팝업 내용...</sd-dropdown-popup></sd-dropdown>
|
|
195
|
+
```
|
|
69
196
|
|
|
70
|
-
##
|
|
197
|
+
## 주의
|
|
71
198
|
|
|
72
|
-
-
|
|
73
|
-
- `
|
|
74
|
-
- `SdForm` submit 시 자동으로 reportValidity 호출 + invalid 인디케이터 표시.
|
|
199
|
+
- `value` model 인 컨트롤은 모두 `[(value)]="..."` 양방향.
|
|
200
|
+
- 입력 컨트롤은 `<sd-form>` 안에 두면 invalid 시 native `:invalid` 처리됨. `SdInvalid` 디렉티브로 커스텀 invalid 표시 추가 가능 ([infrastructure.md](./infrastructure.md)).
|
|
@@ -1,80 +1,231 @@
|
|
|
1
1
|
# @simplysm/angular — infrastructure
|
|
2
2
|
|
|
3
|
-
앱 인프라
|
|
3
|
+
앱 인프라 프로바이더·DOM 이벤트/효과 디렉티브·유틸 함수·타입 헬퍼. 전부 standalone, root 제공자거나 함수.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 설정·저장 프로바이더
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### SdSystemLogProvider (root)
|
|
8
8
|
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const client = factory.get("main");
|
|
13
|
-
await factory.closeAsync("main");
|
|
9
|
+
```ts
|
|
10
|
+
writeFn?: (severity, ...data) => Promise<void>|void;
|
|
11
|
+
writeAsync(severity: "error"|"warn"|"log", ...data): Promise<void>;
|
|
14
12
|
```
|
|
15
13
|
|
|
16
|
-
-
|
|
17
|
-
- request/response progress → `SdToastProvider.info(message, true)` 로 진행률 토스트 자동.
|
|
18
|
-
- destroy 시 모든 클라이언트 close.
|
|
14
|
+
- consola 태그(`angular:system-log`)로 로컬 로그. `writeFn` 세팅 시 서버 등으로 추가 전송. 전송 실패는 로컬 error 만 남기고 throw 안 함.
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
### SdLocalStorageProvider<T> (root)
|
|
21
17
|
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
const files = await inject(SdFileDialogProvider).showAsync(true, "image/*");
|
|
18
|
+
```ts
|
|
19
|
+
set<K>(key: K, value: T[K]); get<K>(key: K): T[K]|undefined; remove(key: K);
|
|
25
20
|
```
|
|
26
21
|
|
|
27
|
-
|
|
22
|
+
- 키 prefix = `clientName` (`SdAngularConfigProvider`). JSON 직렬화. 파싱 실패 시 undefined.
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+
### SdSystemConfigProvider<T> (root)
|
|
30
25
|
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
ls.remove("theme");
|
|
26
|
+
```ts
|
|
27
|
+
fn?: { set<K>(key, data): Promise<void>|void; get(key): PromiseLike<any> };
|
|
28
|
+
setAsync<K>(key, data): Promise<void>;
|
|
29
|
+
getAsync(key): Promise<...>;
|
|
36
30
|
```
|
|
37
31
|
|
|
38
|
-
|
|
32
|
+
- `fn` 미세팅이면 `SdLocalStorageProvider` 위임. `fn` 세팅 시 서버 영구 저장으로 전환. 모달 사이즈·시트 컬럼 설정·프리셋이 이걸 통함.
|
|
39
33
|
|
|
40
|
-
|
|
34
|
+
### injectSdSystemConfigResource<T>
|
|
41
35
|
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
```ts
|
|
37
|
+
function injectSdSystemConfigResource<T>(options: { key: Signal<string|undefined> }): {
|
|
38
|
+
value: Signal<T|undefined>; isLoading: Signal<boolean>;
|
|
39
|
+
status; hasValue(); reload();
|
|
40
|
+
set(value: T|undefined): void;
|
|
41
|
+
update(fn: (prev: T|undefined) => T|undefined): void;
|
|
42
|
+
};
|
|
47
43
|
```
|
|
48
44
|
|
|
49
|
-
`
|
|
45
|
+
- 컴포넌트의 element tag + key signal 조합으로 `SdSystemConfigProvider` 값 resource 화. `set`/`update` 시 microtask 로 server 저장(에러는 `ErrorHandler.handleError`).
|
|
50
46
|
|
|
51
|
-
##
|
|
47
|
+
## 서비스 클라이언트
|
|
52
48
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
### SdServiceClientFactoryProvider (root)
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
connectAsync(key: string, options?: Partial<ServiceConnectionOptions>): Promise<void>;
|
|
53
|
+
closeAsync(key: string): Promise<void>;
|
|
54
|
+
get(key: string): ServiceClient;
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- key 별 `ServiceClient` 풀. `connectAsync` 시 기본 host/port 는 현재 `location` 기준(https 면 443, http 면 80). request/response progress 시 자동으로 `SdToastProvider.info(..., true)` progress 토스트.
|
|
58
|
+
- 중복 connect 또는 closed key 재사용은 throw. destroy 시 모든 클라이언트 close.
|
|
59
|
+
|
|
60
|
+
## 파일·에러·테마
|
|
61
|
+
|
|
62
|
+
### SdFileDialogProvider (root)
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
showAsync(multiple?: false, accept?: string): Promise<File|undefined>;
|
|
66
|
+
showAsync(multiple: true, accept?: string): Promise<File[]|undefined>;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- `<input type="file">` 동적 생성 → click → 선택 후 결과. 취소 시 undefined.
|
|
70
|
+
- `accept` — MIME/확장자(`"image/*"`·`".pdf,.docx"`).
|
|
71
|
+
|
|
72
|
+
### SdGlobalErrorHandlerPlugin (Angular `ErrorHandler` 교체용)
|
|
73
|
+
|
|
74
|
+
- `provideSdAngular` 가 자동 등록. 직접 등록 안 해도 됨.
|
|
75
|
+
- `PromiseRejectionEvent`/`ErrorEvent`/`Error`/임의 값 분류해 `SdSystemLogProvider.writeAsync('error', ...)` + 전체 화면 에러 오버레이 표시 + Angular `ApplicationRef.destroy()`. 오버레이 클릭 → 홈으로 reload.
|
|
76
|
+
|
|
77
|
+
### SdThemeProvider (root)
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
dark: WritableSignal<boolean>;
|
|
81
|
+
readonly fontSizePresets: readonly number[]; // [12,14,16,20,24,28]
|
|
82
|
+
fontSize: WritableSignal<number>; // body html font-size px
|
|
83
|
+
increaseFontSize(): void; decreaseFontSize(): void;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- `dark` 효과 → `<body class="sd-theme-dark">`. `fontSize` → `<html style="font-size:Npx">`.
|
|
87
|
+
- `increase`/`decrease` — presets 의 인접 값으로만 이동.
|
|
88
|
+
|
|
89
|
+
### SdThemeSelector — `<sd-theme-selector>`
|
|
90
|
+
|
|
91
|
+
- inputs 없음. 팔레트(다크 토글) + 폰트 크기 ± 버튼 UI.
|
|
92
|
+
|
|
93
|
+
## 유틸 함수
|
|
94
|
+
|
|
95
|
+
### FormatPipe — `{{ value | format: pattern }}`
|
|
96
|
+
|
|
97
|
+
- `value: string|DateTime|DateOnly|undefined`, `format: string` → 포맷팅된 string.
|
|
98
|
+
- DateTime/DateOnly → `toFormatString(format)`.
|
|
99
|
+
- 문자열 → `X` 자리에 1글자씩 매핑. `|` 로 여러 패턴 alt 가능(value 길이 일치하는 첫 패턴 선택). 매칭 실패 시 원본 반환.
|
|
100
|
+
- 예: `"01012345678" | format: "XXX-XXXX-XXXX|XXX-XXX-XXXX"` → `"010-1234-5678"`.
|
|
101
|
+
|
|
102
|
+
### mark
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
function mark(sig: WritableSignal<any>): void
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- in-place mutation 후 signal 소비자에게 변경 알림. 배열은 shallow copy, 객체는 spread. mutable 데이터로 setter 호출 누락 방지용.
|
|
109
|
+
|
|
110
|
+
### setSafeStyle
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
function setSafeStyle(renderer: Renderer2, el: HTMLElement, style: Partial<CSSStyleDeclaration>): void
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- `Renderer2.setStyle` 을 객체 단위로 일괄 적용. SSR/zoneless 안전.
|
|
117
|
+
|
|
118
|
+
### setupBgTheme
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
function setupBgTheme(options?: {
|
|
122
|
+
theme?: "primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray";
|
|
123
|
+
lightness?: "lightest"|"lighter";
|
|
124
|
+
}): void
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- 컴포넌트 진입 동안 `document.body --background-color` 를 테마 변수로 설정. destroy 시 원복.
|
|
128
|
+
- `lightness` 기본 `lightest`.
|
|
129
|
+
|
|
130
|
+
### setupModelHook
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
function setupModelHook<T>(model: WritableSignal<T>, canFn: Signal<(item: T) => boolean|Promise<boolean>>): void
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- model 의 `set`/`update` 를 가로채 `canFn(value)` 결과가 true(또는 Promise<true>) 일 때만 적용. false 면 무시. Promise reject 는 `ErrorHandler`.
|
|
137
|
+
- 체크박스/스위치 등의 `canChangeFn` 패턴 구현체.
|
|
138
|
+
|
|
139
|
+
## 타입 헬퍼
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
type UndefToOptional<T> // undefined 가능 prop 을 optional 로
|
|
143
|
+
type DirectiveInputSignals<T> // 컴포넌트의 InputSignal prop → 값 타입 객체
|
|
144
|
+
type WithOptional<T, K extends keyof T> // 일부 키를 optional 로
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- `SdModalInfo.inputs` / `SdPrintInput.inputs` 등의 타입 빌딩에 사용.
|
|
148
|
+
|
|
149
|
+
## DOM 이벤트 디렉티브
|
|
150
|
+
|
|
151
|
+
### SdEvents — `<el (click.capture)="..." (scroll.passive)="..." ...>`
|
|
152
|
+
|
|
153
|
+
- 이벤트 이름 끝에 `.capture`/`.passive`/`.once` 조합 가능한 다중 셀렉터 디렉티브. 표준 Angular 이벤트 바인딩으로는 옵션 못 주는 listener option 활성.
|
|
154
|
+
- 지원 이벤트: click/mouse*/keydown/keyup/focus/blur/invalid/scroll/wheel/touch*/drag*/transitionend/animationend.
|
|
155
|
+
|
|
156
|
+
### SdOptionEventPlugin
|
|
157
|
+
|
|
158
|
+
- `provideSdAngular` 가 `EVENT_MANAGER_PLUGINS` 에 등록. `SdEvents` 가 의존. 직접 호출 X.
|
|
159
|
+
|
|
160
|
+
### SdResizeDirective — `[sdResize]`
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
sdResize = output<SdResizeEvent>();
|
|
164
|
+
interface SdResizeEvent { heightChanged: boolean; widthChanged: boolean; target: HTMLElement; contentRect: DOMRectReadOnly; }
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
- `ResizeObserver` + rAF 디바운스. 너비/높이 변경 플래그 포함.
|
|
168
|
+
|
|
169
|
+
### SdIntersectionDirective — `[sdIntersection]`
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
sdIntersection = output<SdIntersectionEvent>();
|
|
173
|
+
interface SdIntersectionEvent { entry: IntersectionObserverEntry; }
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- `IntersectionObserver` 래퍼. 무한 스크롤 트리거 등.
|
|
177
|
+
|
|
178
|
+
### SdCommandDirective — `[sdRefreshCommand]`/`[sdSaveCommand]`/`[sdInsertCommand]`
|
|
179
|
+
|
|
180
|
+
- 전역 키 단축키 출력. `Ctrl+Alt+L` → refresh, `Ctrl+S` → save, `Insert` → insert. 최상위 열린 모달 또는 호스트가 활성 영역일 때만 발화(다른 모달 위면 무시).
|
|
181
|
+
|
|
182
|
+
## 효과 디렉티브
|
|
183
|
+
|
|
184
|
+
### SdRipple — `[sdRipple]` + setupRipple
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
enabled = input.required({ alias: "sdRipple", transform: booleanAttribute });
|
|
57
188
|
```
|
|
58
189
|
|
|
59
|
-
|
|
190
|
+
- 클릭 시 머티리얼풍 잉크 효과. `setupRipple(enableFn?)` 은 컴포넌트 안에서 inject 후 직접 호출하는 형태.
|
|
191
|
+
|
|
192
|
+
### SdShowEffect — `[sdShowEffect]` + setupRevealOnShow
|
|
60
193
|
|
|
61
|
-
|
|
194
|
+
```ts
|
|
195
|
+
enabled = input.required({ alias: "sdShowEffect", transform: booleanAttribute });
|
|
196
|
+
sdShowEffectType = input<"l2r"|"t2b">("t2b");
|
|
197
|
+
```
|
|
62
198
|
|
|
63
|
-
|
|
199
|
+
- 스크롤로 첫 표시 시 페이드인 + 슬라이드. `l2r`: 좌→우, `t2b`: 위→아래(기본).
|
|
64
200
|
|
|
65
|
-
|
|
201
|
+
### SdInvalid — `[sdInvalid]` + setupInvalid
|
|
66
202
|
|
|
67
|
-
|
|
203
|
+
```ts
|
|
204
|
+
invalidMessage = input.required<string>({ alias: "sdInvalid" });
|
|
205
|
+
```
|
|
68
206
|
|
|
69
|
-
|
|
207
|
+
- 호스트 요소를 invalid 상태로 표시(빨간 점 인디케이터 + form submit 막기). 빈 문자열이면 valid. 직접 form 검증 메시지 표시할 때.
|
|
70
208
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
209
|
+
## 템플릿 디렉티브
|
|
210
|
+
|
|
211
|
+
### SdTypedTemplate — `<ng-template typed>`
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
class SdTypedTemplate<T> { typed = input.required<T>(); }
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
- 템플릿 컨텍스트 타입 명시용. `typed` 에 token 값/객체 바인딩.
|
|
218
|
+
|
|
219
|
+
### SdItemOfTemplate — `<ng-template itemOf>`
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
class SdItemOfTemplate<TItem> { itemOf = input.required<TItem[]>(); }
|
|
223
|
+
interface SdItemOfTemplateContext<TItem> { $implicit: TItem; item: TItem; index: number; depth: number; }
|
|
74
224
|
```
|
|
75
225
|
|
|
76
|
-
- 템플릿
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
-
|
|
226
|
+
- 리스트 아이템 템플릿 컨텍스트 타입 추론. `let-item`, `let-index="index"`, `let-depth="depth"` 사용 가능. `SdCalendar` 등이 자식으로 요구.
|
|
227
|
+
|
|
228
|
+
## 주의
|
|
229
|
+
|
|
230
|
+
- `provideSdAngular` 호출만으로 `SdGlobalErrorHandlerPlugin`/`SdOptionEventPlugin`/`SdEvents` 가 모두 활성. 별도 추가 불필요.
|
|
231
|
+
- `SdLocalStorageProvider`/`SdSystemConfigProvider` 의 키는 `clientName.<key>` 형태. 같은 도메인의 다른 simplysm 앱과 충돌 방지.
|