@simplysm/sd-claude 14.0.88 → 14.0.90
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.
- package/claude/references/sd-simplysm14/README.md +16 -17
- package/claude/references/sd-simplysm14/apis/angular/README.md +39 -43
- package/claude/references/sd-simplysm14/apis/angular/controls.md +174 -80
- package/claude/references/sd-simplysm14/apis/angular/crud.md +41 -50
- package/claude/references/sd-simplysm14/apis/angular/directives.md +60 -26
- package/claude/references/sd-simplysm14/apis/angular/features.md +109 -37
- package/claude/references/sd-simplysm14/apis/angular/infra.md +61 -44
- package/claude/references/sd-simplysm14/apis/angular/layout.md +39 -31
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +73 -85
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +54 -39
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +55 -30
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +71 -67
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +82 -72
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +35 -36
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +71 -43
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +38 -30
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +45 -50
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +42 -55
- package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +62 -0
- package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +39 -38
- package/claude/references/sd-simplysm14/apis/core-common/README.md +95 -103
- package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +59 -54
- package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +86 -0
- package/claude/references/sd-simplysm14/apis/core-common/datetime.md +57 -66
- package/claude/references/sd-simplysm14/apis/core-common/errors.md +86 -0
- package/claude/references/sd-simplysm14/apis/core-common/obj.md +60 -42
- package/claude/references/sd-simplysm14/apis/core-common/serialization.md +55 -0
- package/claude/references/sd-simplysm14/apis/core-node/README.md +10 -8
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +29 -32
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +34 -22
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +29 -25
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +40 -53
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +22 -29
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +31 -31
- package/claude/references/sd-simplysm14/apis/excel/README.md +26 -26
- package/claude/references/sd-simplysm14/apis/excel/cell.md +37 -29
- package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +29 -15
- package/claude/references/sd-simplysm14/apis/excel/style.md +33 -27
- package/claude/references/sd-simplysm14/apis/excel/utils.md +29 -19
- package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +78 -55
- package/claude/references/sd-simplysm14/apis/excel/wrapper.md +42 -45
- package/claude/references/sd-simplysm14/apis/lint/README.md +27 -21
- package/claude/references/sd-simplysm14/apis/lint/rules.md +89 -49
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +6 -62
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +149 -67
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +111 -99
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +115 -72
- package/claude/references/sd-simplysm14/apis/orm-common/schema.md +134 -92
- package/claude/references/sd-simplysm14/apis/orm-common/types.md +67 -52
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +63 -26
- package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +51 -40
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +10 -12
- package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +92 -45
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +226 -108
- package/claude/references/sd-simplysm14/apis/service-client/README.md +90 -88
- package/claude/references/sd-simplysm14/apis/service-client/orm.md +37 -29
- package/claude/references/sd-simplysm14/apis/service-client/transport.md +45 -20
- package/claude/references/sd-simplysm14/apis/service-common/README.md +89 -40
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +126 -34
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +109 -54
- package/claude/references/sd-simplysm14/apis/service-server/README.md +70 -66
- package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +47 -47
- package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +71 -34
- package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +31 -32
- package/claude/references/sd-simplysm14/apis/storage/README.md +34 -28
- package/claude/references/sd-simplysm14/manuals/client-app-structure.md +142 -140
- package/claude/references/sd-simplysm14/manuals/client-orm.md +1 -1
- package/claude/references/sd-simplysm14/manuals/client-service.md +19 -7
- package/claude/references/sd-simplysm14/manuals/client-shared-data.md +2 -2
- package/claude/references/sd-simplysm14/manuals/client-system-log.md +11 -3
- package/claude/references/sd-simplysm14/manuals/data-log.md +0 -1
- package/claude/references/sd-simplysm14/manuals/orm.md +16 -0
- package/claude/rules/sd-design-rules.md +10 -0
- package/claude/skills/sd-docs/SKILL.md +58 -46
- package/claude/skills/sd-docs/references/{doc-rules.md → subagent-prompt.md} +103 -103
- package/claude/skills/sd-impl/SKILL.md +1 -1
- package/claude/skills/sd-spec/SKILL.md +858 -858
- package/claude/skills/sd-spec/references/example-spec.md +26 -36
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/apis/core-common/json-transfer.md +0 -47
- package/claude/references/sd-simplysm14/apis/orm-common/query-builder.md +0 -29
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/.specs/inventory/spec.md +0 -99
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/package.json +0 -12
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/index.ts +0 -3
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inbound/inbound.list.ts +0 -150
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inventory/inventory-master.list.ts +0 -143
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/outbound/outbound.list.ts +0 -150
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/pnpm-workspace.yaml +0 -2
- package/claude/skills/sd-demo/evals/fixtures/inventory-list/sd.config.ts +0 -12
- package/claude/skills/sd-demo/evals/golden.jsonl +0 -1
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/package.json +0 -8
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/src/.gitkeep +0 -0
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tests/.gitkeep +0 -0
- package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tsconfig.json +0 -10
- package/claude/skills/sd-dev/evals/golden.jsonl +0 -1
- package/claude/skills/sd-docs/evals/fixtures/new-write/.claude/references/sd-simplysm14/README.md +0 -7
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/src/index.ts +0 -3
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/package.json +0 -6
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/src/index.ts +0 -1
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/src/index.ts +0 -8
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/README.md +0 -7
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/apis/foo/README.md +0 -3
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/src/index.ts +0 -3
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/package.json +0 -6
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/src/index.ts +0 -1
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/package.json +0 -5
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/src/index.ts +0 -8
- package/claude/skills/sd-docs/evals/golden.jsonl +0 -2
- package/claude/skills/sd-impl/evals/fixtures/case-a-new-screen/.specs/260513120000_warehouse/spec.md +0 -101
- package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/.specs/260513120000_warehouse/spec.md +0 -101
- package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/packages/app/src/screens/box-register/box-register.view.ts +0 -46
- package/claude/skills/sd-impl/evals/fixtures/case-c-new-cross/.specs/260513120000_warehouse/spec.md +0 -89
- package/claude/skills/sd-impl/evals/fixtures/case-d-spec-modify/.specs/260513120000_warehouse/spec.md +0 -101
- package/claude/skills/sd-impl/evals/golden.jsonl +0 -4
- package/claude/skills/sd-manual/evals/fixtures/new-manual/src/notification.ts +0 -25
- package/claude/skills/sd-manual/evals/fixtures/update-manual/.claude/references/sd-simplysm14/manuals/notification.md +0 -14
- package/claude/skills/sd-manual/evals/fixtures/update-manual/src/notification.ts +0 -37
- package/claude/skills/sd-manual/evals/golden.jsonl +0 -2
- package/claude/skills/sd-review/evals/fixtures/code-review/src/foo.ts +0 -7
- package/claude/skills/sd-review/evals/fixtures/doc-review/docs/foo.md +0 -4
- package/claude/skills/sd-review/evals/golden.jsonl +0 -2
- package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +0 -14
- package/claude/skills/sd-skill/evals/fixtures/new-skill/.gitkeep +0 -0
- package/claude/skills/sd-skill/evals/golden.jsonl +0 -2
- package/claude/skills/sd-spec/evals/fixtures/case-a-split//355/232/214/354/235/230/353/241/235.md +0 -20
- package/claude/skills/sd-spec/evals/fixtures/case-b-detail/.specs/260513120000_warehouse/spec.md +0 -95
- package/claude/skills/sd-spec/evals/golden.jsonl +0 -2
- package/claude/skills/sd-unpack/evals/fixtures/eml-with-text-attachment/meeting.eml +0 -21
- package/claude/skills/sd-unpack/evals/fixtures/simple-eml/meeting.eml +0 -10
- package/claude/skills/sd-unpack/evals/golden.jsonl +0 -2
- package/claude/skills/sd-use/evals/fixtures/empty/.gitkeep +0 -0
- package/claude/skills/sd-use/evals/golden.jsonl +0 -6
|
@@ -1,115 +1,103 @@
|
|
|
1
|
-
# @simplysm/angular — 모달·토스트·Busy·인쇄 (
|
|
1
|
+
# @simplysm/angular — 모달·토스트·Busy·인쇄 (오버레이/전역 피드백)
|
|
2
2
|
|
|
3
|
-
프로그래밍 방식으로
|
|
3
|
+
화면에서 프로그래밍 방식으로 모달을 띄우거나, 토스트로 알림·진행률을 표시하거나, busy 인디케이터·인쇄/PDF 출력을 호출할 때 함께 읽히는 군. provider 는 모두 `providedIn: "root"`, 컴포넌트는 provider 가 동적으로 body 에 attach 하므로 템플릿에 직접 둘 일은 거의 없음.
|
|
4
4
|
|
|
5
5
|
## SdModalProvider
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- `title: string` — 모달 헤더 제목.
|
|
14
|
-
- `type: Type<T>` — 콘텐츠 컴포넌트 클래스(`SdModalContentDef` 구현).
|
|
15
|
-
- `inputs` — 콘텐츠 컴포넌트의 input 값 객체(`initialized`/`close`/`actionTplRef` 제외, `_optionalModalInputs` 로 지정된 키는 optional).
|
|
16
|
-
|
|
17
|
-
`SdModalOptions`(모두 optional):
|
|
18
|
-
- `key` — 설정 키. 지정 시 크기·위치를 `SdSystemConfigProvider` 에 영속화.
|
|
19
|
-
- `hideHeader` — 헤더 전체 숨김.
|
|
20
|
-
- `hideCloseButton` — 닫기(X) 버튼만 숨김.
|
|
21
|
-
- `headerStyle` — 헤더 인라인 스타일.
|
|
22
|
-
- `useCloseByBackdrop` — 배경 클릭으로 닫기 허용. 기본 true.
|
|
23
|
-
- `useCloseByEscapeKey` — ESC 로 닫기 허용. 기본 true.
|
|
24
|
-
- `float` — 배경 없는 플로팅 모달(다른 조작 가능).
|
|
25
|
-
- `fill` — 전체화면 채움.
|
|
26
|
-
- `resizable` — 모서리/변 드래그 리사이즈.
|
|
27
|
-
- `movable` — 헤더 드래그 이동.
|
|
28
|
-
- `position` — `"bottom-right"|"top-right"`. 고정 위치.
|
|
29
|
-
- `minHeightPx`/`minWidthPx`/`heightPx`/`widthPx` — 크기 px.
|
|
30
|
-
- `noFirstControlFocusing` — 첫 입력요소 자동 포커스 끔(true 면 dialog 자체 포커스).
|
|
31
|
-
|
|
32
|
-
`SdModalContentDef<O>`(콘텐츠 컴포넌트 구현 인터페이스):
|
|
33
|
-
- `initialized: Signal<boolean>` — 초기화 완료 신호.
|
|
34
|
-
- `close: OutputEmitterRef<O | undefined>` — 결과 emit 시 모달 닫힘.
|
|
35
|
-
- `actionTplRef?: TemplateRef<any>` — 헤더 우측 액션 영역 템플릿.
|
|
36
|
-
- `_optionalModalInputs?: string` — optional 처리할 input 키(타입 마커).
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
const result = await sdModal.showAsync(
|
|
40
|
-
{ title: "사용자 선택", type: UserSelectModal, inputs: { deptId } },
|
|
41
|
-
{ resizable: true, key: "user-select" },
|
|
42
|
-
);
|
|
7
|
+
컴포넌트를 모달 셸(`SdModal`) 안에 동적 생성해 body 에 띄움. `close.emit(payload)` 또는 닫기(X/배경/ESC)로 종료.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
showAsync<T extends SdModalContentDef<any>>(
|
|
11
|
+
modal: SdModalInfo<T>, options?: SdModalOptions,
|
|
12
|
+
): Promise<Parameters<T["close"]["emit"]>[0] | undefined>
|
|
43
13
|
```
|
|
44
14
|
|
|
45
|
-
|
|
15
|
+
- `modal.type: Type<T>` — `SdModalContentDef<O>` 를 구현한 컴포넌트 클래스(`SdModal` 자체가 아님). `O` 가 close 페이로드 타입.
|
|
16
|
+
- `modal.title: string` — 모달 헤더 제목.
|
|
17
|
+
- `modal.inputs` — 모달 컴포넌트가 받을 input 값. `initialized`/`close`/`actionTplRef` 와 `_optionalModalInputs` 로 표시된 키는 제외/optional 처리됨. 없으면 `{}`.
|
|
18
|
+
- 반환값 — 컴포넌트가 `close.emit` 한 페이로드. 닫기/취소로 닫히면 `undefined`. 매뉴얼 패턴: `const r = await this._sdModal.showAsync({...}); if (!r) return;`.
|
|
19
|
+
- `modalCount: WritableSignal<number>` — 현재 열린 모달 수.
|
|
20
|
+
|
|
21
|
+
### SdModalContentDef<O> (모달 컴포넌트가 구현)
|
|
22
|
+
|
|
23
|
+
- `initialized: Signal<boolean>` — 초기화 완료 여부. busy 표시 해제 기준.
|
|
24
|
+
- `close: OutputEmitterRef<O | undefined>` — 결과 emit. `O` 가 `showAsync` 반환 타입.
|
|
25
|
+
- `actionTplRef?: TemplateRef<any>` — 헤더 우측에 끼울 액션 영역 템플릿(있으면 모달 헤더로 브릿지됨).
|
|
26
|
+
- `_optionalModalInputs?: string` — (타입 전용 마커) 이 컴포넌트의 input 중 optional 로 둘 키 이름 리터럴. 런타임 값 아님.
|
|
27
|
+
|
|
28
|
+
### SdModalOptions (showAsync 2번째 인자)
|
|
46
29
|
|
|
47
|
-
|
|
30
|
+
- `key?: string` — 설정 저장 키. 지정 시 사용자가 조정한 width/height/위치를 `SdSystemConfigProvider` 에 영속·복원.
|
|
31
|
+
- `hideHeader?: boolean` — true 면 제목/닫기 헤더 숨김. 헤더 없는 풀커스텀 모달용.
|
|
32
|
+
- `hideCloseButton?: boolean` — true 면 헤더 X 버튼만 숨김.
|
|
33
|
+
- `headerStyle?: string` — 헤더 영역 인라인 스타일.
|
|
34
|
+
- `useCloseByBackdrop?: boolean` — 배경 클릭으로 닫기 허용(기본 동작상 컴포넌트 기본 true). false 면 배경 클릭 무시.
|
|
35
|
+
- `useCloseByEscapeKey?: boolean` — ESC 로 닫기 허용. false 면 ESC 무시.
|
|
36
|
+
- `float?: boolean` — true 면 배경(backdrop) 없는 떠있는 패널. 비모달 보조 패널용.
|
|
37
|
+
- `fill?: boolean` — true 면 화면 전체를 채움(풀스크린 모달).
|
|
38
|
+
- `resizable?: boolean` — true 면 8방향 리사이즈 핸들 표시.
|
|
39
|
+
- `movable?: boolean` — true 면 헤더 드래그로 이동.
|
|
40
|
+
- `position?: "bottom-right" | "top-right"` — 고정 위치. 토스트성 알림 모달에 사용.
|
|
41
|
+
- `minHeightPx?/minWidthPx?/heightPx?/widthPx?: number` — 최소/초기 크기.
|
|
42
|
+
- `noFirstControlFocusing?: boolean` — true 면 첫 입력 요소 자동 포커스를 끔(다이얼로그 자체에 포커스).
|
|
48
43
|
|
|
49
|
-
|
|
50
|
-
- `title`/`hideHeader`/`hideCloseButton`/`headerStyle`/`useCloseByBackdrop`/`useCloseByEscapeKey`/`float`/`fill`/`resizable`/`movable`/`position`/`minHeightPx`/`minWidthPx`/`heightPx`/`widthPx`/`actionTplRef` — `SdModalOptions` 와 동일 의미의 input.
|
|
51
|
-
- `key` — 크기·위치 영속화 키.
|
|
52
|
-
- `closeRequest = output<void>()` — 배경/ESC/닫기버튼으로 닫기 요청 시 emit.
|
|
44
|
+
### 내장 모달 컴포넌트
|
|
53
45
|
|
|
54
|
-
|
|
46
|
+
- `SdPromptModal` (`SdModalContentDef<string>`) — 메시지 + 텍스트 입력 후 확인/취소. `message: input.required<string>` (innerHTML). 확인 시 입력값, 취소/닫기 시 `undefined`. 입력은 required 라 빈 값이면 네이티브 검증으로 차단.
|
|
47
|
+
- `SdConfirmModal` (`SdModalContentDef<boolean>`) — 메시지 + 확인/취소. `message: input.required<string>`. 확인 시 `true`, 취소/닫기 시 `undefined`.
|
|
48
|
+
- 사용: `const ok = await this._sdModal.showAsync({ type: SdConfirmModal, title: "확인", inputs: { message: "삭제할까요?" } }); if (!ok) return;`.
|
|
55
49
|
|
|
56
|
-
|
|
50
|
+
### SdActivatedModalProvider
|
|
57
51
|
|
|
58
|
-
|
|
59
|
-
- `contentComponent: Signal<T | undefined>` — 콘텐츠 컴포넌트 인스턴스.
|
|
60
|
-
- `canDeactivateFn: () => boolean` — 닫기 차단 함수(true 면 닫힘 허용). `setupCanDeactivate` 가 설정.
|
|
52
|
+
모달 컴포넌트 내부에서 inject. 자기 모달의 셸/콘텐츠 참조와 이탈 가드를 보유.
|
|
61
53
|
|
|
62
|
-
|
|
54
|
+
- `modalComponent: Signal<SdModal | undefined>` / `contentComponent: Signal<T | undefined>` — 셸/콘텐츠 컴포넌트 참조.
|
|
55
|
+
- `canDeactivateFn: () => boolean` — 닫기 시도 시 false 면 닫힘 차단. `setupCanDeactivate`(routing-appstructure.md) 가 모달 컨텍스트에서 이걸 설정.
|
|
63
56
|
|
|
64
|
-
|
|
57
|
+
### SdModal (모달 셸)
|
|
65
58
|
|
|
66
|
-
|
|
67
|
-
- `SdConfirmModal` — `SdModalContentDef<boolean>`. `message` 표시 후 확인 시 `true`, 취소 시 `undefined` emit.
|
|
59
|
+
`SdModalProvider` 가 내부적으로 생성하는 셸 컴포넌트. 상속·직접 배치 대상 아님. `<ng-content>` 로 콘텐츠를 투영하고 위 `SdModalOptions` 와 동일한 input(`title`/`open`/`resizable`/... `closeRequest` output) 을 보유.
|
|
68
60
|
|
|
69
61
|
## SdToastProvider
|
|
70
62
|
|
|
71
|
-
|
|
63
|
+
화면 우상단(또는 overlap 모드)에 토스트를 띄움. 알림·비동기 에러 가드·진행률에 사용.
|
|
72
64
|
|
|
73
|
-
- `
|
|
74
|
-
- `
|
|
75
|
-
- `
|
|
76
|
-
- `
|
|
77
|
-
- `
|
|
78
|
-
- `
|
|
65
|
+
- `info/success/warning/danger(message: string): void` — 심각도별 토스트 1개 표시(3초 후 자동 해제, hover 중이면 지연). `info`/`success` 는 `aria-live=polite`, `warning`/`danger` 는 `assertive`. 심각도 의미는 `sd-design-rules` 의 분류를 따름(error=문제 발생).
|
|
66
|
+
- `info/...(message: string, useProgress: true): WritableSignal<number>` — progress 모드. 반환된 signal 에 0~100 을 set 하면 진행바 갱신, 100 도달 1초 후 자동 해제. 업로드/다운로드 진행률 표시에 사용.
|
|
67
|
+
- `try<R>(fn: () => Promise<R> | R, messageFn?: (err: Error) => string): Promise<R | undefined>` — `fn` 실행 중 `Error` 가 throw 되면 잡아서 `danger` 토스트 + 시스템로그 `error` 적재 후 `undefined` 반환(에러를 외부로 전파하지 않음). `Error` 가 아닌 throw 는 그대로 재전파. 매뉴얼의 비동기 작업 표준 가드: `await this._sdToast.try(async () => { ... })`.
|
|
68
|
+
- `notify<T extends SdToastContentDef<any>>(input: SdToastInput<T>): Promise<...>` — 커스텀 컴포넌트를 토스트로 띄우고 `close` 페이로드를 반환(5초 후 자동 `undefined`).
|
|
69
|
+
- `alertThemes: WritableSignal<SdToastSeverity[]>` — 여기 든 심각도는 토스트 대신 `window.alert` 로 표시(키오스크 등 강제 확인 필요 화면).
|
|
70
|
+
- `overlap: WritableSignal<boolean>` — true 면 새 토스트가 기존 토스트를 제거하고 단독 표시.
|
|
71
|
+
- `beforeShowFn?: (theme: SdToastSeverity) => void` — 토스트 표시 직전 콜백(사운드 등).
|
|
79
72
|
|
|
80
73
|
타입:
|
|
81
|
-
- `SdToastSeverity` — `"info"|"success"|"warning"|"danger"`.
|
|
82
|
-
- `SdToastTheme` — `"primary"|"secondary"|SdToastSeverity|"gray"|"blue-gray"`.
|
|
83
|
-
- `SdToastContentDef<O>` — `{ close: OutputEmitterRef<O|undefined> }`. notify 콘텐츠 구현.
|
|
84
|
-
- `SdToastInput<T>` — `{ type: Type<T>; inputs }`(`close` 제외 input).
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
sdToast.danger("저장 실패");
|
|
88
|
-
const progress = sdToast.info("업로드 중", true);
|
|
89
|
-
progress.set(50);
|
|
90
|
-
await sdToast.try(() => api.saveAsync());
|
|
91
|
-
```
|
|
92
74
|
|
|
93
|
-
|
|
75
|
+
- `SdToastSeverity = "info"|"success"|"warning"|"danger"`.
|
|
76
|
+
- `SdToastTheme = "primary"|"secondary"|SdToastSeverity|"gray"|"blue-gray"` — `sd-toast` 컴포넌트 `theme` 입력 범위.
|
|
77
|
+
- `SdToastContentDef<O> = { close: OutputEmitterRef<O | undefined> }` — `notify` 커스텀 컴포넌트 규약.
|
|
78
|
+
- `SdToastInput<T> = { type: Type<T>; inputs: Omit<DirectiveInputSignals<T>, "close"> }`.
|
|
94
79
|
|
|
95
|
-
|
|
96
|
-
- `<sd-toast-container>` — 토스트 컨테이너. `overlap = input(false)` — 겹침 모드.
|
|
80
|
+
`SdToast`/`SdToastContainer` 는 provider 가 동적 생성하는 표시 컴포넌트(직접 배치 불필요).
|
|
97
81
|
|
|
98
82
|
## SdBusyProvider / SdBusyContainer
|
|
99
83
|
|
|
100
|
-
|
|
84
|
+
영역 단위 busy 오버레이.
|
|
101
85
|
|
|
102
|
-
- `SdBusyProvider
|
|
103
|
-
- `
|
|
104
|
-
-
|
|
86
|
+
- `SdBusyProvider.type: WritableSignal<SdBusyType>` — 전역 기본 인디케이터 종류. `SdBusyType = "spinner"|"bar"|"cube"`. `"bar"` = 상단 가는 진행바, `"spinner"` = 회전 원, `"cube"` = 큐브 애니메이션.
|
|
87
|
+
- `SdBusyProvider.globalBusyCount: WritableSignal<number>` — 전역 busy 카운트(>0 이면 화면 전체 busy). 라우팅·인쇄가 ±1. 직접 ±1 해 전역 차단 가능.
|
|
88
|
+
- `SdBusyContainer` (`sd-busy-container`) — 자식 영역에 busy 오버레이를 씌우는 컨테이너 컴포넌트.
|
|
89
|
+
- `busy: boolean` — true 면 오버레이 표시 + 영역 내 키입력 차단.
|
|
90
|
+
- `message: string` — 인디케이터 옆/아래 표시 메시지.
|
|
91
|
+
- `type: SdBusyType` — 이 영역만의 인디케이터 종류(미지정 시 provider 기본값).
|
|
92
|
+
- `progressPercent: number` — 지정 시 상단 진행바(0~100). 결정형 작업 진행률에 사용.
|
|
93
|
+
- 사용: `<sd-busy-container [busy]="busyCount() > 0">...</sd-busy-container>` (단, `sd-base-container` 가 이미 내장).
|
|
105
94
|
|
|
106
95
|
## SdPrintProvider
|
|
107
96
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
- `printAsync<T>(template: SdPrintInput<T>, options?: { size?: string; margin?: string }): Promise<void>` — 템플릿 컴포넌트를 body 에 부착·`@page` 스타일 주입 후 `window.print()`. 이미지 로드 대기.
|
|
111
|
-
- `getPdfBufferAsync<T>(template, options?: { orientation?: "portrait"|"landscape"; pageSize?: string }): Promise<Uint8Array>` — `.page` 요소(없으면 전체)를 캔버스화해 jsPDF 로 PDF 버퍼 생성.
|
|
97
|
+
인쇄 템플릿 컴포넌트를 동적 생성해 `window.print()` 하거나 PDF 버퍼로 변환. 호출 동안 `globalBusyCount` ±1.
|
|
112
98
|
|
|
113
|
-
|
|
114
|
-
- `SdPrint
|
|
115
|
-
- `
|
|
99
|
+
- `printAsync<T extends SdPrint>(template: SdPrintInput<T>, options?: { size?: string; margin?: string }): Promise<void>` — 템플릿을 숨겨 붙인 뒤 `@media print` CSS 로 그것만 출력. `size` 기본 `"A4 auto"`, `margin` 기본 `"0"`. 이미지 로드 완료를 기다린 후 인쇄.
|
|
100
|
+
- `getPdfBufferAsync<T extends SdPrint>(template: SdPrintInput<T>, options?: { orientation?: "portrait"|"landscape"; pageSize?: string }): Promise<Uint8Array>` — `.page` 요소들(없으면 루트)을 캔버스로 렌더해 jsPDF 로 PDF 바이트 생성. `orientation` 기본 portrait, `pageSize` 기본 `"a4"`. 첨부/저장용 PDF 가 필요할 때.
|
|
101
|
+
- `SdPrint = { initialized: Signal<boolean>; _optionalPrintInputs?: string }` — 인쇄 템플릿 컴포넌트 규약. `initialized` 가 true 가 되어야 인쇄 진행(데이터 로드 대기).
|
|
102
|
+
- `SdPrintInput<T> = { type: Type<T>; inputs: ... }` — 인쇄 컴포넌트 + input 값(`_optionalPrintInputs` 표시 키는 optional).
|
|
103
|
+
- 사용: `await this._sdPrint.printAsync({ type: OutboundPrintTemplate, inputs: { id } })`. 인쇄 템플릿 파일은 `<domain>.print-template.ts`(client-component.md).
|
|
@@ -1,64 +1,79 @@
|
|
|
1
1
|
# @simplysm/angular — 라우팅 / 앱 구조(메뉴·권한)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
라우터 링크·현재 페이지 식별·뷰 컨텍스트(page/control/modal)·이탈 가드, 그리고 앱 구조 트리에서 메뉴·권한을 파생하는 군. 화면 컴포넌트의 표준 시그널 `viewType`, 권한 가드 `injectPermsSignal`, 사이드바/탑바 메뉴가 이 군에 의존.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## injectViewTypeSignal / SdViewType
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```ts
|
|
8
|
+
function injectViewTypeSignal(): Signal<SdViewType>
|
|
9
|
+
type SdViewType = "page" | "modal" | "control"
|
|
10
|
+
```
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
- `open(navigate, params?, features?)` — 라우트 열기. 창 모드이거나 `features` 있으면 `window.open` 으로 새 창(부모 unload 시 자동 닫힘), 아니면 새 탭(`_blank`).
|
|
12
|
+
현재 컴포넌트가 어느 컨텍스트에서 동작 중인지 판정하는 signal. `"page"` = 라우팅 진입 화면, `"modal"` = 모달로 열림, `"control"` = 다른 화면 안에 임베드된 자식. 판정 기준: 모달 컨텍스트면 modal, 라우트 컴포넌트의 selector 가 현재 엘리먼트 태그와 일치하고 full/current 페이지 코드가 같으면 page, 그 외 control. 매뉴얼 표준 시그널 `viewType = injectViewTypeSignal()` 로 받아 `sd-base-container [viewType]` 에 전달.
|
|
11
13
|
|
|
12
|
-
##
|
|
14
|
+
## injectViewTitleSignal
|
|
13
15
|
|
|
14
|
-
`
|
|
16
|
+
- `function injectViewTitleSignal(): Signal<string>` — 현재 뷰의 표시 제목. 모달이면 모달 컴포넌트 `title`, 아니면 앱 구조에서 현재 페이지 코드로 찾은 제목(`[상위 > 경로] 현재`). 못 찾으면 `""`. `sd-base-container` 가 page 탑바 제목에 사용.
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
## injectFullPageCodeSignal / injectCurrentPageCodeSignal
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
- `function injectFullPageCodeSignal(): Signal<string>` — 라우터 URL 전체에서 파생한 페이지 코드(`/` → `.` 로 합침, 앞 2세그먼트 제외, `;`/`?` 이후 제거). 메뉴 선택 상태·뷰 타입 판정에 사용.
|
|
21
|
+
- `function injectCurrentPageCodeSignal(): Signal<string> | undefined` — 현재 `ActivatedRoute` 기준 상대 페이지 코드. 라우트 컨텍스트 없으면 `undefined`. 중첩 라우트에서 자기 위치 코드가 필요할 때.
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
## setupCanDeactivate
|
|
21
24
|
|
|
22
|
-
- `
|
|
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 면 닫기/이탈 차단.
|
|
25
|
+
- `function setupCanDeactivate(fn: () => boolean): void` — 라우터 이탈/모달 닫기 시점에 `fn()` 이 false 면 이탈/닫기를 차단. 모달 컨텍스트면 `SdActivatedModalProvider.canDeactivateFn` 에, 라우트 컨텍스트면 해당 route 의 `canDeactivate` 에 등록(파괴 시 자동 해제). detail 화면의 변경 가드 표준: `setupCanDeactivate(() => this._checkIgnoreChanges())`(client-component.md).
|
|
27
26
|
|
|
28
|
-
##
|
|
27
|
+
## SdRouterLink (`[sdRouterLink]`)
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
라우터 이동을 호스트 클릭에 붙이는 디렉티브. Ctrl/Shift 클릭·window 모드면 새 창/탭으로 분기.
|
|
31
30
|
|
|
32
|
-
- `
|
|
33
|
-
- `
|
|
31
|
+
- `sdRouterLink: { link: string; params?: Record<string,string>; window?: { width?; height? }; outletName?: string; queryParams?: Record<string,string> } | undefined` — 이동 옵션.
|
|
32
|
+
- `link` — 라우트 경로. `outletName` 있으면 named outlet 이동.
|
|
33
|
+
- `params` — 매트릭스 파라미터, `queryParams` — 쿼리 파라미터.
|
|
34
|
+
- `window` — Ctrl/Shift 클릭 또는 window 컨텍스트일 때 팝업 창 크기(기본 800x800).
|
|
35
|
+
- 미지정(`undefined`) 이면 클릭 무시 + 커서 기본. 메뉴 항목이 leaf 가 아닐 때 등.
|
|
36
|
+
- Alt+클릭은 무시. 사이드바/탑바 메뉴가 `getMenuRouterLinkOption(menu)` 결과를 이 입력에 바인딩.
|
|
34
37
|
|
|
35
|
-
##
|
|
38
|
+
## SdNavigateWindowProvider
|
|
36
39
|
|
|
37
|
-
`
|
|
40
|
+
- `isWindow: boolean` — 현재 문서가 `window=true` 로 열린 팝업인지(해시 파라미터 검사).
|
|
41
|
+
- `open(navigate: string, params?: Record<string,string>, features?: string): void` — 새 창/탭으로 라우트 열기. window 컨텍스트이거나 `features` 가 있으면 `window=true` 팝업으로(부모 unload 시 자동 close), 아니면 `_blank` 탭으로. `SdRouterLink` 내부 + 화면에서 보조 창을 띄울 때.
|
|
38
42
|
|
|
39
|
-
|
|
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)`.
|
|
43
|
+
## SdAppStructureProvider<TModule> / injectPermsSignal
|
|
45
44
|
|
|
46
|
-
`
|
|
45
|
+
앱 구조 트리(`AppStructureItem[]`, `@simplysm/service-common`)에서 메뉴·권한을 파생하는 root provider. 화면은 보통 `injectPermsSignal` 만 직접 씀.
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
```ts
|
|
48
|
+
function injectPermsSignal<K extends string>(viewCodes: string[], keys: K[]): Signal<K[]>
|
|
49
|
+
```
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
- `viewCodes` — 권한 path 목록(도메인 트리 좌표). `keys` — 확인할 action 목록. 반환 signal 은 사용자가 보유한 action 들의 배열. 매뉴얼 패턴: `perms = injectPermsSignal(["inventory.outbound"], ["use","edit"])` → `this.perms().includes("use")` 인라인 가드.
|
|
52
|
+
- provider 멤버:
|
|
53
|
+
- `usableModules: WritableSignal<TModule[] | undefined>` / `permRecord: WritableSignal<Record<string, boolean> | undefined>` — 인증 후 주입하는 활성 모듈·권한 레코드. 메뉴/권한 계산의 입력.
|
|
54
|
+
- `items: WritableSignal<AppStructureItem<TModule>[]>` / `initialize(items): void` — 앱 구조 트리 세팅.
|
|
55
|
+
- `usableMenus: Signal<SdMenu[]>` — 권한·모듈 필터를 적용한 트리형 메뉴(사이드바용).
|
|
56
|
+
- `usableFlatMenus: Signal<SdFlatMenu<TModule>[]>` — 평탄화된 메뉴 목록(검색/전체메뉴용).
|
|
57
|
+
- `getPermsByFullCode<K>(fullCodes, permKeys): K[]` — 코드 목록에 대해 보유 action 계산(`injectPermsSignal` 내부). 권한 정의 자체가 없는 항목은 모든 action 허용으로 간주.
|
|
58
|
+
- `getPermissionsByStructure(items, codeChain?)` — 권한표(`sd-permission-table`)용 `SdPermission` 트리 생성.
|
|
59
|
+
- `findTitleByFullCode(fullCode): string | undefined` / `getTitleByFullCode(fullCode): string`(못 찾으면 throw) / `getItemChainByFullCode(fullCode)` — 코드로 제목·항목 체인 조회.
|
|
51
60
|
|
|
52
|
-
##
|
|
61
|
+
## SdAppStructureUtils (static 유틸)
|
|
53
62
|
|
|
54
|
-
|
|
55
|
-
- `SdFlatMenu<TModule>` — 평탄 메뉴. `titleChain`/`codeChain`/`modulesChain`.
|
|
56
|
-
- `SdPermission<TModule>` — 권한 노드. `title`/`codeChain`/`modules`/`perms: ("use"|"edit")[] | undefined`/`children`.
|
|
63
|
+
`SdAppStructureProvider` 가 내부적으로 쓰는 순수 함수 모음(abstract 클래스의 static). 트리 → 메뉴/권한/제목 변환을 provider 밖에서 직접 할 때만 사용.
|
|
57
64
|
|
|
58
|
-
|
|
65
|
+
- `getMenus(items, codeChain, usableModules, permRecord): SdMenu[]` — 모듈·`use` 권한 필터 적용 트리 메뉴. `isNotMenu` 항목·빈 그룹 제외.
|
|
66
|
+
- `getFlatMenus(items, usableModules, permRecord): SdFlatMenu[]` — BFS 평탄화 메뉴.
|
|
67
|
+
- `getPermissions(items, codeChain, usableModules): SdPermission[]` — 권한표용 트리(leaf 의 `perms`/`subPerms` 포함).
|
|
68
|
+
- `getFlatPermissions(items, usableModules)` / `findTitleByFullCode` / `getTitleByFullCode` / `getItemChainByFullCode` / `getPermsByFullCode` — provider 동명 메서드의 구현.
|
|
59
69
|
|
|
60
|
-
|
|
70
|
+
## menu-utils
|
|
71
|
+
|
|
72
|
+
- `getMenuRouterLinkOption(menu: SdMenu): { link: string; queryParams: Record<string,string> | undefined } | undefined` — 메뉴를 `sdRouterLink` 옵션으로 변환. children 이 있거나 `url`(외부 링크) 이면 `undefined`(이동 불가 = leaf 아님). 그 외 `codeChain` 으로 `/home/<코드/...>` 링크 + 쿼리 분리.
|
|
73
|
+
- `getIsMenuSelected(menu: SdMenu, fullPageCode: string | undefined, customFn?: (menu) => boolean): boolean` — 메뉴 선택 여부. `customFn` 있으면 위임, 없으면 `fullPageCode === menu.codeChain.join(".")`.
|
|
74
|
+
|
|
75
|
+
## 타입
|
|
61
76
|
|
|
62
|
-
- `
|
|
63
|
-
- `
|
|
64
|
-
- `
|
|
77
|
+
- `SdMenu = { title; codeChain: string[]; url?; icon?; children?: SdMenu[] }` — 트리 메뉴 항목. `url` 있으면 외부 링크, `children` 있으면 그룹.
|
|
78
|
+
- `SdFlatMenu<TModule> = { titleChain: string[]; codeChain: string[]; modulesChain: TModule[][] }` — 평탄 메뉴(경로 누적).
|
|
79
|
+
- `SdPermission<TModule> = { title; codeChain; modules; perms: ("use"|"edit")[] | undefined; children }` — 권한표 노드. `perms` 가 undefined 면 그룹(권한 없음). `sd-permission-table` 의 `items` 입력 타입.
|
|
@@ -1,43 +1,68 @@
|
|
|
1
|
-
# @simplysm/angular —
|
|
1
|
+
# @simplysm/angular — selection/sorting/expanding 매니저 (use* 컴포저블)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
커스텀 목록 컴포넌트에서 선택·정렬·트리펼침 상태 로직을 signal 기반으로 합성하는 함수 컴포저블 군. `sd-sheet` 가 이들을 조합해 만들어졌고, 직접 그리드/리스트를 만들 때 같은 로직을 재사용. 모두 함수 호출로 signal·메서드 묶음을 반환(컴포넌트 필드에 보관).
|
|
4
4
|
|
|
5
|
-
## useSelectionManager
|
|
5
|
+
## useSelectionManager<TItem, TKey>
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
행 선택(single/multi)·전체선택·선택 가능 여부 로직.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
```ts
|
|
10
|
+
useSelectionManager<TItem, TKey>(options: {
|
|
11
|
+
displayItems: Signal<TItem[]>;
|
|
12
|
+
selectedKeys: WritableSignal<TKey[]>;
|
|
13
|
+
selectMode: Signal<"single" | "multi" | undefined>;
|
|
14
|
+
getItemSelectableFn: Signal<((item: TItem) => boolean | string) | undefined>;
|
|
15
|
+
trackByFn: Signal<(item: TItem, index: number) => TKey>;
|
|
16
|
+
}): { ... }
|
|
17
|
+
```
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
- `options.displayItems` — 현재 표시 항목. `selectedKeys` — 선택 키(WritableSignal, 키는 `trackByFn` 반환값). `selectMode` — 모드(undefined 면 선택 비활성). `getItemSelectableFn` — 행별 선택 가능: `true`=가능, `false`=불가, 문자열=불가+사유. `trackByFn` — 항목→키.
|
|
20
|
+
- 반환:
|
|
21
|
+
- `hasSelectable: Signal<boolean>` — 선택 모드가 켜졌는지.
|
|
22
|
+
- `isAllSelected: Signal<boolean>` — 선택 가능한 항목이 모두 선택됐는지(전체선택 체크 상태).
|
|
23
|
+
- `getSelectable(item): true | string | undefined` — 항목 선택 가능 여부(문자열=사유 툴팁).
|
|
24
|
+
- `getCanChangeFn(item): () => boolean` — 체크박스 `canChangeFn` 에 넘길 가드.
|
|
25
|
+
- `select`/`deselect`/`toggle(item)` — 선택 조작(single 은 단일 키로 대체).
|
|
26
|
+
- `toggleAll()` — 선택 가능 항목 전체 토글.
|
|
27
|
+
- `isSelected(item): boolean`.
|
|
28
|
+
- 키 비교는 `===` 후 `obj.equal`(복합 키 지원).
|
|
17
29
|
|
|
18
30
|
## useSortingManager
|
|
19
31
|
|
|
20
|
-
|
|
32
|
+
정렬 상태(다중 컬럼) 토글·적용. `sd-sheet` 의 `sorts` 와 `SortingDef` 를 공유.
|
|
21
33
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
```ts
|
|
35
|
+
useSortingManager(options: { sorts: WritableSignal<SortingDef[]> }): {
|
|
36
|
+
defMap: Signal<Map<string, { indexText?: string; desc: boolean }>>;
|
|
37
|
+
toggle(key: string, multiple: boolean): void;
|
|
38
|
+
sort<T>(items: T[]): T[];
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- `SortingDef = { key: string; desc: boolean }` — 한 정렬 기준. `key`=컬럼 키, `desc`=내림차순 여부.
|
|
43
|
+
- `defMap` — 키별 정렬 상태(헤더 아이콘 표시용; `indexText` 는 다중 정렬 시 순번).
|
|
44
|
+
- `toggle(key, multiple)` — 정렬 토글. 한 키를 누를 때마다 없음→오름차순→내림차순→해제 순환. `multiple`(Shift) true 면 기존 정렬 유지하고 추가, false 면 단일 정렬로 대체.
|
|
45
|
+
- `sort<T>(items)` — 현재 정렬을 적용한 새 배열 반환. null 은 가장 앞, 문자열은 localeCompare, 숫자는 수치 비교. 클라이언트 정렬 시 사용.
|
|
46
|
+
|
|
47
|
+
## useExpandingManager<T>
|
|
27
48
|
|
|
28
|
-
|
|
49
|
+
트리 항목 펼침/접힘 + 표시 항목 평탄화.
|
|
29
50
|
|
|
30
|
-
|
|
51
|
+
```ts
|
|
52
|
+
useExpandingManager<T>(binding: {
|
|
53
|
+
items: Signal<T[]>;
|
|
54
|
+
expandedItems: WritableSignal<T[]>;
|
|
55
|
+
getChildrenFn: Signal<((item: T, index: number) => T[] | undefined) | undefined>;
|
|
56
|
+
sort: (items: T[]) => T[];
|
|
57
|
+
}): { ... }
|
|
58
|
+
```
|
|
31
59
|
|
|
32
|
-
binding
|
|
33
|
-
- `items: Signal<T[]>` — 루트 항목.
|
|
34
|
-
- `expandedItems: WritableSignal<T[]>` — 펼친 항목(양방향).
|
|
35
|
-
- `getChildrenFn: Signal<((item, index) => T[] | undefined) | undefined>` — 자식 추출.
|
|
36
|
-
- `sort: (items) => T[]` — 각 레벨 정렬 함수.
|
|
60
|
+
- `binding.items` — 루트 항목. `expandedItems` — 펼쳐진 항목(WritableSignal). `getChildrenFn` — 자식 조회(undefined 면 자식 없음). `sort` — 각 레벨 정렬 함수(보통 `useSortingManager.sort`).
|
|
37
61
|
- 반환:
|
|
38
|
-
- `displayItems: Signal<T[]>` — 펼침
|
|
39
|
-
- `hasExpandable
|
|
40
|
-
- `
|
|
41
|
-
- `
|
|
42
|
-
- `
|
|
43
|
-
- `ExpandItemDef<T>` —
|
|
62
|
+
- `displayItems: Signal<T[]>` — 펼침 상태를 반영해 평탄화·정렬된 표시 항목.
|
|
63
|
+
- `hasExpandable: Signal<boolean>` — 펼칠 수 있는 항목이 있는지(토글 컬럼 표시 기준).
|
|
64
|
+
- `isAllExpanded: Signal<boolean>` — 전체 펼침 상태.
|
|
65
|
+
- `toggle(item)` / `toggleAll()` — 펼침 토글.
|
|
66
|
+
- `isVisible(item): boolean` — 조상이 모두 펼쳐져 보이는지.
|
|
67
|
+
- `def(item): ExpandItemDef<T>` — 항목 메타(못 찾으면 throw).
|
|
68
|
+
- `ExpandItemDef<T> = { item: T; parentDef: ExpandItemDef<T> | undefined; hasChildren: boolean; depth: number }` — 항목의 부모·자식유무·깊이. 들여쓰기·토글 렌더에 사용.
|
|
@@ -1,70 +1,74 @@
|
|
|
1
|
-
# @simplysm/angular — 공유 데이터
|
|
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`.
|
|
1
|
+
# @simplysm/angular — 공유 마스터 데이터 + 선택 컨트롤
|
|
64
2
|
|
|
65
|
-
|
|
3
|
+
고객사·품목 등 자주 참조하는 마스터 데이터를 한 번 등록해 어느 화면에서든 공유 signal 로 쓰고, 그 데이터를 선택하는 드롭다운/버튼/리스트 컨트롤을 제공하는 군. 등록·항목 추가 절차는 `client-shared-data.md` 참조.
|
|
4
|
+
|
|
5
|
+
## SdSharedDataProvider<T> (abstract)
|
|
6
|
+
|
|
7
|
+
마스터 데이터를 이름별로 등록·로드·이벤트 동기화하는 root provider. 앱은 이걸 상속한 `AppSharedDataProvider` 를 만들고 `useSharedSignal` 헬퍼를 함께 export(client-shared-data.md).
|
|
8
|
+
|
|
9
|
+
- `abstract initialize(): void` — 여기서 `register(name, info)` 로 항목 등록(앱이 구현).
|
|
10
|
+
- `register<K>(name: K, info: SharedDataInfo<T[K]>): void` — 항목 등록. 재호출 시 기존 리스너 정리 + generation 증가로 이전 결과 무시 후 재로드.
|
|
11
|
+
- `getHandle<K>(name: K): SharedDataHandle<T[K]>` — 항목 핸들 반환(첫 접근 시 lazy 로드 + 변경 이벤트 리스너 등록). 미등록 이름이면 throw. `useSharedSignal` 이 이걸 감쌈.
|
|
12
|
+
- `emitAsync<K>(name: K, changeKeys?: (string|number)[]): Promise<void>` — 변경 브로드캐스트. `changeKeys` 주면 해당 키만 부분 갱신, 없으면 전체 리로드(다른 클라이언트 포함).
|
|
13
|
+
- `wait(): Promise<void>` — 진행 중 로드가 끝날 때까지 대기. `sd-base-container` 가 ready 전에 호출.
|
|
14
|
+
- `loadingCount: WritableSignal<number>` — 진행 중 로드 수.
|
|
15
|
+
|
|
16
|
+
### 타입
|
|
17
|
+
|
|
18
|
+
- `SharedDataBase<TKey extends string|number>` — 모든 공유 항목이 상속할 베이스. 매직 필드: `__valueKey: TKey`(항목 키), `__searchText: string`(검색용 텍스트), `__isHidden: boolean`(숨김), `__parentKey?: TKey`(트리 부모). getter 의 select 결과에 빠짐없이 포함.
|
|
19
|
+
- `SharedDataInfo<T>` — 등록 정보. `serviceKey: string`(이벤트 채널), `getter: (changeKeys?) => Promise<T[]>`(조회; changeKeys 주면 부분), `filter?: unknown`(이벤트 필터 매칭), `orderBy?: (item) => string|number|DateOnly|DateTime|Time|undefined`(정렬 키).
|
|
20
|
+
- `SharedDataHandle<T>` — `{ items: Signal<T[]>; get(key): T | undefined }`. 화면이 `useSharedSignal(name)` 으로 받아 `.items()`·`.get(id)` 사용.
|
|
21
|
+
- `SdSharedDataChangeEvent` — 변경 동기화에 쓰이는 `defineEvent`. payload `{ name; filter }`, data `(string|number)[] | undefined`.
|
|
22
|
+
|
|
23
|
+
사용(화면): `sharedCustomers = useSharedSignal("고객사"); sharedCustomers.items(); sharedCustomers.get(id)`.
|
|
24
|
+
|
|
25
|
+
## 선택 컨트롤
|
|
26
|
+
|
|
27
|
+
공유 데이터(또는 `SharedDataBase` 호환 배열)를 항목으로 받아 선택. 매직 필드(`__searchText`/`__isHidden`/`__parentKey`)를 자동 활용(검색·숨김·트리).
|
|
28
|
+
|
|
29
|
+
### SdSharedDataSelect (`sd-shared-data-select`)
|
|
66
30
|
|
|
67
|
-
|
|
31
|
+
드롭다운 셀렉트(검색창·트리·미지정 항목·모달 연동 내장).
|
|
32
|
+
|
|
33
|
+
- `value: model<...>` — 선택 키(single) 또는 키 배열(multi). 미지정은 `undefined`.
|
|
34
|
+
- `items: input.required<TItem[]>` — 공유 항목 배열(`SharedDataBase` 상속).
|
|
35
|
+
- `selectMode: "single"|"multi"` — 선택 모드(기본 single).
|
|
36
|
+
- `required: boolean` — 빈 값이면 invalid.
|
|
37
|
+
- `useUndefined: boolean` — multi 에서도 "미지정" 항목 노출(single 은 required 아니면 자동 노출).
|
|
38
|
+
- `filterFn: (item, index, ...params) => boolean` + `filterFnParams: any[]` — 표시 항목 필터.
|
|
39
|
+
- `getIsHiddenFn: (item, index) => boolean` — 숨김 판정(기본 `__isHidden`; 숨김 항목은 취소선 + 검색 시에만 표시).
|
|
40
|
+
- `getSearchTextFn: (item, index) => string` — 검색 대상 텍스트(기본 `__searchText`).
|
|
41
|
+
- `displayOrderByFn: (item) => ...` — 표시 정렬 키.
|
|
42
|
+
- `modal: SdSelectModalInfo<TModal>` — 검색 버튼으로 띄울 선택 모달. `editModal: SdModalInfo<...>` — 편집 버튼 모달.
|
|
43
|
+
- `multiSelectionDisplayDirection: "vertical"` — multi 표시 세로 나열.
|
|
44
|
+
- `disabled`/`inset`/`inline`/`size`/`selectClass` — 공통/스타일.
|
|
45
|
+
- 항목 템플릿: `<ng-template [itemOf]="items()" let-item="item">`, 미지정 표시 `#undefinedTpl`.
|
|
46
|
+
- 사용: `<sd-shared-data-select [items]="sharedCustomers.items()" [(value)]="data().customerId"><ng-template [itemOf]="sharedCustomers.items()" let-item="item">{{ item.name }}</ng-template></sd-shared-data-select>`.
|
|
47
|
+
|
|
48
|
+
### SdSharedDataSelectButton (`sd-shared-data-select-button`)
|
|
49
|
+
|
|
50
|
+
값 표시 + 모달 검색 버튼(드롭다운 없이 모달 전용). 항목 수가 많아 드롭다운이 부적합할 때.
|
|
51
|
+
|
|
52
|
+
- `value: model<...>` — 선택 키/키배열.
|
|
53
|
+
- `items: TItem[]` — 표시명 매핑용 항목 배열.
|
|
54
|
+
- `modal: input.required<SdSelectModalInfo<TModal>>` — 띄울 선택 모달.
|
|
55
|
+
- `selectMode: "single"|"multi"` / `disabled` / `required` / `inset` / `size` — 공통.
|
|
56
|
+
- 선택 항목 표시 템플릿: `<ng-template [itemOf]>`(필수).
|
|
57
|
+
|
|
58
|
+
### SdSharedDataSelectList (`sd-shared-data-select-list`)
|
|
59
|
+
|
|
60
|
+
검색창 + 리스트로 단건 선택(좌측 마스터 리스트 패널 등). `flex-column fill`.
|
|
61
|
+
|
|
62
|
+
- `selectedItem: model<TItem>` — 선택된 항목(키 아닌 항목 객체). `canChangeFn: (item|undefined) => boolean|Promise<boolean>` — 변경 가드.
|
|
63
|
+
- `items: input.required<TItem[]>` — 항목 배열(`__isHidden` 항목 자동 제외).
|
|
64
|
+
- `useUndefined: boolean` — "미지정" 항목 노출.
|
|
65
|
+
- `filterFn: (item, index) => boolean` — 추가 필터.
|
|
66
|
+
- `selectedIcon: string` — 선택 표시 아이콘.
|
|
67
|
+
- `pageItemCount: number` — 페이지당 항목 수(지정 시 페이지네이션).
|
|
68
|
+
- `modal: SdSelectModalInfo<TModal>` — 우상단 외부 링크로 띄울 모달.
|
|
69
|
+
- `header: string` — 상단 헤더 텍스트.
|
|
70
|
+
- 템플릿: `#headerTpl`(헤더 우측), `#filterTpl`(검색창 대체), `<ng-template [itemOf]>`(항목), `#undefinedTpl`(미지정).
|
|
71
|
+
|
|
72
|
+
## matchesSearchText
|
|
68
73
|
|
|
69
|
-
- `itemText` —
|
|
70
|
-
- `searchQuery` — 검색어. 빈/`undefined` 면 모두 매치(true). 각 단어가 모두 포함돼야 매치.
|
|
74
|
+
- `function matchesSearchText(itemText: string, searchQuery: string | undefined): boolean` — 공백 구분 다중 검색어 AND 매칭(대소문자 무시). 빈 쿼리면 true. 위 선택 컨트롤들이 내부 검색에 사용. 커스텀 목록에서 동일 검색 동작이 필요할 때 직접 호출.
|