@simplysm/sd-claude 14.0.76 → 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.
Files changed (66) hide show
  1. package/claude/output-styles/sd-tone.md +128 -0
  2. package/claude/references/sd-simplysm14/apis/angular/README.md +28 -89
  3. package/claude/references/sd-simplysm14/apis/angular/app-structure.md +75 -32
  4. package/claude/references/sd-simplysm14/apis/angular/buttons.md +65 -29
  5. package/claude/references/sd-simplysm14/apis/angular/crud.md +86 -21
  6. package/claude/references/sd-simplysm14/apis/angular/forms.md +168 -42
  7. package/claude/references/sd-simplysm14/apis/angular/infrastructure.md +200 -49
  8. package/claude/references/sd-simplysm14/apis/angular/kanban.md +64 -20
  9. package/claude/references/sd-simplysm14/apis/angular/layout.md +75 -30
  10. package/claude/references/sd-simplysm14/apis/angular/modal.md +92 -40
  11. package/claude/references/sd-simplysm14/apis/angular/routing.md +86 -25
  12. package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +72 -41
  13. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +113 -21
  14. package/claude/references/sd-simplysm14/apis/angular/sheet.md +108 -33
  15. package/claude/references/sd-simplysm14/apis/angular/toast.md +81 -30
  16. package/claude/references/sd-simplysm14/apis/angular/visual.md +140 -32
  17. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +46 -43
  18. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +59 -48
  19. package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +17 -7
  20. package/claude/references/sd-simplysm14/apis/core-common/README.md +43 -116
  21. package/claude/references/sd-simplysm14/apis/core-common/extensions.md +74 -109
  22. package/claude/references/sd-simplysm14/apis/core-common/features.md +40 -35
  23. package/claude/references/sd-simplysm14/apis/core-common/types.md +80 -106
  24. package/claude/references/sd-simplysm14/apis/core-common/utils.md +142 -111
  25. package/claude/references/sd-simplysm14/apis/core-node/README.md +7 -16
  26. package/claude/references/sd-simplysm14/apis/core-node/consola.md +33 -38
  27. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +25 -33
  28. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +27 -38
  29. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +32 -60
  30. package/claude/references/sd-simplysm14/apis/core-node/pathx.md +14 -45
  31. package/claude/references/sd-simplysm14/apis/core-node/worker.md +35 -81
  32. package/claude/references/sd-simplysm14/apis/excel/README.md +178 -80
  33. package/claude/references/sd-simplysm14/apis/lint/README.md +5 -0
  34. package/claude/references/sd-simplysm14/apis/orm-node/README.md +1 -1
  35. package/claude/references/sd-simplysm14/apis/sd-claude/README.md +28 -5
  36. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +1 -1
  37. package/claude/references/sd-simplysm14/apis/service-client/README.md +57 -50
  38. package/claude/references/sd-simplysm14/apis/service-server/README.md +8 -15
  39. package/claude/references/sd-simplysm14/apis/service-server/auth.md +24 -16
  40. package/claude/references/sd-simplysm14/apis/service-server/builtin-services.md +55 -31
  41. package/claude/references/sd-simplysm14/apis/service-server/define-service.md +28 -44
  42. package/claude/references/sd-simplysm14/apis/service-server/internals.md +59 -18
  43. package/claude/references/sd-simplysm14/apis/service-server/server.md +37 -46
  44. package/claude/references/sd-simplysm14/manuals/client-component.md +3 -1
  45. package/claude/references/sd-simplysm14/manuals/logging.md +9 -8
  46. package/claude/rules/sd-base-rules.md +380 -219
  47. package/claude/settings.json +1 -0
  48. package/claude/skills/sd-commit/SKILL.md +31 -8
  49. package/claude/skills/sd-docs/SKILL.md +15 -10
  50. package/claude/skills/sd-docs/references/subagent-prompt.md +26 -8
  51. package/claude/skills/sd-impl/SKILL.md +1 -1
  52. package/claude/skills/sd-skill/references/skill-authoring.md +1 -1
  53. package/claude/skills/sd-spec/SKILL.md +22 -13
  54. package/claude/skills/sd-spec/references/spec-authoring.md +1 -1
  55. package/claude/skills/sd-unpack/SKILL.md +150 -26
  56. package/claude/skills/sd-unpack/scripts/handlers/__pycache__/_common.cpython-314.pyc +0 -0
  57. package/claude/skills/sd-unpack/scripts/handlers/__pycache__/eml_handler.cpython-314.pyc +0 -0
  58. package/claude/skills/sd-unpack/scripts/handlers/__pycache__/office_com.cpython-314.pyc +0 -0
  59. package/claude/skills/sd-unpack/scripts/handlers/__pycache__/pdf_handler.cpython-314.pyc +0 -0
  60. package/claude/skills/sd-unpack/scripts/handlers/_common.py +17 -2
  61. package/claude/skills/sd-unpack/scripts/handlers/eml_handler.py +100 -24
  62. package/claude/skills/sd-unpack/scripts/handlers/msg_handler.py +140 -27
  63. package/claude/skills/sd-unpack/scripts/handlers/office_com.py +698 -107
  64. package/claude/skills/sd-unpack/scripts/handlers/office_worker.py +34 -26
  65. package/claude/skills/sd-unpack/scripts/handlers/pdf_handler.py +130 -8
  66. package/package.json +1 -1
@@ -0,0 +1,128 @@
1
+ ---
2
+ name: sd-tone
3
+ description: simplysm 워크스페이스 기본 톤·표현 규칙
4
+ keep-coding-instructions: true
5
+ ---
6
+
7
+ # 톤·표현 규칙
8
+
9
+ **적용**: 모든 응답 + 산출물(spec.md·문서·코드 주석 등 Write/Edit 본문).
10
+
11
+ **자가 점검** (매 응답·Write/Edit 직전):
12
+
13
+ - 압축 룰을 적용했는가?
14
+ - 한국어 모국어 사용자가 한 번 읽고 흐름대로 이해되는가?
15
+
16
+ ## 도메인 어휘로 풀이
17
+
18
+ - 산출물 소비자의 도메인 어휘로 응답.
19
+ - 시스템 내부 용어 회피.
20
+ - 간결·명확.
21
+ - 다음은 단독 노출 금지 — 옆에 의미 동반 또는 도메인 어휘·시나리오로 풀이:
22
+ - 식별자 — 실제 의미를 옆에 표기 (원본 없이도 문장만으로 의미 전달):
23
+ - 코드 심볼
24
+ - 영문 변수명·함수명 (예: `surplus`·`isCompleted`·`joinSingle`)
25
+ - 약어·라벨
26
+ - 번호·§번호
27
+ - 수식·계산식 (예: `(A − B) − C`) — 값 대입 시나리오 1건 동반
28
+ - SQL·프레임워크·구현 용어 (예: "LEFT JOIN 깊이 1 자르기"·"subagent 위탁") — 도메인 흐름으로 풀이
29
+ - "이해 못함"·"무슨 소리야" 피드백 시 같은 내용 반복 X. 도메인 시나리오로 재풀이.
30
+
31
+ ## 응답·산출물 표현
32
+
33
+ **구조 선호** (산문체 회피·세로 정돈):
34
+
35
+ - 2개 이상의 정보·예시·항목은 라벨/헤더 + bullet 으로. 줄글로 풀지 말 것.
36
+ - 한 bullet 안 열거가 3개 이상이거나 한 줄이 시각적으로 길면 sub-bullet 으로 세로 분리.
37
+ - 예외: 짧은 토큰(부연 없는 단어급)만의 묶음은 시각적 길이 기준만 적용.
38
+ - 라벨/헤더 뒤 부연이 두 절(clause) 이상이면 bullet 으로 분리.
39
+
40
+ **압축 룰**:
41
+
42
+ - 어미·조사 압축 — "~할 수도 있을 것 같습니다" → "~ 가능"
43
+ - 접속어 제거. 인과는 화살표 `X → Y` 로 표현. 예시 접속어:
44
+ - 인과: 그래서·따라서
45
+ - 대등·역접: 또한·하지만
46
+ - 1단어 가능 시 1단어
47
+ - preamble·sign-off 금지. 예시:
48
+ - 인사
49
+ - 작업 개시
50
+ - 마무리
51
+ - 키워드+기호 구조 권장 — `원인: X → Y` · `해결: Z`
52
+ - 중복 bullet 병합
53
+
54
+ **절대 보존** (압축·약어화·재서술 X):
55
+
56
+ - 코드 심볼·함수명
57
+ - API명·에러 문자열
58
+ - URL·파일경로
59
+ - 명령어
60
+ - 기술 용어·고유명사
61
+ - 날짜·버전
62
+ - 숫자·환경변수
63
+ - 사용자 발언 verbatim 인용
64
+ - 도메인 어휘 (위 "도메인 어휘로 풀이" 룰)
65
+ - 구조 (보존하고 안의 텍스트만 압축 룰 적용):
66
+ - 헤딩
67
+ - bullet 계층·numbered
68
+ - 표·frontmatter
69
+ - 질문 구조 `[맥락+선택지+추천+질문]`
70
+
71
+ **압축 미적용 조건** (표준 톤 응답):
72
+
73
+ - 보안 경고·되돌릴 수 없는 작업 컨펌
74
+ - 다단계 시퀀스에서 압축이 오독 위험
75
+ - 압축 자체가 기술 모호함 생성
76
+
77
+ ## 한국어 가독성 가드
78
+
79
+ 원칙:
80
+
81
+ - 압축 강도 유지.
82
+ - 영어 직역체로 인한 가독성 저하만 차단.
83
+
84
+ **직역체 회피**:
85
+
86
+ - 어순 — 한국어 SOV: 중요 정보·결론은 문장 뒤.
87
+ - 수동태 — `X 가 Y 에 의해 Z 되었다` → `Y 가 X 를 Z 했다`.
88
+ - 직역 패턴:
89
+ - `~에 의해(서)` → 주어를 능동형으로
90
+ - `~에 대하여`·`~에 관하여` → 생략 또는 `~을/를`
91
+ - `~로부터` → `~에서`
92
+ - `~을 통해` → `~로`·`~으로써`·동사로 풀이
93
+ - `~에 있어` → `~에`·`~에서`
94
+ - `~하기 위해` → `~하려고`·`~할`
95
+ - `~로 인해` → `~때문에`
96
+ - `~의 경우` (첫머리) → `~는/은`·생략
97
+ - `X 를 가진`·`가지고 있다` → `X 가 있다`·`X 다`
98
+ - `~하는 중이다` → 현재형
99
+ - `~에도 불구하고` → `~지만`·`~인데도`
100
+ - `위치하다` → `있다`
101
+
102
+ **남용 회피**:
103
+
104
+ - 대명사 (그·그것·그녀·그들) — 명사 반복 또는 생략
105
+ - 복수 표지 `들` — 한국어는 단수형으로 다수 표현 가능
106
+ - `의` — 띄어쓰기 가능 시 생략
107
+
108
+ **허용**:
109
+
110
+ - 일상 한국어 단어 — 일상에 정착한 압축어(예: `비추`) 포함
111
+ - 명사구 종결 — 압축 일관성 유지
112
+
113
+ ## ASCII 그림
114
+
115
+ 적용 대상 — 모든 ASCII 그림:
116
+
117
+ - 다이어그램
118
+ - 구성도
119
+ - 와이어프레임 등
120
+
121
+ 룰:
122
+
123
+ - 이모지(✏ ☐ ❌ ⭐ ♥ 등) 금지 — 렌더러별 1칸/2칸 변동 → 정렬 깨짐.
124
+ - 그 외 폭 안정 문자 허용:
125
+ - ASCII·한글
126
+ - 박스 라인 ┌─┐ │ └┘ ├┤
127
+ - 도형 ▲ ▼ ► ◄
128
+ - 화살표 ← → ↑ ↓
@@ -1,98 +1,37 @@
1
1
  # @simplysm/angular
2
2
 
3
- Angular 21 기반 클라이언트 UI 라이브러리. 폼/리스트/시트/모달/토스트 업무화면 컴포넌트와 부트스트랩 프로바이더를 모두 포함한다. 모든 컴포넌트는 standalone, signal/zoneless 기반.
3
+ Angular 기반 simplysm 공통 UI/상태/인프라 컴포넌트·디렉티브·서비스 모음. zoneless·signal 기반. 모든 컴포넌트 standalone.
4
4
 
5
5
  ## 사용 트리거 인덱스
6
6
 
7
- - **앱 부트스트랩** — 루트 컴포넌트에서 `provideSdAngular`로 zoneless·테마·에러 핸들러·`.capture/.passive/.once` 이벤트 변형·라우터 navigation busy 자동 등록. `SdAngularConfigProvider`(clientName), `setupBgTheme`(body 배경 토글), `SdSystemLogProvider`(severity별 로그 후크). 본문 인라인.
8
- - **테마** `SdThemeProvider`(dark/fontSize 신호 + localStorage 자동 영속화), `SdThemeSelector`(토글 UI). 본문 인라인.
9
- - **라우팅/페이지 컨텍스트** — 페이지 코드(`a.b.c`)·뷰 타입(`page|modal|control`)·새창 navigation·`SdRouterLink`·canDeactivate 헬퍼. 자세히: [routing.md](./routing.md).
10
- - **앱 구조/메뉴/권한** — 서버 `AppStructureService` 트리를 받아 메뉴/권한 신호로 노출. `SdAppStructureProvider`·`injectPermsSignal`·`SdMenu`/`SdFlatMenu`/`SdPermission`. 자세히: [app-structure.md](./app-structure.md).
11
- - **모달** — 프로그래밍 `SdModalProvider.showAsync` 또는 선언형 `<sd-modal>`. 내장 `SdPromptModal`/`SdConfirmModal`/`SdAddressSearchModal`. 자세히: [modal.md](./modal.md).
12
- - **토스트** `SdToastProvider`로 info/success/warning/danger 전역 알림 + 커스텀 컴포넌트 `notify` + 에러 자동 처리 `try`. 자세히: [toast.md](./toast.md).
13
- - **버튼류** 일반 `SdButton`, 링크형 `SdAnchor`, 본문+부가 `SdAdditionalButton`, 모달 검색 선택 `SdModalSelectButton`. 자세히: [buttons.md](./buttons.md).
14
- - **입력/폼 컨트롤** — `<sd-form>` 안에 텍스트/숫자/날짜/체크박스 류 컨트롤. `SdTextfield`, `SdTextarea`, `SdNumpad`, `SdRange`, `SdDateRangePicker`, `SdCheckbox`/`SdSwitch`/`SdCheckboxGroup(Item)`. 자세히: [forms.md](./forms.md).
15
- - **드롭다운/셀렉트** — 트리거+팝업 `SdDropdown(Popup)`, 옵션 선택 `SdSelect(Item|Button)`. 자세히: [select-dropdown.md](./select-dropdown.md).
16
- - **레이아웃 (사이드바/탑바)** 화면 `<sd-sidebar-container>` 와 상단바 컨테이너. `SdSidebar*`, `SdTopbar*`. 자세히: [layout.md](./layout.md).
17
- - **시트(테이블)**가상 스크롤 데이터 그리드. 컬럼 정의·정렬·페이징·선택·확장 트리·설정 모달 내장. `SdSheet`, `SdSheetColumn`, `SdSheetColumnCellTemplate`, `SdSheetConfigModal`. 자세히: [sheet.md](./sheet.md).
18
- - **CRUD 화면 골격**페이지/모달 공통 컨테이너 + 리스트/디테일 골격. `SdBaseContainer`, `SdCrudList`, `SdCrudDetail`. 자세히: [crud.md](./crud.md).
19
- - **서버 공유 데이터 (코드성 마스터)**부서·거래처 키 기반 등록·구독·자동 부분 갱신. `SdSharedDataProvider`, `SdSharedDataSelect(Button|List)`, `matchesSearchText`. 자세히: [shared-data.md](./shared-data.md).
20
- - **선택/확장/정렬 매니저 훅** — `<sd-sheet>`/`<sd-select>` 내부 로직을 외부 컴포넌트에서 재사용. `useSelectionManager`, `useExpandingManager`, `useSortingManager`. 자세히: [selection-managers.md](./selection-managers.md).
21
- - **칸반 보드** — 드래그·드롭 카드 보드. `SdKanbanBoard`, `SdKanban`, `SdKanbanLane`. 자세히: [kanban.md](./kanban.md).
22
- - **시각 컴포넌트** — 라벨 `SdLabel`, 알림 박스 `SdNote`, 진행률 `SdProgress`, 월별 달력 `SdCalendar`, 바코드 `SdBarcode`, ECharts 래퍼 `SdEcharts`. 자세히: [visual.md](./visual.md).
23
- - **인프라 프로바이더** — 서비스 클라이언트 팩토리 `SdServiceClientFactoryProvider`, 파일 다이얼로그 `SdFileDialogProvider`, localStorage 래퍼 `SdLocalStorageProvider`, 시스템 설정 `SdSystemConfigProvider` + `injectSdSystemConfigResource`, 인쇄/PDF `SdPrintProvider`, 글로벌 에러 핸들러/이벤트 플러그인. 자세히: [infrastructure.md](./infrastructure.md).
24
- - **`SdBusyContainer` / `SdBusyProvider`** — busy 오버레이 컴포넌트와 전역 busy 카운트. 본문 인라인.
25
- - **`SdPermissionTable`** — 권한 트리 편집 표. `SdPermission<TModule>[]` 입력 → `Record<string, boolean>` 모델. 본문 인라인.
26
- - **`SdStatePreset` / `SdStatePresetDef`** 화면 상태 프리셋 저장/복원. 본문 인라인.
27
- - **`SdTiptapEditor`** — 리치 텍스트 에디터. 본문 인라인.
28
- - **유틸 디렉티브/파이프** — 이벤트(`SdResize`/`SdIntersection`/`SdEvents`)·단축키(`SdCommandDirective`)·표시 효과(`SdRipple`/`SdShowEffect`)·검증(`SdInvalid`)·템플릿(`SdTypedTemplate`/`SdItemOfTemplate`)·포맷(`FormatPipe`)·spacer(`SdGap`)·접힘(`SdCollapse`/`SdCollapseIcon`)·탭(`SdTab`/`SdTabItem`)·리스트(`SdList`/`SdListItem`)·페이저(`SdPagination`)·signal 헬퍼(`mark`/`setSafeStyle`/`setupModelHook`). 본문 인라인.
29
- - **유틸 타입** — `DirectiveInputSignals`/`UndefToOptional`/`WithOptional`/`SelectModalOutputResult`. 본문 인라인.
30
-
31
- ## 앱 부트스트랩
32
-
33
- ```typescript
34
- bootstrapApplication(AppComponent, {
35
- providers: [provideSdAngular({ clientName: "myapp" }), provideRouter(routes)],
36
- });
7
+ - **provideSdAngular / SdAngularConfigProvider** 부트스트랩 1회. 아래 "부트스트랩" 참조.
8
+ - **버튼류** (`SdButton`/`SdAnchor`/`SdAdditionalButton`/`SdModalSelectButton`/`SdSelectModal`/`SdSelectModalInfo`) 클릭 트리거 UI. 자세히: [buttons.md](./buttons.md)
9
+ - **폼 입력류** (`SdTextfield`/`SdTextfieldTypes`/`sdTextfieldTypes`/`SdTextarea`/`SdNumpad`/`SdRange`/`SdDateRangePicker`/`SdSelect`/`SelectModeValue`/`SdSelectItem`/`SdSelectButton`/`SdCheckbox`/`SdSwitch`/`SdCheckboxGroup`/`SdCheckboxGroupItem`/`SdForm`/`SdDropdown`/`SdDropdownPopup`) 입력·서밋. 자세히: [forms.md](./forms.md)
10
+ - **모달** (`SdModalProvider`/`SdModal`/`SdActivatedModalProvider`/`SdModalContentDef`/`SdModalInfo`/`SdModalOptions`/`SdPromptModal`/`SdConfirmModal`/`SelectModalOutputResult`) 프로그래밍 다이얼로그. 자세히: [modal.md](./modal.md)
11
+ - **토스트·바쁨·프린트** (`SdToastProvider`/`SdToast`/`SdToastContainer`/`SdToastSeverity`/`SdToastTheme`/`SdToastContentDef`/`SdToastInput`/`SdBusyProvider`/`SdBusyContainer`/`SdBusyType`/`SdPrintProvider`/`SdPrint`/`SdPrintInput`) 알림·로딩·인쇄. 자세히: [toast.md](./toast.md)
12
+ - **앱 구조·권한** (`SdAppStructureProvider`/`SdAppStructureUtils`/`SdMenu`/`SdFlatMenu`/`SdPermission`/`injectPermsSignal`/`SdPermissionTable`) 메뉴 트리·권한 매트릭스. 자세히: [app-structure.md](./app-structure.md)
13
+ - **공유 데이터** (`SdSharedDataProvider`/`SharedDataBase`/`SharedDataInfo`/`SharedDataHandle`/`SdSharedDataChangeEvent`/`SdSharedDataSelect`/`SdSharedDataSelectButton`/`SdSharedDataSelectList`/`matchesSearchText`) 서버 마스터데이터 캐시+선택 UI. 자세히: [shared-data.md](./shared-data.md)
14
+ - **시트** (`SdSheet`/`SdSheetColumn`/`SdSheetColumnCellTemplate`/`SdSheetConfigModal`/`SdSheetCellContext`/`SdSheetColumnDef`/`SdSheetConfig`/`SdSheetHeaderDef`/`SdSheetItemKeydownEventParam`/`SdSheetCellKeydownEventParam`) 그리드. 자세히: [sheet.md](./sheet.md)
15
+ - **칸반** (`SdKanbanBoard`/`SdKanban`/`SdKanbanLane`/`SdKanbanBoardDropInfo`/`SdKanbanDragRef`/`SdKanbanDropTarget`) 드래그 보드. 자세히: [kanban.md](./kanban.md)
16
+ - **CRUD 화면 골격** (`SdBaseContainer`/`SdCrudList`/`SdCrudDetail`/`SdStatePreset`/`SdStatePresetDef`) — 목록/상세 페이지 컨테이너. 자세히: [crud.md](./crud.md)
17
+ - **레이아웃** (`SdSidebarContainer`/`SdSidebar`/`SdSidebarMenu`/`SdSidebarUser`/`SdSidebarUserMenu`/`SdTopbarContainer`/`SdTopbar`/`SdTopbarMenu`/`SdTopbarUser`/`SdTopbarUserMenu`) — 사이드바·탑바 골격. 자세히: [layout.md](./layout.md)
18
+ - **셀렉트/확장/정렬 매니저** (`useSelectionManager`/`useExpandingManager`/`useSortingManager`/`ExpandItemDef`/`SortingDef`)리스트 내부 상태 헬퍼. 자세히: [selection-managers.md](./selection-managers.md)
19
+ - **라우팅** (`SdRouterLink`/`SdNavigateWindowProvider`/`injectCurrentPageCodeSignal`/`injectFullPageCodeSignal`/`injectViewTitleSignal`/`injectViewTypeSignal`/`SdViewType`/`setupCanDeactivate`/`getMenuRouterLinkOption`/`getIsMenuSelected`) — 라우터 보조. 자세히: [routing.md](./routing.md)
20
+ - **인프라/유틸** (`SdSystemLogProvider`/`SdLocalStorageProvider`/`SdSystemConfigProvider`/`injectSdSystemConfigResource`/`SdServiceClientFactoryProvider`/`SdFileDialogProvider`/`SdGlobalErrorHandlerPlugin`/`SdThemeProvider`/`SdThemeSelector`/`FormatPipe`/`mark`/`setSafeStyle`/`setupBgTheme`/`setupModelHook`/`DirectiveInputSignals`/`UndefToOptional`/`WithOptional`/`SdEvents`/`SdOptionEventPlugin`/`SdResizeDirective`/`SdResizeEvent`/`SdIntersectionDirective`/`SdIntersectionEvent`/`SdCommandDirective`/`SdRipple`/`setupRipple`/`SdShowEffect`/`setupRevealOnShow`/`SdInvalid`/`setupInvalid`/`SdTypedTemplate`/`SdItemOfTemplate`/`SdItemOfTemplateContext`) 자세히: [infrastructure.md](./infrastructure.md)
21
+ - **시각 위젯** (`SdLabel`/`SdNote`/`SdProgress`/`SdCalendar`/`SdBarcode`/`BarcodeType`/`SdEcharts`/`SdTiptapEditor`/`SdAddressSearchModal`/`Address`/`SdCollapse`/`SdCollapseIcon`/`SdTab`/`SdTabItem`/`SdList`/`SdListItem`/`SdGap`/`SdPagination`) 자세히: [visual.md](./visual.md)
22
+
23
+ ## 부트스트랩
24
+
25
+ ```ts
26
+ provideSdAngular(opt: { clientName: string }): EnvironmentProviders
37
27
  ```
38
28
 
39
- - `provideSdAngular({ clientName })`: zoneless CD, NgIcons config, 글로벌 에러 핸들러(`SdGlobalErrorHandlerPlugin`), `SdOptionEventPlugin`(이벤트 `.capture`/`.passive`/`.once`), 테마 dark/fontSize ↔ localStorage 동기화, SwUpdate 폴링(실패 시 백오프 5분→1시간), Router navigation `SdBusyProvider.globalBusyCount` 자동 ±1.
40
- - `SdAngularConfigProvider.clientName`: localStorage prefix·service client name 으로 사용. `provideSdAngular` 옵션에서 설정됨.
41
- - `SdSystemLogProvider.writeFn?: (severity: "error"|"warn"|"log", ...data) => Promise<void> | void`: severity별 로그 후크 등록(서버 전송 등). 호출 시 console에도 항상 출력.
42
- - `setupBgTheme({ theme?, lightness? })`: 컴포넌트 constructor 내에서 호출. body `--background-color` CSS 변수 토글, destroy 시 자동 복원. `theme: "primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray"`, `lightness: "lightest"|"lighter"` (default `"lightest"`).
43
-
44
- ## 테마
45
-
46
- - `SdThemeProvider`: `dark = signal<boolean>`, `fontSize = signal<number>` (presets `[12,14,16,20,24,28]`), `increaseFontSize()`/`decreaseFontSize()`. dark=true 시 body에 `sd-theme-dark` 클래스, fontSize는 html `font-size` 적용. `provideSdAngular`가 localStorage 영속화.
47
- - `SdThemeSelector`: dropdown 형 토글 UI (글자 크기 ± 버튼 + dark 스위치). 별도 입력 없음.
48
-
49
- ## SdBusyContainer / SdBusyProvider
50
-
51
- `<sd-busy-container [busy] [message] [type] [progressPercent]>`. type: `"spinner" | "bar" | "cube"` (default = `SdBusyProvider.type()` = `"bar"`). `busy=true` 동안 keydown 차단.
52
-
53
- `SdBusyProvider`:
54
- - `globalBusyCount = signal(0)`. > 0이면 body 전면 오버레이.
55
- - `type = signal<SdBusyType>("bar")`: 전역 busy 컨테이너의 기본 type. 변경 시 즉시 반영.
56
-
57
- ## SdPermissionTable
58
-
59
- `<sd-permission-table [items] [(value)] [disabled]>`. `items: SdPermission<TModule>[]` (`SdAppStructureUtils.getPermissions` 결과), `value: Record<string, boolean>` (`<fullCode>.use|edit` 형식). 트리 접기/펼치기 + 그룹 일괄 토글.
29
+ - `clientName` — `SdAngularConfigProvider.clientName` 으로 저장. `SdLocalStorageProvider` prefix, `SdServiceClientFactoryProvider` `createServiceClient(clientName, )`, `SdAppStructureProvider.initialize` `itemsMap[clientName]` 조회에 사용.
30
+ - 호출 부수효과: zoneless change detection 활성, `IMAGE_CONFIG` 경고 끔, ng-icons 기본(stroke 1.5/size 1.33em), `EVENT_MANAGER_PLUGINS` `SdOptionEventPlugin` 추가, `ErrorHandler` 를 `SdGlobalErrorHandlerPlugin` 으로 교체, `unhandledrejection`·`error` 글로벌 리스너 등록, `SdThemeProvider.dark`/`fontSize` 를 `SdLocalStorageProvider` 와 양방향 sync(`sd-theme-dark`·`sd-theme-font-size` 키), `Router` 네비게이션 동안 `SdBusyProvider.globalBusyCount` 증감, `SwUpdate` 활성 시 5분~1시간 백오프로 업데이트 확인 후 사용자 컨펌 → reload.
60
31
 
61
- ## SdStatePreset
62
-
63
- `<sd-state-preset [key] [(state)] [size]>`. `key` 신호 아래 `SdStatePresetDef[]` = `{ name, state }[]` 를 `SdSystemConfigProvider` 에 저장. 별 아이콘 클릭 → 이름 프롬프트 → 추가. 각 프리셋 클릭 시 `state.set(obj.clone(preset.state))`.
64
-
65
- ## SdTiptapEditor
66
-
67
- `<sd-tiptap-editor [(value)] [disabled] [readonly] [required] [placeholder] [validatorFn] [extensions]>`. value=HTML string. 기본 extensions: StarterKit + TextStyle + Color + Highlight + TextAlign + Image + Underline. `extensions?: AnyExtension[]` 으로 Tiptap 확장 주입(기본 위에 추가).
68
-
69
- ## 유틸 디렉티브/파이프
70
-
71
- 이벤트·표시 보조용. constructor injection 또는 셀렉터 attach.
72
-
73
- - `SdOptionEventPlugin`: `(click.capture)`, `(scroll.passive)`, `(touchmove.capture.passive)`, `(transitionend.once)` 등 `.capture/.passive/.once` 변형 이벤트 바인딩 활성화. `provideSdAngular`로 자동 등록.
74
- - `SdResizeDirective` (`[sdResize]`): ResizeObserver 기반 size 변화 emit (`SdResizeEvent { heightChanged, widthChanged, target, contentRect }`). requestAnimationFrame 디바운스.
75
- - `SdIntersectionDirective` (`[sdIntersection]`): IntersectionObserver entry emit (`SdIntersectionEvent { entry }`).
76
- - `SdEvents`: 다양한 native event의 `.capture`/`.passive`/`.once` output 디렉티브 (예: `(scroll.passive)`, `(touchstart.passive)`, `(focus.capture)`, `(transitionend.once)`).
77
- - `SdCommandDirective` (`[sdRefreshCommand]`/`[sdSaveCommand]`/`[sdInsertCommand]`): Ctrl+Alt+L/Ctrl+S/Insert 단축키 emit. 최상위 열린 모달 내부 또는 모달 없는 페이지일 때만 처리.
78
- - `SdRipple` (`[sdRipple]="bool"`) / `setupRipple(enableFn?)`: pointerdown 시 원형 ripple.
79
- - `SdShowEffect` (`[sdShowEffect]="bool"` + `[sdShowEffectType]="'l2r'|'t2b'"`) / `setupRevealOnShow`: viewport intersection 시 fade-in.
80
- - `SdInvalid` (`[sdInvalid]="msg"`) / `setupInvalid(getMsg)`: hidden input의 customValidity 로 form 검증 + 좌상단 빨간 점 인디케이터.
81
- - `SdTypedTemplate` (`<ng-template [typed]="typeToken">`): template context 타입 추론용.
82
- - `SdItemOfTemplate` (`<ng-template [itemOf]="items">`, ctx `SdItemOfTemplateContext { $implicit, item, index, depth }`) — 컬렉션 컴포넌트(`SdSelect`/`SdCalendar` 등) 항목 템플릿.
83
- - `FormatPipe` (`{{ v | format:fmt }}`): `DateTime`/`DateOnly`는 `toFormatString(fmt)`, string은 `X` 자리표시(예: `'XXX-XXXX-XXXX'`, `|` 로 다중 길이).
84
- - `SdGap`: spacer. `height|width` 단위 키(`xxs|xs|sm|default|lg|xl|xxl`), `heightPx|widthPx|widthEm` 픽셀/em. 값 0이면 `display:none`.
85
- - `SdCollapse [open]` / `SdCollapseIcon [open] [openRotate=90] [icon]`: 접힘 패널/아이콘.
86
- - `SdTab [(value)]`/`SdTabItem [value]`: 탭.
87
- - `SdList [inset]`/`SdListItem [layout="accordion"|"flat"] [open] [selected] [selectedIcon] [readonly] [contentStyle/Class]` + `<ng-template #toolTpl>` (옵션 도구 영역).
88
- - `SdPagination [(currentPage)] [totalPageCount] [visiblePageCount=10]`. 그룹 단위 페이지 이동.
89
- - `mark(signal)`: array/object signal의 in-place mutation 후 shallow copy로 trigger.
90
- - `setSafeStyle(renderer, el, partial)`: renderer.setStyle 일괄.
91
- - `setupModelHook(model, canFnSignal)`: WritableSignal의 set/update를 `canFn(value) -> boolean | Promise<boolean>`로 가로채기. `canFn` 자체가 `Signal<...>` 형식 (`input<(v)=>...>()` 그대로 전달). constructor 내에서 호출.
92
-
93
- ## 유틸 타입/기타
32
+ ```ts
33
+ @Injectable({ providedIn: "root" }) class SdAngularConfigProvider { clientName!: string }
34
+ ```
94
35
 
95
- - `DirectiveInputSignals<T>`: 컴포넌트의 InputSignal 프로퍼티만 추출(`{ name: T }`). undefined 포함 필드는 optional.
96
- - `UndefToOptional<T>`: undefined 포함 필드를 optional 변환.
97
- - `WithOptional<T, K>`: 특정 키만 optional 로.
98
- - `SelectModalOutputResult<TKey> = { selectedKeys: TKey[] }`: 모달 선택 결과.
36
+ - 직접 일은 거의 없음. 다른 simplysm 프로바이더가 inject prefix·키로 사용.
37
+ - 사용 예: `bootstrapApplication(App, { providers: [provideSdAngular({ clientName: "my-app" })] })`
@@ -1,49 +1,92 @@
1
1
  # @simplysm/angular — app-structure
2
2
 
3
- 서버의 `AppStructureService`에서 받은 메뉴/권한 트리(`AppStructureItem<TModule>[]`)를 클라이언트 측에서 사용 가능 형태로 변환.
3
+ 서버 `AppStructureService` 에서 받은 메뉴·권한 트리(`AppStructureItem<TModule>[]`)를 클라이언트에서 사용 가능 형태로 변환·캐시.
4
4
 
5
- ## `SdAppStructureProvider<TModule>`
5
+ ## SdAppStructureProvider<TModule> (root)
6
6
 
7
- ```typescript
8
- const sas = inject<SdAppStructureProvider<MyModule>>(SdAppStructureProvider);
9
- await sas.initialize("main"); // 서비스 키 → AppStructureService.getItems()
10
- sas.usableModules.set(myModules); // 활성 모듈
11
- sas.permRecord.set({ "order.list.use": true });
7
+ ```ts
8
+ usableModules: WritableSignal<TModule[]|undefined>;
9
+ permRecord: WritableSignal<Record<string, boolean>|undefined>;
10
+ items: WritableSignal<AppStructureItem<TModule>[]>;
12
11
 
13
- sas.usableMenus(); // Signal<SdMenu[]> (트리)
14
- sas.usableFlatMenus(); // Signal<SdFlatMenu[]> (flat)
15
- sas.getTitleByFullCode("order.list");
16
- sas.getPermsByFullCode(["order.list"], ["use","edit"]);
17
- sas.getPermissionsByStructure(items, codeChain);
12
+ usableMenus: Signal<SdMenu[]>; // items × modules × perms 필터된 트리 메뉴
13
+ usableFlatMenus: Signal<SdFlatMenu<TModule>[]>; // 평탄화된 메뉴 리스트 (검색 등)
14
+
15
+ initialize(serviceKey: string): Promise<void>;
16
+ getPermissionsByStructure(items, codeChain?): SdPermission<TModule>[];
17
+ getTitleByFullCode(fullCode: string): string; // 부모 chain 포함 타이틀("[A > B] C")
18
+ getItemChainByFullCode(fullCode: string): AppStructureItem<TModule>[];
19
+ getPermsByFullCode<K extends string>(fullCodes: string[], permKeys: K[]): K[];
18
20
  ```
19
21
 
20
- 내부적으로 `SdAppStructureUtils.getMenus/getFlatMenus/getPermissions/...` 위임.
22
+ - `initialize` — `SdServiceClientFactoryProvider.get(serviceKey)` 에서 `AppStructureService.getItems()` 호출, `clientName` (`SdAngularConfigProvider`) 키로 트리 적재.
23
+ - `usableModules` — 활성 모듈 식별자 배열. 메뉴/권한 필터링에 사용. 미세팅(`undefined`) 이면 모듈 체크 통과(전체 허용).
24
+ - `permRecord` — `<fullCode>.<permKey>` (예: `sales.invoice.use`) → boolean. `undefined` 면 권한 체크 통과.
25
+ - `usableMenus` — 그룹 메뉴는 표시 가능한 leaf 자식이 있어야 포함. leaf 는 `<code>.use` 권한 검사.
26
+ - `usableFlatMenus` — leaf 만 평탄화. modulesChain 정보 포함.
27
+ - `getPermsByFullCode` — 해당 화면들에 대해 사용자가 가진 권한키들 추출(`perms` 자체가 정의 안된 화면은 모든 permKey 통과).
21
28
 
22
- ## `injectPermsSignal<K>(viewCodes, keys)`
29
+ ## SdAppStructureUtils (abstract static class)
23
30
 
24
- ```typescript
25
- const perms = injectPermsSignal(["order.list"], ["use", "edit"] as const);
26
- perms(); // 갖고 있는 권한만 필터된 배열
31
+ ```ts
32
+ static getTitleByFullCode/getPermsByFullCode/getItemChainByFullCode
33
+ static getMenus(items, codeChain, usableModules, permRecord): SdMenu[]
34
+ static getFlatMenus(items, usableModules, permRecord): SdFlatMenu<TModule>[]
35
+ static getPermissions(items, codeChain, usableModules): SdPermission<TModule>[]
36
+ static getFlatPermissions(items, usableModules) // service-common 의 동명 함수 위임
27
37
  ```
28
38
 
29
- ## 타입
39
+ - 프로바이더가 내부적으로 호출. 트리 변환 로직 직접 쓰고 싶으면 호출 가능.
40
+
41
+ ## injectPermsSignal
42
+
43
+ ```ts
44
+ function injectPermsSignal<K extends string>(viewCodes: string[], keys: K[]): Signal<K[]>
45
+ ```
46
+
47
+ - 컴포넌트/페이지에서 자기 화면 코드들과 검사할 권한키 배열을 주면, 현재 사용자가 가진 키만 담은 signal 반환. 버튼 enable 조건 등에 사용.
48
+
49
+ ```ts
50
+ readonly perms = injectPermsSignal(["sales.invoice"], ["use", "edit"]);
51
+ // 템플릿: @if (perms().includes("edit")) { <sd-button>편집</sd-button> }
52
+ ```
53
+
54
+ ## SdPermissionTable — `<sd-permission-table>`
30
55
 
31
- ```typescript
32
- interface SdMenu { title; codeChain: string[]; url?; icon?; children? }
33
- interface SdFlatMenu { titleChain; codeChain; modulesChain: TModule[][] }
34
- interface SdPermission { title; codeChain; modules; perms: ("use"|"edit")[]?; children? }
56
+ ```ts
57
+ class SdPermissionTable<TModule>
58
+ value = model<Record<string, boolean>>({}); // permRecord 형태(key: <fullCode>.<permKey>)
59
+ items = input<SdPermission<TModule>[]>([]);
60
+ disabled = input(false);
35
61
  ```
36
62
 
37
- ## `SdAppStructureUtils` 정적 메서드
63
+ - 권한 트리를 표 형태로 표시·편집. `value` 양방향. 관리자 권한 설정 화면용.
38
64
 
39
- - `getMenus(items, codeChain, usableModules, permRecord)` — `isNotMenu` 제외, 모듈 활성·`.use` 권한 통과한 항목.
40
- - `getFlatMenus(items, usableModules, permRecord)` — 평탄화 + 부모 modules 누적 검사.
41
- - `getPermissions(items, codeChain, usableModules)` — 권한 트리 (`SdPermissionTable` 입력용).
42
- - `getFlatPermissions(items, usableModules)` — `@simplysm/service-common` 재노출.
43
- - `getTitleByFullCode`, `getItemChainByFullCode`, `getPermsByFullCode`.
65
+ ## 타입
44
66
 
45
- ## 주의
67
+ ```ts
68
+ interface SdMenu {
69
+ title: string; codeChain: string[]; url?: string; icon?: string; children?: SdMenu[];
70
+ }
71
+ interface SdFlatMenu<TModule = unknown> {
72
+ titleChain: string[]; codeChain: string[]; modulesChain: TModule[][];
73
+ }
74
+ interface SdPermission<TModule = unknown> {
75
+ title: string; codeChain: string[]; modules: TModule[]|undefined;
76
+ perms: ("use"|"edit")[]|undefined;
77
+ children: SdPermission<TModule>[]|undefined;
78
+ }
79
+ ```
46
80
 
47
- - `permRecord` 키는 `"<code>.<perm>"` (예: `"order.list.use"`).
48
- - 그룹 메뉴는 자식 하나라도 표시 가능해야 노출.
49
- - Leaf 가 `perms`를 가지면 `.use` 권한 필수, `perms`가 없거나 권한 자체가 없으면 통과.
81
+ - `SdMenu` `url` 또는 `children` 중 하나. 라우터 링크 분기는 `getMenuRouterLinkOption` 이 담당 ([routing.md](./routing.md)).
82
+ - `SdFlatMenu.modulesChain` 조상부터 자신까지 누적된 modules 배열 묶음. 모듈 활성 여부 검사 시 사용.
83
+ - `SdPermission.perms` 해당 화면이 정의한 권한 키들. undefined 권한 개념 없음(모두 허용).
84
+
85
+ ## 부트스트랩 순서
86
+
87
+ ```ts
88
+ const sdAppStructure = inject(SdAppStructureProvider);
89
+ sdAppStructure.usableModules.set(myActiveModules);
90
+ sdAppStructure.permRecord.set(myPermRecord);
91
+ await sdAppStructure.initialize("main"); // serviceKey = SdServiceClientFactoryProvider 의 등록 key
92
+ ```
@@ -1,52 +1,88 @@
1
1
  # @simplysm/angular — buttons
2
2
 
3
- ## `<sd-button>`
3
+ ## SdButton — `<sd-button>`
4
4
 
5
- `type: "button"|"submit" = "button"`, `theme`(`primary|secondary|info|success|warning|danger|gray|blue-gray|link|link-<theme>|link-rev`), `inline`, `inset`, `size: "sm"|"lg"`, `disabled`, `buttonStyle`, `buttonClass`. content projection.
5
+ ```ts
6
+ type = input<"button" | "submit">("button");
7
+ theme = input<"primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray"|"link"|"link-primary"|"link-secondary"|"link-info"|"link-success"|"link-warning"|"link-danger"|"link-gray"|"link-blue-gray"|"link-rev">();
8
+ inline = input(false); inset = input(false); size = input<"sm"|"lg">();
9
+ disabled = input(false); buttonStyle = input<string>(); buttonClass = input<string>();
10
+ ```
11
+
12
+ - `type` — 내부 `<button type>`. `submit` 이면 둘러싼 `<sd-form>`·`<form>` 의 서밋을 트리거.
13
+ - `theme` — 색상·강조. `link-*` 는 배경 없는 텍스트 링크 룩. 미지정이면 디폴트 회색.
14
+ - `inline` — true 면 인라인 블록 폭(콘텐츠 크기). false 면 부모 폭 채움.
15
+ - `inset` — true 면 외곽 보더/그림자 제거(컨테이너 안에 박힌 룩).
16
+ - `size` — `sm`/`lg` 만. 미지정 = 기본 크기.
17
+ - `disabled` — true 면 클릭·포커스 차단.
18
+ - `buttonStyle`/`buttonClass` — 내부 `<button>` 에 style/class 추가.
6
19
 
7
20
  ```html
8
- <sd-button [theme]="'primary'" (click)="save()">저장</sd-button>
21
+ <sd-button theme="primary" (click)="onSave()">저장</sd-button>
9
22
  ```
10
23
 
11
- ## `<sd-anchor>`
24
+ ## SdAnchor — `<sd-anchor>`
12
25
 
13
- 링크형 클릭 요소. `disabled`, `theme`(`primary|secondary|...|blue-gray`, default `primary`). 비활성 시 tabindex 제거.
26
+ ```ts
27
+ disabled = input(false);
28
+ theme = input<"primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray"|...>();
29
+ ```
30
+
31
+ - 링크 룩 클릭 영역. 버튼보다 강조 낮음. `theme` 미지정이면 현재 텍스트 색 상속.
32
+ - `disabled` — 클릭·포커스 차단.
14
33
 
15
34
  ```html
16
- <sd-anchor [theme]="'danger'" (click)="del()">삭제</sd-anchor>
35
+ <sd-anchor (click)="onEdit()">수정</sd-anchor>
17
36
  ```
18
37
 
19
- ## `<sd-additional-button>`
38
+ ## SdAdditionalButton — `<sd-additional-button>`
39
+
40
+ ```ts
41
+ size = input<"sm"|"lg">(); inset = input(false);
42
+ ```
20
43
 
21
- 본문 영역 + 우측 부가 버튼 슬롯(`<sd-anchor>`, `<sd-button>` projection). `size: "sm"|"lg"`, `inset`.
44
+ - 입력 컨트롤(`<sd-textfield>` 등) 옆에 붙이는 보조 버튼 슬롯. `<ng-content>` 아이콘/텍스트 투영. 키패드 등 입력 우측에 액션 붙일 때.
22
45
 
23
46
  ```html
24
- <sd-additional-button>
25
- 본문 내용
26
- <sd-button (click)="...">+</sd-button>
27
- </sd-additional-button>
47
+ <sd-textfield type="text" [(value)]="q" /><sd-additional-button (click)="onSearch()">검색</sd-additional-button>
28
48
  ```
29
49
 
30
- ## `<sd-modal-select-button>`
50
+ ## SdModalSelectButton — `<sd-modal-select-button>`
51
+
52
+ ```ts
53
+ class SdModalSelectButton<M extends "single"|"multi", K, T extends SdSelectModal<K>>
54
+ modal = input.required<SdSelectModalInfo<SdSelectModal<K>>>();
55
+ value = model<SelectModeValue<K>[M]>();
56
+ disabled = input(false); required = input(false); inset = input(false);
57
+ size = input<"sm"|"lg">(); selectMode = input<M>("single" as M);
58
+ modalOptions = input<SdModalOptions>();
59
+ searchIcon = input(tablerSearch);
31
60
 
32
- 검색 모달을 띄워 값을 선택받는 입력 위젯. `setupInvalid` 로 required 검증 내장.
61
+ interface SdSelectModal<TKey> extends SdModalContentDef<SelectModalOutputResult<TKey>> {
62
+ selectMode: InputSignal<"single"|"multi"|undefined>;
63
+ selectedKeys: InputSignal<TKey[]>;
64
+ }
65
+ type SdSelectModalInfo<T extends SdSelectModal<any>> = SdModalInfo<T, "selectMode"|"selectedKeys">;
66
+ ```
67
+
68
+ - 입력 옆에 검색 버튼이 붙은 모달 트리거 컨트롤. 검색 아이콘 클릭 → 지정 모달 표시 → 모달이 `SelectModalOutputResult<TKey>` emit → `value` 에 반영.
69
+ - `modal` — 표시할 모달 컴포넌트 정의(`SdSelectModal` 구현). 필수.
70
+ - `value` — `single` 모드면 단일 키, `multi` 면 키 배열. `model` 이므로 양방향.
71
+ - `selectMode` — 모달에 전달되는 선택 모드. `single` 기본.
72
+ - `required` — true 면 값이 있어도 지우개 아이콘 표시 안 함. false + 값 있음 → 우측에 지우개 아이콘 노출.
73
+ - `inset` — 컨테이너 안에 박힌 룩(보더 제거).
74
+ - `disabled` — 검색·지우개 버튼 모두 숨김.
75
+ - `modalOptions` — `SdModalProvider.showAsync` 에 전달되는 옵션 ([modal.md](./modal.md)).
76
+ - `searchIcon` — 우측 버튼 아이콘. 기본 `tablerSearch`.
77
+ - `<ng-content>` — 좌측 값 표시 영역.
33
78
 
34
79
  ```html
35
- <sd-modal-select-button
36
- [modal]="orderSelectModalInfo" <!-- SdSelectModalInfo<SdSelectModal<TKey>> -->
37
- [(value)]="selectedKey" <!-- single 모드: TKey | multi 모드: TKey[] -->
38
- [selectMode]="'single'"
39
- [modalOptions]="{ resizable: true }"
40
- [required]="true"
41
- [disabled]="false"
42
- [size]="'sm'"
43
- [inset]="false"
44
- [searchIcon]="customIcon">
45
- {{ displayLabel() }}
80
+ <sd-modal-select-button [(value)]="userId" [modal]="{ title: '직원선택', type: EmpSelectModal, inputs: {} }">
81
+ {{ userName() }}
46
82
  </sd-modal-select-button>
47
83
  ```
48
84
 
49
- - `SdSelectModal<TKey>` = `SdModalContentDef<SelectModalOutputResult<TKey>>` + `selectMode: InputSignal<"single"|"multi"|undefined>` + `selectedKeys: InputSignal<TKey[]>`.
50
- - `SdSelectModalInfo<T>` = `SdModalInfo<T, "selectMode"|"selectedKeys">`.
51
- - value 있고 required 아니면 좌측에 erase 아이콘 노출 → 클릭 시 초기화(single 은 `undefined`, multi 는 `[]`).
52
- - 검색 버튼 클릭 `SdModalProvider.showAsync` 호출, 결과 `{ selectedKeys }` `selectMode` 맞춰 `value` 반영.
85
+ ## 공통 주의
86
+
87
+ - 모든 버튼류는 standalone. 별도 NgModule 등록 불필요.
88
+ - `theme` 같은 8개 baseline(`primary`~`blue-gray`)은 디자인 토큰 `--theme-<name>-default` 연결. `SdButton.theme` `link-*` 변종 추가.