@simplysm/sd-claude 14.0.82 → 14.0.83
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-requirement-source-handling.md +20 -20
- package/claude/references/sd-simplysm14/README.md +13 -13
- package/claude/references/sd-simplysm14/manuals/client-component.md +92 -92
- package/claude/references/sd-simplysm14/manuals/client-crud.md +11 -11
- package/claude/references/sd-simplysm14/manuals/client-demo.md +28 -28
- package/claude/references/sd-simplysm14/manuals/client-rules.md +1 -1
- package/claude/references/sd-simplysm14/manuals/client-setup.md +21 -21
- package/claude/references/sd-simplysm14/manuals/client-tab.md +3 -3
- package/claude/references/sd-simplysm14/manuals/logging.md +15 -15
- package/claude/references/sd-simplysm14/manuals/orm-union.md +6 -6
- package/claude/references/sd-simplysm14/manuals/orm.md +19 -19
- package/claude/references/sd-simplysm14/manuals/test.md +33 -33
- package/claude/rules/sd-base-rules.md +44 -43
- package/claude/rules/sd-design-rules.md +18 -18
- package/claude/skills/sd-commit/SKILL.md +10 -10
- package/claude/skills/sd-config/SKILL.md +2 -2
- package/claude/skills/sd-demo/SKILL.md +45 -45
- package/claude/skills/sd-dev/SKILL.md +15 -15
- package/claude/skills/sd-docs/SKILL.md +7 -7
- package/claude/skills/sd-docs/references/subagent-prompt.md +33 -33
- package/claude/skills/sd-impl/SKILL.md +60 -60
- package/claude/skills/sd-review/SKILL.md +9 -9
- package/claude/skills/sd-skill/SKILL.md +74 -74
- package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +1 -1
- package/claude/skills/sd-spec/SKILL.md +355 -319
- package/claude/skills/sd-spec/references/example-spec.md +104 -104
- package/claude/skills/sd-unpack/SKILL.md +34 -34
- package/claude/skills/sd-use/SKILL.md +4 -4
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/apis/angular/README.md +0 -37
- package/claude/references/sd-simplysm14/apis/angular/app-structure.md +0 -92
- package/claude/references/sd-simplysm14/apis/angular/buttons.md +0 -88
- package/claude/references/sd-simplysm14/apis/angular/crud.md +0 -100
- package/claude/references/sd-simplysm14/apis/angular/forms.md +0 -200
- package/claude/references/sd-simplysm14/apis/angular/infrastructure.md +0 -231
- package/claude/references/sd-simplysm14/apis/angular/kanban.md +0 -80
- package/claude/references/sd-simplysm14/apis/angular/layout.md +0 -92
- package/claude/references/sd-simplysm14/apis/angular/modal.md +0 -115
- package/claude/references/sd-simplysm14/apis/angular/routing.md +0 -107
- package/claude/references/sd-simplysm14/apis/angular/select-dropdown.md +0 -35
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +0 -82
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +0 -134
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +0 -127
- package/claude/references/sd-simplysm14/apis/angular/toast.md +0 -97
- package/claude/references/sd-simplysm14/apis/angular/visual.md +0 -167
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +0 -79
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +0 -83
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +0 -91
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +0 -49
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +0 -143
- package/claude/references/sd-simplysm14/apis/core-common/README.md +0 -58
- package/claude/references/sd-simplysm14/apis/core-common/extensions.md +0 -88
- package/claude/references/sd-simplysm14/apis/core-common/features.md +0 -51
- package/claude/references/sd-simplysm14/apis/core-common/types.md +0 -88
- package/claude/references/sd-simplysm14/apis/core-common/utils.md +0 -189
- package/claude/references/sd-simplysm14/apis/core-node/README.md +0 -12
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +0 -59
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +0 -44
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +0 -42
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +0 -53
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +0 -24
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +0 -65
- package/claude/references/sd-simplysm14/apis/excel/README.md +0 -193
- package/claude/references/sd-simplysm14/apis/lint/README.md +0 -94
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +0 -58
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +0 -77
- package/claude/references/sd-simplysm14/apis/orm-common/executable.md +0 -20
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +0 -92
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +0 -98
- package/claude/references/sd-simplysm14/apis/orm-common/schema-builders.md +0 -128
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +0 -69
- package/claude/references/sd-simplysm14/apis/sd-claude/README.md +0 -32
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +0 -80
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config.md +0 -155
- package/claude/references/sd-simplysm14/apis/service-client/README.md +0 -131
- package/claude/references/sd-simplysm14/apis/service-common/README.md +0 -29
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +0 -63
- package/claude/references/sd-simplysm14/apis/service-common/messages.md +0 -56
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +0 -64
- package/claude/references/sd-simplysm14/apis/service-common/service-types.md +0 -43
- package/claude/references/sd-simplysm14/apis/service-server/README.md +0 -13
- package/claude/references/sd-simplysm14/apis/service-server/auth.md +0 -39
- package/claude/references/sd-simplysm14/apis/service-server/builtin-services.md +0 -71
- package/claude/references/sd-simplysm14/apis/service-server/define-service.md +0 -55
- package/claude/references/sd-simplysm14/apis/service-server/internals.md +0 -82
- package/claude/references/sd-simplysm14/apis/service-server/server.md +0 -57
- package/claude/references/sd-simplysm14/apis/storage/README.md +0 -71
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# Requirement Source 부정확성 처리
|
|
1
|
+
# 요구사항 원본(Requirement Source, 회의록·메일·문서 등 사용자 제공 원본 자료) 부정확성 처리
|
|
2
2
|
|
|
3
|
-
## STT 텍스트 보정
|
|
3
|
+
## STT(음성→텍스트 변환) 텍스트 보정
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
명백한 오타만 보정. 보정 시 `[원문]` 발췌로 원본도 보존.
|
|
6
6
|
|
|
7
7
|
```markdown
|
|
8
8
|
> [2026-03-17 회의] "PDF에 빨간색으로 강조"
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
판정:
|
|
14
|
-
-
|
|
15
|
-
-
|
|
14
|
+
- 명백 (오타 1~2글자, 의미 자명): 보정함.
|
|
15
|
+
- 모호 (의미가 여러 갈래로 해석 가능): 사용자에게 즉시 확인, 원문 그대로 발췌.
|
|
16
16
|
|
|
17
17
|
## 화자 추정
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
회의록의 화자 표기가 부정확하거나 누락된 경우, 앞뒤 대화 맥락으로 추정. `[추정: ...]` 표기.
|
|
20
20
|
|
|
21
21
|
```markdown
|
|
22
22
|
> [2026-03-17 회의, 추정: B 차장] "주문 단위로 가는 게 맞다"
|
|
@@ -24,41 +24,41 @@
|
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
판정:
|
|
27
|
-
-
|
|
28
|
-
-
|
|
27
|
+
- 앞뒤 대화 맥락으로 화자가 명확: 추정 표기.
|
|
28
|
+
- 모호: 사용자에게 즉시 확인, 화자 미상으로 발췌.
|
|
29
29
|
|
|
30
30
|
## 모호 발화 처리
|
|
31
31
|
|
|
32
|
-
지시대명사·생략 표현·비격식
|
|
32
|
+
지시대명사·생략 표현·비격식 발언 예:
|
|
33
33
|
- "그거 그렇게" / "이렇게 가는 걸로" / "지난번처럼" / "알아서".
|
|
34
34
|
|
|
35
35
|
처리:
|
|
36
|
-
-
|
|
37
|
-
-
|
|
36
|
+
- 자동 해석 금지 (이전 발언이나 맥락을 추측해서 채워 넣지 말 것).
|
|
37
|
+
- 사용자에게 즉시 확인 — "그거" 가 무엇을 가리키는지, "그렇게" 가 어떤 방식인지.
|
|
38
38
|
|
|
39
39
|
## 다중 화자 발언 섞임 (회의록)
|
|
40
40
|
|
|
41
41
|
여러 사람이 같은 주제를 다른 입장에서 말한 경우:
|
|
42
|
-
-
|
|
43
|
-
- 사용자에게 어느
|
|
42
|
+
- 모든 화자의 발언을 발췌하여 보존.
|
|
43
|
+
- 사용자에게 어느 의견을 채택할지 즉시 확인.
|
|
44
44
|
|
|
45
|
-
## 비격식 메일
|
|
45
|
+
## 비격식 메일 또는 붙여넣기 텍스트
|
|
46
46
|
|
|
47
47
|
주어 생략, 맥락 누락:
|
|
48
|
-
- 보충 가능한 부분(자명한 주어 등): 발췌 시 `[추정 보충: ...]`
|
|
48
|
+
- 보충 가능한 부분(자명한 주어 등): 발췌 시 `[추정 보충: ...]` 표기를 사용하여, 원문 자체는 수정하지 않고 보충분을 별도로 명시.
|
|
49
49
|
- 모호한 부분: 사용자에게 즉시 확인.
|
|
50
50
|
|
|
51
51
|
## 도메인 용어 다의성
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
요구사항 원본에 등장하는 업무 용어는 시스템 용어가 아니라 현장 은어. 같은 단어가 시스템상 여러 동작에 매핑될 수 있음.
|
|
54
54
|
|
|
55
55
|
- 예: "출고" → 창고간 재고이동 / 고객사 납품 / 차량 적재 / 그 외.
|
|
56
56
|
- 예: "마감" → 일마감 / 월마감 / 정산마감 / 작업종료.
|
|
57
57
|
- 예: "주문" → 고객 발주 / 내부 작업지시 / 견적 단계.
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
위험도 역설: 일반적으로 들리는 업무 용어(출고·입고·재고·주문·마감·등록 등)일수록 더 의심해야 함. 낯선 용어는 자연스럽게 의문이 생기지만, 익숙한 용어는 모두가 같은 뜻으로 안다고 착각하기 쉬움.
|
|
60
60
|
|
|
61
61
|
처리:
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
62
|
+
- 자동 매핑 금지.
|
|
63
|
+
- 사용자에게 즉시 확인 — 해당 단어가 시스템상 어떤 동작을 가리키는지 묻기.
|
|
64
|
+
- 후보 나열 금지 — 에이전트가 추측한 후보를 먼저 제시하면, 사용자가 그 후보 안에서만 고르도록 가두는 효과 발생. 후보 없이 사용자가 직접 답하도록 둘 것.
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
# @simplysm/* v14 행동 지침
|
|
2
2
|
|
|
3
|
-
Claude 에이전트가 반드시 지켜야 할 행동 지침.
|
|
3
|
+
Claude 에이전트가 `@simplysm/*` v14 패키지를 사용·변경하는 작업에서 반드시 지켜야 할 행동 지침.
|
|
4
4
|
|
|
5
|
-
## 코드 위치 원칙
|
|
5
|
+
## 코드 작성 위치 원칙
|
|
6
6
|
|
|
7
|
-
기본 위치는
|
|
7
|
+
업무 로직 코드의 기본 작성 위치는 **클라이언트 패키지**. 서버 패키지(`@simplysm/service-server` 기반)에는 다음 두 경우에만 코드를 둠:
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
- **클라이언트
|
|
9
|
+
- **보안 필요**: 클라이언트에 노출 불가한 자격증명·키, 권한 우회 위험이 있는 처리, 외부에 직접 노출하면 안 되는 연산.
|
|
10
|
+
- **클라이언트 실행 불가**: 브라우저·모바일 런타임에서 실행 불가능한 기능 (특정 네이티브 API, 서버 측 자원 접근 등).
|
|
11
11
|
|
|
12
|
-
ORM 호출, 파일 변환, 비즈니스 로직 등은 위 두
|
|
12
|
+
ORM 호출, 파일 변환, 비즈니스 로직 등은 위 두 경우에 해당하지 않는 한 클라이언트 코드에 직접 둠. "서버에 두는 게 관행"이라는 이유로 서버 패키지로 이관 금지.
|
|
13
13
|
|
|
14
|
-
## CLAUDE.md 명령어 표기
|
|
14
|
+
## 프로젝트 `CLAUDE.md` 명령어 표기 규칙
|
|
15
15
|
|
|
16
|
-
`CLAUDE.md` 작성 시, 검증
|
|
16
|
+
`@simplysm/*` v14 기반 프로젝트의 `CLAUDE.md` 작성 시, 검증 명령 표기 규칙:
|
|
17
17
|
|
|
18
|
-
- **기본 검증 (평소 사용)**: `pnpm check --fix` — typecheck
|
|
19
|
-
-
|
|
20
|
-
- **`-t` 타겟 표기**: `sd.config.ts` 의 `packages` 키(`@simplysm/`
|
|
18
|
+
- **기본 검증 (평소 사용)**: `pnpm check --fix` — typecheck 와 lint 를 일괄 수행, 자동 수정 포함.
|
|
19
|
+
- **보조 명령**: `pnpm typecheck`, `pnpm lint` — `pnpm check` 에서 문제가 났을 때 각각 따로 확인하는 용도. 단독 사용 회피.
|
|
20
|
+
- **`-t` 타겟 인자 표기**: `-t` 인자 값은 `sd.config.ts` 의 `packages` 키 (`@simplysm/` 접두사를 **제외** 한 짧은 이름. 예: `excel`, `core-node`, `sd-cli`) 임을 본문에 명시. 풀네임 사용을 막기 위해 예시도 짧은 이름으로 통일.
|
|
21
21
|
|
|
22
22
|
## 개발 매뉴얼
|
|
23
23
|
|
|
24
|
-
트리거 조건이 처음
|
|
24
|
+
아래 표의 트리거 조건이 현재 작업에서 처음 충족되는 시점에 해당 매뉴얼 파일을 Read 도구로 읽기.
|
|
25
25
|
|
|
26
26
|
| 트리거 | 매뉴얼 |
|
|
27
27
|
| ------------------------------------------------------- | ------------------------------------------------------ |
|
|
28
|
-
| 클라이언트 코드(
|
|
28
|
+
| 클라이언트 코드 (앱 패키지·`@simplysm/angular`) 를 작성·수정하는 모든 작업 | [client-rules.md](./manuals/client-rules.md) |
|
|
29
29
|
| 화면 컴포넌트(`<domain>.<역할>.ts`) 작성/수정 | [client-component.md](./manuals/client-component.md) |
|
|
30
30
|
| `sd-crud-list` / `sd-crud-detail` 채택한 목록·단건 화면 | [client-crud.md](./manuals/client-crud.md) |
|
|
31
31
|
| 클라이언트 데모 컴포넌트 작성 | [client-demo.md](./manuals/client-demo.md) |
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## 파일명·역할·위치
|
|
4
4
|
|
|
5
|
-
화면
|
|
5
|
+
화면 파일명은 `<domain>.<역할>.ts` 형식. 역할 접미사로 책임을 표시.
|
|
6
6
|
|
|
7
7
|
| 파일명 형식 | 역할 |
|
|
8
8
|
| ---------------------------- | ------------------------------------------------------------------------- |
|
|
9
|
-
| `<domain>.view.ts` | list/detail
|
|
9
|
+
| `<domain>.view.ts` | list/detail 합성 화면. list/detail 자식을 두고 상호 트리거를 중계. |
|
|
10
10
|
| `<domain>.list.ts` | 목록. `sd-crud-list` 사용. |
|
|
11
11
|
| `<domain>.detail.ts` | 단건 보기/편집. `sd-crud-detail` 사용. |
|
|
12
12
|
| `<domain>.modal.ts` | 모달 전용 화면. |
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
| `<domain>.ts` | 컨트롤(접미사 없음). 여러 화면에서 재사용되는 단위. |
|
|
16
16
|
|
|
17
17
|
- 모든 파일명은 dash-case.
|
|
18
|
-
- 라이브러리(`@simplysm/angular`)
|
|
18
|
+
- 라이브러리(`@simplysm/angular`) 의 파일은 `sd-` prefix 적용 (`sd-button.ts`, `sd-crud-list.ts`).
|
|
19
19
|
|
|
20
20
|
**위치**: 도메인이 있는 파일은 도메인 폴더 안에 둠. 도메인이 없는(범용) 파일은 `src/<역할>s/` 하위에 둠. 예: `src/controls/`, `src/modals/`.
|
|
21
21
|
|
|
22
|
-
**변형 파일**: 한 도메인 폴더 안에 같은 역할 파일이 2개 이상이면 `<domain>-<갈래>.<역할>.ts` 형식으로
|
|
22
|
+
**변형 파일**: 한 도메인 폴더 안에 같은 역할 파일이 2개 이상이면 `<domain>-<갈래>.<역할>.ts` 형식으로 갈래를 표시. 예 (`outbound-instruction/` 폴더):
|
|
23
23
|
|
|
24
24
|
- `outbound-instruction.list.ts` (헤더 목록).
|
|
25
25
|
- `outbound-instruction-item.list.ts` (품목 목록).
|
|
@@ -43,25 +43,25 @@ Angular 기본과 다른 부분만 명시:
|
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
- **`changeDetection: OnPush`** — 항상.
|
|
46
|
-
- **`encapsulation: ViewEncapsulation.None`** — 항상. 글로벌 SCSS 와 일관된 스타일을
|
|
46
|
+
- **`encapsulation: ViewEncapsulation.None`** — 항상. 글로벌 SCSS 와 일관된 스타일을 적용하기 위함.
|
|
47
47
|
- **`standalone: true`** — 항상. NgModule 신규 도입 금지.
|
|
48
|
-
- **`selector` prefix** — 앱 컴포넌트는 `app-`, 라이브러리(`@simplysm/angular`)
|
|
48
|
+
- **`selector` prefix** — 앱 컴포넌트는 `app-`, 라이브러리(`@simplysm/angular`) 컴포넌트는 `sd-`.
|
|
49
49
|
- **`template`** 은 인라인 (`*.html` 파일 분리 없음).
|
|
50
50
|
|
|
51
|
-
**`styles`** (선택) — 다음 두
|
|
51
|
+
**`styles`** (선택 사용) — 다음 두 가지를 simplysm 약속으로 따름:
|
|
52
52
|
|
|
53
|
-
- 첫 줄에 `/* language=SCSS */`
|
|
54
|
-
- 내부 전용
|
|
53
|
+
- 첫 줄에 `/* language=SCSS */` 주석 배치 (IDE 가 SCSS 로 인식하게 함).
|
|
54
|
+
- 내부 전용 클래스명은 `_` prefix (예: `._content`, `._button`).
|
|
55
55
|
|
|
56
56
|
## 화면 합성 패턴
|
|
57
57
|
|
|
58
58
|
화면은 list / detail / view 단위로 책임을 분리해 합성함.
|
|
59
59
|
|
|
60
|
-
- **`*.list.ts`** —
|
|
61
|
-
- **`*.detail.ts`** — 식별자(`input.required`)를 받아 자체
|
|
62
|
-
- **`*.view.ts`** — list/detail 합성 + 자식 간 트리거 중계. 데이터 페치는 view
|
|
60
|
+
- **`*.list.ts`** — 자체 검색·페이지·정렬·재조회를 책임. `selectMode` 같은 입력을 받아 부모가 선택 동작을 제어할 수 있게 노출.
|
|
61
|
+
- **`*.detail.ts`** — 식별자(`input.required`) 를 받아 자체 로드·저장. 변경·삭제 후 `submitted` output 으로 부모에게 알림.
|
|
62
|
+
- **`*.view.ts`** — list/detail 합성 + 자식 간 트리거 중계. 데이터 페치는 view 에서 수행 금지.
|
|
63
63
|
|
|
64
|
-
화면이 list 또는 detail 하나로 끝나면 view 를 만들지
|
|
64
|
+
화면이 list 또는 detail 하나로 끝나면 view 를 만들지 않음. 이 경우 list/detail 자체가 라우팅 진입 단위.
|
|
65
65
|
|
|
66
66
|
### list + detail 합성
|
|
67
67
|
|
|
@@ -89,9 +89,9 @@ view 의 합성 패턴 (예: `outbound-instruction.view.ts`):
|
|
|
89
89
|
|
|
90
90
|
핵심 약속:
|
|
91
91
|
|
|
92
|
-
- view 는 list 컴포넌트를 템플릿 변수(`#headerSheet`)로 잡아 `selectedKeys()` 를 읽고 `doRefresh()` 를
|
|
93
|
-
- detail 의 단건 변경·삭제는 list 가 표시하는
|
|
94
|
-
- view 는 `sd-base-container` 를 루트로 두고, 내부
|
|
92
|
+
- view 는 list 컴포넌트를 템플릿 변수(`#headerSheet`) 로 잡아 `selectedKeys()` 를 읽고 `doRefresh()` 를 호출.
|
|
93
|
+
- detail 의 단건 변경·삭제는 list 가 표시하는 동일 데이터에 반영해야 하므로, detail 의 `submitted` → list 의 `doRefresh()` 호출로 동기화.
|
|
94
|
+
- view 는 `sd-base-container` 를 루트로 두고, 내부 콘텐츠는 `#contentTpl` 슬롯에 배치.
|
|
95
95
|
|
|
96
96
|
### list + list 합성 (마스터-라인)
|
|
97
97
|
|
|
@@ -120,22 +120,22 @@ view 의 합성 패턴 (예: `outbound-instruction.view.ts`):
|
|
|
120
120
|
|
|
121
121
|
핵심 약속:
|
|
122
122
|
|
|
123
|
-
- 우 list 는
|
|
124
|
-
- 우 list 의 저장·삭제 후 좌 헤더 목록까지 갱신해야
|
|
125
|
-
- 우 list 안에 추가 분기(탭 등)
|
|
123
|
+
- 우 list 는 좌 list 의 선택 키를 `input` 으로 받아 자동 재조회. 외부 input → filter 머지 패턴은 아래 "외부 input 을 filter 에 반영" 섹션 참조.
|
|
124
|
+
- 우 list 의 저장·삭제 후 좌 헤더 목록까지 갱신해야 하면, 우 list 가 `submitted` output 을 emit 하고, view 가 받아 `#headerSheet.doRefresh()` 호출.
|
|
125
|
+
- 우 list 안에 추가 분기(탭 등) 가 필요하면 [client-tab.md](./client-tab.md) 매뉴얼 따름.
|
|
126
126
|
|
|
127
127
|
## 화면 컴포넌트의 표준 시그널
|
|
128
128
|
|
|
129
|
-
화면 컴포넌트(view/list/detail/modal) 가 공통으로
|
|
129
|
+
화면 컴포넌트(view/list/detail/modal) 가 공통으로 사용하는 시그널 4종. **필요한 것만 채택**하되, 채택 시 아래 약속된 이름·의미·전파를 그대로 따름.
|
|
130
130
|
|
|
131
131
|
| 이름 | 종류 | 의미 |
|
|
132
132
|
| ------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
133
|
-
| `ready` | `signal(false)` | 컴포넌트가 데이터 로드를 시작해도 되는 시점.
|
|
134
|
-
| `initialized` | `signal(false)` | 첫 데이터
|
|
135
|
-
| `busyCount` | `signal(0)` | 진행 중인 비동기 작업 수. 시작 시 `+1`,
|
|
136
|
-
| `viewType` | `injectViewTypeSignal()` | 화면이 page / control / modal 어느 컨텍스트에서 동작 중인지. 라우팅 진입이면 `'page'`, view 자식이면 `'control'`, 모달이면 `'modal'`. |
|
|
133
|
+
| `ready` | `signal(false)` | 컴포넌트가 데이터 로드를 시작해도 되는 시점. 부모·컨테이너가 true 로 set 하면 자식의 effect 발화. |
|
|
134
|
+
| `initialized` | `signal(false)` | 첫 데이터 로드 완료 여부. 자식이 자기 로드 종료 후 true 로 set. |
|
|
135
|
+
| `busyCount` | `signal(0)` | 진행 중인 비동기 작업 수. 시작 시 `+1`, 종료 시 `-1`. 값이 0 보다 크면 화면이 busy 표시. |
|
|
136
|
+
| `viewType` | `injectViewTypeSignal()` | 화면이 page / control / modal 중 어느 컨텍스트에서 동작 중인지. 라우팅 진입이면 `'page'`, view 자식이면 `'control'`, 모달이면 `'modal'`. |
|
|
137
137
|
|
|
138
|
-
**전파**: 부모가 자식에게 위 시그널들을 그대로
|
|
138
|
+
**전파**: 부모가 자식에게 위 시그널들을 그대로 전달. `sd-base-container` / `sd-crud-list` / `sd-crud-detail` 는 이 시그널들을 입력으로 받는 표준 컴포넌트.
|
|
139
139
|
|
|
140
140
|
**`busyCount` 사용 패턴**:
|
|
141
141
|
|
|
@@ -149,7 +149,7 @@ this.busyCount.update((v) => v - 1);
|
|
|
149
149
|
|
|
150
150
|
## 권한 (perms)
|
|
151
151
|
|
|
152
|
-
화면 컴포넌트는
|
|
152
|
+
화면 컴포넌트는 권한 정보를 `injectPermsSignal(<paths>, <actions>)` 로 받음.
|
|
153
153
|
|
|
154
154
|
```ts
|
|
155
155
|
perms = injectPermsSignal(
|
|
@@ -159,13 +159,13 @@ perms = injectPermsSignal(
|
|
|
159
159
|
```
|
|
160
160
|
|
|
161
161
|
- 첫 인자: **권한 path 목록** (도메인 트리 좌표).
|
|
162
|
-
- 둘째 인자: **확인할 action 목록**. `perms()`
|
|
162
|
+
- 둘째 인자: **확인할 action 목록**. `perms()` 의 반환값은 사용자가 보유한 action 의 string 배열.
|
|
163
163
|
|
|
164
164
|
**사용 약속**:
|
|
165
165
|
|
|
166
|
-
-
|
|
167
|
-
- `restricted` 입력은 `[restricted]="!perms().includes('use')"` 형태로 인라인 전달.
|
|
168
|
-
- 권한 체크 뒤에 추가 조건(데이터 상태 등)이 결합되어 **같은 결합이 2회 이상
|
|
166
|
+
- 단순 권한 체크는 `this.perms().includes("use")` 를 템플릿·코드에 인라인으로 작성. 별도 computed 로 묶지 않음.
|
|
167
|
+
- `restricted` 입력은 `[restricted]="!perms().includes('use')"` 형태로 인라인 전달. 별도 `canUse` / `restricted` computed 생성 금지.
|
|
168
|
+
- 권한 체크 뒤에 추가 조건(데이터 상태 등) 이 결합되어 **같은 결합이 2회 이상 참조되는 경우에만** computed 로 묶음.
|
|
169
169
|
|
|
170
170
|
```ts
|
|
171
171
|
canEdit = computed(() => this.perms().includes("edit") && this.data().state === "작성");
|
|
@@ -185,7 +185,7 @@ effect(() => {
|
|
|
185
185
|
|
|
186
186
|
## 에러·토스트
|
|
187
187
|
|
|
188
|
-
비동기 작업은 `_sdToast.try(async () => { ... })` 로 감쌈.
|
|
188
|
+
비동기 작업은 `_sdToast.try(async () => { ... })` 로 감쌈. 콜백 내에서 throw 된 에러는 토스트로 표시되며 외부로 전파되지 않음.
|
|
189
189
|
|
|
190
190
|
```ts
|
|
191
191
|
private readonly _sdToast = inject(SdToastProvider);
|
|
@@ -206,7 +206,7 @@ this.busyCount.update((v) => v - 1);
|
|
|
206
206
|
- `_sdToast.info("...")`.
|
|
207
207
|
- `_sdToast.danger("...")`.
|
|
208
208
|
|
|
209
|
-
**중복 작업 가드**: 진행 중인 작업이 있으면 새 작업은
|
|
209
|
+
**중복 작업 가드**: 진행 중인 작업이 있으면 새 작업은 건너뛰고 즉시 반환.
|
|
210
210
|
|
|
211
211
|
```ts
|
|
212
212
|
if (this.busyCount() > 0) return;
|
|
@@ -214,7 +214,7 @@ if (this.busyCount() > 0) return;
|
|
|
214
214
|
|
|
215
215
|
## DI 명명
|
|
216
216
|
|
|
217
|
-
`inject()` 한 의존은 외부 노출 멤버(시그널·output·공개 메서드 등)와 구분하기 위해 `_` prefix
|
|
217
|
+
`inject()` 한 의존은 외부 노출 멤버(시그널·output·공개 메서드 등) 와 구분하기 위해 `_` prefix 적용.
|
|
218
218
|
|
|
219
219
|
```ts
|
|
220
220
|
private readonly _sdToast = inject(SdToastProvider);
|
|
@@ -223,8 +223,8 @@ private readonly _appOrm = inject(AppOrmProvider);
|
|
|
223
223
|
private readonly _router = inject(Router);
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
-
- 시그널·input·output·공개 메서드는 prefix
|
|
227
|
-
- 항상 `private readonly`.
|
|
226
|
+
- 시그널·input·output·공개 메서드는 prefix 없음.
|
|
227
|
+
- DI 멤버는 항상 `private readonly`.
|
|
228
228
|
|
|
229
229
|
## 모달 호출
|
|
230
230
|
|
|
@@ -245,16 +245,16 @@ if (!result) return;
|
|
|
245
245
|
// result 처리
|
|
246
246
|
```
|
|
247
247
|
|
|
248
|
-
- **`type`** — `SdModal` 을 구현(상속)한 컴포넌트 클래스.
|
|
248
|
+
- **`type`** — `SdModal` 을 구현(상속) 한 컴포넌트 클래스.
|
|
249
249
|
- **`title`** — 모달 헤더 제목.
|
|
250
250
|
- **`inputs`** — 모달 컴포넌트가 받을 input 시그널 값. 없으면 `{}`.
|
|
251
|
-
- **반환값** — 모달 컴포넌트가 close 시 emit 한 페이로드. 사용자가 닫기(X)
|
|
251
|
+
- **반환값** — 모달 컴포넌트가 close 시 emit 한 페이로드. 사용자가 닫기(X)·취소로 닫으면 `undefined`.
|
|
252
252
|
|
|
253
253
|
## `mark` 헬퍼
|
|
254
254
|
|
|
255
|
-
`@simplysm/angular` 의 `mark(signal)` 은 시그널 값은 그대로 두고 **변경 알림만**
|
|
255
|
+
`@simplysm/angular` 의 `mark(signal)` 은 시그널 값은 그대로 두고 **변경 알림만** 발행. effect 가 의존하는 시그널을 강제 재발화시키거나, 객체 시그널 내부 필드 변경을 알릴 때 사용.
|
|
256
256
|
|
|
257
|
-
**1. 외부 트리거로 effect
|
|
257
|
+
**1. 외부 트리거로 effect 재발화** — 값은 동일하지만 effect 를 다시 발화시켜야 할 때.
|
|
258
258
|
|
|
259
259
|
```ts
|
|
260
260
|
doRefresh(): void {
|
|
@@ -262,7 +262,7 @@ doRefresh(): void {
|
|
|
262
262
|
}
|
|
263
263
|
```
|
|
264
264
|
|
|
265
|
-
**2.
|
|
265
|
+
**2. 객체·배열 시그널 내부 변경 알림** — 시그널이 들고 있는 객체의 _필드만_ 변경된 경우 시그널 자체는 변경 알림을 보내지 않음. 양방향 바인딩 자식의 변경 이벤트에 묶어 호출.
|
|
266
266
|
|
|
267
267
|
```ts
|
|
268
268
|
filter = signal<IFilter>({ name: "", state: "" });
|
|
@@ -279,7 +279,7 @@ mark(this.data);
|
|
|
279
279
|
|
|
280
280
|
## list 데이터 흐름
|
|
281
281
|
|
|
282
|
-
list 컴포넌트는 자체 검색·페이지·정렬·재조회를
|
|
282
|
+
list 컴포넌트는 자체 검색·페이지·정렬·재조회를 책임.
|
|
283
283
|
|
|
284
284
|
### 시그널 구성
|
|
285
285
|
|
|
@@ -296,7 +296,7 @@ lastFilter = signal<IFilter>({ ... }); // 마지막 조회 시점 — effec
|
|
|
296
296
|
trackByFn = (item: IItem) => item.id;
|
|
297
297
|
```
|
|
298
298
|
|
|
299
|
-
**`filter` vs `lastFilter` 분리**:
|
|
299
|
+
**`filter` vs `lastFilter` 분리**: 폼 입력 도중 매번 재조회되지 않게 하기 위함. 사용자가 조회 버튼을 눌러야 `lastFilter` 가 갱신되고 effect 가 발화.
|
|
300
300
|
|
|
301
301
|
### 자동 재조회 effect
|
|
302
302
|
|
|
@@ -325,7 +325,7 @@ constructor() {
|
|
|
325
325
|
```
|
|
326
326
|
|
|
327
327
|
- `lastFilter` / `page` / `sortingDefs` 변경 시 자동 재조회.
|
|
328
|
-
- 비동기 본체는 `untracked` 안에서 실행해 자기 자신이 의존성에
|
|
328
|
+
- 비동기 본체는 `untracked` 안에서 실행해 자기 자신이 의존성에 등록되지 않게 함.
|
|
329
329
|
|
|
330
330
|
### 조회 트리거
|
|
331
331
|
|
|
@@ -335,9 +335,9 @@ onFilterSubmit(): void {
|
|
|
335
335
|
this.lastFilter.set({ ...this.filter() }); // effect 발화
|
|
336
336
|
}
|
|
337
337
|
|
|
338
|
-
doRefresh(): void { // 부모(view)가 호출하는 외부 API
|
|
338
|
+
doRefresh(): void { // 부모(view) 가 호출하는 외부 API
|
|
339
339
|
if (!this.perms().includes("use")) return;
|
|
340
|
-
mark(this.lastFilter); // 값은
|
|
340
|
+
mark(this.lastFilter); // 값은 동일하나 effect 재발화
|
|
341
341
|
}
|
|
342
342
|
```
|
|
343
343
|
|
|
@@ -351,30 +351,30 @@ private async _refresh(): Promise<void> {
|
|
|
351
351
|
}
|
|
352
352
|
```
|
|
353
353
|
|
|
354
|
-
`_search` 는 ORM 쿼리 실행. 자세한
|
|
354
|
+
`_search` 는 ORM 쿼리 실행. 자세한 사용법은 [orm.md](./orm.md) 참조.
|
|
355
355
|
|
|
356
356
|
### 페이지네이션
|
|
357
357
|
|
|
358
|
-
두 패턴 중 택일. 데이터 규모와 검색·정렬 책임에 따라 화면 작성자가 판단(명확한 컷오프 없음).
|
|
358
|
+
두 패턴 중 택일. 데이터 규모와 검색·정렬 책임에 따라 화면 작성자가 판단 (명확한 컷오프 없음).
|
|
359
359
|
|
|
360
|
-
**서버 페이징** — 한 페이지 분량만 매번 서버에서 가져옴.
|
|
360
|
+
**서버 페이징** — 한 페이지 분량만 매번 서버에서 가져옴. 위의 "시그널 구성" / "자동 재조회 effect" / "`_refresh` 구조" 섹션이 가정하는 기본 패턴.
|
|
361
361
|
|
|
362
|
-
- `pageLength` 시그널을
|
|
362
|
+
- `pageLength` 시그널을 두고, `_refresh` 에서 서버 응답의 총 페이지 수로 set.
|
|
363
363
|
- `page` / `sortingDefs` / `lastFilter` 모두 effect 의존성. 변경 시 재조회.
|
|
364
|
-
- `<sd-crud-list>` 에 `[totalPageCount]="pageLength()"` 전달. `[itemsPerPage]` 는 생략(=0).
|
|
364
|
+
- `<sd-crud-list>` 에 `[totalPageCount]="pageLength()"` 전달. `[itemsPerPage]` 는 생략 (= 0).
|
|
365
365
|
|
|
366
|
-
**클라이언트 페이징** — 전체 데이터를 한 번에
|
|
366
|
+
**클라이언트 페이징** — 전체 데이터를 한 번에 로드. 시트가 자체적으로 slice·sort 수행.
|
|
367
367
|
|
|
368
|
-
- `pageLength`
|
|
368
|
+
- `pageLength` 시그널과 `sortingDefs` effect 의존성 불필요 (정렬은 시트 내부에서 처리).
|
|
369
369
|
- `_refresh` 는 전체 아이템을 한 번에 `items.set(all)`.
|
|
370
|
-
- `<sd-crud-list>` 에 `[itemsPerPage]="<페이지당 행 수>"` 전달. `[totalPageCount]` 는 생략(=0).
|
|
371
|
-
- `[(sorts)]` 는 화면이 정렬 상태를
|
|
370
|
+
- `<sd-crud-list>` 에 `[itemsPerPage]="<페이지당 행 수>"` 전달. `[totalPageCount]` 는 생략 (= 0).
|
|
371
|
+
- `[(sorts)]` 는 화면이 정렬 상태를 보유해야 하는 경우에만 바인딩. 그 외에는 생략.
|
|
372
372
|
|
|
373
|
-
**`[visiblePageCount]`** (기본 10) — 페이지네이터가 한 번에 표시하는 페이지 번호 개수. 두 패턴 모두 사용자가 명시 지시한 경우에만
|
|
373
|
+
**`[visiblePageCount]`** (기본 10) — 페이지네이터가 한 번에 표시하는 페이지 번호 개수. 두 패턴 모두 사용자가 명시 지시한 경우에만 설정.
|
|
374
374
|
|
|
375
375
|
### 외부 input 을 filter 에 반영
|
|
376
376
|
|
|
377
|
-
list 가 다른 화면 안에 임베드되어 외부에서 filter 의 일부를 input 으로
|
|
377
|
+
list 가 다른 화면 안에 임베드되어 외부에서 filter 의 일부를 input 으로 받는 경우, effect 로 input → filter → lastFilter 흐름을 구성.
|
|
378
378
|
|
|
379
379
|
```ts
|
|
380
380
|
constructor() {
|
|
@@ -403,7 +403,7 @@ constructor() {
|
|
|
403
403
|
|
|
404
404
|
## detail 데이터 흐름
|
|
405
405
|
|
|
406
|
-
detail 컴포넌트는 식별자를 받아 자체
|
|
406
|
+
detail 컴포넌트는 식별자를 받아 자체 로드·저장을 수행하고, 변경·삭제 후 `submitted` 로 부모에게 알림.
|
|
407
407
|
|
|
408
408
|
### 시그널 구성
|
|
409
409
|
|
|
@@ -441,8 +441,8 @@ constructor() {
|
|
|
441
441
|
}
|
|
442
442
|
```
|
|
443
443
|
|
|
444
|
-
- 식별자(`dataId`)
|
|
445
|
-
- `setupCanDeactivate(fn)` (`@simplysm/angular`) 는 라우터 이탈 시점에 `fn()` 이 false
|
|
444
|
+
- 식별자(`dataId`) 가 effect 의존성. 부모가 다른 항목으로 전환하면 자동 재로드.
|
|
445
|
+
- `setupCanDeactivate(fn)` (`@simplysm/angular`) 는 라우터 이탈 시점에 `fn()` 이 false 를 반환하면 이탈을 차단.
|
|
446
446
|
|
|
447
447
|
### `_refresh` + 원본 스냅샷
|
|
448
448
|
|
|
@@ -502,9 +502,9 @@ async onSubmit(): Promise<void> {
|
|
|
502
502
|
|
|
503
503
|
- 식별자는 `input.required<>` 로 받음.
|
|
504
504
|
- 로드 후 `_orgData = obj.clone(loaded)` 로 원본 보관.
|
|
505
|
-
- 페이지 이탈 가드는 `setupCanDeactivate` + `obj.equal`
|
|
506
|
-
- 저장
|
|
507
|
-
- 삭제·취소 등 다른 액션도 끝에 `submitted.emit(true)` 를 emit 해 부모(list)가 새로고침할 수 있게 함.
|
|
505
|
+
- 페이지 이탈 가드는 `setupCanDeactivate` + `obj.equal` 비교로 처리.
|
|
506
|
+
- 저장 완료 후 `_refresh()` 로 다시 로드 → `submitted.emit(true)`.
|
|
507
|
+
- 삭제·취소 등 다른 액션도 끝에 `submitted.emit(true)` 를 emit 해 부모(list) 가 새로고침할 수 있게 함.
|
|
508
508
|
|
|
509
509
|
## 시트 컬럼·셀 표준
|
|
510
510
|
|
|
@@ -518,21 +518,21 @@ async onSubmit(): Promise<void> {
|
|
|
518
518
|
|
|
519
519
|
**폭 약속**:
|
|
520
520
|
|
|
521
|
-
- `[width]` 는
|
|
521
|
+
- `[width]` 는 **미명시가 기본** (자동). px 지정은 사용자가 명시 지시한 경우에만 적용.
|
|
522
522
|
- 영역 폭(`flex-min` 의 `style="width: ..."` 등) 도 동일.
|
|
523
523
|
|
|
524
524
|
**셀 본문 약속**:
|
|
525
525
|
|
|
526
|
-
- 시트 셀에는 패딩이 없으므로 본문 div 에 `p-xs-sm`
|
|
527
|
-
- 정렬 클래스(`tx-right` / `tx-center` / `tx-left`)는 **사용자가 명시 지시한 경우에만** 사용. 기본은 미지정(브라우저 기본 left). "라벨은 가운데" 같은 자동 휴리스틱 적용 금지.
|
|
526
|
+
- 시트 셀에는 패딩이 없으므로 본문 div 에 `p-xs-sm` 클래스 적용이 기본.
|
|
527
|
+
- 정렬 클래스(`tx-right` / `tx-center` / `tx-left`) 는 **사용자가 명시 지시한 경우에만** 사용. 기본은 미지정 (브라우저 기본 left). "라벨은 가운데" 같은 자동 휴리스틱 적용 금지.
|
|
528
528
|
- 단, **숫자 셀은 `tx-right` 기본 적용** (수량·금액·단가·합계 등 숫자값 컬럼).
|
|
529
|
-
- `[cell]="items()"` 는 타입 추론용
|
|
529
|
+
- `[cell]="items()"` 는 타입 추론용 더미. 실제 행 데이터는 `<sd-sheet>` 의 `[items]` 가 보유.
|
|
530
530
|
- 셀 컨텍스트: `let-item="item"` / `let-index="index"` / `let-depth="depth"` / `let-edit="edit"`.
|
|
531
|
-
- 셀 안 div 에 배경색 클래스(`bg-theme-*-lightest` 등)를 토글할 때는 빈 값 자리에 ` 
|
|
532
|
-
- 좋은 예: `{{ item.surveyLocationCode ?? " " }}`.
|
|
533
|
-
- 나쁜 예: `{{ item.surveyLocationCode }}`, `{{ item.surveyLocationCode ?? "
|
|
531
|
+
- 셀 안 div 에 배경색 클래스(`bg-theme-*-lightest` 등) 를 토글할 때는 빈 값 자리에 ` ` 를 채워 div 가 셀 높이를 유지하게 함 (table cell 자식 div 가 콘텐츠 없을 시 높이 0 → bg 가 셀을 채우지 못함).
|
|
532
|
+
- 좋은 예: `{{ item.surveyLocationCode ?? " " }}`.
|
|
533
|
+
- 나쁜 예: `{{ item.surveyLocationCode }}`, `{{ item.surveyLocationCode ?? "" }}`, `{{ item.surveyLocationCode ?? " " }}`.
|
|
534
534
|
|
|
535
|
-
**list 안에서**: `<sd-crud-list>` 의 직속 자식으로 `<sd-sheet-column>` 을 두면 내부 시트로 자동
|
|
535
|
+
**list 안에서**: `<sd-crud-list>` 의 직속 자식으로 `<sd-sheet-column>` 을 두면 내부 시트로 자동 투영.
|
|
536
536
|
|
|
537
537
|
```html
|
|
538
538
|
<sd-crud-list ...>
|
|
@@ -546,7 +546,7 @@ async onSubmit(): Promise<void> {
|
|
|
546
546
|
|
|
547
547
|
### 요약 행
|
|
548
548
|
|
|
549
|
-
컬럼에 `<ng-template #summaryTpl>` 을 두면 시트의 헤더 영역 하단(`thead` 내부)에 요약 행이 렌더됨. 스크롤 시 헤더와 함께 상단 고정되며, 배경은 warning 계열로 자동
|
|
549
|
+
컬럼에 `<ng-template #summaryTpl>` 을 두면 시트의 헤더 영역 하단(`thead` 내부) 에 요약 행이 렌더됨. 스크롤 시 헤더와 함께 상단 고정되며, 배경은 warning 계열로 자동 강조.
|
|
550
550
|
|
|
551
551
|
```html
|
|
552
552
|
<sd-sheet-column [key]="'quantity'" [header]="'수량'">
|
|
@@ -559,9 +559,9 @@ async onSubmit(): Promise<void> {
|
|
|
559
559
|
</sd-sheet-column>
|
|
560
560
|
```
|
|
561
561
|
|
|
562
|
-
- 컬럼 중 하나라도 `#summaryTpl` 을 가지면 요약 행 전체가 활성화됨. 정의 없는 컬럼은 빈
|
|
563
|
-
- 셀 본문 약속(`p-xs-sm`, 정렬 클래스 등)은 요약 셀에도 동일하게 적용.
|
|
564
|
-
- 합계·평균 등 집계 값은 시트가
|
|
562
|
+
- 컬럼 중 하나라도 `#summaryTpl` 을 가지면 요약 행 전체가 활성화됨. 정의 없는 컬럼은 빈 셀로 표시.
|
|
563
|
+
- 셀 본문 약속(`p-xs-sm`, 정렬 클래스 등) 은 요약 셀에도 동일하게 적용.
|
|
564
|
+
- 합계·평균 등 집계 값은 시트가 계산하지 않음. 화면 컴포넌트에서 `computed` 로 직접 만들어 노출.
|
|
565
565
|
|
|
566
566
|
```ts
|
|
567
567
|
totalQuantity = computed(() => this.items().sum((i) => i.quantity) ?? 0);
|
|
@@ -571,11 +571,11 @@ totalQuantity = computed(() => this.items().sum((i) => i.quantity) ?? 0);
|
|
|
571
571
|
|
|
572
572
|
### 폼 항목 레이아웃
|
|
573
573
|
|
|
574
|
-
label
|
|
574
|
+
label 과 입력 그룹을 묶는 전용 클래스 3종:
|
|
575
575
|
|
|
576
|
-
- `form-box` — 세로 스택. `> div`
|
|
577
|
-
- `form-box-inline` — 가로 인라인 flex (wrap). 라벨이 입력 옆에 붙음.
|
|
578
|
-
- `form-table` — `<table>` 기반. `<th>` 가 우측 정렬 라벨, `<td>` 가 입력. `<th class="form-table-header">` 는 섹션 헤더(좌측 정렬, 회색, 위쪽 여백 큼).
|
|
576
|
+
- `form-box` — 세로 스택. `> div` 안에 `<label>` + 입력. 항목 사이 간격은 `gap-default`.
|
|
577
|
+
- `form-box-inline` — 가로 인라인 flex (wrap). 라벨이 입력 옆에 붙음. 검색·필터 폼에 사용. 라벨 없는 `form-box-item` 도 허용 (버튼 등).
|
|
578
|
+
- `form-table` — `<table>` 기반. `<th>` 가 우측 정렬 라벨, `<td>` 가 입력. `<th class="form-table-header">` 는 섹션 헤더 (좌측 정렬, 회색, 위쪽 여백 큼). 라벨·입력 폭을 정렬해야 하는 등록·편집 폼에 사용.
|
|
579
579
|
|
|
580
580
|
```html
|
|
581
581
|
<div class="form-box-inline">
|
|
@@ -591,7 +591,7 @@ label + 입력 그룹을 묶는 전용 클래스 3종:
|
|
|
591
591
|
|
|
592
592
|
### 양방향 바인딩 + `mark`
|
|
593
593
|
|
|
594
|
-
객체 시그널 내부 필드를 양방향으로 묶고, 변경 시
|
|
594
|
+
객체 시그널 내부 필드를 양방향으로 묶고, 변경 시 위의 "`mark` 헬퍼" 섹션 패턴으로 알림.
|
|
595
595
|
|
|
596
596
|
```html
|
|
597
597
|
<sd-textfield [(value)]="data().name" (valueChange)="mark(data)" />
|
|
@@ -611,7 +611,7 @@ label + 입력 그룹을 묶는 전용 클래스 3종:
|
|
|
611
611
|
|
|
612
612
|
### 버튼 스타일
|
|
613
613
|
|
|
614
|
-
화면 액션 `<sd-button>` 은 역할별로 `theme`·`size` 를
|
|
614
|
+
화면 액션 `<sd-button>` 은 역할별로 `theme`·`size` 를 구분 적용.
|
|
615
615
|
|
|
616
616
|
| 역할 | `[theme]` | `[size]` |
|
|
617
617
|
| ------------------------------------------------------------- | --------------------------------------------------------------------------- | -------- |
|
|
@@ -621,7 +621,7 @@ label + 입력 그룹을 묶는 전용 클래스 3종:
|
|
|
621
621
|
|
|
622
622
|
### `<sd-form>` 으로 감싸기
|
|
623
623
|
|
|
624
|
-
폼 안 입력에서
|
|
624
|
+
폼 안 입력에서 Enter 키로 submit 이 자동 처리되게 하려면 `<sd-form>` 으로 감싸고 `(formSubmit)` 으로 받음. `sd-crud-list` / `sd-crud-detail` 는 내부에 이미 `sd-form` 을 보유하므로 별도 래핑 불필요.
|
|
625
625
|
|
|
626
626
|
## 서비스 호출 (`AppServiceProvider`)
|
|
627
627
|
|
|
@@ -645,11 +645,11 @@ await this._appOrm.connectAsync(async (db) => {
|
|
|
645
645
|
```
|
|
646
646
|
|
|
647
647
|
- 기본은 `connectAsync` (트랜잭션). `connectWithoutTransAsync` 는 트랜잭션 안에서 동작하지 않는 작업용 헬퍼.
|
|
648
|
-
- 쿼리
|
|
648
|
+
- 쿼리 작성법은 [orm.md](./orm.md), Provider 정의 컨벤션은 [client-setup.md#appormprovider](./client-setup.md#appormprovider) 참조.
|
|
649
649
|
|
|
650
650
|
## 공유 데이터 (`useSharedSignal`)
|
|
651
651
|
|
|
652
|
-
마스터 데이터(고객사·품목 등)는 `AppSharedDataProvider` 에 등록되어 있고, 화면에서는 `useSharedSignal(name)` 으로
|
|
652
|
+
마스터 데이터(고객사·품목 등) 는 `AppSharedDataProvider` 에 등록되어 있고, 화면에서는 `useSharedSignal(name)` 으로 접근.
|
|
653
653
|
|
|
654
654
|
```ts
|
|
655
655
|
sharedCustomers = useSharedSignal("고객사");
|
|
@@ -666,7 +666,7 @@ sharedCustomers = useSharedSignal("고객사");
|
|
|
666
666
|
|
|
667
667
|
## 레이아웃·유틸 클래스
|
|
668
668
|
|
|
669
|
-
**화면 레이아웃** (영역 분할)
|
|
669
|
+
**화면 레이아웃** (영역 분할) 은 flex 유틸 클래스로 구성.
|
|
670
670
|
|
|
671
671
|
상하 분할 (상단 고정 + 본문 fill):
|
|
672
672
|
|
|
@@ -694,10 +694,10 @@ sharedCustomers = useSharedSignal("고객사");
|
|
|
694
694
|
</div>
|
|
695
695
|
```
|
|
696
696
|
|
|
697
|
-
자주
|
|
697
|
+
자주 사용하는 유틸:
|
|
698
698
|
|
|
699
699
|
- **Flex**: `flex-row` / `flex-column` (컨테이너), `flex-fill` (남은 공간), `flex-min` (콘텐츠 크기), `gap-sm` / `gap-default`.
|
|
700
|
-
- **부모
|
|
700
|
+
- **부모 가득 채움**: `fill`.
|
|
701
701
|
- **패딩**: `p-{vertical}-{horizontal}` (예: `p-default`, `p-xs-sm`, `p-sm-default`). 단일 방향: `pt-` / `pb-` / `pl-` / `pr-`.
|
|
702
702
|
- **텍스트**: `tx-left` / `tx-center` / `tx-right`.
|
|
703
703
|
- **테마 색**: 텍스트 `tx-theme-{theme}-default`, 배경 `bg-{theme}-lightest`.
|
|
@@ -705,12 +705,12 @@ sharedCustomers = useSharedSignal("고객사");
|
|
|
705
705
|
|
|
706
706
|
**약속**:
|
|
707
707
|
|
|
708
|
-
- 영역 분할·배치 모두 flex 유틸 클래스
|
|
709
|
-
- 글로벌 클래스
|
|
708
|
+
- 영역 분할·배치 모두 flex 유틸 클래스 우선 적용. 자체 styles 작성은 최후 수단.
|
|
709
|
+
- 글로벌 클래스 정의 위치는 `@simplysm/angular/scss/commons/`.
|
|
710
710
|
|
|
711
711
|
## 아이콘
|
|
712
712
|
|
|
713
|
-
`@ng-icons/core` 의 `NgIcon` + `@ng-icons/tabler-icons` 의 `tabler*` 셋트를
|
|
713
|
+
`@ng-icons/core` 의 `NgIcon` + `@ng-icons/tabler-icons` 의 `tabler*` 셋트를 사용.
|
|
714
714
|
|
|
715
715
|
```ts
|
|
716
716
|
import { NgIcon } from "@ng-icons/core";
|
|
@@ -731,9 +731,9 @@ export class SomeComponent {
|
|
|
731
731
|
|
|
732
732
|
**약속**:
|
|
733
733
|
|
|
734
|
-
- 아이콘 셋트는 `tabler-icons` 통일.
|
|
735
|
-
- 사용할 아이콘은 컴포넌트 클래스에 `protected readonly tablerXxx = tablerXxx` 로
|
|
734
|
+
- 아이콘 셋트는 `tabler-icons` 로 통일.
|
|
735
|
+
- 사용할 아이콘은 컴포넌트 클래스에 `protected readonly tablerXxx = tablerXxx` 로 노출한 뒤 템플릿에서 `[svg]` 바인딩.
|
|
736
736
|
|
|
737
737
|
## sd-crud-* 컴포넌트
|
|
738
738
|
|
|
739
|
-
목록 화면 표준
|
|
739
|
+
목록 화면 표준 골격은 `sd-crud-list`, 단건 편집 화면 표준 골격은 `sd-crud-detail`. 화면 작성 시 채택 여부를 결정. 채택 시 사용법은 [client-crud.md](./client-crud.md) 참조.
|