@simplysm/sd-claude 14.0.88 → 14.0.89

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 (122) hide show
  1. package/claude/references/sd-simplysm14/README.md +17 -17
  2. package/claude/references/sd-simplysm14/apis/angular/README.md +27 -53
  3. package/claude/references/sd-simplysm14/apis/angular/controls.md +37 -105
  4. package/claude/references/sd-simplysm14/apis/angular/crud.md +46 -43
  5. package/claude/references/sd-simplysm14/apis/angular/directives.md +22 -32
  6. package/claude/references/sd-simplysm14/apis/angular/features.md +40 -55
  7. package/claude/references/sd-simplysm14/apis/angular/infra.md +40 -40
  8. package/claude/references/sd-simplysm14/apis/angular/layout.md +25 -53
  9. package/claude/references/sd-simplysm14/apis/angular/overlay.md +70 -82
  10. package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +44 -39
  11. package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +21 -36
  12. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +52 -65
  13. package/claude/references/sd-simplysm14/apis/angular/sheet.md +65 -70
  14. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +33 -35
  15. package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +7 -7
  16. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +29 -29
  17. package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +45 -50
  18. package/claude/references/sd-simplysm14/apis/core-browser/README.md +42 -55
  19. package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +62 -0
  20. package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +13 -12
  21. package/claude/references/sd-simplysm14/apis/core-common/README.md +222 -98
  22. package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +102 -53
  23. package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +128 -0
  24. package/claude/references/sd-simplysm14/apis/core-common/datetime.md +98 -64
  25. package/claude/references/sd-simplysm14/apis/core-common/errors.md +91 -0
  26. package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +34 -28
  27. package/claude/references/sd-simplysm14/apis/core-common/obj.md +104 -40
  28. package/claude/references/sd-simplysm14/apis/core-node/README.md +11 -8
  29. package/claude/references/sd-simplysm14/apis/core-node/consola.md +23 -31
  30. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +33 -22
  31. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +28 -25
  32. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +39 -53
  33. package/claude/references/sd-simplysm14/apis/core-node/pathx.md +26 -29
  34. package/claude/references/sd-simplysm14/apis/core-node/worker.md +27 -29
  35. package/claude/references/sd-simplysm14/apis/excel/README.md +14 -14
  36. package/claude/references/sd-simplysm14/apis/lint/README.md +27 -21
  37. package/claude/references/sd-simplysm14/apis/lint/rules.md +89 -49
  38. package/claude/references/sd-simplysm14/apis/orm-common/README.md +5 -59
  39. package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +98 -67
  40. package/claude/references/sd-simplysm14/apis/orm-common/expr.md +107 -92
  41. package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +99 -65
  42. package/claude/references/sd-simplysm14/apis/orm-common/schema.md +83 -98
  43. package/claude/references/sd-simplysm14/apis/orm-common/types.md +62 -52
  44. package/claude/references/sd-simplysm14/apis/orm-node/README.md +62 -25
  45. package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +27 -27
  46. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +12 -15
  47. package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +92 -45
  48. package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +226 -108
  49. package/claude/references/sd-simplysm14/apis/service-client/README.md +84 -86
  50. package/claude/references/sd-simplysm14/apis/service-client/orm.md +14 -11
  51. package/claude/references/sd-simplysm14/apis/service-client/transport.md +33 -10
  52. package/claude/references/sd-simplysm14/apis/service-common/README.md +37 -23
  53. package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +9 -9
  54. package/claude/references/sd-simplysm14/apis/service-common/protocol.md +13 -13
  55. package/claude/references/sd-simplysm14/apis/service-server/README.md +81 -65
  56. package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +32 -35
  57. package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +44 -33
  58. package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +34 -45
  59. package/claude/references/sd-simplysm14/apis/storage/README.md +24 -18
  60. package/claude/skills/sd-demo/SKILL.md +6 -0
  61. package/claude/skills/sd-impl/SKILL.md +4 -7
  62. package/claude/skills/sd-spec/SKILL.md +31 -858
  63. package/claude/skills/sd-spec/references/spec-authoring.md +519 -0
  64. package/claude/workflows/sd-docs.js +84 -0
  65. package/package.json +1 -1
  66. package/claude/references/sd-simplysm14/apis/orm-common/query-builder.md +0 -29
  67. package/claude/skills/sd-demo/evals/fixtures/inventory-list/.specs/inventory/spec.md +0 -99
  68. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/package.json +0 -12
  69. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/index.ts +0 -3
  70. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inbound/inbound.list.ts +0 -150
  71. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inventory/inventory-master.list.ts +0 -143
  72. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/outbound/outbound.list.ts +0 -150
  73. package/claude/skills/sd-demo/evals/fixtures/inventory-list/pnpm-workspace.yaml +0 -2
  74. package/claude/skills/sd-demo/evals/fixtures/inventory-list/sd.config.ts +0 -12
  75. package/claude/skills/sd-demo/evals/golden.jsonl +0 -1
  76. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/package.json +0 -8
  77. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/src/.gitkeep +0 -0
  78. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tests/.gitkeep +0 -0
  79. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tsconfig.json +0 -10
  80. package/claude/skills/sd-dev/evals/golden.jsonl +0 -1
  81. package/claude/skills/sd-docs/SKILL.md +0 -46
  82. package/claude/skills/sd-docs/evals/fixtures/new-write/.claude/references/sd-simplysm14/README.md +0 -7
  83. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/package.json +0 -5
  84. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/src/index.ts +0 -3
  85. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/package.json +0 -6
  86. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/src/index.ts +0 -1
  87. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/package.json +0 -5
  88. package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/src/index.ts +0 -8
  89. package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/README.md +0 -7
  90. package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/apis/foo/README.md +0 -3
  91. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/package.json +0 -5
  92. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/src/index.ts +0 -3
  93. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/package.json +0 -6
  94. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/src/index.ts +0 -1
  95. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/package.json +0 -5
  96. package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/src/index.ts +0 -8
  97. package/claude/skills/sd-docs/evals/golden.jsonl +0 -2
  98. package/claude/skills/sd-impl/evals/fixtures/case-a-new-screen/.specs/260513120000_warehouse/spec.md +0 -101
  99. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/.specs/260513120000_warehouse/spec.md +0 -101
  100. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/packages/app/src/screens/box-register/box-register.view.ts +0 -46
  101. package/claude/skills/sd-impl/evals/fixtures/case-c-new-cross/.specs/260513120000_warehouse/spec.md +0 -89
  102. package/claude/skills/sd-impl/evals/fixtures/case-d-spec-modify/.specs/260513120000_warehouse/spec.md +0 -101
  103. package/claude/skills/sd-impl/evals/golden.jsonl +0 -4
  104. package/claude/skills/sd-manual/evals/fixtures/new-manual/src/notification.ts +0 -25
  105. package/claude/skills/sd-manual/evals/fixtures/update-manual/.claude/references/sd-simplysm14/manuals/notification.md +0 -14
  106. package/claude/skills/sd-manual/evals/fixtures/update-manual/src/notification.ts +0 -37
  107. package/claude/skills/sd-manual/evals/golden.jsonl +0 -2
  108. package/claude/skills/sd-review/evals/fixtures/code-review/src/foo.ts +0 -7
  109. package/claude/skills/sd-review/evals/fixtures/doc-review/docs/foo.md +0 -4
  110. package/claude/skills/sd-review/evals/golden.jsonl +0 -2
  111. package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +0 -14
  112. package/claude/skills/sd-skill/evals/fixtures/new-skill/.gitkeep +0 -0
  113. package/claude/skills/sd-skill/evals/golden.jsonl +0 -2
  114. package/claude/skills/sd-spec/evals/fixtures/case-a-split//355/232/214/354/235/230/353/241/235.md +0 -20
  115. package/claude/skills/sd-spec/evals/fixtures/case-b-detail/.specs/260513120000_warehouse/spec.md +0 -95
  116. package/claude/skills/sd-spec/evals/golden.jsonl +0 -2
  117. package/claude/skills/sd-unpack/evals/fixtures/eml-with-text-attachment/meeting.eml +0 -21
  118. package/claude/skills/sd-unpack/evals/fixtures/simple-eml/meeting.eml +0 -10
  119. package/claude/skills/sd-unpack/evals/golden.jsonl +0 -2
  120. package/claude/skills/sd-use/evals/fixtures/empty/.gitkeep +0 -0
  121. package/claude/skills/sd-use/evals/golden.jsonl +0 -6
  122. /package/claude/{skills/sd-docs/references/doc-rules.md → workflows/sd-docs.rules.md} +0 -0
@@ -1,64 +1,69 @@
1
1
  # @simplysm/angular — 라우팅 / 앱 구조(메뉴·권한)
2
2
 
3
- 해시 기반 SPA 내비게이션, 현재 페이지 코드·뷰타입·제목 신호, 구조(AppStructureItem 트리)→메뉴/권한 변환, 권한 테이블 UI. 메뉴 컴포넌트(layout 군)·CRUD 컨테이너(crud 군)가 신호·타입을 소비.
3
+ 현재 페이지 식별·뷰 제목/타입 판정, 라우터 링크,메뉴/권한 트리 구성을 다룰 함께 읽힘. 구조 데이터 원본은 `@simplysm/service-common` `AppStructureItem`.
4
4
 
5
- ## SdNavigateWindowProvider
5
+ ## injectFullPageCodeSignal
6
6
 
7
- `class SdNavigateWindowProvider`해시 라우트를 창/탭으로 여는 루트 프로바이더.
7
+ `injectFullPageCodeSignal(): Signal<string>`현재 라우터 URL 에서 2 세그먼트(`/home` 등)를 제외한 나머지를 `.` 으로 이은 페이지 코드. 네비게이션 종료마다 갱신. 메뉴 선택 표시·뷰 제목 조회에 사용.
8
8
 
9
- - `isWindow: boolean` — 현재가 별도 창 모드인지(해시 쿼리 `window=true`).
10
- - `open(navigate, params?, features?)` — 라우트 열기. 창 모드이거나 `features` 있으면 `window.open` 으로 새 창(부모 unload 시 자동 닫힘), 아니면 새 탭(`_blank`).
9
+ ## injectCurrentPageCodeSignal
11
10
 
12
- ## SdRouterLink
11
+ `injectCurrentPageCodeSignal(): Signal<string> | undefined` — 현재 `ActivatedRoute` 의 pathFromRoot 기준 코드(중첩 outlet/모달 안에서 자기 자신 경로). ActivatedRoute 없으면 undefined. fullPageCode 와 비교해 page/control 판정에 사용.
13
12
 
14
- `[sdRouterLink]` 디렉티브 — 클릭 시 라우팅. Ctrl/Shift 클릭은 새 창, 창 모드는 팝업으로 분기.
13
+ ## injectViewTitleSignal
15
14
 
16
- - `option = input<{ link; params?; window?: { width?; height? }; outletName?; queryParams? } | undefined>()`(alias `sdRouterLink`) 이동 정보. `link`(경로), `params`(matrix 파라미터), `queryParams`, `outletName`(보조 outlet), `window`(팝업 크기). `undefined` 면 비활성.
15
+ `injectViewTitleSignal(): Signal<string>` 모달 안이면 모달 제목, 아니면 구조에서 현재 페이지 코드로 찾은 제목(`[상위 > 상위] 현재`). 찾으면 `""`. 화면 컨테이너 제목 표시에 사용.
17
16
 
18
- ## 페이지 코드·타이틀·뷰타입 신호
17
+ ## injectViewTypeSignal
19
18
 
20
- 컴포넌트 생성자/필드에서 호출하는 inject 함수. 라우터·활성모달 컨텍스트에서 값 도출.
19
+ `injectViewTypeSignal(): Signal<SdViewType>` — 현재 컴포넌트가 어떤 맥락으로 떠 있는지 판정. `SdViewType = "page"|"modal"|"control"`. 모달 안이면 "page"가 아닌 "modal", 라우트의 페이지 컴포넌트로 직접 떠 있고 fullPageCode===currPageCode 면 "page", 그 외 "control"(다른 화면에 박힌 재사용 컴포넌트). CRUD 컨테이너의 `viewType` input 그대로 전달.
21
20
 
22
- - `injectFullPageCodeSignal(): Signal<string>` — 전체 라우트 경로를 `.` 연결 페이지 코드로 변환(예: `sale.order`). 메뉴 선택표시·제목 조회 기준.
23
- - `injectCurrentPageCodeSignal(): Signal<string> | undefined` — 현재 활성 라우트 세그먼트 기준 코드(중첩 라우트용). 라우트 없으면 `undefined`.
24
- - `injectViewTitleSignal(): Signal<string>` — 화면 제목. 활성 모달이면 모달 제목, 아니면 앱 구조에서 코드로 제목 조회.
25
- - `injectViewTypeSignal(): Signal<SdViewType>` — `"page"|"modal"|"control"`. 모달 컨텍스트면 modal, 라우트 페이지 컴포넌트면 page, 그 외 control. `SdViewType` 타입 동봉.
26
- - `setupCanDeactivate(fn: () => boolean): void` — 이탈 차단 등록. 모달이면 `canDeactivateFn`, 라우트면 route 의 `canDeactivate` 가드에 추가(파괴 시 해제). `fn()` 이 false 면 닫기/이탈 차단.
21
+ ## setupCanDeactivate
27
22
 
28
- ## 메뉴 유틸
23
+ `setupCanDeactivate(fn: () => boolean): void` — 컴포넌트 내 호출. 모달 안이면 `SdActivatedModalProvider.canDeactivateFn` 에, 라우트면 해당 route 의 `canDeactivate` 가드에 fn 을 등록(컴포넌트 파괴 시 해제). fn 이 false 면 이탈/닫기 차단. 미저장 변경 보호에 사용.
29
24
 
30
- `SdMenu` 를 라우터링크/선택판정으로 변환(layout 메뉴 컴포넌트가 사용).
25
+ ```ts
26
+ setupCanDeactivate(() => !this.dirty() || confirm("저장하지 않고 나갈까요?"));
27
+ ```
31
28
 
32
- - `getMenuRouterLinkOption(menu: SdMenu): { link; queryParams } | undefined` — 리프 메뉴면 `/home/{codeChain}` 링크 + 쿼리파라미터, 그룹/외부url 메뉴면 `undefined`.
33
- - `getIsMenuSelected(menu, fullPageCode, customFn?): boolean` — 선택 여부. `customFn` 있으면 그 결과, 없으면 `fullPageCode === codeChain.join(".")`.
29
+ ## SdRouterLink
34
30
 
35
- ## SdAppStructureProvider
31
+ `[sdRouterLink]="option"` 디렉티브. 클릭 시 option 으로 라우터 이동(또는 새 창).
32
+ - option: `{ link: string; params?; window?: {width?;height?}; outletName?: string; queryParams? } | undefined` — undefined 면 동작 없음(커서도 기본). 현재가 window 모드거나 Ctrl/Shift+클릭이면 새 창으로, outletName 있으면 named outlet 으로 이동. Alt+클릭은 무시.
36
33
 
37
- `class SdAppStructureProvider<TModule>` — 앱 구조(메뉴·권한) 트리 보관·계산 루트 프로바이더.
34
+ ## SdNavigateWindowProvider
38
35
 
39
- - `usableModules: WritableSignal<TModule[] | undefined>` — 활성 모듈 목록(메뉴/권한 필터링 기준).
40
- - `permRecord: WritableSignal<Record<string, boolean> | undefined>` 권한 레코드(`{코드.use: bool}`).
41
- - `items: WritableSignal<AppStructureItem<TModule>[]>`원본 구조. `initialize(items)` 로 설정.
42
- - `usableMenus: Signal<SdMenu[]>` — 모듈·권한 적용된 메뉴 트리.
43
- - `usableFlatMenus: Signal<SdFlatMenu<TModule>[]>` — 평탄화 메뉴 목록.
44
- - `getPermissionsByStructure(items, codeChain?)` / `getTitleByFullCode(fullCode)`(없으면 throw) / `findTitleByFullCode(fullCode)`(없으면 undefined, 결측 보존) / `getItemChainByFullCode(fullCode)` / `getPermsByFullCode(fullCodes, permKeys)`.
36
+ `@Injectable({providedIn:"root"})`. 창/팝업 네비게이션.
37
+ - isWindow: boolean 현재 URL 해시에 `window=true` 가 있는지(팝업으로 열린 창인지).
38
+ - open(navigate: string, params?, features?): void window 모드거나 features 지정 시 `window.open` 팝업(닫힐 때 부모와 함께 정리), 아니면 `_blank` 탭.
45
39
 
46
- `injectPermsSignal<K>(viewCodes: string[], keys: K[]): Signal<K[]>` — 특정 화면코드들의 권한 중 보유 키만 반환하는 computed.
40
+ ## getMenuRouterLinkOption / getIsMenuSelected
47
41
 
48
- ## SdAppStructureUtils
42
+ - `getMenuRouterLinkOption(menu: SdMenu): { link; queryParams } | undefined` — leaf 메뉴(children/url 없음)면 `/home/<코드체인>` 링크 + 쿼리파라미터 옵션, 그 외 undefined. `SdRouterLink` 에 바로 전달.
43
+ - `getIsMenuSelected(menu, fullPageCode, customFn?): boolean` — customFn 있으면 그 결과, 없으면 `fullPageCode === menu.codeChain.join(".")`. 메뉴 선택 강조에 사용.
49
44
 
50
- `abstract class SdAppStructureUtils` — 앱 구조 변환 정적 유틸(프로바이더가 위임). `getMenus`/`getFlatMenus`/`getPermissions`/`getFlatPermissions`/`getTitleByFullCode`/`findTitleByFullCode`/`getItemChainByFullCode`/`getPermsByFullCode` 정적 메서드 제공. 모듈 활성/권한 use 여부로 필터링.
45
+ ## SdAppStructureProvider<TModule>
51
46
 
52
- ## 타입
47
+ `@Injectable({providedIn:"root"})`. 앱 메뉴·권한 트리의 단일 소스.
48
+ - usableModules: Signal<TModule[]|undefined> — 활성 모듈 목록. 메뉴/권한 필터에 사용(미설정 시 전체 허용 취급).
49
+ - permRecord: Signal<Record<string,boolean>|undefined> — `<코드>.<권한키>` → 허용 여부 맵.
50
+ - items: Signal<AppStructureItem<TModule>[]> — 구조 원본.
51
+ - initialize(items) — 구조 주입.
52
+ - usableMenus: Signal<SdMenu[]> — 모듈·권한 통과한 메뉴 트리(사이드바/탑바용).
53
+ - usableFlatMenus: Signal<SdFlatMenu<TModule>[]> — 평탄화된 메뉴 목록.
54
+ - getPermissionsByStructure(items, codeChain?) — 권한 편집표용 `SdPermission` 트리 생성.
55
+ - getTitleByFullCode(fullCode) / findTitleByFullCode(fullCode) — 전자는 못 찾으면 throw, 후자는 undefined(결측 보존).
56
+ - getItemChainByFullCode(fullCode) — 코드 체인에 해당하는 항목 배열(없으면 빈 배열).
57
+ - getPermsByFullCode(fullCodes, permKeys) — 해당 코드들에서 보유한 권한 키 목록.
58
+
59
+ `injectPermsSignal<K>(viewCodes: string[], keys: K[]): Signal<K[]>` — 현재 보유 권한 키를 computed signal 로. 화면에서 편집/사용 권한 분기에 사용.
53
60
 
54
- - `SdMenu` — 메뉴 노드. `title`/`codeChain: string[]`/`url?`/`icon?`/`children?`.
55
- - `SdFlatMenu<TModule>` — 평탄 메뉴. `titleChain`/`codeChain`/`modulesChain`.
56
- - `SdPermission<TModule>` — 권한 노드. `title`/`codeChain`/`modules`/`perms: ("use"|"edit")[] | undefined`/`children`.
61
+ ## SdAppStructureUtils
57
62
 
58
- ## SdPermissionTable
63
+ `abstract class`. `SdAppStructureProvider` 가 내부 사용하는 정적 유틸 모음(직접 호출 가능): `getMenus`/`getFlatMenus`/`getPermissions`/`getFlatPermissions`/`getTitleByFullCode`/`findTitleByFullCode`/`getItemChainByFullCode`/`getPermsByFullCode`. 시그니처는 provider 메서드와 대응(추가로 items/usableModules/permRecord 를 인자로 받음).
59
64
 
60
- `<sd-permission-table>` — 권한 트리 체크박스 표(use/edit 토글, 상하위 연동). 제네릭 `<TModule>`.
65
+ ## 타입
61
66
 
62
- - `value = model<Record<string, boolean>>({})` 권한 체크 상태(`{코드.use|edit: bool}`). use 해제 edit 자동 해제, edit use 체크 후에만.
63
- - `items = input<SdPermission<TModule>[]>([])` 권한 트리(`getPermissionsByStructure` 결과).
64
- - `disabled = input(false)` 전체 비활성.
67
+ - **SdMenu** — `{ title; codeChain: string[]; url?; icon?; children?: SdMenu[] }`. 메뉴 트리 노드.
68
+ - **SdFlatMenu<TModule>** — `{ titleChain: string[]; codeChain: string[]; modulesChain: TModule[][] }`. 평탄 메뉴.
69
+ - **SdPermission<TModule>** — `{ title; codeChain; modules; perms: ("use"|"edit")[]|undefined; children }`. 권한 트리 노드(권한표 입력).
@@ -1,43 +1,28 @@
1
- # @simplysm/angular — 선택·정렬·확장 매니저
1
+ # @simplysm/angular — 선택·정렬·확장 매니저(use* 컴포저블)
2
2
 
3
- 리스트/시트류 컴포넌트 내부에서 signal 바인딩으로 선택·다중정렬·트리확장 상태를 다루는 컴포저블 함수. 컴포넌트 클래스 필드 초기화 시 호출하며, signal 입력(items/selectedKeys/sorts 등)메서드 묶음을 반환. `sd-sheet` 가 모두 사용.
3
+ 커스텀 리스트/그리드 컴포넌트에 선택·정렬·트리 확장 로직을 붙이는 함수형 컴포저블. signal 바인딩을 넘기면 파생 signal 과 조작 메서드를 돌려줌. `sd-sheet` 가 내부적으로 이들을 조합함.
4
4
 
5
- ## useSelectionManager
5
+ ## useSelectionManager<TItem, TKey>
6
6
 
7
- `useSelectionManager<TItem, TKey>(options): { ... }` — 단일/다중 선택 상태 관리.
7
+ 다중/단일 선택 상태 관리.
8
+ - options: `{ displayItems: Signal<TItem[]>; selectedKeys: WritableSignal<TKey[]>; selectMode: Signal<"single"|"multi"|undefined>; getItemSelectableFn: Signal<((item) => boolean|string)|undefined>; trackByFn: Signal<(item,index) => TKey> }` — selectMode 미지정이면 선택 비활성, getItemSelectableFn 이 string 반환 시 그 사유로 불가, trackByFn 으로 키 비교(`obj.equal` 깊은 비교).
9
+ - 반환: `hasSelectable`/`isAllSelected`(Signal), `getSelectable(item): true|string|undefined`, `getCanChangeFn(item)`, `select`/`deselect`/`toggle`/`toggleAll`/`isSelected`. single 은 1개로 교체, multi 는 누적.
8
10
 
9
- options(모두 Signal/WritableSignal):
10
- - `displayItems: Signal<TItem[]>` — 현재 표시 항목.
11
- - `selectedKeys: WritableSignal<TKey[]>` — 선택 키 배열(양방향).
12
- - `selectMode: Signal<"single"|"multi"|undefined>` — 선택 모드. `undefined` 면 선택 비활성.
13
- - `getItemSelectableFn: Signal<((item) => boolean | string) | undefined>` — 선택 가능 판정. `string` 이면 비활성 + 사유.
14
- - `trackByFn: Signal<(item, index) => TKey>` — 키 추출.
11
+ ## useSortingManager
15
12
 
16
- 반환: `hasSelectable`/`isAllSelected: Signal<boolean>`, `getSelectable(item): true | string | undefined`, `getCanChangeFn(item): () => boolean`, `select`/`deselect`/`toggle`/`toggleAll`/`isSelected(item)`. single 모드 select 는 단일 키로 교체, multi 는 추가/제거.
13
+ 헤더 클릭 정렬 상태 + 정렬 실행.
14
+ - options: `{ sorts: WritableSignal<SortingDef[]> }`.
15
+ - 반환: `defMap: Signal<Map<key, { indexText?; desc }>>`(다중 정렬 시 순번 표시), `toggle(key, multiple)`(단일/다중 토글: 없음→오름차순→내림차순→해제 순환), `sort<T>(items): T[]`(null 은 앞, 문자열 localeCompare, 숫자 차이 기준).
16
+ - **SortingDef** — `{ key: string; desc: boolean }`. 정렬 1건.
17
17
 
18
- ## useSortingManager
18
+ ## useExpandingManager<T>
19
+
20
+ 트리 펼침 상태 + 가시 항목 평탄화.
21
+ - binding: `{ items: Signal<T[]>; expandedItems: WritableSignal<T[]>; getChildrenFn: Signal<((item,index) => T[]|undefined)|undefined>; sort: (items) => T[] }` — getChildrenFn 으로 자식 조회, sort 로 각 레벨 정렬.
22
+ - 반환: `displayItems`/`hasExpandable`/`isAllExpanded`(Signal), `toggle(item)`/`toggleAll()`, `isVisible(item)`(조상이 모두 펼쳐졌는지), `def(item): ExpandItemDef<T>`(못 찾으면 throw).
23
+ - **ExpandItemDef<T>** — `{ item; parentDef: ExpandItemDef<T>|undefined; hasChildren; depth }`. 항목의 트리 위치 정의.
19
24
 
20
- `useSortingManager(options: { sorts: WritableSignal<SortingDef[]> }): { ... }` — 다중 정렬 토글·적용.
21
-
22
- - `options.sorts` 정렬 정의 배열(양방향). `SortingDef = { key: string; desc: boolean }`.
23
- - 반환:
24
- - `defMap: Signal<Map<key, { indexText?; desc }>>` — 컬럼별 정렬 상태(다중 시 순번 indexText).
25
- - `toggle(key, multiple)` — 정렬 토글. `multiple=true`(Shift) 면 누적, 동일 키 재클릭 시 asc→desc→해제 순환.
26
- - `sort<T>(items): T[]` — 현재 정렬 정의로 배열 정렬(null 은 먼저, 문자열은 localeCompare).
27
-
28
- ## useExpandingManager
29
-
30
- `useExpandingManager<T>(binding): { ... }` — 트리 펼침/접힘 상태 관리.
31
-
32
- binding:
33
- - `items: Signal<T[]>` — 루트 항목.
34
- - `expandedItems: WritableSignal<T[]>` — 펼친 항목(양방향).
35
- - `getChildrenFn: Signal<((item, index) => T[] | undefined) | undefined>` — 자식 추출.
36
- - `sort: (items) => T[]` — 각 레벨 정렬 함수.
37
- - 반환:
38
- - `displayItems: Signal<T[]>` — 펼침 반영된 평탄 표시 목록.
39
- - `hasExpandable`/`isAllExpanded: Signal<boolean>`.
40
- - `toggle(item)`/`toggleAll()` — 펼침 토글.
41
- - `isVisible(item): boolean` — 모든 조상이 펼쳐졌는지.
42
- - `def(item): ExpandItemDef<T>` — 항목 메타(없으면 throw).
43
- - `ExpandItemDef<T>` — `{ item; parentDef?; hasChildren; depth }`.
25
+ ```ts
26
+ const sorting = useSortingManager({ sorts });
27
+ const selection = useSelectionManager({ displayItems, selectedKeys, selectMode, getItemSelectableFn, trackByFn });
28
+ ```
@@ -1,70 +1,57 @@
1
1
  # @simplysm/angular — 공유 데이터(shared-data)
2
2
 
3
- 서버 마스터데이터(코드·분류 등)를 클라이언트에 캐시하고 서버 변경 이벤트로 동기화하며, 선택 UI 로 노출. `SdSharedDataProvider` 상속해 데이터셋을 등록하고, 선택 컨트롤(select/select-button/select-list)이 그 핸들의 items 를 소비.
4
-
5
- ## SdSharedDataProvider
6
-
7
- `abstract class SdSharedDataProvider<T extends Record<string, SharedDataBase<...>>>` 공유 데이터 등록·로드·동기화 추상 프로바이더. 앱별로 상속해 `initialize()` 에서 `register` 호출.
8
-
9
- - `loadingCount: WritableSignal<number>` 로딩 데이터 수.
10
- - `abstract initialize(): void` — 앱이 구현. 보통 여러 `register` 호출.
11
- - `register<K>(name, info: SharedDataInfo<T[K]>)` — 데이터셋 등록(재호출 시 갱신·리스너 재설정).
12
- - `getHandle<K>(name): SharedDataHandle<T[K]>` — 핸들 반환. 최초 접근 시 lazy 로드·이벤트 리스너 등록. 미등록이면 throw.
13
- - `emitAsync<K>(name, changeKeys?)` 변경 이벤트 발행. `changeKeys` 없으면 전체 리로드 신호, 있으면 해당 키만 부분 갱신.
14
- - `wait(): Promise<void>``loadingCount<=0` 까지 대기(CRUD 기반 컨테이너가 초기 로드 동기화에 사용).
15
-
16
- 타입:
17
- - `SharedDataBase<TKey>`공유 항목 기본형. `__valueKey`(고유키), `__searchText`(검색대상), `__isHidden`(숨김), `__parentKey?`(트리 부모키).
18
- - `SharedDataInfo<T>` — 등록 정보. `serviceKey`(서비스 클라이언트 키), `getter: (changeKeys?) => Promise<T[]>`(전체/부분 로더), `filter?`(이벤트 필터), `orderBy?`(부분 갱신 정렬 키).
19
- - `SharedDataHandle<T>``{ items: Signal<T[]>; get(key) => T | undefined }`.
20
- - `SdSharedDataChangeEvent` — 변경 동기화에 쓰는 `defineEvent` 정의(서버↔클라이언트).
21
-
22
- ## SdSharedDataSelect
23
-
24
- `<sd-shared-data-select>` — 공유데이터 드롭다운 선택(검색·트리·모달 연계). 제네릭 `<TItem, TMode, TModal>`.
25
-
26
- - `value = model<...>()`선택 키(single=단일, multi=배열). 타입은 `TItem["__valueKey"] | undefined`.
27
- - `items = input.required<TItem[]>()`공유 항목 배열(핸들의 items).
28
- - `selectMode: TMode("single"|"multi")` — 선택 모드. 기본 `"single"`.
29
- - `disabled`/`required`/`inset`/`inline`/`size` — 공통.
30
- - `useUndefined` — multi 에서도 "미지정" 항목 노출.
31
- - `filterFn?: (item, index, ...params) => boolean` / `filterFnParams?: any[]` — 추가 필터.
32
- - `modal?: SdSelectModalInfo<TModal>` — 검색 아이콘 선택 모달.
33
- - `editModal?: SdModalInfo<SdModalContentDef<boolean>>` — 편집 아이콘 편집 모달.
34
- - `selectClass`/`multiSelectionDisplayDirection: "vertical"` — 표시 옵션.
35
- - `getIsHiddenFn?: (item, index) => boolean` 숨김 판정(기본 `__isHidden`, 숨김 항목은 취소선).
36
- - `getSearchTextFn?: (item, index) => string` — 검색 대상 텍스트(기본 `__searchText`).
37
- - `displayOrderByFn?: (item) => 정렬키` 표시 정렬.
38
- - 항목 템플릿은 `<ng-template [itemOf]>`, 미지정 표시는 `#undefinedTpl`. `__parentKey` 있으면 트리.
39
-
40
- ## SdSharedDataSelectButton
41
-
42
- `<sd-shared-data-select-button>` 모달 선택 버튼 + 선택값 인라인 표시. 제네릭 `<TItem, TMode, TModal>`.
43
-
44
- - `value = model<...>()` — 선택 키(single/multi).
45
- - `items = input<TItem[]>([])` — 표시 라벨 조회용 전체 항목.
46
- - `modal = input.required<SdSelectModalInfo<TModal>>()` — 선택 모달.
47
- - `selectMode: TMode` 기본 `"single"`.
48
- - `disabled`/`required`/`inset`/`size`공통.
49
- - 선택 항목 라벨은 `<ng-template [itemOf]>`(required)로 렌더.
50
-
51
- ## SdSharedDataSelectList
52
-
53
- `<sd-shared-data-select-list>` — 검색·페이징되는 리스트형 단일 선택(패널 영역용). 제네릭 `<TItem, TModal>`.
54
-
55
- - `selectedItem = model<TItem>()` — 선택 항목(객체). `canChangeFn?: (item) => boolean|Promise<boolean>` 로 변경 차단.
56
- - `items = input.required<TItem[]>()` — 항목 배열. `__isHidden` 항목은 제외.
57
- - `selectedIcon?` — 선택 표시 아이콘.
58
- - `useUndefined` — "미지정" 항목 표시.
59
- - `filterFn?: (item, index) => boolean` — 추가 필터.
60
- - `modal?: SdSelectModalInfo<TModal>` — 외부 검색 모달 버튼.
61
- - `header?` — 패널 헤더 텍스트.
62
- - `pageItemCount?` — 페이지당 항목 수(지정 시 페이지네이션).
63
- - 슬롯: `#headerTpl`/`#filterTpl`(기본 검색 textfield 대체)/`[itemOf]` 항목/`#undefinedTpl`.
3
+ 서버의 마스터 데이터(코드·거래처 등)를 클라이언트 전역에서 캐시·구독하고, 데이터를 고른 select/list/button UI 로 노출하는 묶음. 데이터 변경은 서비스 이벤트로 전파되어 자동 갱신됨.
4
+
5
+ ## 데이터 규약 타입
6
+
7
+ - **SharedDataBase<TKey>** — 공유 데이터 항목의 베이스. `{ __valueKey: TKey; __searchText: string; __isHidden: boolean; __parentKey?: TKey }`. `__searchText` 검색, `__isHidden` 으로 목록 숨김, `__parentKey` 있으면 트리 구성. 도메인 타입이 이 인터페이스를 확장.
8
+ - **SharedDataInfo<T>** — 등록 정보. `{ serviceKey: string; getter: (changeKeys?) => Promise<T[]>; filter?: unknown; orderBy?: (item) => 비교키 }`. getter 는 전체/부분(changeKeys) 로드, filter 는 이벤트 매칭, orderBy 는 정렬키.
9
+ - **SharedDataHandle<T>** — `{ items: Signal<T[]>; get(key): T | undefined }`. 화면에서 데이터 소비 핸들.
10
+
11
+ ## SdSharedDataProvider<T>
12
+
13
+ `@Injectable()` abstract. 앱별로 상속해 `initialize()` 구현. T `{ name: SharedDataBase 파생 }` 맵.
14
+ - loadingCount: WritableSignal<number>로딩 카운트.
15
+ - abstract initialize(): void — 앱 시작 시 각 데이터 register.
16
+ - register<K>(name, info: SharedDataInfo<T[K]>) — 데이터 등록(재호출 시 generation 증가로 이전 이벤트 무시·재로드).
17
+ - getHandle<K>(name): SharedDataHandle<T[K]> 핸들 획득(첫 호출 lazy 로드 + 이벤트 리스너 등록). 미등록이면 throw.
18
+ - emitAsync<K>(name, changeKeys?) 변경 이벤트 발행(같은 name·filter 구독자 갱신). changeKeys 지정 시 부분 갱신.
19
+ - wait(): Promise<void>loadingCount 0 이 될 때까지 대기(화면 진입 데이터 준비).
20
+
21
+ **SdSharedDataChangeEvent** — `defineEvent` 로 정의된 서비스 이벤트(`{ name; filter }`, 페이로드 `(string|number)[] | undefined`). provider 가 내부 사용.
22
+
23
+ ## SdSharedDataSelect<TItem, TMode, TModal>
24
+
25
+ `<sd-shared-data-select [items]="...">` — 공유 데이터 드롭다운 선택(검색·트리·모달 연동).
26
+ - value = model<...>() — 선택값(single=키, multi=키 배열). 키는 `TItem["__valueKey"] | undefined`.
27
+ - items: input.required<TItem[]> — 후보(보통 handle.items()).
28
+ - selectMode: "single"|"multi"(기본 single).
29
+ - disabled/required/inset/inline/size — 컨트롤 공통.
30
+ - useUndefined: boolean — multi 에서도 "미지정" 항목 노출.
31
+ - filterFn?/filterFnParams? — 후보 필터(item,index,...params).
32
+ - modal?: SdSelectModalInfo — 우측 검색 버튼으로 띄울 선택 모달.
33
+ - editModal?: SdModalInfo<SdModalContentDef<boolean>> — 편집 버튼으로 띄울 모달.
34
+ - selectClass?/multiSelectionDisplayDirection?("vertical").
35
+ - getIsHiddenFn?(item,index)/getSearchTextFn?(item,index)/displayOrderByFn?(item)기본은 `__isHidden`/`__searchText`/없음. 검색·표시·정렬 재정의.
36
+ - (contentChild) `itemOf` 템플릿 항목 렌더. `undefinedTpl` 로 "미지정" 표시 커스텀.
37
+ - `__parentKey` 있으면 자동 트리(자식은 부모 펼침 노출).
38
+
39
+ ## SdSharedDataSelectButton<TItem, TMode, TModal>
40
+
41
+ `<sd-shared-data-select-button [modal]="...">` — 모달 선택 버튼 + 선택 항목 인라인 표시(`SdModalSelectButton` 래퍼).
42
+ - value = model<...>(), items: TItem[](선택값→표시용 매핑), modal: input.required<SdSelectModalInfo>, selectMode(기본 single), disabled/required/inset/size.
43
+ - (contentChild) `itemOf` 템플릿 필수 — 선택된 항목 표시.
44
+
45
+ ## SdSharedDataSelectList<TItem, TModal>
46
+
47
+ `<sd-shared-data-select-list [items]="...">`단일 선택 리스트(검색·페이징·모달 연동).
48
+ - selectedItem = model<TItem>(), canChangeFn?(item) 선택 변경 가드.
49
+ - items: input.required<TItem[]>, selectedIcon?, useUndefined(미지정 항목), filterFn?(item,index).
50
+ - modal? — 우상단 외부창 버튼으로 띄울 선택 모달.
51
+ - header?: string — 상단 헤더 텍스트.
52
+ - pageItemCount?: number — >0 이면 페이지당 항목 수로 페이징.
53
+ - (contentChild) `itemOf`/`headerTpl`/`filterTpl`/`undefinedTpl` 템플릿.
64
54
 
65
55
  ## matchesSearchText
66
56
 
67
- `matchesSearchText(itemText: string, searchQuery: string | undefined): boolean` — 공백 분리 AND 부분일치 검색 매처(소문자 비교). 위 선택 컨트롤이 검색에 사용.
68
-
69
- - `itemText` — 항목의 검색 대상 텍스트.
70
- - `searchQuery` — 검색어. 빈/`undefined` 면 모두 매치(true). 각 단어가 모두 포함돼야 매치.
57
+ `matchesSearchText(itemText: string, searchQuery: string | undefined): boolean` — 검색어를 공백으로 나눈 모든 토큰이 itemText(소문자)에 포함되면 true(AND 매칭). 빈 검색어면 true. select/list 내부 사용하나 커스텀 검색에도 활용 가능.
@@ -1,78 +1,73 @@
1
1
  # @simplysm/angular — 시트 (sd-sheet)
2
2
 
3
- 선택·다중정렬·트리확장·컬럼 고정/숨김/리사이즈·페이지네이션·셀편집·설정 영속화를 갖춘 데이터 그리드. 컬럼은 `<sd-sheet-column>` 디렉티브 + `<ng-template [cell]>` 템플릿으로 선언. 선택/정렬/확장은 selection-managers 컴포저블을 내부 사용.
4
-
5
- ## SdSheet
6
-
7
- `<sd-sheet>` 데이터 그리드. 제네릭 `<TItem>`.
8
-
9
- inputs:
10
- - `key = input<string>()`설정 영속화 키. 지정 시 설정 버튼·컬럼폭/순서/고정/숨김을 `SdSystemConfigProvider` 에 저장.
11
- - `items = input<TItem[]>([])` — 표시 데이터.
12
- - `trackByFn = input<(item, index) => unknown>` — 행 추출. 기본 `(item) => item`. 선택키·정렬 추적 기준.
13
- - `selectMode: "single"|"multi"` — 선택 모드. 미지정 시 선택 비활성. multi 헤더 전체선택 체크박스.
14
- - `autoSelect: "click"|"focus"` — 자동 선택 트리거. `"click"` = 행/셀 클릭 시 선택, `"focus"` = 셀 포커스 선택. 키보드 위주 화면이면 `"focus"`.
15
- - `getItemSelectableFn?: (item) => boolean | string` — 행 선택 가능 여부. `string` 반환 시 비활성 + 문자열을 툴팁 사유로 표시.
16
- - `getChildrenFn?: (item, index) => TItem[] | undefined` — 트리 자식. 지정 시 확장 토글 컬럼 노출.
17
- - `useAutoSort = input(false)` — 클라이언트 정렬. true 면 `sorts` 변경 시 시트가 직접 `items` 정렬. 서버측 정렬/페이징이면 false 로 두고 외부에서 재조회.
18
- - `visiblePageCount = input(10)`/`totalPageCount = input(0)`/`itemsPerPage = input(0)` 페이지네이션. `totalPageCount>0` 서버 페이징, `itemsPerPage>0` 면 클라이언트 페이징.
19
- - `focusMode: "row"|"cell"`키보드 포커스 단위. `"row"` = 행 강조만, `"cell"` = 셀 단위 포커스/편집. 기본 `"cell"`.
20
- - `inset = input(false)` 테두리 없는 삽입형.
21
- - `contentStyle`스크롤 컨테이너 인라인 스타일.
22
- - `getItemCellClassFn?: (item, colKey) => string` / `getItemCellStyleFn?: (item, colKey) => string | undefined` — 셀별 동적 클래스/스타일.
23
- - `hideConfigBar = input(false)` 상단 설정/페이지 숨김.
24
- - `columnControlsInput = input<readonly SdSheetColumn[]>([])` 투영 추가 컬럼 컨트롤(예: CRUD 목록이 삭제 컬럼 주입).
25
-
26
- outputs:
27
- - `itemKeydown = output<SdSheetItemKeydownEventParam<TItem>>()` — 행에서 키 입력(`{ item, event }`).
28
- - `cellKeydown = output<SdSheetCellKeydownEventParam<TItem>>()` — 셀에서 키 입력(`{ item, key, event }`, key=컬럼키).
29
-
30
- models(양방향):
31
- - `selectedKeys = model<unknown[]>([])`선택 행 키 배열.
32
- - `expandedItems = model<TItem[]>([])`펼친 트리 항목.
33
- - `sorts = model<SortingDef[]>([])` — 정렬 정의(`{ key, desc }[]`). 헤더 클릭으로 토글(Shift=다중).
34
- - `currentPage = model(0)` — 현재 페이지(0-base).
35
-
36
- ## SdSheetColumn
37
-
38
- `<sd-sheet-column>` 디렉티브 컬럼 정의. 제네릭 `<T>`.
39
-
40
- - `key = input.required<string>()`컬럼 식별키(설정 저장·정렬·이벤트 기준).
41
- - `header: string | string[]` — 헤더 텍스트. 배열이면 다단(그룹) 헤더.
42
- - `headerStyle`/`tooltip` — 헤더 스타일·툴팁.
43
- - `width` — 컬럼 폭(CSS 값).
44
- - `fixed = input(false)` — 좌측 고정.
45
- - `hidden = input(false)` — 숨김.
46
- - `collapse = input(false)` — 접힘.
47
- - `disableSorting = input(false)` — 정렬 비활성.
48
- - `disableResizing = input(false)` — 폭 조절 비활성.
49
- - `ordering = input(0)` — 컬럼 정렬 순서.
50
- - 본문은 `<ng-template [cell]="items()" let-item="item" let-edit="edit">`, 헤더 커스텀은 `#headerTpl`, 합계행은 `#summaryTpl`.
51
-
52
- `SdSheetCellContext<T>` (셀 템플릿 컨텍스트): `$implicit`/`item`(행 데이터), `index`(행 인덱스), `depth`(트리 깊이), `edit`(현재 셀 편집모드 여부).
53
-
54
- ## SdSheetColumnCellTemplate
55
-
56
- `<ng-template [cell]>` 디렉티브 — 셀 본문 템플릿 마커. `cell = input.required<T[]>()` 로 타입 추론용 items 를 받아 `SdSheetCellContext<T>` 컨텍스트 타입 가드 제공.
57
-
58
- ## SdSheetConfigModal
59
-
60
- `<sd-sheet-config-modal>` — 시트 설정(컬럼 표시/순서/고정/폭) 편집 모달. `sd-sheet` 의 설정 버튼이 내부적으로 띄움. 직접 사용은 드묾.
61
-
62
- ## 타입
63
-
64
- - `SdSheetColumnDef` — 해석된 컬럼 정의(`key`/`header`/`width`/`fixed`/`hidden`/`collapse`/`disableSorting`/`disableResizing`/`ordering`/`headerStyle`/`tooltip`).
65
- - `SdSheetHeaderDef` — 헤더 셀 메타(`text`/`colspan`/`rowspan`/`isLastRow`/`fixed`/`colDef`/`colIndex`).
66
- - `SdSheetConfig` — 영속화 형태. `columnRecord: Record<키, { width?; hidden?; fixed?; ordering? }>`.
67
- - `SdSheetItemKeydownEventParam<T>` — `{ item, event }`.
68
- - `SdSheetCellKeydownEventParam<T>` — `{ item, key, event }`.
69
- - `SortingDef`(re-export) — `{ key: string; desc: boolean }`.
3
+ 데이터 그리드. 정렬·선택·페이징·컬럼 고정·셀 편집·트리 확장·컬럼 설정 영속을 한 컴포넌트로 다룸. 컬럼은 `sd-sheet-column` 디렉티브로 선언하고 셀은 `ng-template[cell]` 그림.
4
+
5
+ ## SdSheet<TItem>
6
+
7
+ `<sd-sheet [items]="..." [trackByFn]="...">`.
8
+
9
+ ### Inputs
10
+ - key?: string — 지정 시 컬럼 폭/순서/숨김/고정 상태를 `SdSystemConfigProvider` 에 영속하고 설정 버튼(톱니) 노출. 사용자 컬럼 커스터마이즈를 저장하려면 지정.
11
+ - items: TItem[] — 표시 데이터(기본 []).
12
+ - trackByFn: (item, index) => unknown — 행 식별 키. 선택키도 이 값 기준. 기본 `(item) => item`.
13
+ - selectMode?: "single"|"multi" — 선택 모드. 미지정 시 선택 비활성. single=단일 행, multi=다중 + 헤더 전체선택 체크박스.
14
+ - autoSelect?: "click"|"focus" — 자동 선택 트리거. "click"=행 클릭 시 선택, "focus"=셀 포커스 이동만으로 선택. 키보드 위주면 "focus".
15
+ - getItemSelectableFn?: (item) => boolean | string — 행 선택 가능 여부. string 반환 시 그 사유로 선택 불가.
16
+ - getChildrenFn?: (item, index) => TItem[] | undefined — 트리 자식. 지정 시 확장(▶) 토글 표시.
17
+ - useAutoSort: boolean — 클라이언트 정렬. true 면 sorts 변경 시 sd-sheet items 를 직접 정렬. 서버측 정렬/페이징이면 false 로 두고 외부에서 items 재조회.
18
+ - visiblePageCount: number페이지네이션 그룹 표시 수(기본 10).
19
+ - totalPageCount: number서버측 페이징 전체 페이지 수.
20
+ - itemsPerPage: number>0 이면 클라이언트 페이징(페이지당 행 수).
21
+ - focusMode: "row"|"cell" 키보드 포커스 단위(기본 cell). "row"=행 전체 이동, "cell"=셀 단위 이동(셀 편집·복사 화면이면 cell).
22
+ - inset: boolean 테두리 제거(컨테이너 내부 삽입).
23
+ - contentStyle?: string스크롤 영역 인라인 스타일.
24
+ - getItemCellClassFn?/getItemCellStyleFn?: (item, colKey) => ... 셀별 클래스/스타일 동적 지정.
25
+ - hideConfigBar: boolean — 상단 도구 바(설정·페이지네이션) 숨김.
26
+ - columnControlsInput: readonly SdSheetColumn[] — 템플릿이 아닌 코드로 컬럼을 넘길 때(투영 `sd-sheet-column` 과 합쳐짐).
27
+
28
+ ### Outputs / Models
29
+ - (output) itemKeydown: `SdSheetItemKeydownEventParam<TItem>` = `{ item; event: KeyboardEvent }` — 행에서 키 입력.
30
+ - (output) cellKeydown: `SdSheetCellKeydownEventParam<TItem>` = `{ item; key: string; event }` — 셀에서 키 입력(key=컬럼 key).
31
+ - (model) selectedKeys: unknown[] — 선택된 행 키 배열(trackByFn 값).
32
+ - (model) expandedItems: TItem[] — 확장된 트리 행.
33
+ - (model) sorts: SortingDef[] — 정렬 상태(`{ key; desc }[]`, 헤더 클릭으로 토글, selection-managers.md 참조).
34
+ - (model) currentPage: number — 현재 페이지(0 기반).
35
+
36
+ ## SdSheetColumn<T>
37
+
38
+ `<sd-sheet-column [key]="...">` 디렉티브. 컬럼 1개 정의.
39
+ - key: input.required<string> — 컬럼 식별·정렬/설정 키.
40
+ - header: string | string[]헤더 텍스트(배열이면 다단 헤더 그룹).
41
+ - headerStyle?: string — 헤더 스타일.
42
+ - tooltip?: string — 헤더 툴팁.
43
+ - width?: string — 컬럼 폭.
44
+ - fixed: boolean — 좌측 고정 컬럼.
45
+ - hidden: boolean — 숨김.
46
+ - collapse: boolean — 접힘(폭 축소).
47
+ - disableSorting: boolean — 정렬 비활성.
48
+ - disableResizing: boolean — 폭 조절 비활성.
49
+ - ordering: number — 컬럼 정렬 순서(기본 0).
50
+ - (contentChild) cellTplRef: `ng-template[cell]` 필수 본문. headerTpl/summaryTpl 템플릿으로 커스텀 헤더·요약 행.
51
+
52
+ ## SdSheetColumnCellTemplate<T>
53
+
54
+ `<ng-template cell let-item="item" ...>` 디렉티브. 컬럼 셀 본문 템플릿 규약. 컨텍스트 `SdSheetCellContext<T>` = `{ $implicit; item; index; depth; edit }`(edit=현재 셀 편집모드 여부). `cell = input.required<T[]>()` 로 항목 배열 타입 추론.
70
55
 
71
56
  ```html
72
- <sd-sheet [items]="rows()" [(selectedKeys)]="sel" [selectMode]="'multi'"
73
- [(sorts)]="sorts" [useAutoSort]="true" key="order-sheet">
57
+ <sd-sheet [items]="rows()" [trackByFn]="trackByFn" [(selectedKeys)]="selectedKeys" selectMode="multi">
74
58
  <sd-sheet-column key="name" header="이름" [fixed]="true">
75
- <ng-template [cell]="rows()" let-item="item">{{ item.name }}</ng-template>
59
+ <ng-template cell let-item="item">{{ item.name }}</ng-template>
76
60
  </sd-sheet-column>
77
61
  </sd-sheet>
78
62
  ```
63
+
64
+ ## SdSheetConfigModal
65
+
66
+ 컬럼 설정(폭/순서/고정/숨김) 편집 모달 컴포넌트. `SdSheet` 가 설정 버튼 클릭 시 내부적으로 띄움. 직접 사용 드묾.
67
+
68
+ ## 타입(types.ts)
69
+
70
+ - **SdSheetColumnDef** — 내부 계산된 컬럼 정의(`key; header; headerStyle; tooltip; width; fixed; hidden; collapse; disableSorting; disableResizing; ordering`).
71
+ - **SdSheetHeaderDef** — 헤더 셀 레이아웃 정의(`text; colspan; rowspan; isLastRow; fixed; colDef; colIndex`).
72
+ - **SdSheetConfig** — 영속되는 설정(`columnRecord: Record<key, { width?; hidden?; fixed?; ordering? }>`).
73
+ - **SdSheetItemKeydownEventParam<T>** / **SdSheetCellKeydownEventParam<T>** — 위 output 이벤트 형태.