@simplysm/sd-claude 14.0.94 → 14.0.96

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 (38) hide show
  1. package/claude/references/sd-simplysm14/README.md +6 -2
  2. package/claude/references/sd-simplysm14/apis/angular/README.md +180 -43
  3. package/claude/references/sd-simplysm14/apis/angular/controls.md +275 -125
  4. package/claude/references/sd-simplysm14/apis/angular/crud.md +54 -59
  5. package/claude/references/sd-simplysm14/apis/angular/directives.md +139 -48
  6. package/claude/references/sd-simplysm14/apis/angular/features.md +102 -88
  7. package/claude/references/sd-simplysm14/apis/angular/kanban.md +54 -0
  8. package/claude/references/sd-simplysm14/apis/angular/layout.md +60 -36
  9. package/claude/references/sd-simplysm14/apis/angular/overlay.md +127 -75
  10. package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +97 -51
  11. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +74 -58
  12. package/claude/references/sd-simplysm14/apis/angular/sheet.md +81 -60
  13. package/claude/references/sd-simplysm14/apis/excel/README.md +5 -5
  14. package/claude/references/sd-simplysm14/apis/excel/cell.md +3 -3
  15. package/claude/references/sd-simplysm14/apis/excel/style.md +2 -2
  16. package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +5 -4
  17. package/claude/references/sd-simplysm14/apis/excel/wrapper.md +2 -2
  18. package/claude/references/sd-simplysm14/manuals/client-app-structure.md +5 -3
  19. package/claude/references/sd-simplysm14/manuals/client-component.md +31 -26
  20. package/claude/references/sd-simplysm14/manuals/client-crud.md +154 -4
  21. package/claude/references/sd-simplysm14/manuals/client-demo.md +5 -18
  22. package/claude/references/sd-simplysm14/manuals/client-orm.md +3 -12
  23. package/claude/references/sd-simplysm14/manuals/client-service.md +18 -7
  24. package/claude/references/sd-simplysm14/manuals/client-shared-data.md +24 -5
  25. package/claude/references/sd-simplysm14/manuals/data-log.md +1 -1
  26. package/claude/sd-system-prompt.md +7 -0
  27. package/claude/skills/sd-debug/SKILL.md +142 -27
  28. package/claude/skills/sd-review/SKILL.md +158 -20
  29. package/claude/skills/sd-spec/SKILL.md +53 -61
  30. package/claude/skills/sd-spec/references/format.md +476 -0
  31. package/package.json +1 -1
  32. package/claude/references/sd-simplysm14/apis/angular/infra.md +0 -82
  33. package/claude/skills/sd-debug/workflow.js +0 -390
  34. package/claude/skills/sd-review/workflow.js +0 -324
  35. package/claude/skills/sd-spec/references/format-analyze.md +0 -232
  36. package/claude/skills/sd-spec/references/format-design.md +0 -248
  37. package/claude/skills/sd-spec/workflow-analyze.js +0 -615
  38. package/claude/skills/sd-spec/workflow-design.js +0 -667
@@ -2,6 +2,10 @@
2
2
 
3
3
  Claude 에이전트가 `@simplysm/*` v14 패키지를 사용·변경하는 작업에서 반드시 지켜야 할 행동 지침.
4
4
 
5
+ ## 매뉴얼·apis 문서의 위상
6
+
7
+ 이 문서 트리의 매뉴얼(개발 매뉴얼 섹션)과 apis(패키지 인덱스 섹션)는 `@simplysm/*` 사용법을 안내하는 참고 가이드임. 권장 방법·제안에 해당하며 그 자체가 결정 근거는 아님. 문서가 권하는 방식이라도 자동 채택하지 말고, 채택 여부는 결정 근거 규칙(기존 코드 패턴·사용자 합의 등)을 따름.
8
+
5
9
  ## 코드 작성 위치 원칙
6
10
 
7
11
  업무 로직 코드의 기본 작성 위치는 **클라이언트 패키지**. 서버 패키지(`@simplysm/service-server` 기반)에는 다음 두 경우에만 코드를 둠:
@@ -44,7 +48,7 @@ ORM 호출, 파일 변환, 비즈니스 로직 등은 위 두 경우에 해당
44
48
 
45
49
  ## 패키지 인덱스
46
50
 
47
- - **angular** — Angular(zoneless) 기반 SI/업무 클라이언트용 UI 컴포넌트·디렉티브·전역 프로바이더·signal 헬퍼 부트스트랩(provideSdAngular)·모달/토스트/busy/인쇄·라우팅/메뉴/권한·폼 입력 컨트롤·시트(sd-sheet)·공유 마스터 데이터·CRUD 화면 골격·사이드바/탑바 레이아웃·칸반/권한표/에디터/시각화를 때. 자세히: [apis/angular/README.md](./apis/angular/README.md)
51
+ - **angular** — Angular 21 zoneless 프론트엔드 UI 라이브러리 provideSdAngular 부트스트랩, 모달/토스트/busy/인쇄 오버레이, 폼 입력·버튼·셀렉트 등 컨트롤, sd-sheet 그리드, sd-crud-list/detail 화면 골격, 공유 마스터 데이터 선택, 사이드바/탑바 레이아웃, 라우팅·메뉴·권한, core 디렉티브·signal 헬퍼, 칸반/권한표/에디터/시각화. 앱 화면 작성·수정 사용. 자세히: [apis/angular/README.md](./apis/angular/README.md)
48
52
  - **capacitor-plugin-auto-update** — Android APK 자동 업데이트 Capacitor 플러그인 — 부팅 시 서버/외부저장소의 최신 APK 를 받아 설치하는 오케스트레이터(AutoUpdate.run/runByExternalStorage)와 저수준 설치·권한·버전 조회 정적 클래스(ApkInstaller) 및 브리지 타입(ApkInstallerPlugin/VersionInfo)을 쓸 때. 자세히: [apis/capacitor-plugin-auto-update/README.md](./apis/capacitor-plugin-auto-update/README.md)
49
53
  - **capacitor-plugin-file-system** — Capacitor 네이티브 파일 시스템 접근(Android OS 파일 시스템 / 웹 IndexedDB 에뮬레이션). FileSystem 정적 메서드로 권한 확인·요청, 디렉토리 읽기/생성, 파일 읽기/쓰기/삭제, 저장소 경로·파일 URI 조회 시. 자세히: [apis/capacitor-plugin-file-system/README.md](./apis/capacitor-plugin-file-system/README.md)
50
54
  - **capacitor-plugin-intent** — Android 인텐트 송수신 Capacitor 플러그인(Intent 정적 클래스) — 브로드캐스트 구독/전송, 실행 인텐트 조회, newIntent 리스닝, startActivityForResult 외부 Activity 실행·결과 수신. 바코드 스캐너·PDA 등 산업용 디바이스 연동 시 사용. 자세히: [apis/capacitor-plugin-intent/README.md](./apis/capacitor-plugin-intent/README.md)
@@ -52,7 +56,7 @@ ORM 호출, 파일 변환, 비즈니스 로직 등은 위 두 경우에 해당
52
56
  - **core-browser** — 브라우저 전용 유틸리티 — DOM 요소 탐색·위치 계산·가시성 확장, IndexedDB 영속화 및 가상 파일시스템, Blob 다운로드·URL 바이너리 수신·파일 선택 대화상자가 필요할 때. 자세히: [apis/core-browser/README.md](./apis/core-browser/README.md)
53
57
  - **core-common** — 브라우저·Node 공용 기반 유틸 — 날짜/시간 값 타입(DateTime/DateOnly/Time/Uuid), 에러 클래스(SdError 등), 배열/Set/Map 프로토타입 확장, 객체 깊은 복사·비교·병합(obj), 직렬화(json/xml/bytes/transfer), 비동기 큐·이벤트·대기·자동만료 Map, 문자열/숫자/경로/날짜포맷 유틸, 로거·환경변수·원시타입 매핑이 필요할 때. 자세히: [apis/core-common/README.md](./apis/core-common/README.md)
54
58
  - **core-node** — Node 전용 유틸: 파일시스템 IO(fsx)·경로 가공(pathx)·자식 프로세스 실행(cpx)·glob 감시(FsWatcher)·consola 로깅 셋업(setupConsola)·worker_threads 타입 안전 래퍼(Worker/createWorker)가 필요할 때. 자세히: [apis/core-node/README.md](./apis/core-node/README.md)
55
- - **excel** — OOXML(.xlsx) 워크북을 ZIP 단위 lazy-load 로 읽고 쓰는 라이브러리. ExcelWorkbook/ExcelWorksheet 시트·셀 값/수식·스타일·조건부 서식·이미지·행 복사·뷰를, ExcelWrapperZod 스키마 기반 레코드 ↔ 엑셀 변환을, ExcelUtils 로 주소·날짜 시리얼·숫자형식 변환을 다룰 때. 자세히: [apis/excel/README.md](./apis/excel/README.md)
59
+ - **excel** — xlsx(엑셀) 파일을 코드로 읽기/쓰기 ExcelWorkbook 으로 시트·셀 값/수식·스타일·조건부서식·이미지·뷰(틀고정/줌/자동필터)를 다루고, ExcelWrapper(Zod 스키마)로 레코드 배열 ↔ 엑셀 변환, ExcelUtils 로 주소·날짜·숫자형식 변환할 때. 자세히: [apis/excel/README.md](./apis/excel/README.md)
56
60
  - **lint** — 심플리즘 ESLint 자산. 커스텀 규칙 9종 플러그인(`@simplysm/lint/eslint-plugin`)과 그 규칙 + typescript-eslint/angular-eslint/import/unused-imports 를 묶은 flat config 프리셋(`@simplysm/lint/eslint-recommended`)을 프로젝트 eslint.config 에 적용하거나 개별 규칙의 검사 대상·메시지·autofix·옵션을 파악할 때. 자세히: [apis/lint/README.md](./apis/lint/README.md)
57
61
  - **orm-common** — Dialect(MySQL/MSSQL/PostgreSQL) 독립 ORM 코어 — Table/View/Procedure 스키마 빌더, DbContext 상속(연결·트랜잭션·DDL·마이그레이션), Queryable 체이닝(SELECT/CUD·join/include/union/recursive·검색), expr 표현식 빌더(비교·집계·조건·윈도우·서브쿼리), QueryDef/Expr AST·dialect QueryBuilder·결과 파싱을 다룰 때. 자세히: [apis/orm-common/README.md](./apis/orm-common/README.md)
58
62
  - **orm-node** — Node.js 환경에서 DbContext 를 MySQL/MSSQL/PostgreSQL 에 연결·실행하는 ORM 런타임 — 고수준 createOrm(트랜잭션 경계) 과 저수준 createDbConn/DbConn(raw SQL·파라미터 쿼리·bulk insert·수동 트랜잭션) 제공. 자세히: [apis/orm-node/README.md](./apis/orm-node/README.md)
@@ -1,77 +1,214 @@
1
1
  # @simplysm/angular
2
2
 
3
- Angular(zoneless) 기반 SI/업무 클라이언트용 UI 컴포넌트·디렉티브·전역 프로바이더·signal 헬퍼 모음. `provideSdAngular` 부트스트랩 위에서 모달/토스트/busy/인쇄, 라우팅/메뉴/권한, 입력 컨트롤, 시트(sd-sheet), 공유 마스터 데이터, CRUD 화면 골격, 사이드바/탑바 레이아웃, 칸반/권한표/에디터/시각화를 제공. `import "@simplysm/core-browser"` 를 side-effect 로 로드하며, 컴포넌트는 standalone + OnPush + `ViewEncapsulation.None`, selector 는 `sd-` prefix.
3
+ Angular 21 zoneless 프론트엔드 UI 라이브러리. 부트스트랩 프로바이더, signal 기반 standalone 컴포넌트/디렉티브, 모달·토스트·busy 오버레이, 시트·CRUD 골격, 공유데이터·레이아웃·시각화 컴포넌트를 제공. `import "@simplysm/core-browser"` 를 side-effect 로 로드하며, 컴포넌트는 standalone + OnPush + `ViewEncapsulation.None`, selector 는 `sd-` prefix. 앱 화면을 작성·수정할 때 거의 항상 이 패키지를 import.
4
4
 
5
5
  ## 사용 트리거 인덱스
6
6
 
7
- - **앱 부트스트랩·전역 설정**`provideSdAngular` zoneless 앱을 띄우고, 클라이언트명·테마·로컬스토리지·시스템설정·시스템로그·서비스클라이언트 프로바이더를 설정할 때. 자세히: [infra.md](./infra.md)
8
- - **오버레이(모달·토스트·busy·인쇄)** — 코드로 모달/토스트를 띄우거나, 화면 busy 표시·인쇄/PDF 출력을 때. 자세히: [overlay.md](./overlay.md)
9
- - **라우팅·메뉴·권한(app-structure)** 페이지 코드·뷰 타입·제목 시그널, 라우터 링크/창 열기, 이탈 가드, 메뉴/권한 트리 계산을 때. 자세히: [routing-appstructure.md](./routing-appstructure.md)
10
- - **공유 마스터 데이터**`SdSharedDataProvider` 고객사·품목 마스터를 한 번 등록해 화면에서 공유 시그널로 쓰고, 선택 컨트롤로 관리·선택 모달을 띄울 때. 자세히: [shared-data.md](./shared-data.md)
11
- - **시트(sd-sheet)** — 컬럼·셀 템플릿·정렬·페이징·선택·트리·요약 행을 가진 데이터 그리드를 그릴 때. 자세히: [sheet.md](./sheet.md)
12
- - **CRUD 화면 골격**목록(`sd-crud-list`)·단건(`sd-crud-detail`)·공통 컨테이너(`sd-base-container`) 표준 화면 골격을 채택할 때. 자세히: [crud.md](./crud.md)
13
- - **폼·입력 컨트롤** 버튼·텍스트필드·체크박스·셀렉트·드롭다운·폼·페이지네이션 입력 컨트롤을 때. 자세히: [controls.md](./controls.md)
14
- - **레이아웃(사이드바·탑바)** 셸의 사이드바/탑바/메뉴/유저 메뉴를 배치할 때. 자세히: [layout.md](./layout.md)
15
- - **호스트 디렉티브·signal 헬퍼·선택 매니저** 리사이즈/교차/리플/등장효과/유효성 디렉티브, 명령 단축키, 옵션 이벤트 플러그인, 템플릿 타입 가드, 선택/정렬/펼침 매니저를 쓸 때. 자세히: [directives.md](./directives.md)
16
- - **부가 기능(칸반·권한표·상태프리셋·테마·주소·에디터·시각화)** 칸반 보드, 권한 트리 표, 상태 프리셋, 테마 토글, 주소 검색 모달, Tiptap 에디터, 라벨/노트/진행바/달력/바코드/ECharts 를 쓸 때. 자세히: [features.md](./features.md)
7
+ - **provideSdAngular / SdAngularConfigProvider** 부트스트랩 시 1회 등록(테마·에러핸들러·zoneless·SW 업데이트·라우팅 busy 연동). 아래 "부트스트랩" 인라인 섹션.
8
+ - **SdThemeProvider / setupBgTheme** 다크모드·폰트크기 전역 테마 제어, 배경 테마 지정. 아래 "테마·배경" 인라인 섹션. 셀렉터 UI 는 `자세히: [features.md](./features.md)`.
9
+ - **SdSystemLogProvider / SdLocalStorageProvider / SdSystemConfigProvider / injectSdSystemConfigResource** 시스템 로그 적재 훅, 클라이언트별 localStorage, key 기반 영속 설정(시트/프리셋/모달 위치 저장). 아래 "설정·로그·인프라" 인라인 섹션.
10
+ - **SdServiceClientFactoryProvider / SdFileDialogProvider**서버 서비스 클라이언트 연결, 파일 선택 대화상자. 아래 "설정·로그·인프라" 인라인 섹션.
11
+ - **모달·토스트·busy·인쇄(Provider + 컴포넌트 + Def 타입)** — 프로그래밍 방식 오버레이를 띄울 때. `자세히: [overlay.md](./overlay.md)`.
12
+ - **버튼·폼 입력·선택·체크박스·드롭다운·탭·리스트·페이징·gap 컨트롤** — 화면 폼/조작 UI 작성. `자세히: [controls.md](./controls.md)`.
13
+ - **SdSheet 시트 컬럼/설정** 데이터 그리드(정렬·페이징·트리·고정·선택·인라인편집·설정저장). `자세히: [sheet.md](./sheet.md)`.
14
+ - **SdBaseContainer / SdCrudList / SdCrudDetail** 목록·단건 화면 표준 골격. `자세히: [crud.md](./crud.md)`.
15
+ - **SdSharedDataProvider / sd-shared-data-select\***공유 마스터 데이터 정의·선택 컨트롤. `자세히: [shared-data.md](./shared-data.md)`.
16
+ - **sidebar·topbar 레이아웃 + 메뉴/사용자** 레이아웃. `자세히: [layout.md](./layout.md)`.
17
+ - **라우팅 헬퍼 + SdAppStructureProvider/Utils** — 페이지 코드/제목/뷰타입/권한 시그널, 메뉴·권한 트리 구성. `자세히: [routing-appstructure.md](./routing-appstructure.md)`.
18
+ - **core 디렉티브·signal 헬퍼** — resize/intersection/ripple/show-effect/invalid/명령단축키/template/모델훅 등. `자세히: [directives.md](./directives.md)`.
19
+ - **useSelectionManager / useSortingManager / useExpandingManager** — 시트류 컴포넌트의 선택·정렬·확장 로직 합성 헬퍼(컴포넌트 작성용). 아래 "선택·정렬·확장 매니저" 인라인 섹션.
20
+ - **SdPermissionTable / SdStatePreset** — 권한 트리 편집표, 화면 상태 프리셋 저장 컨트롤. `자세히: [features.md](./features.md)`.
21
+ - **테마 셀렉터·주소검색·tiptap 에디터·label·note·progress·calendar·barcode·echarts** — 부가 기능 컴포넌트. `자세히: [features.md](./features.md)`.
22
+ - **kanban 보드** — 드래그 가능 칸반. `자세히: [kanban.md](./kanban.md)`.
23
+
24
+ ## 부트스트랩
25
+
26
+ ### provideSdAngular
17
27
 
18
- ## 공통 인라인 (소형 심볼)
28
+ ```ts
29
+ provideSdAngular(opt: { clientName: string }): EnvironmentProviders
30
+ ```
19
31
 
20
- ### FormatPipe
32
+ - `opt.clientName` — 클라이언트 식별자. `SdAngularConfigProvider.clientName` 으로 보관되며 localStorage 키 접두사·서비스 클라이언트 이름으로 쓰임. 앱마다 고유 문자열.
21
33
 
22
- 문자열·날짜를 표시 포맷으로 변환하는 standalone pipe. name `format`.
34
+ `makeEnvironmentProviders` 다음을 번에 등록: `IMAGE_CONFIG`(이미지 경고 비활성), ng-icons 기본 설정(strokeWidth 1.5, size 1.33em), 테마 dark/fontSize 의 localStorage 복원·저장 effect, 전역 `unhandledrejection`/`error` 리스너→`ErrorHandler`, `SdAngularConfigProvider`(clientName 주입), `SdOptionEventPlugin`(이벤트 수식어 지원), `ErrorHandler=SdGlobalErrorHandlerPlugin`, `provideZonelessChangeDetection()`, `SwUpdate` 주기 점검(5분 시작 → 실패 시 지수 백오프 최대 60분, 업데이트 발견 시 confirm 후 reload), 라우팅 네비게이션을 `SdBusyProvider.globalBusyCount` 와 연동. 앱 `ApplicationConfig.providers` 에 1회 추가.
23
35
 
24
- - `transform(value: string | DateTime | DateOnly | undefined, format: string): string` — `value` 가 null 이면 `""`. `DateTime`/`DateOnly` 면 `value.toFormatString(format)`. 문자열이면 `format` 을 `|` 로 분리해 `X` 개수가 문자열 길이와 같은 패턴을 골라 `X` 자리에 글자를 끼워 넣음(전화번호·사업자번호 등 자릿수 마스킹). 매칭 패턴 없으면 원문 반환.
36
+ ```ts
37
+ export const appConfig: ApplicationConfig = {
38
+ providers: [provideRouter(routes), provideSdAngular({ clientName: "my-app" })],
39
+ };
40
+ ```
25
41
 
26
- ```html
27
- {{ phone | format: "XXX-XXXX-XXXX|XX-XXXX-XXXX" }}
28
- {{ regDate | format: "yyyy-MM-dd" }}
42
+ ### SdAngularConfigProvider
43
+
44
+ ```ts
45
+ @Injectable({ providedIn: "root" }) class SdAngularConfigProvider { clientName: string }
29
46
  ```
30
47
 
31
- ### mark
48
+ - `clientName` — `provideSdAngular` 가 채우는 클라이언트 이름. 직접 set 하지 말고 `provideSdAngular` 로 주입. localStorage/서비스 클라이언트가 참조.
32
49
 
33
- 시그널 값을 in-place 변경한 뒤 소비자에게 변경 알림만 발행.
50
+ ## 테마·배경
34
51
 
35
- - `mark(sig: WritableSignal<any>): void` — `sig` 가 배열이면 `[...v]`, 객체면 `{...v}` 로 shallow copy 해 set. 객체·배열 시그널 내부 필드만 바꾼 뒤(`data().name = ...; mark(data)`) 양방향 바인딩의 `(valueChange)` 에 묶어 호출하거나, 값이 같아도 effect 를 강제 재발화시킬 때 사용.
52
+ ### SdThemeProvider
36
53
 
37
- ```html
38
- <sd-textfield [(value)]="data().name" (valueChange)="mark(data)" />
54
+ ```ts
55
+ @Injectable({ providedIn: "root" }) class SdThemeProvider {
56
+ dark: WritableSignal<boolean>;
57
+ fontSizePresets: readonly number[]; // [12,14,16,20,24,28]
58
+ fontSize: WritableSignal<number>; // 기본 12
59
+ increaseFontSize(): void;
60
+ decreaseFontSize(): void;
61
+ }
39
62
  ```
40
63
 
41
- ### setSafeStyle
64
+ - `dark` — true 면 `<body>` 에 `sd-theme-dark` 클래스 토글. `provideSdAngular` 가 localStorage 와 동기화.
65
+ - `fontSize` — html 루트 `font-size(px)` 에 반영(rem 스케일 전체 변동). presets 안에서만 단계 이동 권장.
66
+ - `increaseFontSize`/`decreaseFontSize` — presets 기준 다음/이전 단계로 이동. 경계면 무동작.
42
67
 
43
- `Renderer2` 로 여러 스타일 속성을 한 번에 설정.
44
-
45
- - `setSafeStyle(renderer: Renderer2, el: HTMLElement, style: Partial<CSSStyleDeclaration>): void` — `style` 의 각 키를 `renderer.setStyle` 로 적용. 디렉티브·setup 헬퍼에서 호스트 엘리먼트에 스타일을 줄 때 사용.
68
+ ```ts
69
+ inject(SdThemeProvider).dark.set(true);
70
+ ```
46
71
 
47
72
  ### setupBgTheme
48
73
 
49
- 현재 컴포넌트가 살아있는 동안 `document.body` 배경색 CSS 변수를 테마색으로 설정(파괴 시 해제). injection 컨텍스트(생성자)에서 호출.
74
+ ```ts
75
+ setupBgTheme(options?: {
76
+ theme?: "primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray";
77
+ lightness?: "lightest" | "lighter";
78
+ }): void
79
+ ```
80
+
81
+ - `theme` — 본문 배경에 적용할 테마색. 미지정 시 `--background-color` 해제(기본 배경). 화면 톤을 구분할 때 지정.
82
+ - `lightness` — 배경 명도. `"lightest"`(기본) 가 더 옅음, `"lighter"` 가 약간 진함.
83
+
84
+ 컴포넌트 생성자(주입 컨텍스트)에서 호출. effect 로 `document.body` 의 `--background-color` 를 설정/cleanup.
85
+
86
+ ## 설정·로그·인프라
87
+
88
+ ### SdSystemLogProvider
89
+
90
+ ```ts
91
+ @Injectable({ providedIn: "root" }) class SdSystemLogProvider {
92
+ writeFn?: (severity: "error" | "warn" | "log", ...data: any[]) => Promise<void> | void;
93
+ writeAsync(severity: "error" | "warn" | "log", ...data: any[]): Promise<void>;
94
+ }
95
+ ```
96
+
97
+ - `writeFn` — 외부 적재 훅. 지정하면 `writeAsync` 가 콘솔 로깅 후 이 함수도 호출(예: 서버 DB 적재). 미지정 시 콘솔만.
98
+ - `writeAsync(severity, ...data)` — 콘솔(`logger[severity]`) 출력 후 `writeFn` 호출. `writeFn` 이 throw 해도 로깅으로 흡수. 전역 에러 핸들러가 내부적으로 사용.
99
+
100
+ ### SdLocalStorageProvider
101
+
102
+ ```ts
103
+ @Injectable({ providedIn: "root" }) class SdLocalStorageProvider<T> {
104
+ set<K extends keyof T & string>(key: K, value: T[K]): void;
105
+ get<K extends keyof T & string>(key: K): T[K] | undefined;
106
+ remove(key: keyof T & string): void;
107
+ }
108
+ ```
109
+
110
+ - 키는 `<clientName>.<key>` 로 prefix 되어 JSON 직렬화 저장. `get` 은 파싱 실패 시 undefined(결측 보존).
111
+ - 제네릭 `T` 로 키별 값 타입을 지정해 타입 안전하게 사용.
112
+
113
+ ### SdSystemConfigProvider
50
114
 
51
- - `options.theme: "primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray"` — 배경 테마 계열. 미지정 시 배경색 변수를 빈 값으로 둠(기본 배경 유지).
52
- - `options.lightness: "lightest"|"lighter"` 테마색 밝기. 미지정 시 `"lightest"`. 페이지 전체 배경을 옅게 깔 때 사용.
115
+ ```ts
116
+ @Injectable({ providedIn: "root" }) class SdSystemConfigProvider<T> {
117
+ fn?: { set(key, data): Promise<void> | void; get(key): PromiseLike<unknown> };
118
+ setAsync<K extends keyof T & string>(key: K, data: T[K] | undefined): Promise<void>;
119
+ getAsync(key: keyof T & string): Promise<unknown>;
120
+ }
121
+ ```
122
+
123
+ - `fn` — 외부(서버) 저장 백엔드. 지정하면 set/get 을 서버로 위임, 미지정 시 `SdLocalStorageProvider` 사용. set 데이터가 null 이면 localStorage 경로에서 remove.
124
+ - 시트/상태프리셋/모달 위치 등 영속 UI 설정 저장의 백엔드. 보통 `injectSdSystemConfigResource` 를 통해 사용.
125
+
126
+ ### injectSdSystemConfigResource
127
+
128
+ ```ts
129
+ injectSdSystemConfigResource<T>(options: { key: Signal<string | undefined> }): {
130
+ value: Signal<T | undefined>; isLoading: Signal<boolean>; status; hasValue(): boolean;
131
+ reload(): void; set(value: T | undefined): void; update(fn: (prev: T | undefined) => T | undefined): void;
132
+ }
133
+ ```
134
+
135
+ - `options.key` — 설정 키 시그널. key 가 null 이면 로드/저장 안 함. 저장 키는 `<호스트엘리먼트태그>.<key>` 로 구성(컴포넌트 종류별 분리).
136
+ - `value`/`isLoading`/`status` — Angular `resource` 위임. `set`/`update` 는 즉시 value 갱신 후 microtask 로 `SdSystemConfigProvider.setAsync` 영속화(에러는 `ErrorHandler`).
137
+ - 주입 컨텍스트에서 호출(`ElementRef`/`SdSystemConfigProvider`/`ErrorHandler` inject). 시트·상태프리셋이 내부 사용.
138
+
139
+ ### SdServiceClientFactoryProvider
140
+
141
+ ```ts
142
+ @Injectable({ providedIn: "root" }) class SdServiceClientFactoryProvider {
143
+ connectAsync(key: string, options?: Partial<ServiceConnectionOptions>): Promise<void>;
144
+ closeAsync(key: string): Promise<void>;
145
+ get(key: string): ServiceClient;
146
+ }
147
+ ```
148
+
149
+ - `connectAsync(key, options)` — `key` 별 `ServiceClient` 생성·연결. options 미지정 시 현재 location(host/port/ssl)으로 접속. 이미 연결·이미 종료된 key 면 throw. 요청/응답 진행률을 progress 토스트로 표시.
150
+ - `closeAsync(key)` — 연결 종료 후 해당 key 를 종료 상태로 표시(이후 재연결 불가). 미연결 key 면 throw.
151
+ - `get(key)` — 연결된 클라이언트 반환. 미연결·종료 key 면 throw(silent 반환 안 함). 앱 서비스/이벤트 호출의 기반(공유데이터·서버 함수 provider 가 내부 사용).
152
+
153
+ ### SdFileDialogProvider
53
154
 
54
155
  ```ts
55
- constructor() { setupBgTheme({ theme: "gray", lightness: "lightest" }); }
156
+ @Injectable({ providedIn: "root" }) class SdFileDialogProvider {
157
+ showAsync(multiple?: false, accept?: string): Promise<File | undefined>;
158
+ showAsync(multiple: true, accept?: string): Promise<File[] | undefined>;
159
+ }
56
160
  ```
57
161
 
58
- ### setupModelHook
162
+ - `multiple` — true 면 다중 선택(`File[]`), 미지정/false 면 단건(`File`). 타입이 오버로드로 분기.
163
+ - `accept` — 파일 형식 필터(예: `".xlsx"`, `"image/*"`). 취소·미선택 시 undefined.
59
164
 
60
- `WritableSignal` 의 `set`/`update` 를 가로채 변경 허용 여부를 콜백으로 검사(비동기 허용). injection 컨텍스트에서 호출.
165
+ ```ts
166
+ const file = await inject(SdFileDialogProvider).showAsync(false, ".xlsx");
167
+ ```
61
168
 
62
- - `model: WritableSignal<T>` — 가드를 걸 대상 모델 시그널.
63
- - `canFn: Signal<(item: T) => boolean | Promise<boolean>>` — 새 값을 받기 전 호출. `false` 면 반영 차단, `true` 면 즉시 반영, `Promise` 면 resolve 가 `false` 가 아닐 때만 반영(reject 는 `ErrorHandler` 로). 체크박스·스위치의 변경 확인 후에만 모델을 바꿔야 할 때.
169
+ ## 선택·정렬·확장 매니저
64
170
 
65
- ### SelectModalOutputResult
171
+ 컴포넌트 작성 시 시트류 동작을 합성하는 헬퍼. 주입 컨텍스트가 아닌 일반 함수로, signal 바인딩을 받아 파생 시그널·조작 함수를 반환. `SdSheet` 내부도 이를 사용.
66
172
 
67
- 선택 모달이 close 페이로드로 돌려주는 결과 타입.
173
+ ### useSelectionManager
68
174
 
69
- - `selectedKeys: TKey[]` — 모달에서 선택된 키 배열. 단건 선택도 배열로 반환(첫 키만 사용). `sd-modal-select-button`·`sd-shared-data-select` 가 이 페이로드로 선택을 갱신.
175
+ ```ts
176
+ useSelectionManager<TItem, TKey>(options: {
177
+ displayItems: Signal<TItem[]>; selectedKeys: WritableSignal<TKey[]>;
178
+ selectMode: Signal<"single" | "multi" | undefined>;
179
+ getItemSelectableFn: Signal<((item: TItem) => boolean | string) | undefined>;
180
+ trackByFn: Signal<(item: TItem, index: number) => TKey>;
181
+ }): { hasSelectable; isAllSelected; getSelectable(item); getCanChangeFn(item); select(item); deselect(item); toggle(item); toggleAll(); isSelected(item); }
182
+ ```
183
+
184
+ - `selectMode` — `"single"`=단일(선택 시 기존 교체), `"multi"`=다중, undefined=선택 비활성.
185
+ - `getItemSelectableFn` — 행별 선택 가능 여부. `true`=가능, `false`/undefined=불가, `string`=불가+사유(툴팁). `getSelectable` 이 이를 그대로 반환.
186
+ - 키 비교는 참조 동일 또는 `obj.equal` 로 깊은 비교. `toggleAll` 은 선택 가능 항목 기준 전체 토글.
70
187
 
71
- ### 타입 유틸 (directive-input-signals)
188
+ ### useSortingManager
72
189
 
73
- 컴포넌트 input 시그널에서 값 타입을 뽑는 매핑 타입. 모달/토스트/인쇄 `inputs` 의 정적 타입 검증에 쓰임.
190
+ ```ts
191
+ useSortingManager(options: { sorts: WritableSignal<SortingDef[]> }): {
192
+ defMap: Signal<Map<string, { indexText?: string; desc: boolean }>>;
193
+ toggle(key: string, multiple: boolean): void;
194
+ sort<T>(items: T[]): T[];
195
+ }
196
+ // SortingDef = { key: string; desc: boolean }
197
+ ```
198
+
199
+ - `toggle(key, multiple)` — 클릭 정렬 토글. `multiple`=true 면 다중 정렬 누적(asc→desc→제거 순환), false 면 단일 정렬로 교체. 헤더 클릭의 shift 여부를 넘김.
200
+ - `defMap` — 정렬 중인 컬럼의 방향·표시순번(`indexText`, 2개 이상일 때만). `sort` 는 null-우선 정렬로 클라이언트 정렬 수행.
201
+
202
+ ### useExpandingManager
203
+
204
+ ```ts
205
+ useExpandingManager<T>(binding: {
206
+ items: Signal<T[]>; expandedItems: WritableSignal<T[]>;
207
+ getChildrenFn: Signal<((item: T, index: number) => T[] | undefined) | undefined>;
208
+ sort: (items: T[]) => T[];
209
+ }): { displayItems; hasExpandable; isAllExpanded; toggle(item); toggleAll(); isVisible(item); def(item); }
210
+ // ExpandItemDef<T> = { item: T; parentDef: ExpandItemDef<T> | undefined; hasChildren: boolean; depth: number }
211
+ ```
74
212
 
75
- - `DirectiveInputSignals<T>``T` `InputSignal` 프로퍼티만 골라 값 타입으로 변환한 객체 타입. `undefined` 포함 필드는 optional 로.
76
- - `UndefToOptional<T>` — `undefined` 포함하는 프로퍼티를 optional(`?`) 변환.
77
- - `WithOptional<T, K>` — `T` 에서 키 `K` 들만 optional 로 변환.
213
+ - `getChildrenFn`자식 배열 반환 함수(트리). undefined 평면.
214
+ - `displayItems`펼침 상태를 반영해 평탄화된 표시 목록(접힌 노드 하위 제외 여부는 `isVisible` 판단). `def(item)` 항목의 depth/부모/자식유무 메타 반환(없으면 throw).