@simplysm/sd-claude 14.0.97 → 14.0.99

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 (77) hide show
  1. package/claude/references/sd-simplysm14/README.md +16 -16
  2. package/claude/references/sd-simplysm14/apis/angular/README.md +81 -153
  3. package/claude/references/sd-simplysm14/apis/angular/controls.md +179 -205
  4. package/claude/references/sd-simplysm14/apis/angular/crud.md +71 -57
  5. package/claude/references/sd-simplysm14/apis/angular/directives.md +49 -109
  6. package/claude/references/sd-simplysm14/apis/angular/features.md +58 -86
  7. package/claude/references/sd-simplysm14/apis/angular/kanban.md +32 -40
  8. package/claude/references/sd-simplysm14/apis/angular/layout.md +38 -52
  9. package/claude/references/sd-simplysm14/apis/angular/overlay.md +86 -110
  10. package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +54 -86
  11. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +82 -74
  12. package/claude/references/sd-simplysm14/apis/angular/sheet.md +56 -80
  13. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +15 -15
  14. package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +21 -21
  15. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +79 -53
  16. package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +9 -11
  17. package/claude/references/sd-simplysm14/apis/core-browser/README.md +15 -15
  18. package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +20 -20
  19. package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +18 -18
  20. package/claude/references/sd-simplysm14/apis/core-common/README.md +20 -49
  21. package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +66 -55
  22. package/claude/references/sd-simplysm14/apis/core-common/collection-ext.md +83 -56
  23. package/claude/references/sd-simplysm14/apis/core-common/errors.md +32 -21
  24. package/claude/references/sd-simplysm14/apis/core-common/obj.md +57 -39
  25. package/claude/references/sd-simplysm14/apis/core-common/serialization.md +36 -30
  26. package/claude/references/sd-simplysm14/apis/core-common/value-types.md +69 -41
  27. package/claude/references/sd-simplysm14/apis/core-node/README.md +4 -4
  28. package/claude/references/sd-simplysm14/apis/core-node/consola.md +15 -13
  29. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +11 -7
  30. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +8 -8
  31. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +29 -20
  32. package/claude/references/sd-simplysm14/apis/core-node/pathx.md +14 -6
  33. package/claude/references/sd-simplysm14/apis/core-node/worker.md +3 -3
  34. package/claude/references/sd-simplysm14/apis/excel/README.md +3 -3
  35. package/claude/references/sd-simplysm14/apis/excel/cell.md +32 -32
  36. package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +23 -24
  37. package/claude/references/sd-simplysm14/apis/excel/style.md +24 -30
  38. package/claude/references/sd-simplysm14/apis/excel/utils.md +20 -23
  39. package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +60 -71
  40. package/claude/references/sd-simplysm14/apis/excel/wrapper.md +36 -36
  41. package/claude/references/sd-simplysm14/apis/lint/README.md +7 -9
  42. package/claude/references/sd-simplysm14/apis/lint/recommended.md +59 -37
  43. package/claude/references/sd-simplysm14/apis/lint/rules.md +81 -74
  44. package/claude/references/sd-simplysm14/apis/orm-common/README.md +6 -6
  45. package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +112 -78
  46. package/claude/references/sd-simplysm14/apis/orm-common/expr.md +131 -75
  47. package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +126 -82
  48. package/claude/references/sd-simplysm14/apis/orm-common/schema.md +170 -113
  49. package/claude/references/sd-simplysm14/apis/orm-common/types.md +102 -48
  50. package/claude/references/sd-simplysm14/apis/orm-node/README.md +12 -13
  51. package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +3 -3
  52. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +5 -5
  53. package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +67 -65
  54. package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +130 -123
  55. package/claude/references/sd-simplysm14/apis/service-client/README.md +63 -63
  56. package/claude/references/sd-simplysm14/apis/service-client/orm.md +22 -22
  57. package/claude/references/sd-simplysm14/apis/service-client/transport.md +30 -26
  58. package/claude/references/sd-simplysm14/apis/service-common/README.md +8 -8
  59. package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +13 -6
  60. package/claude/references/sd-simplysm14/apis/service-common/protocol.md +1 -1
  61. package/claude/references/sd-simplysm14/apis/service-server/README.md +43 -47
  62. package/claude/references/sd-simplysm14/apis/service-server/built-in-services.md +35 -0
  63. package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +20 -19
  64. package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +23 -25
  65. package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +9 -9
  66. package/claude/references/sd-simplysm14/apis/storage/README.md +26 -26
  67. package/claude/references/sd-simplysm14/manuals/client-component.md +9 -1
  68. package/claude/references/sd-simplysm14/manuals/client-crud.md +1 -1
  69. package/claude/references/sd-simplysm14/manuals/client-orm.md +1 -0
  70. package/claude/references/sd-simplysm14/manuals/client-service.md +1 -0
  71. package/claude/references/sd-simplysm14/manuals/client-shared-data.md +1 -0
  72. package/claude/references/sd-simplysm14/manuals/client-ssg.md +1 -0
  73. package/claude/sd-system-prompt.md +11 -26
  74. package/claude/skills/sd-docs/references/subagent-prompt.md +4 -3
  75. package/claude/skills/sd-spec/SKILL.md +87 -18
  76. package/claude/skills/sd-spec/references/format.md +2 -2
  77. package/package.json +1 -1
@@ -1,75 +1,89 @@
1
- # @simplysm/angular — CRUD 화면 골격
1
+ # @simplysm/angular — CRUD 화면 골격·권한표·상태프리셋
2
2
 
3
- 목록/단건 화면의 표준 컨테이너 골격. `sd-base-container`(공통 셸) 위에 `sd-crud-list`(목록), `sd-crud-detail`(단건)이 얹힘. 표준 시그널(ready/initialized/busyCount/viewType)·page/modal/control 컨텍스트별 탑바·하단바 자동 구성·CTRL+S 저장을 내장. 사용 절차는 [client-crud.md](../manuals/client-crud.md) 참조.
3
+ 목록/단건 화면의 표준 컨테이너 골격. `sd-base-container`(공통 셸) 위에 `sd-crud-list`(목록)·`sd-crud-detail`(단건)이 얹힘. 표준 시그널(`ready`/`initialized`/`busyCount`/`viewType`)·page/modal/control 컨텍스트별 탑바·하단바 자동 구성·CTRL+S 저장을 내장. 화면 작성 절차·데이터 흐름은 [client-crud.md](../manuals/client-crud.md) · [client-component.md](../manuals/client-component.md) 참조. 함께 쓰는 권한 테이블·상태 프리셋도 이 군에 둠.
4
4
 
5
- ## SdBaseContainer `<sd-base-container>`
5
+ 공통: 컨테이너 모두 `viewType: SdViewType`(required, `"page"|"modal"|"control"`)에 따라 동작이 갈림. `"page"` = 라우팅 진입(탑바에 액션), `"modal"` = 모달(하단 명령바·확인 버튼), `"control"` = view 임베드(명령 영역에 액션).
6
6
 
7
- ```ts
8
- ready = model(false); initialized = input(false); busyCount = model(0);
9
- restricted = input(false); viewType = input.required<SdViewType>(); // "page"|"modal"|"control"
10
- viewTitle = injectViewTitleSignal(); // 자동
11
- // 슬롯: #topbarTpl #commandTpl #contentTpl #bottomCommandTpl
7
+ ## `SdBaseContainer` — `<sd-base-container>`
8
+
9
+ busy 컨테이너로 감싸고(`page` 탑바 포함) 권한 없음 placeholder 를 제공하는 공통 셸. `SdSharedDataProvider` 로드를 기다린 뒤 `ready` 를 set.
10
+
11
+ - `ready: model(false)` 공유데이터 로드 완료(또는 `restricted` 면 즉시) 후 자동 `true`. 자식 effect 발화 시점.
12
+ - `initialized: input(false)` — true 일 때만 콘텐츠 렌더. busy 스피너는 `initialized() && busyCount() > 0` 일 때.
13
+ - `busyCount: model(0)` — 진행 중 작업 수. `>0` 이면 busy.
14
+ - `restricted: input(false)` — true 면 "사용권한 없음" 메시지 렌더 + `ready` 즉시 set(공유데이터 대기 스킵).
15
+ - `viewType: input.required<SdViewType>` — `"page"` 면 `<sd-topbar-container>` + viewTitle 렌더, `"modal"`/`"control"` 면 탑바 없이 콘텐츠.
16
+ - 슬롯: `#topbarTpl`(page 탑바 추가 버튼) / `#commandTpl`(콘텐츠 위 명령바) / `#contentTpl`(본문) / `#bottomCommandTpl`(하단 명령바).
17
+
18
+ ```html
19
+ <sd-base-container [(ready)]="ready" [initialized]="initialized()" [(busyCount)]="busyCount" [restricted]="!perms().includes('use')" [viewType]="viewType()">
20
+ <ng-template #contentTpl>...</ng-template>
21
+ </sd-base-container>
12
22
  ```
13
23
 
14
- - `initialized` — false 동안 busy 표시. `busyCount`>0 이면 busy(model 양방향, 화면이 +1/-1 누적). `restricted`=권한 없음 안내 화면 표시(콘텐츠 미렌더).
15
- - `viewType` — `"page"`=탑바(제목+#topbarTpl) 포함, `"modal"`/`"control"`=콘텐츠만. `ready` 는 공유데이터 로드 완료 후 true(model, 화면이 이를 보고 초기화 진행).
16
- - 직접 쓰기보다 `sd-crud-list`/`sd-crud-detail` 또는 커스텀 화면 셸로 사용. 슬롯은 `#topbarTpl`(탑바 추가), `#commandTpl`(명령영역), `#contentTpl`(본문), `#bottomCommandTpl`(하단).
17
-
18
- ## SdCrudList`<sd-crud-list>`
19
-
20
- ```ts
21
- ready = model(false); initialized = input(false); busyCount = model(0);
22
- restricted = input(false); readonly = input(false); inlineEdit = input(true);
23
- viewType = input.required<SdViewType>(); selectMode = input<"single" | "multi">();
24
- key = input.required<string>();
25
- items = input<TItem[]>([]); selectedKeys = model<NonNullable<TKey>[]>([]);
26
- currDeletedItems = input<TItem[]>([]);
27
- currentPage = model(0); totalPageCount = input(0); itemsPerPage = input(0); visiblePageCount = input(10);
28
- sorts = model<SortingDef[]>([]);
29
- trackByFn = input.required<(item: TItem) => TKey>();
30
- getItemSelectableFn = input<(item: TItem) => boolean | string>();
31
-
32
- filterSubmit = output(); submit = output(); create = output();
33
- delete = output<TItem[]>(); restore = output<TItem[]>();
34
- // 슬롯: #filterTpl #toolTpl #commandTpl #bottomCommandTpl, 직속 <sd-sheet-column>
24
+ ## `SdCrudDetail` — `<sd-crud-detail>`
25
+
26
+ 단건 편집 골격(`sd-base-container` 기반). `readonly` 아니면 콘텐츠를 `<sd-form>` 으로 감싸고 저장 컨트롤 제공. `SdCommandDirective` 호스트(CTRL+S → 저장).
27
+
28
+ - `ready: model(false)` / `initialized: input(false)` / `busyCount: model(0)` / `restricted: input(false)` base 로 전달.
29
+ - `readonly: input(false)` — true 면 저장 버튼 숨김 + `<sd-form>` 없이 plain `<div>` 렌더(제출 불가); false 면 `<sd-form>` 래핑 + 저장 컨트롤.
30
+ - `viewType: input.required<SdViewType>` — `"page"` = 탑바 `#topbarTpl` 에 "저장 (CTRL+S)" 버튼; `"control"` = `#commandTpl` 에 저장 버튼; `"modal"` = 하단 명령바에 "확인" 버튼.
31
+ - `submit: output()` 내부 `<sd-form>` 유효 제출 시 emit.
32
+ - 슬롯: `#contentTpl`(필수, 본문) / `#commandTpl` / `#bottomCommandTpl`.
33
+ - 메서드: `onSaveButtonClick()` `formCtrl().requestSubmit()`.
34
+
35
+ ```html
36
+ <sd-crud-detail [(ready)]="ready" [initialized]="initialized()" [(busyCount)]="busyCount" [restricted]="!perms().includes('use')" [readonly]="!canEdit()" [viewType]="viewType()" (submit)="onSubmit()">
37
+ <ng-template #contentTpl>...</ng-template>
38
+ </sd-crud-detail>
35
39
  ```
36
40
 
37
- - 목록 표준 골격(시트 + 검색폼 + 등록/삭제/복구 버튼 + CTRL+S 저장 + 모달 선택모드).
38
- - `readonly` — 편집 전체 불가(시트 선택만). `inlineEdit`(기본 true) — true 면 시트를 `<sd-form>` 으로 감싸 셀 인라인 편집 + per-row 삭제컬럼, false 면 조회·선택 전용(편집은 외부 상세/모달). 둘은 직교.
39
- - `selectMode` `"single"`=행 클릭 즉시(modal 이면 close), `"multi"`=하단 확인 버튼. modal+selectMode close `{ selectedKeys }` 자동 전달.
40
- - `currDeletedItems` — 현재 삭제(soft delete)된 항목들. 해당 행은 취소선 + 복구 버튼으로 표시. `key` 는 시트 설정 저장 키(`<key>-sheet`).
41
- - 출력: `filterSubmit`(검색), `submit`(인라인 편집 저장, inlineEdit=true 때만), `create`(등록), `delete`/`restore`(선택 항목 배열). `<sd-sheet-column>` 직속에 두면 내부 시트로 투영.
41
+ ## `SdCrudList<TItem, TKey>` `<sd-crud-list>`
42
+
43
+ 목록 골격(`sd-base-container` + `sd-sheet`). 시트·검색 폼·등록/삭제/복구·CTRL+S 저장·페이징·정렬·선택·인라인 편집·모달 선택을 일괄 제공. `SdCommandDirective` 호스트.
44
+
45
+ - `ready: model(false)` / `initialized: input(false)` / `busyCount: model(0)` / `restricted: input(false)` base 전달.
46
+ - `readonly: input(false)` — true 면 등록/삭제/복구 버튼 숨김 + 인라인 편집 비활성 + 삭제 행 취소선.
47
+ - `inlineEdit: input(true)` — true(비-readonly)면 시트를 `<sd-form>` 으로 감싸 셀 인라인 편집 + 삭제 컬럼 + 저장. false 면 인라인 편집 chrome 제거(조회·선택 전용, `submit` 미발화).
48
+ - `viewType: input.required<SdViewType>` — `"page"` = 탑바 저장 버튼(인라인 편집 시); `"modal"` = 하단 선택 명령바("선택 해제", multi 면 "확인(n)").
49
+ - `selectMode: "single"|"multi"|undefined` — `"single"` = 선택 삭제/복구 숨김·클릭 즉시 modal close; `"multi"` = 다중 선택·삭제/복구·"확인(n)"; `undefined`(비-modal) = 비-readonly 면 `'multi'`.
50
+ - `key: input.required<string>` — 시트 설정 키(내부 시트는 `key()+'-sheet'`).
51
+ - `items: TItem[]` (기본 `[]`) — 행 데이터.
52
+ - `currDeletedItems: TItem[]` (기본 `[]`) — 삭제(soft delete) 행. 취소선·복구 버튼·삭제/복구 아이콘 토글에. 삭제항목 포함 검색 목록은 필수.
53
+ - `trackByFn: input.required<(item: TItem) => TKey>` — 키 추출(선택 멤버십·시트 추적).
54
+ - `getItemSelectableFn: (item) => boolean | string | undefined` — 시트로 전달, `string`=불가+툴팁.
55
+ - `currentPage: model(0)` / `totalPageCount: input(0)`(서버 페이징; `0`이면 useAutoSort 활성) / `itemsPerPage: input(0)`(클라이언트 페이징) / `visiblePageCount: input(10)` / `sorts: model<SortingDef[]>([])` — 시트로 전달.
56
+ - `selectedKeys: model<NonNullable<TKey>[]>([])` — 선택 키(시트와 양방향).
57
+ - output: `filterSubmit`(조회 폼 제출) / `submit`(인라인 편집 저장) / `create`(등록) / `delete: TItem[]`(삭제 대상) / `restore: TItem[]`(복구 대상).
58
+ - 슬롯: `#filterTpl`(검색 폼; 내부가 이미 `form-box-inline`) / `#toolTpl`(도구 버튼) / `#commandTpl` / `#bottomCommandTpl`. `<sd-sheet-column>` 직속 자식은 내부 시트로 자동 투영.
42
59
 
43
60
  ```html
44
- <sd-crud-list [(ready)]="ready" [initialized]="initialized()" [(busyCount)]="busyCount"
45
- [restricted]="!perms().includes('use')" [readonly]="!canEdit()" [viewType]="viewType()"
46
- [key]="'role'" [items]="items()" [trackByFn]="trackByFn" [(selectedKeys)]="selectedKeys"
47
- (create)="onCreate()" (delete)="onDelete($event)" (restore)="onRestore($event)">
61
+ <sd-crud-list [(ready)]="ready" [initialized]="initialized()" [(busyCount)]="busyCount" [restricted]="!perms().includes('use')" [readonly]="!canEdit()" [viewType]="viewType()" [selectMode]="selectMode() ?? 'multi'" [key]="'role'" [items]="items()" [currDeletedItems]="deletedItems()" [trackByFn]="trackByFn" [(selectedKeys)]="selectedKeys" [(currentPage)]="page" [totalPageCount]="pageLength()" [(sorts)]="sortingDefs" (filterSubmit)="onFilterSubmit()" (submit)="onSubmit()" (create)="onCreate()" (delete)="onDelete($event)" (restore)="onRestore($event)">
48
62
  <ng-template #filterTpl>...</ng-template>
49
- <sd-sheet-column [key]="'name'" [header]="'이름'">
50
- <ng-template [cell]="items()" let-item="item">{{ item.name }}</ng-template>
51
- </sd-sheet-column>
63
+ <sd-sheet-column [key]="'name'" [header]="'이름'"><ng-template [cell]="items()" let-item="item">...</ng-template></sd-sheet-column>
52
64
  </sd-crud-list>
53
65
  ```
54
66
 
55
- ## SdCrudDetail — `<sd-crud-detail>`
67
+ ## `SdStatePreset<TState>` — `<sd-state-preset>`
56
68
 
57
- ```ts
58
- ready = model(false); initialized = input(false); busyCount = model(0);
59
- restricted = input(false); readonly = input(false);
60
- viewType = input.required<SdViewType>();
61
- submit = output();
62
- // 슬롯: #contentTpl(필수) #commandTpl #bottomCommandTpl
63
- ```
69
+ 임의 상태의 명명 스냅샷을 저장·복원(system config 영속화). 필터 프리셋 등에.
70
+
71
+ - `key: input.required<string>` 프리셋 배열 저장 키.
72
+ - `state: model.required<TState>` — 현재 상태(양방향). 프리셋 클릭 시 그 상태로 set(deep clone), 저장 시 현재 상태 clone 보관.
73
+ - `size: "sm"|"lg"|undefined` — 추가 버튼/칩 패딩 스케일.
74
+ - 메서드: `onAddClick()`(이름 입력·중복 거부·추가) / `onPresetClick(preset)`(적용) / `onSaveClick(preset)`(덮어쓰기) / `onDeleteClick(preset)`(확인 후 삭제).
75
+ - `SdStatePresetDef<TState>` — `{ name: string; state: TState }`.
64
76
 
65
- - 단건 편집 표준 골격(폼 래핑 + CTRL+S 저장 + 저장 버튼 + modal "확인" 자동).
66
- - `readonly` — true 면 `#contentTpl` 을 `<sd-form>` 없이 그대로(읽기), false 면 폼으로 감싸 `submit` 출력. `viewType` `"page"`=상단 저장버튼, `"control"`=명령영역 저장버튼, `"modal"`=하단 우측 "확인" 자동.
67
- - `#contentTpl`(필수) 본문, `#commandTpl`/`#bottomCommandTpl` 추가 액션.
77
+ ## `SdPermissionTable<TModule>` `<sd-permission-table>`
78
+
79
+ 권한 트리(사용/편집 체크박스) 계층 표시. 부모/자식·use→edit 의존 규칙 강제. 권한 관리 화면에서 `getPermissionsByStructure` 결과를 넘김([client-app-structure.md](../manuals/client-app-structure.md)).
80
+
81
+ - `value: model<Record<string, boolean>>({})` — `"<codeChain>.<use|edit>" → boolean` 맵. 토글이 자식에 캐스케이드, `use` 해제 시 `edit` 자동 해제, `use` 미체크면 `edit` 체크 무시.
82
+ - `items: SdPermission<TModule>[]` (기본 `[]`) — 권한 트리.
83
+ - `disabled: boolean` — true 면 전체 체크박스 비활성.
68
84
 
69
85
  ```html
70
- <sd-crud-detail [(ready)]="ready" [initialized]="initialized()" [(busyCount)]="busyCount"
71
- [restricted]="!perms().includes('use')" [readonly]="!canEdit()" [viewType]="viewType()"
72
- (submit)="onSubmit()">
73
- <ng-template #contentTpl><!-- 폼 본문 --></ng-template>
74
- </sd-crud-detail>
86
+ <sd-permission-table [items]="permissions()" [(value)]="data" />
75
87
  ```
88
+
89
+ (`SdPermission<TModule>` 타입은 [routing-appstructure.md](./routing-appstructure.md) 참조.)
@@ -1,167 +1,107 @@
1
- # @simplysm/angular — 호스트 디렉티브·signal 헬퍼
1
+ # @simplysm/angular — 디렉티브·signal 헬퍼
2
2
 
3
- DOM 관찰(리사이즈/교차)·캡처 이벤트·커맨드 단축키·ripple·노출 애니메이션·invalid 표시·타입드 템플릿을 호스트 엘리먼트에 붙이는 디렉티브와, signal/model 다루는 작은 헬퍼 군. `setup*` 헬퍼는 컴포넌트 `constructor`(주입 컨텍스트)에서 호출(`inject(ElementRef)` 의존), `Sd*` 디렉티브는 헬퍼를 attribute 로 래핑.
3
+ DOM 관찰(리사이즈/교차)·캡처 이벤트·커맨드 단축키·ripple·노출 애니메이션·invalid 표시·타입드 템플릿을 호스트 엘리먼트에 붙이는 디렉티브와, 디렉티브가 래핑하는 `setup*` 헬퍼 군. `setup*`/`inject*` 헬퍼는 컴포넌트 `constructor`(주입 컨텍스트)에서 호출(`inject(ElementRef)` 의존). 모든 디렉티브는 standalone, attribute selector.
4
4
 
5
5
  ## DOM 관찰 디렉티브
6
6
 
7
- ### SdResizeDirective — `[sdResize]`
7
+ ### `SdResizeDirective` — `[sdResize]`
8
8
 
9
- ```ts
10
- sdResize = output<SdResizeEvent>();
11
- // SdResizeEvent { heightChanged: boolean; widthChanged: boolean; target: HTMLElement; contentRect: DOMRectReadOnly }
12
- ```
13
-
14
- - `ResizeObserver` 로 크기 변화를 rAF 디바운스해 방출. `heightChanged`/`widthChanged` 로 변경 축을 구분(불필요한 재계산 회피). 시트·collapse·echarts 가 사용.
9
+ - `sdResize: output<SdResizeEvent>` — `ResizeObserver` 기반, `requestAnimationFrame` 디바운스. `SdResizeEvent` = `{ heightChanged: boolean; widthChanged: boolean; target: HTMLElement; contentRect: DOMRectReadOnly }`.
15
10
 
16
11
  ```html
17
12
  <div (sdResize)="onResize($event)">...</div>
18
13
  ```
19
14
 
20
- ### SdIntersectionDirective — `[sdIntersection]`
21
-
22
- ```ts
23
- sdIntersection = output<SdIntersectionEvent>();
24
- // SdIntersectionEvent { entry: IntersectionObserverEntry }
25
- ```
26
-
27
- - `IntersectionObserver` 로 뷰포트 진입/이탈을 방출. 지연 로드·노출 트리거에 사용. `entry.isIntersecting` 으로 판정.
15
+ ### `SdIntersectionDirective` — `[sdIntersection]`
28
16
 
29
- ## 이벤트·커맨드 디렉티브
17
+ - `sdIntersection: output<SdIntersectionEvent>` — `IntersectionObserver` 기반, 콜백 배치의 마지막 엔트리 emit. `SdIntersectionEvent` = `{ entry: IntersectionObserverEntry }`.
30
18
 
31
- ### SdEvents 이벤트 수식어 출력
19
+ ## 캡처/옵션 이벤트
32
20
 
33
- ```ts
34
- // selector 의 각 어트리뷰트가 output. 예:
35
- "click.capture", "click.once", "scroll.passive", "wheel.passive",
36
- "touchstart.passive", "keydown.capture", "focus.capture", "blur.capture",
37
- "invalid.capture", "transitionend.once", "animationend.once" ...
38
- ```
21
+ ### `SdEvents` (디렉티브)
39
22
 
40
- - capture/passive/once 수식어가 붙은 DOM 이벤트를 Angular 출력으로 노출(`SdOptionEventPlugin` 과 함께 동작). 성능·캡처가 필요한 이벤트 바인딩에 사용. 호스트 디렉티브로도 쓰임(시트가 `keydown.capture` 사용).
23
+ native DOM 리스너 옵션(`capture`/`passive`/`once`)을 이벤트명 접미사로 노출하는 디렉티브. `SdOptionEventPlugin` 과 함께 동작. 출력은 접미사 그대로의 이름: `click.capture`/`click.once`/`click.capture.once`, `mousedown.capture`/`mouseup.capture`/`mouseover.capture`/`mouseout.capture`, `keydown.capture`/`keyup.capture`, `focus.capture`/`blur.capture`, `invalid.capture`, `scroll.capture`/`scroll.passive`/`scroll.capture.passive`, `wheel.passive`/`wheel.capture.passive`, `touchstart.passive`/`touchmove.passive`/`touchend.passive`( `.capture.passive` 변형), `dragover.capture`/`dragenter.capture`/`dragleave.capture`/`drop.capture`, `transitionend.once`, `animationend.once`. 각 출력의 페이로드 타입은 해당 native 이벤트(`MouseEvent`/`KeyboardEvent`/`FocusEvent`/`DragEvent`/`WheelEvent`/`TouchEvent`/`TransitionEvent`/`AnimationEvent`/`Event`).
41
24
 
42
25
  ```html
43
- <div (scroll.passive)="onScroll()" (keydown.capture)="onKeydown($event)">...</div>
44
- ```
45
-
46
- ### SdOptionEventPlugin
47
-
48
- ```ts
49
- class SdOptionEventPlugin extends EventManagerPlugin
26
+ <div (keydown.capture)="onKeydownCapture($event)" (scroll.passive)="onScroll($event)">...</div>
50
27
  ```
51
28
 
52
- - `.capture`/`.passive`/`.once` 수식어 이벤트를 처리하는 Angular `EVENT_MANAGER_PLUGINS`. `provideSdAngular` 가 등록(직접 사용 안 함). `SdEvents` 디렉티브의 기반.
29
+ ### `SdOptionEventPlugin`
53
30
 
54
- ### SdCommandDirective `[sdRefreshCommand]` / `[sdSaveCommand]` / `[sdInsertCommand]`
55
-
56
- ```ts
57
- sdRefreshCommand = output<KeyboardEvent>(); // Ctrl+Alt+L
58
- sdSaveCommand = output<KeyboardEvent>(); // Ctrl+S
59
- sdInsertCommand = output<KeyboardEvent>(); // Insert
60
- ```
31
+ `EventManagerPlugin` 확장(`provideSdAngular` `EVENT_MANAGER_PLUGINS` multi 로 등록). 이벤트명 접미사 `.capture`/`.passive`/`.once` native 리스너 옵션으로 변환. 위 `SdEvents` 출력이 이 플러그인 위에서 동작.
61
32
 
62
- - 전역 키보드 단축키를 출력으로. 최상위 열린 모달 안에서만 동작(다른 화면 간섭 방지). crud 골격이 `sdSaveCommand` 로 CTRL+S 저장 연결.
33
+ ## 커맨드 단축키
63
34
 
64
- ### SdGlobalErrorHandlerPlugin
35
+ ### `SdCommandDirective` — `[sdRefreshCommand],[sdSaveCommand],[sdInsertCommand]`
65
36
 
66
- ```ts
67
- class SdGlobalErrorHandlerPlugin implements ErrorHandler
68
- ```
37
+ 전역 키 조합을 받아 출력으로 발화하는 디렉티브. 호스트가 최상위 열린 모달 안이거나 모달이 없을 때만 처리.
69
38
 
70
- - 전역 에러 핸들러. 처리되지 않은 에러/Promise 거부를 시스템 로그 적재 + 전체화면 에러 오버레이로 표시(앱 destroy 후 클릭 시 reload). `provideSdAngular` 가 `ErrorHandler` 로 등록(직접 사용 안 함).
39
+ - `sdRefreshCommand: output<KeyboardEvent>` `Ctrl+Alt+L`.
40
+ - `sdSaveCommand: output<KeyboardEvent>` — `Ctrl+S`(Alt 없이). `sd-crud-list`/`sd-crud-detail` 이 hostDirective 로 사용해 저장에 배선.
41
+ - `sdInsertCommand: output<KeyboardEvent>` — `Ctrl+Insert`.
71
42
 
72
- ## 시각 효과·검증 디렉티브
43
+ ## ripple
73
44
 
74
- ### setupRipple / SdRipple — `[sdRipple]`
45
+ ### `setupRipple`
75
46
 
76
47
  ```ts
77
- setupRipple(enableFn?: () => boolean): void;
78
- // SdRipple: enabled = input.required({ alias: "sdRipple", transform: booleanAttribute });
48
+ function setupRipple(enableFn?: () => boolean): void
79
49
  ```
80
50
 
81
- - 클릭 파동(ripple) 효과. `setupRipple` constructor 에서, `[sdRipple]="true"` 디렉티브는 템플릿에서. `enableFn`/`enabled` false 효과 비활성(disabled 컨트롤). 버튼·체크박스·리스트가 사용.
51
+ - 주입 컨텍스트에서 호출. 호스트를 `position:relative; overflow:hidden` 으로 만들고 `pointerdown` 확장 원형 ripple 생성. `enableFn` false 반환 스킵. SSR no-op.
82
52
 
83
- ### setupRevealOnShow / SdShowEffect — `[sdShowEffect]`
53
+ ### `SdRipple` — `[sdRipple]`
84
54
 
85
- ```ts
86
- setupRevealOnShow(optFn?: () => { type?: "l2r" | "t2b"; enabled?: boolean }): void;
87
- // SdShowEffect: enabled = input.required({ alias: "sdShowEffect" }); sdShowEffectType = input<"l2r"|"t2b">("t2b");
88
- ```
55
+ - `enabled: input.required({ alias: "sdRipple", transform: booleanAttribute })` — 속성값을 boolean 으로. `setupRipple(() => enabled())` 배선.
89
56
 
90
- - 뷰포트 진입 시 페이드+슬라이드 노출 애니메이션. `type` `"t2b"`=위→아래(기본), `"l2r"`=좌→우. `enabled`=false 면 애니메이션 없이 즉시 표시.
57
+ ## 노출 애니메이션
91
58
 
92
- ### setupInvalid / SdInvalid — `[sdInvalid]`
59
+ ### `setupRevealOnShow`
93
60
 
94
61
  ```ts
95
- setupInvalid(getInvalidMessage: () => string): void;
96
- // SdInvalid: invalidMessage = input.required<string>({ alias: "sdInvalid" });
62
+ function setupRevealOnShow(optFn?: () => { type?: "l2r" | "t2b"; enabled?: boolean }): void
97
63
  ```
98
64
 
99
- - 호스트에 숨김 input 붙여 native form 검증에 참여. `getInvalidMessage()`/`invalidMessage` 문자열이 아니면 invalid(좌상단 빨간 인디케이터 + form 제출 차단). 입력 컨트롤이 내부 사용.
65
+ - 초기 숨김(opacity 0 + 이동) `IntersectionObserver` 화면 진입 슬라이드-인. `type` = `"l2r"`(좌→우) / `"t2b"`(위→아래, 기본). `enabled` 기본 true(false 즉시 표시).
100
66
 
101
- ## 타입드 템플릿 디렉티브
67
+ ### `SdShowEffect` `[sdShowEffect]`
102
68
 
103
- ### SdTypedTemplate `ng-template[typed]`
69
+ - `enabled: input.required({ alias: "sdShowEffect", transform: booleanAttribute })`.
70
+ - `sdShowEffectType: input<"l2r" | "t2b">("t2b")` — 노출 방향.
104
71
 
105
- ```ts
106
- typed = input.required<T>();
107
- ```
108
-
109
- - `ng-template` 컨텍스트 타입을 명시(`ngTemplateContextGuard`). 재귀 메뉴/트리 템플릿에서 `let-x` 의 타입 안전성 확보. `[typed]` 에 타입 토큰을 넘김.
72
+ ## invalid 표시
110
73
 
111
- ### SdItemOfTemplate — `ng-template[itemOf]`
74
+ ### `setupInvalid`
112
75
 
113
76
  ```ts
114
- itemOf = input.required<TItem[]>();
115
- // SdItemOfTemplateContext<TItem> { $implicit; item; index; depth }
77
+ function setupInvalid(getInvalidMessage: () => string): void
116
78
  ```
117
79
 
118
- - 반복 항목 템플릿 마커. `[itemOf]="items()"` 항목 타입을 추론해 `let-item`/`let-index`/`let-depth` 제공. select·shared-data·calendar 등의 항목 슬롯에 사용.
80
+ - 호스트에 danger 인디케이터 + 숨김 input(native validity 운반)을 주입. `getInvalidMessage()` 문자열이 아니면 invalid(점 표시·`setCustomValidity`). `sd-form` `checkValidity()` 에 연동. 모든 검증 컨트롤(`sd-textfield` 등)의 내부 기반.
119
81
 
120
- ## signal·model 헬퍼
82
+ ### `SdInvalid` — `[sdInvalid]`
121
83
 
122
- ### setupModelHook
123
-
124
- ```ts
125
- setupModelHook<T>(model: WritableSignal<T>, canFn: Signal<(item: T) => boolean | Promise<boolean>>): void;
126
- ```
84
+ - `invalidMessage: input.required<string>({ alias: "sdInvalid" })` — 비어있지 않으면 호스트를 invalid 표시.
127
85
 
128
- - model 의 `set`/`update` 를 가로채 `canFn` 이 허용할 때만 적용. false 면 변경 거부, Promise 면 비동기 확인 후 적용(에러는 `ErrorHandler`). 체크박스·스위치·select-list 의 `canChangeFn` 이 사용.
86
+ ## 타입드 템플릿
129
87
 
130
- ### mark
88
+ ### `SdTypedTemplate<T>` — `ng-template[typed]`
131
89
 
132
- ```ts
133
- mark(sig: WritableSignal<any>): void;
134
- ```
90
+ - `typed: input.required<T>()` — 템플릿 컨텍스트 타입을 정하는 값. 정적 `ngTemplateContextGuard` 로 컨텍스트를 `T` 로 좁힘.
135
91
 
136
- - in-place mutation 한 signal 값에 shallow copy(배열/객체)로 새 참조를 만들어 변경 통지. 시트 셀에서 객체 필드를 직접 수정한 뒤 호출(`(valueChange)="mark(items)"`).
92
+ ### `SdItemOfTemplate<TItem>` `ng-template[itemOf]`
137
93
 
138
- ### setSafeStyle
139
-
140
- ```ts
141
- setSafeStyle(renderer: Renderer2, el: HTMLElement, style: Partial<CSSStyleDeclaration>): void;
142
- ```
143
-
144
- - `Renderer2.setStyle` 로 여러 스타일을 한 번에 적용하는 헬퍼(키별 순회). `style` 객체의 각 CSS 속성을 엘리먼트에 설정. 디렉티브/composable 에서 DOM 스타일을 안전하게 줄 때 사용(`setupInvalid` 등이 내부 사용).
145
-
146
- ### FormatPipe — `| format`
147
-
148
- ```ts
149
- @Pipe({ name: "format" }) transform(value: string | DateTime | DateOnly | undefined, format: string): string;
150
- ```
151
-
152
- - 값 포맷. `DateTime`/`DateOnly` 는 `toFormatString(format)`, 문자열은 `X` 마스크(`|` 로 길이 분기). null 이면 빈 문자열(결측 보존). calendar 등이 사용.
94
+ - `itemOf: input.required<TItem[]>()` — 항목 배열; 원소 타입으로 per-item 컨텍스트를 정함. 공유데이터 select·calendar 등 항목 렌더 템플릿에 사용.
95
+ - `SdItemOfTemplateContext<TItem>` = `{ $implicit: TItem; item: TItem; index: number; depth: number }`. 템플릿에서 `let-item="item"` 등으로 받음.
153
96
 
154
97
  ```html
155
- {{ date | format: "yyyy-MM-dd" }}
98
+ <sd-shared-data-select [items]="sharedCustomers.items()" ...>
99
+ <ng-template [itemOf]="sharedCustomers.items()" let-item="item">{{ item.name }}</ng-template>
100
+ </sd-shared-data-select>
156
101
  ```
157
102
 
158
- ### 타입 유틸
103
+ ## 전역 에러 핸들러
159
104
 
160
- ```ts
161
- DirectiveInputSignals<T> // 컴포넌트의 InputSignal 프로퍼티 → 값 타입 매핑(undefined 포함 필드는 optional)
162
- UndefToOptional<T> // undefined 포함 프로퍼티를 optional 로 변환
163
- WithOptional<T, K> // 특정 키 K 를 optional 로
164
- SelectModalOutputResult<TKey> { selectedKeys: TKey[] } // 선택 모달 close 페이로드
165
- ```
105
+ ### `SdGlobalErrorHandlerPlugin`
166
106
 
167
- - `DirectiveInputSignals<T>` 모달/토스트/인쇄의 `inputs` 타입 계산에 쓰이는 유틸(컴포넌트 input signal 일반 객체로 매핑). `SelectModalOutputResult` 선택형 모달이 close 돌려주는 표준 페이로드.
107
+ Angular `ErrorHandler` 구현(`provideSdAngular` `ErrorHandler` 등록). `handleError(event)` 브라우저에서 에러를 분류해 1회 전체화면 오버레이 표시 + `SdSystemLogProvider` 적재 + 파괴(클릭 새로고침). SSR 에선 로깅만. 직접 호출할 일은 없고 등록만.
@@ -1,122 +1,94 @@
1
- # @simplysm/angular — 부가 기능(권한표·상태프리셋·테마·주소·에디터·시각화)
1
+ # @simplysm/angular — features(테마·주소·에디터·시각화)
2
2
 
3
- 군에 들지 않는 도메인성/표시용 컴포넌트 모음. 특정 화면 기능을 붙일 때 개별로 읽힘. 모두 standalone `sd-*` 컴포넌트.
3
+ 테마 토글·폰트 크기, 주소 검색 모달, 리치텍스트 에디터, 라벨·노트·진행률·캘린더·바코드·차트 등 표시용 컴포넌트 모음. 특정 화면 기능을 붙일 때 개별로 읽힘.
4
4
 
5
- ## SdPermissionTable — `<sd-permission-table>`
5
+ ## 테마
6
6
 
7
- ```ts
8
- value = model<Record<string, boolean>>({}); // "<코드>.use"/"<코드>.edit" → boolean
9
- items = input<SdPermission<TModule>[]>([]);
10
- disabled = input(false);
11
- ```
7
+ ### `SdThemeProvider`
12
8
 
13
- - 권한 트리 편집표. `items`(`SdPermission` 트리, routing-appstructure.md)사용/편집 체크박스 표로 렌더. `value` `<코드>.use`/`<코드>.edit` 키의 boolean 맵(양방향).
14
- - use 미체크면 edit 불가, use 해제 시 edit 자동 해제, 부모 토글 시 하위 일괄 변경. `disabled`=전체 읽기전용. 권한 관리 화면에 사용.
9
+ `@Injectable({ providedIn: "root" })`. (`provideSdAngular` dark/fontSize 를 `SdLocalStorageProvider` 영속화)
15
10
 
16
- ## SdStatePreset`<sd-state-preset>`
11
+ - `dark: WritableSignal<boolean>` (초기 false) `effect` 로 body `sd-theme-dark` 클래스 토글(브라우저 전용).
12
+ - `fontSize: WritableSignal<number>` (초기 12) — `effect` 로 `documentElement.style.fontSize` 설정.
13
+ - `fontSizePresets: readonly number[]` = `[12, 14, 16, 20, 24, 28]`.
14
+ - `increaseFontSize()` / `decreaseFontSize()` — 다음/이전 프리셋으로(경계에서 no-op).
17
15
 
18
- ```ts
19
- key = input.required<string>(); state = model.required<TState>(); size = input<"sm"|"lg">();
20
- // SdStatePresetDef<TState> { name: string; state: TState }
21
- ```
16
+ ### `SdThemeSelector` — `<sd-theme-selector>`
22
17
 
23
- - 현재 화면 상태(`state`)를 이름붙여 저장·복원하는 프리셋 바(검색 조건 즐겨찾기 등). 버튼=현재 상태 저장(이름 prompt), 프리셋 클릭=상태 적용, 저장/삭제 버튼 제공.
24
- - `key` 로 `injectSdSystemConfigResource` 에 영속. `state` 는 화면이 들고 있는 상태 시그널(양방향).
18
+ 팔레트 아이콘 드롭다운(폰트 +/- · 다크모드 스위치). input 없음. `isMinFontSize`/`isMaxFontSize: computed` +/- 버튼 비활성.
25
19
 
26
- ## SdThemeProvider 셀렉터
20
+ ## 주소
27
21
 
28
- ### SdThemeSelector — `<sd-theme-selector>`
22
+ ### `SdAddressSearchModal` — `<sd-address-search-modal>`
29
23
 
30
- ```ts
31
- // 입력 없음. SdThemeProvider 를 inject.
32
- ```
24
+ Daum 우편번호 위젯 모달. `SdModalContentDef<Address>` 구현 — `_sdModal.showAsync({ type: SdAddressSearchModal, ... })` 로 띄움.
33
25
 
34
- - 다크모드 토글 + 글자크기 증감 UI 드롭다운. `SdThemeProvider` 직접 조작(`fontSize`/`dark`). 탑바 등에 배치. provider 본체는 [README.md](./README.md) "테마·배경".
26
+ - input 없음. `close: output<Address>` 선택 완료 주소 emit.
27
+ - `Address` = `{ postNumber: string | undefined; address: string | undefined; buildingName: string | undefined }`.
35
28
 
36
- ## SdAddressSearchModal — `<sd-address-search-modal>`
37
-
38
- ```ts
39
- close = output<Address>(); // SdModalContentDef<Address>
40
- // Address { postNumber: string | undefined; address: string | undefined; buildingName: string | undefined }
41
- ```
29
+ ## 에디터
42
30
 
43
- - 다음(Daum) 우편번호 검색 모달. `SdModalProvider.showAsync({ type: SdAddressSearchModal, inputs: {} })` 띄움. 스크립트를 동적 로드하며 실패 시 에러 메시지 표시. 선택 시 `{ postNumber, address, buildingName }` 으로 close.
31
+ ### `SdTiptapEditor` `<sd-tiptap-editor>`
44
32
 
45
- ```ts
46
- const addr = await this._sdModal.showAsync({ title: "주소 검색", type: SdAddressSearchModal, inputs: {} });
47
- ```
48
-
49
- ## SdTiptapEditor — `<sd-tiptap-editor>`
50
-
51
- ```ts
52
- value = model<string>(); // HTML
53
- disabled; readonly; required; placeholder = input<string>();
54
- validatorFn = input<(value: string | undefined) => string | undefined>();
55
- extensions = input<AnyExtension[]>();
56
- editor: WritableSignal<Editor | undefined>; // @internal — TipTap 인스턴스
57
- ```
33
+ 툴바 내장 리치텍스트(TipTap) 에디터.
58
34
 
59
- - 리치 텍스트(WYSIWYG) 에디터. `value` HTML 문자열( 내용이면 undefined, 결측 보존). 내장 툴바(제목·굵게·색·정렬·목록·인용·코드블록 등) 제공.
60
- - `extensions` 지정 기본 확장 대체, 미지정 시 StarterKit + 색/하이라이트/정렬/이미지/밑줄(+placeholder). `disabled`/`readonly`=편집 불가, `required`/`validatorFn`=form 검증(`setupInvalid`).
35
+ - `value: model<string>` HTML 콘텐츠(비면 `undefined`).
36
+ - `disabled: boolean` true 툴바 숨김 + 비편집.
37
+ - `readonly: boolean` — 비편집(기본 커서 유지). 편집 가능 = `!disabled && !readonly`.
38
+ - `required: boolean` — 빈 값일 때 "값을 입력하세요.".
39
+ - `placeholder: string` — Placeholder 확장 추가(`extensions` 미지정 시).
40
+ - `validatorFn: (value) => string | undefined` — 커스텀 검증.
41
+ - `extensions: AnyExtension[]` — 기본 확장 셋 전체 override.
42
+ - 기본 확장: StarterKit·TextStyle·Color·Highlight·TextAlign·Image(base64)·Underline(+placeholder 시 Placeholder). 툴바: h1/h2·bold/italic/underline/strike·텍스트/배경색·리스트·들여쓰기·인용·코드블록·정렬·clean.
61
43
 
62
44
  ## 시각화
63
45
 
64
- ### SdLabel — `<sd-label>`
46
+ ### `SdLabel` — `<sd-label>`
65
47
 
66
- ```ts
67
- theme = input<"primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray">();
68
- color = input<string>(); clickable = input(false);
69
- ```
48
+ - `theme: "primary"|...|"blue-gray"|undefined` — 배경(`--theme-{key}-default`; 미지정 시 gray-darker).
49
+ - `color: string` — 명시 배경색(theme 보다 우선).
50
+ - `clickable: boolean` true 면 포인터 커서 + hover 진해짐.
70
51
 
71
- - 짧은 배지/태그. `theme` 또는 임의 `color`(배경) 지정. `clickable`=호버 강조 + 커서 포인터. 상태 표시에 사용.
52
+ ### `SdNote` `<sd-note>`
72
53
 
73
- ### SdNote`<sd-note>`
54
+ - `theme: "primary"|...|"blue-gray"|undefined` `--theme-{key}-lightest` 배경+테두리(미지정 시 gray-lightest, 테두리 없음).
55
+ - `size: "sm"|"lg"` — `"sm"` 작은 폰트/패딩, `"lg"` 큰 패딩.
56
+ - `inset: boolean` — true 면 라운드 제거(flush).
74
57
 
75
- ```ts
76
- theme = input<...8색>(); size = input<"sm"|"lg">(); inset = input(false);
77
- ```
58
+ ### `SdProgress` — `<sd-progress>`
78
59
 
79
- - 안내 박스(callout). `theme` 옅은 배경. `inset`=라운드 제거(영역 내장). 주의/도움말 문구에 사용.
60
+ - `theme: input.required<"primary"|...|"blue-gray">` 진행 (`--theme-{key}-default`).
61
+ - `value: input.required<number>` — 0~1 비율(퍼센트 표시).
62
+ - `inset: boolean` — true 면 라운드/테두리 제거. `size: "sm"|"lg"` — 패딩.
80
63
 
81
- ### SdProgress — `<sd-progress>`
64
+ ### `SdCalendar<T>` — `<sd-calendar>`
82
65
 
83
- ```ts
84
- theme = input.required<...8색>(); value = input.required<number>(); // 0~1
85
- inset; size = input<"sm"|"lg">();
86
- ```
66
+ 6×7 월 그리드에 일자별 항목 투영.
87
67
 
88
- - 진행률 막대. `value`(0~1)를 퍼센트 텍스트 + 채움 막대로 표시(0~100% clamp). `theme` 필수.
89
-
90
- ### SdCalendar`<sd-calendar>`
91
-
92
- ```ts
93
- items = input.required<T[]>(); getItemDateFn = input.required<(item: T, index: number) => DateOnly>();
94
- yearMonth = input(new DateOnly().setDay(1));
95
- weekStartDay = input(0); minDaysInFirstWeek = input(1);
96
- itemTplRef = contentChild.required(SdItemOfTemplate); // [itemOf] 셀 항목 템플릿(필수)
97
- ```
98
-
99
- - 월간 캘린더. `getItemDateFn` 으로 각 항목의 날짜를 산출해 해당 칸에 `[itemOf]` 템플릿으로 렌더. `yearMonth`=표시 월, `weekStartDay`=주 시작 요일(0=일), `minDaysInFirstWeek`=첫 주 판정.
68
+ - `items: input.required<T[]>` 데이터.
69
+ - `getItemDateFn: input.required<(item, index) => DateOnly>` — 항목→일자 매핑.
70
+ - `yearMonth: DateOnly` (기본 이번달 1일) 표시 월(밖 일자는 `not-current` 클래스).
71
+ - `weekStartDay: number` (기본 0=일요일) — 첫 열 요일.
72
+ - `minDaysInFirstWeek: number` (기본 1) — 첫 주 시작 계산.
73
+ - 콘텐츠: `[itemOf]` 항목 템플릿(필수).
100
74
 
101
75
  ```html
102
- <sd-calendar [items]="schedules()" [getItemDateFn]="getDate" [yearMonth]="month()">
103
- <ng-template [itemOf]="schedules()" let-item="item">{{ item.title }}</ng-template>
76
+ <sd-calendar [items]="events()" [getItemDateFn]="getDate" [(yearMonth)]="month">
77
+ <ng-template [itemOf]="events()" let-item="item">{{ item.title }}</ng-template>
104
78
  </sd-calendar>
105
79
  ```
106
80
 
107
- ### SdBarcode — `<sd-barcode>`
81
+ ### `SdBarcode` — `<sd-barcode>`
108
82
 
109
- ```ts
110
- type = input.required<BarcodeType>(); value = input<string>();
111
- // BarcodeType: "qrcode"|"code128"|"ean13"|"datamatrix"|... (bwip-js 전체 심볼 유니온)
112
- ```
83
+ bwip-js 로 바코드/QR 을 인라인 SVG 렌더.
113
84
 
114
- - 바코드/QR 렌더(bwip-js SVG). `type`=심볼 종류, `value`=인코딩 문자열(빈 값이면 미표시). `BarcodeType` bwip-js 지원하는 전체 바코드 유형 리터럴 유니온.
85
+ - `type: input.required<BarcodeType>` — bwip-js `bcid`(심볼로지). `BarcodeType` bwip-js 심볼로지 문자열 union(예 `"qrcode"`·`"code128"`·`"code39"`·`"ean13"`·`"datamatrix"`·`"pdf417"`·`"upca"` ~150종).
86
+ - `value: string` — 바코드 텍스트(비면 미렌더).
115
87
 
116
- ### SdEcharts — `<sd-echarts>`
88
+ ### `SdEcharts` — `<sd-echarts>`
117
89
 
118
- ```ts
119
- option = input.required<echarts.EChartsOption>(); notMerge = input(false); loading = input(false);
120
- ```
90
+ Apache ECharts(SVG) 래퍼. `SdResizeDirective` hostDirective 로 자동 리사이즈.
121
91
 
122
- - ECharts 차트. `option` 변경 `setOption` 적용(`notMerge`=true 면 기존 옵션 병합 안 함). `loading`=로딩 인디케이터. 호스트 리사이즈 시 자동 `resize`(svg 렌더).
92
+ - `option: input.required<echarts.EChartsOption>` 차트 옵션(반응형 `setOption`).
93
+ - `notMerge: boolean` (기본 false) — true 면 이전 옵션과 병합 없이 교체.
94
+ - `loading: boolean` (기본 false) — true 면 `showLoading()`, false 면 `hideLoading()`.