@simplysm/sd-claude 14.0.93 → 14.0.95
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 +10 -6
- package/claude/references/sd-simplysm14/apis/angular/README.md +180 -43
- package/claude/references/sd-simplysm14/apis/angular/controls.md +275 -125
- package/claude/references/sd-simplysm14/apis/angular/crud.md +54 -59
- package/claude/references/sd-simplysm14/apis/angular/directives.md +139 -48
- package/claude/references/sd-simplysm14/apis/angular/features.md +102 -88
- package/claude/references/sd-simplysm14/apis/angular/kanban.md +54 -0
- package/claude/references/sd-simplysm14/apis/angular/layout.md +60 -36
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +127 -75
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +97 -51
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +74 -58
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +81 -60
- package/claude/references/sd-simplysm14/apis/excel/README.md +5 -5
- package/claude/references/sd-simplysm14/apis/excel/cell.md +3 -3
- package/claude/references/sd-simplysm14/apis/excel/style.md +2 -2
- package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +5 -4
- package/claude/references/sd-simplysm14/apis/excel/wrapper.md +2 -2
- package/claude/references/sd-simplysm14/manuals/client-app-structure.md +4 -2
- package/claude/references/sd-simplysm14/manuals/client-component.md +24 -24
- package/claude/references/sd-simplysm14/manuals/client-crud.md +328 -0
- package/claude/references/sd-simplysm14/manuals/client-demo.md +6 -19
- package/claude/references/sd-simplysm14/manuals/client-shared-data.md +49 -0
- package/claude/references/sd-simplysm14/manuals/data-log.md +33 -1
- package/claude/references/sd-simplysm14/manuals/orm.md +37 -0
- package/claude/sd-system-prompt.md +11 -0
- package/claude/skills/sd-debug/SKILL.md +142 -27
- package/claude/skills/sd-review/SKILL.md +158 -20
- package/claude/skills/sd-spec/SKILL.md +1 -0
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/apis/angular/infra.md +0 -82
- package/claude/skills/sd-debug/workflow.js +0 -390
- package/claude/skills/sd-review/workflow.js +0 -324
|
@@ -1,76 +1,167 @@
|
|
|
1
|
-
# @simplysm/angular — 호스트 디렉티브·signal
|
|
1
|
+
# @simplysm/angular — 호스트 디렉티브·signal 헬퍼
|
|
2
2
|
|
|
3
|
-
DOM 관찰(리사이즈/교차)·캡처 이벤트·커맨드 단축키·ripple·노출 애니메이션·invalid 표시·타입드 템플릿을 호스트 엘리먼트에 붙이는 디렉티브와,
|
|
3
|
+
DOM 관찰(리사이즈/교차)·캡처 이벤트·커맨드 단축키·ripple·노출 애니메이션·invalid 표시·타입드 템플릿을 호스트 엘리먼트에 붙이는 디렉티브와, signal/model 을 다루는 작은 헬퍼 군. `setup*` 헬퍼는 컴포넌트 `constructor`(주입 컨텍스트)에서 호출(`inject(ElementRef)` 의존), `Sd*` 디렉티브는 그 헬퍼를 attribute 로 래핑.
|
|
4
4
|
|
|
5
5
|
## DOM 관찰 디렉티브
|
|
6
6
|
|
|
7
7
|
### SdResizeDirective — `[sdResize]`
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
sdResize = output<SdResizeEvent>();
|
|
11
|
+
// SdResizeEvent { heightChanged: boolean; widthChanged: boolean; target: HTMLElement; contentRect: DOMRectReadOnly }
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- `ResizeObserver` 로 크기 변화를 rAF 디바운스해 방출. `heightChanged`/`widthChanged` 로 변경 축을 구분(불필요한 재계산 회피). 시트·collapse·echarts 가 사용.
|
|
15
|
+
|
|
16
|
+
```html
|
|
17
|
+
<div (sdResize)="onResize($event)">...</div>
|
|
18
|
+
```
|
|
10
19
|
|
|
11
20
|
### SdIntersectionDirective — `[sdIntersection]`
|
|
12
|
-
IntersectionObserver 로 화면 교차 감지.
|
|
13
|
-
- `sdIntersection: output<SdIntersectionEvent>` — `{ entry: IntersectionObserverEntry }`. 마지막 entry 전달. 무한 스크롤·등장 트리거에.
|
|
14
21
|
|
|
15
|
-
|
|
22
|
+
```ts
|
|
23
|
+
sdIntersection = output<SdIntersectionEvent>();
|
|
24
|
+
// SdIntersectionEvent { entry: IntersectionObserverEntry }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- `IntersectionObserver` 로 뷰포트 진입/이탈을 방출. 지연 로드·노출 트리거에 사용. `entry.isIntersecting` 으로 판정.
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
|
|
29
|
+
## 이벤트·커맨드 디렉티브
|
|
30
|
+
|
|
31
|
+
### SdEvents — 이벤트 수식어 출력
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// selector 의 각 어트리뷰트가 output. 예:
|
|
35
|
+
"click.capture", "click.once", "scroll.passive", "wheel.passive",
|
|
36
|
+
"touchstart.passive", "keydown.capture", "focus.capture", "blur.capture",
|
|
37
|
+
"invalid.capture", "transitionend.once", "animationend.once" ...
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- capture/passive/once 수식어가 붙은 DOM 이벤트를 Angular 출력으로 노출(`SdOptionEventPlugin` 과 함께 동작). 성능·캡처가 필요한 이벤트 바인딩에 사용. 호스트 디렉티브로도 쓰임(시트가 `keydown.capture` 등 사용).
|
|
41
|
+
|
|
42
|
+
```html
|
|
43
|
+
<div (scroll.passive)="onScroll()" (keydown.capture)="onKeydown($event)">...</div>
|
|
44
|
+
```
|
|
19
45
|
|
|
20
46
|
### SdOptionEventPlugin
|
|
21
|
-
위 `.capture`/`.passive`/`.once` 접미사 이벤트를 Angular 가 인식하게 하는 `EventManagerPlugin`. `provideSdAngular` 가 등록하므로 직접 쓸 일은 없음.
|
|
22
47
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- `
|
|
48
|
+
```ts
|
|
49
|
+
class SdOptionEventPlugin extends EventManagerPlugin
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- `.capture`/`.passive`/`.once` 수식어 이벤트를 처리하는 Angular `EVENT_MANAGER_PLUGINS`. `provideSdAngular` 가 등록(직접 사용 안 함). `SdEvents` 디렉티브의 기반.
|
|
53
|
+
|
|
54
|
+
### SdCommandDirective — `[sdRefreshCommand]` / `[sdSaveCommand]` / `[sdInsertCommand]`
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
sdRefreshCommand = output<KeyboardEvent>(); // Ctrl+Alt+L
|
|
58
|
+
sdSaveCommand = output<KeyboardEvent>(); // Ctrl+S
|
|
59
|
+
sdInsertCommand = output<KeyboardEvent>(); // Insert
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- 전역 키보드 단축키를 출력으로. 최상위 열린 모달 안에서만 동작(다른 화면 간섭 방지). crud 골격이 `sdSaveCommand` 로 CTRL+S 저장 연결.
|
|
63
|
+
|
|
64
|
+
### SdGlobalErrorHandlerPlugin
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
class SdGlobalErrorHandlerPlugin implements ErrorHandler
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- 전역 에러 핸들러. 처리되지 않은 에러/Promise 거부를 시스템 로그 적재 + 전체화면 에러 오버레이로 표시(앱 destroy 후 클릭 시 reload). `provideSdAngular` 가 `ErrorHandler` 로 등록(직접 사용 안 함).
|
|
71
|
+
|
|
72
|
+
## 시각 효과·검증 디렉티브
|
|
73
|
+
|
|
74
|
+
### setupRipple / SdRipple — `[sdRipple]`
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
setupRipple(enableFn?: () => boolean): void;
|
|
78
|
+
// SdRipple: enabled = input.required({ alias: "sdRipple", transform: booleanAttribute });
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- 클릭 시 파동(ripple) 효과. `setupRipple` 은 constructor 에서, `[sdRipple]="true"` 디렉티브는 템플릿에서. `enableFn`/`enabled` 가 false 면 효과 비활성(disabled 컨트롤). 버튼·체크박스·리스트가 사용.
|
|
82
|
+
|
|
83
|
+
### setupRevealOnShow / SdShowEffect — `[sdShowEffect]`
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
setupRevealOnShow(optFn?: () => { type?: "l2r" | "t2b"; enabled?: boolean }): void;
|
|
87
|
+
// SdShowEffect: enabled = input.required({ alias: "sdShowEffect" }); sdShowEffectType = input<"l2r"|"t2b">("t2b");
|
|
88
|
+
```
|
|
28
89
|
|
|
29
|
-
|
|
90
|
+
- 뷰포트 진입 시 페이드+슬라이드 노출 애니메이션. `type` `"t2b"`=위→아래(기본), `"l2r"`=좌→우. `enabled`=false 면 애니메이션 없이 즉시 표시.
|
|
30
91
|
|
|
31
|
-
###
|
|
32
|
-
클릭 위치에서 퍼지는 ripple 효과.
|
|
33
|
-
- `setupRipple(enableFn?: () => boolean): void` — 호스트에 ripple 부착. `enableFn` 이 false 반환 시 비활성.
|
|
34
|
-
- `SdRipple`(`[sdRipple]`): `sdRipple: input.required<boolean>` — ripple 활성 여부.
|
|
92
|
+
### setupInvalid / SdInvalid — `[sdInvalid]`
|
|
35
93
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
94
|
+
```ts
|
|
95
|
+
setupInvalid(getInvalidMessage: () => string): void;
|
|
96
|
+
// SdInvalid: invalidMessage = input.required<string>({ alias: "sdInvalid" });
|
|
97
|
+
```
|
|
40
98
|
|
|
41
|
-
|
|
42
|
-
커스텀 유효성 메시지를 네이티브 폼 검증으로 표시(빨간 인디케이터 + form submit 차단).
|
|
43
|
-
- `setupInvalid(getInvalidMessage: () => string): void` — 빈 문자열이면 유효, 아니면 그 메시지로 invalid. 숨겨진 input 의 `setCustomValidity` 로 처리.
|
|
44
|
-
- `SdInvalid`(`[sdInvalid]`): `sdInvalid: input.required<string>` — 오류 메시지(빈 값=유효).
|
|
99
|
+
- 호스트에 숨김 input 을 붙여 native form 검증에 참여. `getInvalidMessage()`/`invalidMessage` 가 빈 문자열이 아니면 invalid(좌상단 빨간 인디케이터 + form 제출 차단). 폼 입력 컨트롤이 내부 사용.
|
|
45
100
|
|
|
46
101
|
## 타입드 템플릿 디렉티브
|
|
47
102
|
|
|
48
103
|
### SdTypedTemplate — `ng-template[typed]`
|
|
49
|
-
`ng-template` 컨텍스트에 타입을 부여.
|
|
50
|
-
- `typed: input.required<T>` — 컨텍스트 타입 토큰. `ngTemplateContextGuard` 로 `let-` 변수 타입 추론.
|
|
51
104
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
105
|
+
```ts
|
|
106
|
+
typed = input.required<T>();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
- `ng-template` 컨텍스트 타입을 명시(`ngTemplateContextGuard`). 재귀 메뉴/트리 템플릿에서 `let-x` 의 타입 안전성 확보. `[typed]` 에 타입 토큰을 넘김.
|
|
55
110
|
|
|
56
|
-
|
|
57
|
-
|
|
111
|
+
### SdItemOfTemplate — `ng-template[itemOf]`
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
itemOf = input.required<TItem[]>();
|
|
115
|
+
// SdItemOfTemplateContext<TItem> { $implicit; item; index; depth }
|
|
58
116
|
```
|
|
59
117
|
|
|
60
|
-
|
|
118
|
+
- 반복 항목 템플릿 마커. `[itemOf]="items()"` 로 항목 타입을 추론해 `let-item`/`let-index`/`let-depth` 제공. select·shared-data·calendar 등의 항목 슬롯에 사용.
|
|
119
|
+
|
|
120
|
+
## signal·model 헬퍼
|
|
61
121
|
|
|
62
|
-
|
|
122
|
+
### setupModelHook
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
setupModelHook<T>(model: WritableSignal<T>, canFn: Signal<(item: T) => boolean | Promise<boolean>>): void;
|
|
126
|
+
```
|
|
63
127
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
128
|
+
- model 의 `set`/`update` 를 가로채 `canFn` 이 허용할 때만 적용. false 면 변경 거부, Promise 면 비동기 확인 후 적용(에러는 `ErrorHandler`). 체크박스·스위치·select-list 의 `canChangeFn` 이 사용.
|
|
129
|
+
|
|
130
|
+
### mark
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
mark(sig: WritableSignal<any>): void;
|
|
134
|
+
```
|
|
67
135
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
136
|
+
- in-place mutation 한 signal 값에 shallow copy(배열/객체)로 새 참조를 만들어 변경 통지. 시트 셀에서 객체 필드를 직접 수정한 뒤 호출(`(valueChange)="mark(items)"`).
|
|
137
|
+
|
|
138
|
+
### setSafeStyle
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
setSafeStyle(renderer: Renderer2, el: HTMLElement, style: Partial<CSSStyleDeclaration>): void;
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
- `Renderer2.setStyle` 로 여러 스타일을 한 번에 적용하는 헬퍼(키별 순회). `style` 객체의 각 CSS 속성을 엘리먼트에 설정. 디렉티브/composable 에서 DOM 스타일을 안전하게 줄 때 사용(`setupInvalid` 등이 내부 사용).
|
|
145
|
+
|
|
146
|
+
### FormatPipe — `| format`
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
@Pipe({ name: "format" }) transform(value: string | DateTime | DateOnly | undefined, format: string): string;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- 값 포맷. `DateTime`/`DateOnly` 는 `toFormatString(format)`, 문자열은 `X` 마스크(`|` 로 길이 분기). null 이면 빈 문자열(결측 보존). calendar 등이 사용.
|
|
153
|
+
|
|
154
|
+
```html
|
|
155
|
+
{{ date | format: "yyyy-MM-dd" }}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 타입 유틸
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
DirectiveInputSignals<T> // 컴포넌트의 InputSignal 프로퍼티 → 값 타입 매핑(undefined 포함 필드는 optional)
|
|
162
|
+
UndefToOptional<T> // undefined 포함 프로퍼티를 optional 로 변환
|
|
163
|
+
WithOptional<T, K> // 특정 키 K 를 optional 로
|
|
164
|
+
SelectModalOutputResult<TKey> { selectedKeys: TKey[] } // 선택 모달 close 페이로드
|
|
165
|
+
```
|
|
72
166
|
|
|
73
|
-
|
|
74
|
-
- 입력: `items`/`expandedItems`(model)/`getChildrenFn`/`sort`.
|
|
75
|
-
- 반환: `displayItems`(펼침 반영 평면 목록)/`hasExpandable`/`isAllExpanded`(Signal), `toggle`/`toggleAll`/`isVisible(item)`(조상이 모두 펼쳐졌는지)/`def(item)`(`ExpandItemDef`).
|
|
76
|
-
- `ExpandItemDef<T>` — `{ item; parentDef; hasChildren; depth }`.
|
|
167
|
+
- `DirectiveInputSignals<T>` — 모달/토스트/인쇄의 `inputs` 타입 계산에 쓰이는 유틸(컴포넌트 input signal 을 일반 값 객체로 매핑). `SelectModalOutputResult` — 선택형 모달이 close 로 돌려주는 표준 페이로드.
|
|
@@ -1,108 +1,122 @@
|
|
|
1
|
-
# @simplysm/angular — 부가 기능(
|
|
1
|
+
# @simplysm/angular — 부가 기능(권한표·상태프리셋·테마·주소·에디터·시각화)
|
|
2
2
|
|
|
3
|
-
위 군에 들지 않는 도메인성/표시용 컴포넌트 모음. 특정 화면 기능을 붙일 때 개별로 읽힘.
|
|
3
|
+
위 군에 들지 않는 도메인성/표시용 컴포넌트 모음. 특정 화면 기능을 붙일 때 개별로 읽힘. 모두 standalone `sd-*` 컴포넌트.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## SdPermissionTable — `<sd-permission-table>`
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```ts
|
|
8
|
+
value = model<Record<string, boolean>>({}); // "<코드>.use"/"<코드>.edit" → boolean
|
|
9
|
+
items = input<SdPermission<TModule>[]>([]);
|
|
10
|
+
disabled = input(false);
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- 권한 트리 편집표. `items`(`SdPermission` 트리, routing-appstructure.md)를 사용/편집 체크박스 표로 렌더. `value` 는 `<코드>.use`/`<코드>.edit` 키의 boolean 맵(양방향).
|
|
14
|
+
- use 미체크면 edit 불가, use 해제 시 edit 자동 해제, 부모 토글 시 하위 일괄 변경. `disabled`=전체 읽기전용. 권한 관리 화면에 사용.
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
- `selectedValues: model<T[]>` — 선택된 카드 값(Shift+클릭 다중 선택).
|
|
11
|
-
- `drop: output<SdKanbanBoardDropInfo<L, T>>` — 카드 드롭 시 emit. `{ sourceKanbanValue?, targetLaneValue?, targetKanbanValue? }`(이동한 카드/대상 레인/대상 카드 값).
|
|
16
|
+
## SdStatePreset — `<sd-state-preset>`
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- `collapse: model<boolean>` — 접힘 상태.
|
|
18
|
-
- 슬롯: `#titleTpl`(레인 제목), `#toolTpl`(도구). 자식 `sd-kanban` 들 배치.
|
|
18
|
+
```ts
|
|
19
|
+
key = input.required<string>(); state = model.required<TState>(); size = input<"sm"|"lg">();
|
|
20
|
+
// SdStatePresetDef<TState> { name: string; state: TState }
|
|
21
|
+
```
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
- `
|
|
22
|
-
- `selectable: boolean` — Shift+클릭 선택 가능.
|
|
23
|
-
- `draggable: boolean` — 드래그 가능.
|
|
24
|
-
- `contentClass: string` — 카드 클래스.
|
|
23
|
+
- 현재 화면 상태(`state`)를 이름붙여 저장·복원하는 프리셋 바(검색 조건 즐겨찾기 등). 별 버튼=현재 상태 저장(이름 prompt), 프리셋 클릭=상태 적용, 저장/삭제 버튼 제공.
|
|
24
|
+
- `key` 로 `injectSdSystemConfigResource` 에 영속. `state` 는 화면이 들고 있는 상태 시그널(양방향).
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
## SdThemeProvider 셀렉터
|
|
27
|
+
|
|
28
|
+
### SdThemeSelector — `<sd-theme-selector>`
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
// 입력 없음. SdThemeProvider 를 inject.
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
- 다크모드 토글 + 글자크기 증감 UI 드롭다운. `SdThemeProvider` 를 직접 조작(`fontSize`/`dark`). 탑바 등에 배치. provider 본체는 [README.md](./README.md) "테마·배경".
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
- `value: model<Record<string, boolean>>` — `"코드.액션"→보유` 권한 맵(체크 상태).
|
|
36
|
-
- `items: input<SdPermission<TModule>[]>` — 권한 트리.
|
|
37
|
-
- `disabled: boolean` — 읽기 전용.
|
|
36
|
+
## SdAddressSearchModal — `<sd-address-search-modal>`
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
```ts
|
|
39
|
+
close = output<Address>(); // SdModalContentDef<Address>
|
|
40
|
+
// Address { postNumber: string | undefined; address: string | undefined; buildingName: string | undefined }
|
|
41
|
+
```
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
- `key: input.required<string>` — 프리셋 저장 키(화면 식별).
|
|
43
|
-
- `state: model.required<TState>` — 현재 화면 상태. 프리셋 클릭 시 이 모델에 복원, 저장 시 현재 값을 프리셋에 기록.
|
|
44
|
-
- `size: "sm"|"lg"` — 크기.
|
|
45
|
-
- `SdStatePresetDef<TState>` — `{ name: string; state: TState }`(저장 단위).
|
|
43
|
+
- 다음(Daum) 우편번호 검색 모달. `SdModalProvider.showAsync({ type: SdAddressSearchModal, inputs: {} })` 로 띄움. 스크립트를 동적 로드하며 실패 시 에러 메시지 표시. 선택 시 `{ postNumber, address, buildingName }` 으로 close.
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
```ts
|
|
46
|
+
const addr = await this._sdModal.showAsync({ title: "주소 검색", type: SdAddressSearchModal, inputs: {} });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## SdTiptapEditor — `<sd-tiptap-editor>`
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
value = model<string>(); // HTML
|
|
53
|
+
disabled; readonly; required; placeholder = input<string>();
|
|
54
|
+
validatorFn = input<(value: string | undefined) => string | undefined>();
|
|
55
|
+
extensions = input<AnyExtension[]>();
|
|
56
|
+
editor: WritableSignal<Editor | undefined>; // @internal — TipTap 인스턴스
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- 리치 텍스트(WYSIWYG) 에디터. `value` 는 HTML 문자열(빈 내용이면 undefined, 결측 보존). 내장 툴바(제목·굵게·색·정렬·목록·인용·코드블록 등) 제공.
|
|
60
|
+
- `extensions` 지정 시 기본 확장 대체, 미지정 시 StarterKit + 색/하이라이트/정렬/이미지/밑줄(+placeholder). `disabled`/`readonly`=편집 불가, `required`/`validatorFn`=form 검증(`setupInvalid`).
|
|
61
|
+
|
|
62
|
+
## 시각화
|
|
63
|
+
|
|
64
|
+
### SdLabel — `<sd-label>`
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
theme = input<"primary"|"secondary"|"info"|"success"|"warning"|"danger"|"gray"|"blue-gray">();
|
|
68
|
+
color = input<string>(); clickable = input(false);
|
|
69
|
+
```
|
|
48
70
|
|
|
49
|
-
|
|
71
|
+
- 짧은 배지/태그. `theme` 또는 임의 `color`(배경) 지정. `clickable`=호버 강조 + 커서 포인터. 상태 표시에 사용.
|
|
72
|
+
|
|
73
|
+
### SdNote — `<sd-note>`
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
theme = input<...8색>(); size = input<"sm"|"lg">(); inset = input(false);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- 안내 박스(callout). `theme` 의 옅은 배경. `inset`=라운드 제거(영역 내장). 주의/도움말 문구에 사용.
|
|
80
|
+
|
|
81
|
+
### SdProgress — `<sd-progress>`
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
theme = input.required<...8색>(); value = input.required<number>(); // 0~1
|
|
85
|
+
inset; size = input<"sm"|"lg">();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- 진행률 막대. `value`(0~1)를 퍼센트 텍스트 + 채움 막대로 표시(0~100% clamp). `theme` 필수.
|
|
89
|
+
|
|
90
|
+
### SdCalendar — `<sd-calendar>`
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
items = input.required<T[]>(); getItemDateFn = input.required<(item: T, index: number) => DateOnly>();
|
|
94
|
+
yearMonth = input(new DateOnly().setDay(1));
|
|
95
|
+
weekStartDay = input(0); minDaysInFirstWeek = input(1);
|
|
96
|
+
itemTplRef = contentChild.required(SdItemOfTemplate); // [itemOf] 셀 항목 템플릿(필수)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- 월간 캘린더. `getItemDateFn` 으로 각 항목의 날짜를 산출해 해당 칸에 `[itemOf]` 템플릿으로 렌더. `yearMonth`=표시 월, `weekStartDay`=주 시작 요일(0=일), `minDaysInFirstWeek`=첫 주 판정.
|
|
100
|
+
|
|
101
|
+
```html
|
|
102
|
+
<sd-calendar [items]="schedules()" [getItemDateFn]="getDate" [yearMonth]="month()">
|
|
103
|
+
<ng-template [itemOf]="schedules()" let-item="item">{{ item.title }}</ng-template>
|
|
104
|
+
</sd-calendar>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### SdBarcode — `<sd-barcode>`
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
type = input.required<BarcodeType>(); value = input<string>();
|
|
111
|
+
// BarcodeType: "qrcode"|"code128"|"ean13"|"datamatrix"|... (bwip-js 전체 심볼 유니온)
|
|
112
|
+
```
|
|
50
113
|
|
|
51
|
-
|
|
114
|
+
- 바코드/QR 렌더(bwip-js SVG). `type`=심볼 종류, `value`=인코딩 문자열(빈 값이면 미표시). `BarcodeType` 는 bwip-js 가 지원하는 전체 바코드 유형 리터럴 유니온.
|
|
52
115
|
|
|
53
|
-
|
|
54
|
-
- `close: output<Address>` — 선택 결과. `Address` = `{ postNumber?: string; address?: string; buildingName?: string }`(미입력 필드는 undefined 보존).
|
|
116
|
+
### SdEcharts — `<sd-echarts>`
|
|
55
117
|
|
|
56
118
|
```ts
|
|
57
|
-
|
|
119
|
+
option = input.required<echarts.EChartsOption>(); notMerge = input(false); loading = input(false);
|
|
58
120
|
```
|
|
59
121
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
리치텍스트(Tiptap) 에디터. 색상·정렬·목록 툴바 내장.
|
|
63
|
-
- `value: model<string>` — HTML 값.
|
|
64
|
-
- `disabled`/`readonly`/`required: boolean` — 상태.
|
|
65
|
-
- `placeholder: string` — 빈 상태 안내.
|
|
66
|
-
- `validatorFn: (value) => string | undefined` — 커스텀 검증(반환 문자열이 오류).
|
|
67
|
-
- `extensions: AnyExtension[]` — 추가 Tiptap 확장.
|
|
68
|
-
|
|
69
|
-
보조 헬퍼 `useTiptapToolbar(opt)` — 에디터 시그널을 받아 툴바 상태/명령을 반환(`activeStates`/`activeColor`/`execCmd`/`refreshActiveStates`/`toggleColorPicker`/`applyColor` 등). `TiptapActiveStates` 는 h1/h2/bold/italic/underline/strike/bulletList/orderedList/blockquote/codeBlock/align* 의 활성 여부 맵.
|
|
70
|
-
|
|
71
|
-
## 시각화 컴포넌트
|
|
72
|
-
|
|
73
|
-
### SdLabel — `sd-label`
|
|
74
|
-
배지/태그.
|
|
75
|
-
- `theme` — 테마 계열(미지정=기본 회색).
|
|
76
|
-
- `color: string` — 직접 색상 지정.
|
|
77
|
-
- `clickable: boolean` — 클릭 가능 스타일.
|
|
78
|
-
|
|
79
|
-
### SdNote — `sd-note`
|
|
80
|
-
강조 노트 블록.
|
|
81
|
-
- `theme` — 테마 계열.
|
|
82
|
-
- `size: "sm"|"lg"`, `inset: boolean`.
|
|
83
|
-
|
|
84
|
-
### SdProgress — `sd-progress`
|
|
85
|
-
진행 바.
|
|
86
|
-
- `theme: input.required<테마 계열>` — 바 색상(필수).
|
|
87
|
-
- `value: input.required<number>` — 진행값(0~1, 내부에서 0~100% 클램프).
|
|
88
|
-
- `size: "sm"|"lg"`, `inset: boolean`.
|
|
89
|
-
|
|
90
|
-
### SdCalendar<T> — `sd-calendar`
|
|
91
|
-
월 단위 달력에 항목 배치.
|
|
92
|
-
- `items: input.required<T[]>` — 표시 항목.
|
|
93
|
-
- `getItemDateFn: input.required<(item, index) => DateOnly>` — 항목의 날짜.
|
|
94
|
-
- `yearMonth: DateOnly` — 표시 연월(기본 이번 달 1일).
|
|
95
|
-
- `weekStartDay: number` — 주 시작 요일(기본 0=일).
|
|
96
|
-
- `minDaysInFirstWeek: number` — 첫 주 최소 일수(기본 1).
|
|
97
|
-
- 컨텐츠: `<ng-template [itemOf]>` 로 날짜 셀 항목 렌더.
|
|
98
|
-
|
|
99
|
-
### SdBarcode — `sd-barcode`
|
|
100
|
-
바코드/QR SVG 렌더(bwip-js).
|
|
101
|
-
- `type: input.required<BarcodeType>` — 심볼 종류(`qrcode`/`code128`/`ean13`/`datamatrix` 등 다수, `BarcodeType` union).
|
|
102
|
-
- `value: string` — 인코딩할 데이터(빈 값이면 미표시).
|
|
103
|
-
|
|
104
|
-
### SdEcharts — `sd-echarts`
|
|
105
|
-
ECharts 차트(SVG 렌더).
|
|
106
|
-
- `option: input.required<echarts.EChartsOption>` — 차트 옵션. 변경 시 갱신.
|
|
107
|
-
- `notMerge: boolean` — 옵션 set 시 기존과 병합하지 않고 교체.
|
|
108
|
-
- `loading: boolean` — 로딩 오버레이.
|
|
122
|
+
- ECharts 차트. `option` 변경 시 `setOption` 적용(`notMerge`=true 면 기존 옵션 병합 안 함). `loading`=로딩 인디케이터. 호스트 리사이즈 시 자동 `resize`(svg 렌더).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# @simplysm/angular — 칸반(kanban)
|
|
2
|
+
|
|
3
|
+
드래그앤드롭으로 카드를 레인 간 이동하고 카드를 다중 선택하는 칸반 보드 군. `sd-kanban-board`(보드) > `sd-kanban-lane`(레인) > `sd-kanban`(카드) 의 3계층으로 구성. `L`=레인 값 타입, `T`=카드 값 타입.
|
|
4
|
+
|
|
5
|
+
## SdKanbanBoard — `<sd-kanban-board>`
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
selectedValues = model<T[]>([]);
|
|
9
|
+
drop = output<SdKanbanBoardDropInfo<L, T>>();
|
|
10
|
+
// SdKanbanBoardDropInfo<L,T> { sourceKanbanValue?: T; targetLaneValue?: L; targetKanbanValue?: T }
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- 칸반 전체 보드(레인을 가로 배치). `selectedValues`=선택된 카드 값들(다중선택, model). `drop`=카드를 다른 위치에 떨군 결과(소스 카드값 + 대상 레인값 + 대상 카드값). 호스트가 `drop` 을 받아 데이터 재배치.
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<sd-kanban-board [(selectedValues)]="selected" (drop)="onDrop($event)">
|
|
17
|
+
<sd-kanban-lane [value]="'todo'"> ... </sd-kanban-lane>
|
|
18
|
+
</sd-kanban-board>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## SdKanbanLane — `<sd-kanban-lane>`
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
busy = input(false); useCollapse = input(false); collapse = model(false);
|
|
25
|
+
value = input<L>();
|
|
26
|
+
// 슬롯: #titleTpl(제목) #toolTpl(도구) , 콘텐츠로 <sd-kanban>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- 한 레인(열). `value`=레인 식별값(drop 대상 판정·targetLaneValue). `busy`=레인 busy 오버레이, `useCollapse`=접기 토글 버튼(접으면 카드 숨김, `collapse` model).
|
|
30
|
+
- 선택 가능한 카드가 있으면 레인 전체선택 체크박스 자동 노출. `#titleTpl`/`#toolTpl` 로 헤더/도구 영역.
|
|
31
|
+
|
|
32
|
+
## SdKanban — `<sd-kanban>`
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
value = input<T>(); selectable = input(false); draggable = input(false);
|
|
36
|
+
contentClass = input<string>();
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- 한 카드. `value`=카드 식별값. `draggable`=드래그 이동 허용, `selectable`=Shift+클릭 다중선택 허용(`board.selectedValues` 에 토글). 콘텐츠가 카드 본문. 드래그 중 드롭 위치 표시를 내장.
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<sd-kanban [value]="item" [draggable]="true" [selectable]="true">
|
|
43
|
+
<div>{{ item.title }}</div>
|
|
44
|
+
</sd-kanban>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 드래그/드롭 타입
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
SdKanbanDragRef<_L, T> { value(): T | undefined; heightOnDrag(): number }
|
|
51
|
+
SdKanbanDropTarget<L, T> { targetLaneValue(): L | undefined; targetKanbanValue?(): T | undefined }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- `SdKanbanDragRef` — 드래그 중인 카드 참조(보드가 추적). `SdKanbanDropTarget` — 드롭 대상(레인 또는 카드가 구현). 둘 다 컴포넌트가 내부 구현하는 계약으로, 직접 다룰 일은 드묾.
|
|
@@ -1,53 +1,77 @@
|
|
|
1
1
|
# @simplysm/angular — 레이아웃(사이드바·탑바)
|
|
2
2
|
|
|
3
|
-
앱 셸의 좌측 사이드바·상단바와 그 안의 메뉴/사용자 메뉴 컴포넌트 군. 앱 루트 레이아웃(`app.root` 등)에서 한 번 구성. 메뉴 항목 타입(`SdMenu`)·라우터 링크는 routing-appstructure.md 의 것을 사용.
|
|
3
|
+
앱 셸의 좌측 사이드바·상단바와 그 안의 메뉴/사용자 메뉴 컴포넌트 군. 앱 루트 레이아웃(`app.root` 등)에서 한 번 구성. 메뉴 항목 타입(`SdMenu`)·라우터 링크는 [routing-appstructure.md](./routing-appstructure.md) 의 것을 사용.
|
|
4
4
|
|
|
5
5
|
## 사이드바
|
|
6
6
|
|
|
7
|
-
### SdSidebarContainer —
|
|
8
|
-
사이드바 + 본문을 감싸는 컨테이너. 토글 시 본문 패딩을 조정하고 모바일에서 backdrop 표시. 라우팅 시작 시 자동 닫힘. 입력 없음(내부 `toggle` 상태 보유).
|
|
7
|
+
### SdSidebarContainer — `<sd-sidebar-container>`
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
```ts
|
|
10
|
+
toggle: WritableSignal<boolean>;
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- 사이드바 + 본문을 감싸는 컨테이너. `toggle` 로 사이드바 접힘 제어(데스크탑은 본문 패딩 토글, 모바일은 backdrop). 네비게이션 시작 시 자동 닫힘. 자식 컴포넌트가 `inject` 해 접근.
|
|
14
|
+
|
|
15
|
+
### SdSidebar — `<sd-sidebar>`
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
17
|
+
```ts
|
|
18
|
+
toggle = computed(...); // 부모 컨테이너의 toggle 미러
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- 좌측 고정 사이드바 영역. `SdSidebarContainer` 안에 두면 toggle 상태에 따라 슬라이드. 콘텐츠로 로고·메뉴·사용자를 투영.
|
|
18
22
|
|
|
19
|
-
###
|
|
20
|
-
사이드바 상단 사용자 영역(이름 + 펼침 메뉴).
|
|
21
|
-
- `userMenu: input<SdSidebarUserMenu>` — `{ icon?, title, menus: { title, onClick }[] }`. `title` 이 사용자명, `menus` 가 펼침 항목(로그아웃 등).
|
|
23
|
+
### SdSidebarMenu — `<sd-sidebar-menu>`
|
|
22
24
|
|
|
23
|
-
```
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<sd-sidebar-menu [menus]="menus()" />
|
|
28
|
-
</sd-sidebar>
|
|
29
|
-
<router-outlet />
|
|
30
|
-
</sd-sidebar-container>
|
|
25
|
+
```ts
|
|
26
|
+
menus = input<SdMenu[]>([]);
|
|
27
|
+
layout = input<"accordion" | "accordion-expanded" | "flat">();
|
|
28
|
+
getMenuIsSelectedFn = input<(menu: SdMenu) => boolean>();
|
|
31
29
|
```
|
|
32
30
|
|
|
31
|
+
- 메뉴 트리를 사이드바 리스트로 렌더(`SdRouterLink` 연결). `layout` 미지정 시 루트 메뉴 3개 이하면 `flat`, 초과면 `accordion` 자동. `accordion-expanded`=accordion 과 동일한 클릭 토글 구조이되 모든 깊이 항목이 펼친 채로 시작(이후 클릭하면 접힘), 명시 지정 시에만 적용(자동 선택 대상 아님). `getMenuIsSelectedFn`=선택 강조 커스텀(기본은 현재 페이지 코드 매칭). `menus` 는 보통 `SdAppStructureProvider.usableMenus()`.
|
|
32
|
+
|
|
33
|
+
### SdSidebarUser — `<sd-sidebar-user>`
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
userMenu = input<SdSidebarUserMenu>();
|
|
37
|
+
// SdSidebarUserMenu = { icon?: string; title: string; menus: { title: string; onClick: () => Promise<void>|void }[] }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- 사이드바 하단 사용자 영역. 콘텐츠로 사용자 정보를 투영하고, `userMenu` 지정 시 접이식 메뉴(로그아웃 등) 표시. 각 menu 의 `onClick` 으로 동작.
|
|
41
|
+
|
|
33
42
|
## 탑바
|
|
34
43
|
|
|
35
|
-
### SdTopbarContainer —
|
|
36
|
-
탑바 + 본문 세로 컨테이너. 입력 없음. (`sd-base-container` 가 page 모드에서 내부적으로 사용.)
|
|
44
|
+
### SdTopbarContainer — `<sd-topbar-container>`
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
```ts
|
|
47
|
+
// 입력 없음. flex-column 셸.
|
|
48
|
+
```
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
상단 가로 메뉴.
|
|
44
|
-
- `menus: input<SdMenu[]>` — 메뉴 항목.
|
|
45
|
-
- `getMenuIsSelectedFn: (menu) => boolean` — 선택 판정 커스텀.
|
|
50
|
+
- 탑바 + 본문 세로 셸. 상단 `<sd-topbar>` + `flex-fill` 본문 구조로 사용(`sd-base-container` 가 page 모드에서 내부 사용).
|
|
46
51
|
|
|
47
|
-
###
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
### SdTopbar — `<sd-topbar>`
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
sidebarContainer = input<SdSidebarContainer>();
|
|
56
|
+
hasSidebar = computed(...);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- 상단바. 사이드바가 있으면(주입 또는 `sidebarContainer` 입력) 좌측 토글 버튼 자동 노출. 콘텐츠로 제목·액션을 투영.
|
|
60
|
+
|
|
61
|
+
### SdTopbarMenu — `<sd-topbar-menu>`
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
menus = input<SdMenu[]>([]);
|
|
65
|
+
getMenuIsSelectedFn = input<(menu: SdMenu) => boolean>();
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- 탑바에 드롭다운 형태로 메뉴 트리를 렌더. 루트 메뉴마다 드롭다운, 하위는 평면 리스트. 선택 강조는 사이드바 메뉴와 동일 규약.
|
|
69
|
+
|
|
70
|
+
### SdTopbarUser — `<sd-topbar-user>`
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
menus = input.required<SdTopbarUserMenu[]>();
|
|
74
|
+
// SdTopbarUserMenu = { title: string; onClick: () => void }
|
|
75
|
+
```
|
|
50
76
|
|
|
51
|
-
|
|
52
|
-
- `SdSidebarUserMenu` — `{ icon?: string; title: string; menus: { title: string; onClick: () => Promise<void>|void }[] }`.
|
|
53
|
-
- `SdTopbarUserMenu` — `{ title: string; onClick: () => void }`.
|
|
77
|
+
- 탑바 우측 사용자 드롭다운. 콘텐츠로 사용자 표시명을 투영, `menus` 항목 클릭 시 `onClick` 실행 후 드롭다운 닫힘.
|