@simplysm/sd-claude 14.0.98 → 14.0.100

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,54 +1,46 @@
1
1
  # @simplysm/angular — 칸반(kanban)
2
2
 
3
- 드래그앤드롭으로 카드를 레인 간 이동하고 카드를 다중 선택하는 칸반 보드 군. `sd-kanban-board`(보드) > `sd-kanban-lane`(레인) > `sd-kanban`(카드) 3계층으로 구성. `L`=레인 값 타입, `T`=카드 값 타입.
3
+ 드래그앤드롭으로 카드를 레인 간 이동하고 카드를 다중 선택하는 칸반 보드 군. `sd-kanban-board`(보드) > `sd-kanban-lane`(레인) > `sd-kanban`(카드) 3계층. `L`=레인 값 타입, `T`=카드 값 타입.
4
4
 
5
- ## SdKanbanBoard — `<sd-kanban-board>`
5
+ ## `SdKanbanBoard<L, T>` — `<sd-kanban-board>`
6
6
 
7
- ```ts
8
- selectedValues = model<T[]>([]);
9
- drop = output<SdKanbanBoardDropInfo<L, T>>();
10
- // SdKanbanBoardDropInfo<L,T> { sourceKanbanValue?: T; targetLaneValue?: L; targetKanbanValue?: T }
11
- ```
7
+ - `selectedValues: model<T[]>([])` — 선택된 카드 값.
8
+ - `drop: output<SdKanbanBoardDropInfo<L, T>>` — 드래그를 레인/카드에 드롭 시 emit.
9
+ - `dragKanban: signal<SdKanbanDragRef<L, T> | undefined>` — 현재 드래그 중인 카드.
12
10
 
13
- - 칸반 전체 보드(레인을 가로 배치). `selectedValues`=선택된 카드 값들(다중선택, model). `drop`=카드를 다른 위치에 떨군 결과(소스 카드값 + 대상 레인값 + 대상 카드값). 호스트가 `drop` 을 받아 데이터 재배치.
11
+ 타입:
12
+ - `SdKanbanBoardDropInfo<L, T>` — `{ sourceKanbanValue?: T; targetLaneValue?: L; targetKanbanValue?: T }`. drop 페이로드(이동 처리 시 데이터 갱신에 사용).
13
+ - `SdKanbanDragRef<_L, T>` — `{ value(): T | undefined; heightOnDrag(): number }`.
14
+ - `SdKanbanDropTarget<L, T>` — `{ targetLaneValue(): L | undefined; targetKanbanValue?(): T | undefined }`.
14
15
 
15
- ```html
16
- <sd-kanban-board [(selectedValues)]="selected" (drop)="onDrop($event)">
17
- <sd-kanban-lane [value]="'todo'"> ... </sd-kanban-lane>
18
- </sd-kanban-board>
19
- ```
20
-
21
- ## SdKanbanLane — `<sd-kanban-lane>`
16
+ ## `SdKanbanLane<L, T>` — `<sd-kanban-lane>`
22
17
 
23
- ```ts
24
- busy = input(false); useCollapse = input(false); collapse = model(false);
25
- value = input<L>();
26
- // 슬롯: #titleTpl(제목) #toolTpl(도구) , 콘텐츠로 <sd-kanban>
27
- ```
18
+ `SdKanbanDropTarget` 구현.
28
19
 
29
- - 한 레인(열). `value`=레인 식별값(drop 대상 판정·targetLaneValue). `busy`=레인 busy 오버레이, `useCollapse`=접기 토글 버튼(접으면 카드 숨김, `collapse` model).
30
- - 선택 가능한 카드가 있으면 레인 전체선택 체크박스 자동 노출. `#titleTpl`/`#toolTpl` 헤더/도구 영역.
20
+ - `value: L` 레인 값.
21
+ - `busy: boolean` true `sd-busy-container` 오버레이.
22
+ - `useCollapse: boolean` — true 면 접기 토글(eye/eye-off) 표시.
23
+ - `collapse: model(false)` — 접힘 상태. true 면 레인 콘텐츠 숨김.
24
+ - 콘텐츠: `#toolTpl`(도구) / `#titleTpl`(제목). 자식 `sd-kanban` 들.
25
+ - `isAllSelected: computed` — 레인 내 선택 가능 카드 전부 선택 시 true(없으면 false). 선택 가능 카드 `>0` 이면 전체선택 체크박스 표시.
31
26
 
32
- ## SdKanban — `<sd-kanban>`
27
+ ## `SdKanban<L, T>` — `<sd-kanban>`
33
28
 
34
- ```ts
35
- value = input<T>(); selectable = input(false); draggable = input(false);
36
- contentClass = input<string>();
37
- ```
29
+ `SdKanbanDragRef`·`SdKanbanDropTarget` 구현. 카드 1개.
38
30
 
39
- - 한 카드. `value`=카드 식별값. `draggable`=드래그 이동 허용, `selectable`=Shift+클릭 다중선택 허용(`board.selectedValues` 에 토글). 콘텐츠가 카드 본문. 드래그 중 드롭 위치 표시를 내장.
31
+ - `value: T` 카드 값.
32
+ - `selectable: boolean` — true 면 Shift+Click 으로 보드 `selectedValues` 에 토글.
33
+ - `draggable: boolean` — true 면 드래그 가능(드래그 시작 시 보드 `dragKanban` 등록).
34
+ - `contentClass: string` — 내부 `.card` 클래스.
35
+ - `selected: computed` — `value` 가 보드 `selectedValues` 에 있으면 true.
40
36
 
41
37
  ```html
42
- <sd-kanban [value]="item" [draggable]="true" [selectable]="true">
43
- <div>{{ item.title }}</div>
44
- </sd-kanban>
45
- ```
46
-
47
- ## 드래그/드롭 타입
48
-
49
- ```ts
50
- SdKanbanDragRef<_L, T> { value(): T | undefined; heightOnDrag(): number }
51
- SdKanbanDropTarget<L, T> { targetLaneValue(): L | undefined; targetKanbanValue?(): T | undefined }
38
+ <sd-kanban-board [(selectedValues)]="selected" (drop)="onDrop($event)">
39
+ <sd-kanban-lane [value]="'todo'">
40
+ <ng-template #titleTpl>할 일</ng-template>
41
+ @for (item of todoItems(); track item.id) {
42
+ <sd-kanban [value]="item" [selectable]="true" [draggable]="true">{{ item.title }}</sd-kanban>
43
+ }
44
+ </sd-kanban-lane>
45
+ </sd-kanban-board>
52
46
  ```
53
-
54
- - `SdKanbanDragRef` — 드래그 중인 카드 참조(보드가 추적). `SdKanbanDropTarget` — 드롭 대상(레인 또는 카드가 구현). 둘 다 컴포넌트가 내부 구현하는 계약으로, 직접 다룰 일은 드묾.
@@ -1,77 +1,63 @@
1
1
  # @simplysm/angular — 레이아웃(사이드바·탑바)
2
2
 
3
- 앱 셸의 좌측 사이드바·상단바와 그 안의 메뉴/사용자 메뉴 컴포넌트 군. 앱 루트 레이아웃(`app.root` 등)에서 한 번 구성. 메뉴 항목 타입(`SdMenu`)·라우터 링크는 [routing-appstructure.md](./routing-appstructure.md) 의 것을 사용.
3
+ 앱 셸의 좌측 사이드바·상단바와 그 안의 메뉴/사용자 메뉴 컴포넌트 군. 앱 루트 레이아웃에서 한 번 구성. 메뉴 항목 타입(`SdMenu`)·라우터 링크는 [routing-appstructure.md](./routing-appstructure.md) 의 것을 사용.
4
4
 
5
5
  ## 사이드바
6
6
 
7
- ### SdSidebarContainer — `<sd-sidebar-container>`
7
+ ### `SdSidebarContainer` — `<sd-sidebar-container>`
8
8
 
9
- ```ts
10
- toggle: WritableSignal<boolean>;
11
- ```
12
-
13
- - 사이드바 + 본문을 감싸는 컨테이너. `toggle` 로 사이드바 접힘 제어(데스크탑은 본문 패딩 토글, 모바일은 backdrop). 네비게이션 시작 시 자동 닫힘. 자식 컴포넌트가 `inject` 해 접근.
9
+ 사이드바 + 본문을 감싸는 컨테이너.
14
10
 
15
- ### SdSidebar — `<sd-sidebar>`
11
+ - input 없음.
12
+ - `toggle: WritableSignal<boolean>` (초기 false) — true 면 사이드바 접힘(컨테이너 좌패딩 0); 모바일에선 backdrop 표시. 라우터 있으면 `NavigationStart` 마다 `false` 로 리셋(라우트 전환 시 자동 닫힘).
13
+ - `onBackdropClick(): void` — `toggle` 반전.
16
14
 
17
- ```ts
18
- toggle = computed(...); // 부모 컨테이너의 toggle 미러
19
- ```
15
+ ### `SdSidebar` — `<sd-sidebar>`
20
16
 
21
- - 좌측 고정 사이드바 영역. `SdSidebarContainer` 안에 두면 toggle 상태에 따라 슬라이드. 콘텐츠로 로고·메뉴·사용자를 투영.
17
+ - input 없음. `toggle: Signal<boolean>` 부모 컨테이너 `toggle` 미러(슬라이드 transform 구동).
22
18
 
23
- ### SdSidebarMenu — `<sd-sidebar-menu>`
19
+ ### `SdSidebarMenu` — `<sd-sidebar-menu>`
24
20
 
25
- ```ts
26
- menus = input<SdMenu[]>([]);
27
- layout = input<"accordion" | "accordion-expanded" | "flat">();
28
- getMenuIsSelectedFn = input<(menu: SdMenu) => boolean>();
29
- ```
21
+ - `menus: SdMenu[]` (기본 `[]`) — 메뉴 트리.
22
+ - `layout: "accordion"|"accordion-expanded"|"flat"|undefined` — `"flat"` = 최상위 평면; `"accordion"` = 접힌 아코디언; `"accordion-expanded"` = 전체 펼친 아코디언; `undefined` = 자동(`menus.length <= 3` 이면 flat, 아니면 accordion).
23
+ - `getMenuIsSelectedFn: (menu: SdMenu) => boolean` — 커스텀 선택 판정(미지정 시 fullPageCode 비교).
30
24
 
31
- - 메뉴 트리를 사이드바 리스트로 렌더(`SdRouterLink` 연결). `layout` 미지정 시 루트 메뉴 3개 이하면 `flat`, 초과면 `accordion` 자동. `accordion-expanded`=accordion 과 동일한 클릭 토글 구조이되 모든 깊이 항목이 펼친 채로 시작(이후 클릭하면 접힘), 명시 지정 시에만 적용(자동 선택 대상 아님). `getMenuIsSelectedFn`=선택 강조 커스텀(기본은 현재 페이지 코드 매칭). `menus` 는 보통 `SdAppStructureProvider.usableMenus()`.
32
-
33
- ### SdSidebarUser — `<sd-sidebar-user>`
34
-
35
- ```ts
36
- userMenu = input<SdSidebarUserMenu>();
37
- // SdSidebarUserMenu = { icon?: string; title: string; menus: { title: string; onClick: () => Promise<void>|void }[] }
38
- ```
25
+ ### `SdSidebarUser` `<sd-sidebar-user>`
39
26
 
40
- - 사이드바 하단 사용자 영역. 콘텐츠로 사용자 정보를 투영하고, `userMenu` 지정 접이식 메뉴(로그아웃 등) 표시. 각 menu 의 `onClick` 으로 동작.
27
+ - `userMenu: SdSidebarUserMenu | undefined` 설정 투영 콘텐츠 아래에 접이식 사용자 메뉴 버튼.
28
+ - `SdSidebarUserMenu` = `{ icon?: string; title: string; menus: { title: string; onClick: () => Promise<void> | void }[] }`.
41
29
 
42
30
  ## 탑바
43
31
 
44
- ### SdTopbarContainer — `<sd-topbar-container>`
32
+ ### `SdTopbarContainer` — `<sd-topbar-container>`
45
33
 
46
- ```ts
47
- // 입력 없음. flex-column 셸.
48
- ```
49
-
50
- - 탑바 + 본문 세로 셸. 상단 `<sd-topbar>` + `flex-fill` 본문 구조로 사용(`sd-base-container` 가 page 모드에서 내부 사용).
51
-
52
- ### SdTopbar — `<sd-topbar>`
34
+ 탑바 + 본문 래퍼. input/메서드 없음.
53
35
 
54
- ```ts
55
- sidebarContainer = input<SdSidebarContainer>();
56
- hasSidebar = computed(...);
57
- ```
36
+ ### `SdTopbar` — `<sd-topbar>`
58
37
 
59
- - 상단바. 사이드바가 있으면(주입 또는 `sidebarContainer` 입력) 좌측 토글 버튼 자동 노출. 콘텐츠로 제목·액션을 투영.
38
+ - `sidebarContainer: SdSidebarContainer | undefined` 토글할 컨테이너(주입된 override). 사이드바 있으면 햄버거 토글 버튼(`tablerMenu2`) 표시.
60
39
 
61
- ### SdTopbarMenu — `<sd-topbar-menu>`
40
+ ### `SdTopbarMenu` — `<sd-topbar-menu>`
62
41
 
63
- ```ts
64
- menus = input<SdMenu[]>([]);
65
- getMenuIsSelectedFn = input<(menu: SdMenu) => boolean>();
66
- ```
42
+ - `menus: SdMenu[]` (기본 `[]`) — 각 최상위 메뉴를 드롭다운으로, 자식은 팝업 내 중첩 리스트로.
43
+ - `getMenuIsSelectedFn: (menu: SdMenu) => boolean` — 커스텀 선택 판정.
67
44
 
68
- - 탑바에 드롭다운 형태로 메뉴 트리를 렌더. 루트 메뉴마다 드롭다운, 하위는 평면 리스트. 선택 강조는 사이드바 메뉴와 동일 규약.
45
+ ### `SdTopbarUser` `<sd-topbar-user>`
69
46
 
70
- ### SdTopbarUser`<sd-topbar-user>`
47
+ - `menus: input.required<SdTopbarUserMenu[]>` 드롭다운 안 리스트 항목. 투영 콘텐츠가 트리거 라벨.
48
+ - `SdTopbarUserMenu` = `{ title: string; onClick: () => void }`.
71
49
 
72
- ```ts
73
- menus = input.required<SdTopbarUserMenu[]>();
74
- // SdTopbarUserMenu = { title: string; onClick: () => void }
50
+ ```html
51
+ <sd-sidebar-container>
52
+ <sd-sidebar>
53
+ <sd-sidebar-menu [menus]="menus()" />
54
+ <sd-sidebar-user [userMenu]="userMenu" />
55
+ </sd-sidebar>
56
+ <sd-topbar-container>
57
+ <sd-topbar>
58
+ <sd-topbar-user [menus]="userMenus">{{ userName() }}</sd-topbar-user>
59
+ </sd-topbar>
60
+ <router-outlet />
61
+ </sd-topbar-container>
62
+ </sd-sidebar-container>
75
63
  ```
76
-
77
- - 탑바 우측 사용자 드롭다운. 콘텐츠로 사용자 표시명을 투영, `menus` 항목 클릭 시 `onClick` 실행 후 드롭다운 닫힘.
@@ -1,163 +1,139 @@
1
- # @simplysm/angular — 오버레이(모달·토스트·busy·인쇄)
1
+ # @simplysm/angular — 오버레이(모달·토스트·busy·인쇄·파일)
2
2
 
3
- 화면에서 프로그래밍 방식으로 모달을 띄우거나, 토스트로 알림·진행률을 표시하거나, busy 인디케이터·인쇄/PDF 출력을 호출할 때 함께 읽히는 군. provider 는 모두 `providedIn: "root"`, 동적으로 body 에 attach 하므로 컴포넌트를 템플릿에 직접 둘 일은 거의 없음.
3
+ 화면에서 프로그래밍 방식으로 모달을 띄우거나, 토스트로 알림·진행률을 표시하거나, busy 인디케이터·인쇄/PDF·파일 다이얼로그를 호출할 때 함께 읽히는 군. provider 는 모두 `providedIn: "root"`, 동적으로 body 에 attach 하므로 컴포넌트를 템플릿에 직접 둘 일은 거의 없음. 화면에서의 호출 규약은 [client-component.md](../manuals/client-component.md) 의 '모달 호출' / '에러·토스트' 참조.
4
4
 
5
5
  ## 모달
6
6
 
7
- ### SdModalProvider
7
+ ### `SdModalProvider`
8
8
 
9
- ```ts
10
- @Injectable({ providedIn: "root" }) class SdModalProvider {
11
- modalCount: WritableSignal<number>;
12
- showAsync<T extends SdModalContentDef<any>>(modal: SdModalInfo<T>, options?: SdModalOptions):
13
- Promise<Parameters<T["close"]["emit"]>[0] | undefined>;
14
- }
15
- ```
16
-
17
- - `showAsync(modal, options)` — 모달 컴포넌트를 동적 생성·표시하고, 컨텐츠가 `close.emit(value)` 한 값(또는 배경/ESC/닫기 시 undefined)으로 resolve. 첫 탭 가능 요소에 자동 포커스, 닫힘 후 이전 포커스 복귀.
18
- - `modal.title` — 헤더 제목. `modal.type` — `SdModalContentDef` 구현 컴포넌트. `modal.inputs` — 컴포넌트 input 바인딩(`close`/`initialized`/`actionTplRef` 제외, optional 마킹된 키는 생략 가능).
9
+ `@Injectable({ providedIn: "root" })`. 모달 콘텐츠 컴포넌트를 `SdModal` 셸로 감싸 띄움.
19
10
 
20
11
  ```ts
21
- const result = await inject(SdModalProvider).showAsync(
22
- { title: "역할 선택", type: RoleListModal, inputs: { selectMode: "single" } },
23
- { useCloseByBackdrop: false },
24
- );
12
+ showAsync<T extends SdModalContentDef<any>>(
13
+ modal: SdModalInfo<T>, options?: SdModalOptions,
14
+ ): Promise<Parameters<T["close"]["emit"]>[0] | undefined>
25
15
  ```
26
16
 
27
- ### SdModal `<sd-modal>`
17
+ - `modal.type` 컴포넌트를 생성·`modal.inputs` 바인딩·body 에 attach, z-index 부여, 포커스 관리. 콘텐츠가 `close.emit(payload)` 한 값으로 resolve(backdrop/ESC/닫기로 닫으면 `undefined`).
18
+ - `modalCount: signal(0)` — 현재 열린 모달 수.
28
19
 
29
20
  ```ts
30
- open = model(false); key = input<string>(); title = input("");
31
- hideHeader; hideCloseButton; headerStyle = input<string>();
32
- useCloseByBackdrop = input(true); useCloseByEscapeKey = input(true);
33
- float; fill; resizable; movable;
34
- position = input<"bottom-right" | "top-right" | undefined>();
35
- minHeightPx; minWidthPx; heightPx; widthPx = input<number>();
36
- actionTplRef = input<TemplateRef<any>>(); closeRequest = output<void>();
21
+ const result = await this._sdModal.showAsync({
22
+ type: OutboundInstructionHeaderDetail, title: "출고지시 등록", inputs: { /* ... */ },
23
+ });
24
+ if (!result) return;
37
25
  ```
38
26
 
39
- - 모달 컴포넌트(보통 `SdModalProvider` 생성, 직접 템플릿 사용은 드묾). `key` 지정 크기·위치를 `SdSystemConfigProvider` 저장/복원.
40
- - `useCloseByBackdrop`/`useCloseByEscapeKey` — 배경 클릭/ESC 닫기 허용(기본 true). `float`=배경 없는 부유창, `fill`=전체 채움, `resizable`/`movable`=리사이즈/드래그(헤더), `position`=고정 위치.
27
+ `SdModalInfo<T, X>` `{ title: string; type: Type<T>; inputs: ... }`. `inputs` 콘텐츠 컴포넌트의 input 값(프레임워크 `initialized`/`close`/`actionTplRef`/`_optionalModalInputs` 추가 `X` 제외, 컴포넌트가 `_optionalModalInputs` 로 선언한 키는 optional).
41
28
 
42
- ### 관련 타입·내장 모달
29
+ `SdModalContentDef<O>` 모달 콘텐츠 컴포넌트가 구현할 인터페이스:
30
+ - `initialized: Signal<boolean>` — 준비 완료.
31
+ - `close: OutputEmitterRef<O | undefined>` — 결과 `O | undefined` 로 자기 자신을 닫음.
32
+ - `actionTplRef?: TemplateRef<any>` — 헤더 액션 템플릿(선택).
33
+ - `_optionalModalInputs?: string` — optional input 키 마커(타입 전용).
43
34
 
44
- ```ts
45
- SdModalContentDef<O> { initialized: Signal<boolean>; close: OutputEmitterRef<O | undefined>; actionTplRef?; _optionalModalInputs? }
46
- SdModalInfo<T, X> { title: string; type: Type<T>; inputs: ... }
47
- SdModalOptions { key?; hideHeader?; hideCloseButton?; headerStyle?; useCloseByBackdrop?; useCloseByEscapeKey?; float?; fill?; resizable?; movable?; position?; minHeightPx?; minWidthPx?; heightPx?; widthPx?; noFirstControlFocusing? }
48
- ```
35
+ `SdModalOptions` (전부 선택): `key`(크기·위치 영속) / `hideHeader` / `hideCloseButton` / `headerStyle` / `useCloseByBackdrop`(기본 true) / `useCloseByEscapeKey`(기본 true) / `float`(배경 없는 플로팅) / `fill`(전체 채움) / `resizable` / `movable` / `position: "bottom-right"|"top-right"` / `minHeightPx` / `minWidthPx` / `heightPx` / `widthPx` / `noFirstControlFocusing`(true 면 첫 컨트롤 대신 다이얼로그에 포커스).
49
36
 
50
- - `SdModalContentDef<O>`모달 컨텐츠 컴포넌트 계약(`initialized` 시그널 + `close` 출력). `O` 가 close 페이로드 타입. `_optionalModalInputs` 에 optional input 키를 문자열 리터럴로 선언하면 `showAsync` 호출 시 해당 input 생략 허용.
51
- - `SdModalOptions.noFirstControlFocusing` — true 면 첫 컨트롤 자동 포커스 안 함(다이얼로그만 포커스).
37
+ ### `SdModal``<sd-modal>`
52
38
 
53
- ### SdActivatedModalProvider
39
+ 모달 셸 컴포넌트. `SdModalProvider` 가 내부적으로 사용 — 화면에서 직접 두지 않음(상속 대상도 아님). 위 `SdModalOptions` 키들에 대응하는 input(`open: model`, `title`, `float`, `fill`, `resizable`, `movable`, `position` 등)을 가지며 `closeRequest: output<void>` 발화 전 `SdActivatedModalProvider.canDeactivateFn()` 가드 확인.
54
40
 
55
- ```ts
56
- @Injectable() class SdActivatedModalProvider<T> {
57
- modalComponent: WritableSignal<SdModal | undefined>;
58
- contentComponent: WritableSignal<T | undefined>;
59
- canDeactivateFn: () => boolean; // 기본 () => true
60
- }
61
- ```
41
+ ### `SdActivatedModalProvider<T>`
62
42
 
63
- - 모달 컨텐츠 내부에서 `inject` 해 사용. `canDeactivateFn` 을 세팅하면 닫기 전 가드(미저장 변경 보호). `contentComponent` 자기 컴포넌트 참조(crud-list close 호출에 사용).
43
+ `@Injectable()`(모달별 주입). 콘텐츠 컴포넌트가 inject 호스트 모달과 상호작용.
64
44
 
65
- ### SdPromptModal / SdConfirmModal
45
+ - `modalComponent: signal<SdModal | undefined>` / `contentComponent: signal<T | undefined>` — 호스트 모달·콘텐츠 인스턴스.
46
+ - `canDeactivateFn: () => boolean` (기본 `() => true`) — close 전 가드. `false` 반환 시 닫기 차단. `setupCanDeactivate` 가 모달 컨텍스트에서 이 필드를 설정.
66
47
 
67
- ```ts
68
- // SdPromptModal: SdModalContentDef<string> — message 입력 + 텍스트 입력 후 확인/취소
69
- message = input.required<string>();
70
- // SdConfirmModal: SdModalContentDef<boolean> — message 표시 후 확인(true)/취소(undefined)
71
- message = input.required<string>();
72
- ```
48
+ ### `SdPromptModal` / `SdConfirmModal`
73
49
 
74
- - 범용 입력/확인 모달. `showAsync({ type: SdPromptModal, inputs: { message } })` 로 호출. prompt 는 확인 시 입력 문자열, confirm 은 확인 시 `true`, 취소는 둘 다 undefined.
50
+ 표준 입력/확인 모달. `SdModalContentDef<string>` / `SdModalContentDef<boolean>` 구현.
51
+
52
+ - 둘 다 `message: input.required<string>()`(HTML), `initialized: signal(true)`, `close` output.
53
+ - prompt: 텍스트 입력(필수) → 확인 시 입력 문자열, 취소 시 `undefined`.
54
+ - confirm: 확인 시 `true`, 취소 시 `undefined`.
75
55
 
76
56
  ## 토스트
77
57
 
78
- ### SdToastProvider
58
+ ### `SdToastProvider`
79
59
 
80
- ```ts
81
- @Injectable({ providedIn: "root" }) class SdToastProvider {
82
- alertThemes: WritableSignal<SdToastSeverity[]>; overlap: WritableSignal<boolean>;
83
- beforeShowFn?: (theme: SdToastSeverity) => void;
84
- info(msg, useProgress?): WritableSignal<number> | void; // success/warning/danger 동일 시그니처
85
- notify<T>(input: SdToastInput<T>): Promise<...>;
86
- try<R>(fn: () => Promise<R> | R, messageFn?: (err: Error) => string): Promise<R | undefined>;
87
- }
88
- // SdToastSeverity = "info" | "success" | "warning" | "danger"
89
- ```
60
+ `@Injectable({ providedIn: "root" })`.
90
61
 
91
- - `info`/`success`/`warning`/`danger(msg, useProgress?)` 토스트 표시. `useProgress=true` 진행률 토스트의 `WritableSignal<number>`(0~100) 반환(100 도달 자동 해제), 아니면 3초 (호버 지연) 자동 해제.
92
- - `try(fn, messageFn?)` fn 실행 중 Error 발생 시 `danger` 토스트 + 시스템로그 적재 undefined 반환(Error 외 예외는 rethrow). 화면 핸들러를 감싸 에러를 사용자에게 알림.
93
- - `alertThemes` 해당 severity 토스트 대신 `window.alert` 사용. `overlap`=새 토스트가 기존을 대체. `notify` 커스텀 컴포넌트 토스트.
62
+ - `SdToastSeverity` = `"info" | "success" | "warning" | "danger"` 심각도. `info`/`success` = polite(aria), `warning`/`danger` = assertive. (심각도 분류 기준은 sd-design-rules.md)
63
+ - `SdToastTheme` = `"primary" | "secondary" | SdToastSeverity | "gray" | "blue-gray"`.
64
+ - 심각도 헬퍼(각 overload): `info`/`success`/`warning`/`danger`. `useProgress=true` `WritableSignal<number>`(진행률 0~100) 반환, 아니면 `void`. 비-progress 토스트는 3초 자동 소멸(hover 일시정지), progress 토스트는 ≥100 도달 1초 후 소멸.
94
65
 
95
66
  ```ts
96
- await inject(SdToastProvider).try(async () => { await save(); this._sdToast.success("저장됨"); });
67
+ this._sdToast.success("저장되었습니다.");
68
+ this._sdToast.danger("...");
97
69
  ```
98
70
 
99
- ### SdToast / SdToastContainer — `<sd-toast>` / `<sd-toast-container>`
71
+ - `try` (overload):
72
+ ```ts
73
+ try<R>(fn: () => Promise<R>, messageFn?: (err: Error) => string): Promise<R | undefined>
74
+ try<R>(fn: () => R, messageFn?: (err: Error) => string): R | undefined
75
+ ```
76
+ `fn` 실행(async 면 await). 성공 시 결과 반환. `Error` throw 시 `danger` 토스트(`messageFn(err)` 또는 `err.message`) + `SdSystemLogProvider.writeAsync("error", ...)` 적재 후 `undefined` 반환. 비-Error throw 는 재throw.
100
77
 
101
- ```ts
102
- // toast
103
- open = model(false); useProgress = input(false); theme = input<SdToastTheme>("info");
104
- progress = model(0); message = model<string | undefined>();
105
- // container
106
- overlap = input(false);
107
- // SdToastTheme = "primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray"
108
- ```
78
+ ```ts
79
+ this.busyCount.update((v) => v + 1);
80
+ await this._sdToast.try(async () => { await this._refresh(); });
81
+ this.busyCount.update((v) => v - 1);
82
+ ```
109
83
 
110
- - 토스트 표시 단위/컨테이너(provider 동적 생성, 직접 사용은 드묾). `theme` info/success aria status·polite, warning/danger alert·assertive 접근성 자동 설정.
84
+ - `notify<T extends SdToastContentDef<any>>(input: SdToastInput<T>): Promise<...>` 커스텀 컴포넌트를 토스트로 렌더(5초 자동 소멸), `close` emit 또는 `undefined` resolve.
85
+ - 필드: `alertThemes: signal<SdToastSeverity[]>([])`(여기 든 심각도는 토스트 대신 `window.alert`) / `overlap: signal(false)`(겹침 모드, 새 토스트 전 기존 제거) / `beforeShowFn?: (theme) => void`.
111
86
 
112
- ### 관련 타입
87
+ `SdToastContentDef<O>` `{ close: OutputEmitterRef<O | undefined> }`. `SdToastInput<T>` — `{ type: Type<T>; inputs: Omit<DirectiveInputSignals<T>, "close"> }`.
113
88
 
114
- ```ts
115
- SdToastContentDef<O> { close: OutputEmitterRef<O | undefined> }
116
- SdToastInput<T> { type: Type<T>; inputs: Omit<DirectiveInputSignals<T>, "close"> }
117
- ```
89
+ ### `SdToast` / `SdToastContainer`
118
90
 
119
- - 커스텀 컴포넌트 토스트(`notify`) 계약·입력 타입.
91
+ 토스트 셸·컨테이너 컴포넌트. provider 가 내부 사용 — 화면에서 직접 두지 않음. toast: `open: model`, `theme: SdToastTheme`(기본 `"info"`), `useProgress`, `progress: model(0)`, `message: model`. container: `overlap: boolean`.
120
92
 
121
93
  ## busy
122
94
 
123
- ### SdBusyProvider
95
+ ### `SdBusyProvider`
124
96
 
125
- ```ts
126
- @Injectable({ providedIn: "root" }) class SdBusyProvider {
127
- type: WritableSignal<SdBusyType>; // 기본 "bar"
128
- globalBusyCount: WritableSignal<number>;
129
- }
130
- // SdBusyType = "spinner" | "bar" | "cube"
131
- ```
97
+ `@Injectable({ providedIn: "root" })`.
132
98
 
133
- - `globalBusyCount` 0 초과면 전역 busy 오버레이 표시(라우팅 네비게이션·인쇄가 자동 +1/-1). 화면에서 비동기 작업 동안 직접 증감 가능. `type` 전역 인디케이터 모양.
99
+ - `SdBusyType` = `"spinner" | "bar" | "cube"` 인디케이터 외형. `"spinner"` = 상단에서 내려오는 원형 스피너+메시지; `"bar"` = 상단 얇은 진행 바; `"cube"` = 중앙 회전 큐브.
100
+ - `type: signal<SdBusyType>("bar")` — 전역 기본 인디케이터 타입.
101
+ - `globalBusyCount: signal(0)` — 전역 전체화면 busy 참조 카운트. `>0` 이면 전체화면 오버레이 표시. (`provideSdAngular` 의 라우팅 추적·`SdPrintProvider` 가 증감)
134
102
 
135
- ### SdBusyContainer — `<sd-busy-container>`
103
+ ### `SdBusyContainer` — `<sd-busy-container>`
104
+
105
+ 콘텐츠 위에 busy 오버레이를 거는 컴포넌트. (화면 busy 표시는 보통 `sd-base-container`/`sd-crud-*` 가 처리하므로 직접 사용은 드묾)
106
+
107
+ - `busy: boolean` — 오버레이 활성.
108
+ - `message: string` — 오버레이 메시지.
109
+ - `type: SdBusyType | undefined` — 인디케이터 타입(미지정 시 provider 기본).
110
+ - `progressPercent: number | undefined` — 0~100; 설정 시 상단 진행 바.
111
+
112
+ ## 인쇄
113
+
114
+ ### `SdPrintProvider`
115
+
116
+ `@Injectable({ providedIn: "root" })`. jsPDF·html-to-image 사용. 프린트 템플릿(`<domain>.print-template.ts`)을 대상으로 함.
136
117
 
137
118
  ```ts
138
- busy = input(false); message = input<string>(); type = input<SdBusyType>();
139
- progressPercent = input<number>();
119
+ printAsync<T extends SdPrint>(template: SdPrintInput<T>, options?: { size?: string; margin?: string }): Promise<void>
120
+ getPdfBufferAsync<T extends SdPrint>(template: SdPrintInput<T>, options?: { orientation?: "portrait"|"landscape"; pageSize?: string }): Promise<Uint8Array>
140
121
  ```
141
122
 
142
- - 특정 영역에 busy 오버레이를 씌우는 컨테이너. `busy` true 동안 콘텐츠 위에 인디케이터 + 키보드 차단. `type` 미지정 `SdBusyProvider.type`, `progressPercent`=상단 진행바.
123
+ - `printAsync` 템플릿 컴포넌트 생성·`@page { size; margin }` 주입(기본 `size="A4 auto"`, `margin="0"`), `initialized()`·이미지 로드 대기 `window.print()`. `globalBusyCount` 증감.
124
+ - `getPdfBufferAsync` — 같은 템플릿을 off-screen 래스터화해 jsPDF 페이지로(기본 `pageSize="a4"`, `orientation="p"`) `Uint8Array` 반환.
125
+ - `SdPrint` — `{ initialized: Signal<boolean>; _optionalPrintInputs?: string }`. 템플릿 컴포넌트가 구현.
126
+ - `SdPrintInput<T, X>` — `{ type: Type<T>; inputs: ... }`(`_optionalPrintInputs`·추가 키 `X` 제외, optional 키 적용).
143
127
 
144
- ```html
145
- <sd-busy-container [busy]="loading()"> <ng-content /> </sd-busy-container>
146
- ```
128
+ ## 파일 다이얼로그
147
129
 
148
- ## 인쇄·PDF
130
+ ### `SdFileDialogProvider`
149
131
 
150
- ### SdPrintProvider
132
+ `@Injectable({ providedIn: "root" })`. (단순 파일 선택은 `@simplysm/core-browser` 의 `openFileDialog` 도 사용 — [client-crud.md](../manuals/client-crud.md) 엑셀 업로드 레시피)
151
133
 
152
134
  ```ts
153
- @Injectable({ providedIn: "root" }) class SdPrintProvider {
154
- printAsync<T extends SdPrint>(template: SdPrintInput<T>, options?: { size?: string; margin?: string }): Promise<void>;
155
- getPdfBufferAsync<T extends SdPrint>(template: SdPrintInput<T>, options?: { orientation?: "portrait"|"landscape"; pageSize?: string }): Promise<Uint8Array>;
156
- }
157
- // SdPrint { initialized: Signal<boolean>; _optionalPrintInputs? }
158
- // SdPrintInput<T, X> { type: Type<T>; inputs: ... }
135
+ showAsync(multiple?: false, accept?: string): Promise<File | undefined>
136
+ showAsync(multiple: true, accept?: string): Promise<File[] | undefined>
159
137
  ```
160
138
 
161
- - `printAsync(template, options)` 인쇄용 컴포넌트를 임시 렌더(`initialized` 대기 + 이미지 로드 대기) `window.print()`. `options.size`(예: `"A4 auto"`)/`margin` `@page` 규칙. 동안 globalBusy.
162
- - `getPdfBufferAsync(template, options)` — 같은 방식으로 렌더 후 `.page` 요소(없으면 전체)를 페이지별 이미지로 PDF 생성, `Uint8Array` 반환. `orientation`/`pageSize`(예: `"a4"`) 지정.
163
- - `template.type` 는 `SdPrint` 구현 컴포넌트(`initialized` 시그널 필수). `inputs` 로 데이터 주입.
139
+ - 숨김 `<input type="file">` 생성·클릭으로 native 피커 열기. `multiple` 거짓이면 단일 `File`, true `File[]`, 취소 `undefined`. `accept` MIME/확장자 필터.