@simplysm/angular 14.0.49 → 14.0.51
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/README.md +234 -225
- package/dist/controls/select/sd-select.js +3 -3
- package/dist/layout/dock/sd-dock-container.js +1 -1
- package/docs/bootstrap/provide-sd-angular.md +37 -0
- package/docs/bootstrap/sd-angular-config-provider.md +16 -0
- package/docs/directives/sd-command-directive.md +30 -0
- package/docs/directives/sd-events.md +25 -0
- package/docs/directives/sd-intersection-directive.md +36 -0
- package/docs/directives/sd-invalid.md +24 -0
- package/docs/directives/sd-resize-directive.md +42 -0
- package/docs/directives/sd-ripple.md +23 -0
- package/docs/directives/sd-router-link.md +38 -0
- package/docs/directives/sd-show-effect.md +18 -0
- package/docs/directives/sd-typed-template.md +69 -0
- package/docs/features/sd-address-search-modal.md +50 -0
- package/docs/features/sd-permission-table.md +20 -0
- package/docs/features/sd-shared-data-components.md +158 -0
- package/docs/features/sd-tiptap-editor.md +26 -0
- package/docs/{pipes.md → pipes/format-pipe.md} +14 -5
- package/docs/plugins/sd-global-error-handler.md +23 -0
- package/docs/{plugins.md → plugins/sd-option-event-plugin.md} +9 -12
- package/docs/provider-types/sd-menu.md +65 -0
- package/docs/provider-types/sd-modal-content-def.md +148 -0
- package/docs/provider-types/sd-toast-content-def.md +73 -0
- package/docs/provider-types/shared-data-base.md +59 -0
- package/docs/providers/sd-activated-modal-provider.md +34 -0
- package/docs/providers/sd-app-structure-provider.md +81 -0
- package/docs/providers/sd-busy-provider.md +18 -0
- package/docs/providers/sd-file-dialog-provider.md +40 -0
- package/docs/providers/sd-local-storage-provider.md +20 -0
- package/docs/providers/sd-modal-provider.md +67 -0
- package/docs/providers/sd-navigate-window-provider.md +18 -0
- package/docs/providers/sd-print-provider.md +25 -0
- package/docs/providers/sd-service-client-factory-provider.md +43 -0
- package/docs/providers/sd-shared-data-provider.md +64 -0
- package/docs/providers/sd-system-config-provider.md +46 -0
- package/docs/providers/sd-system-log-provider.md +18 -0
- package/docs/providers/sd-theme-provider.md +38 -0
- package/docs/providers/sd-toast-provider.md +65 -0
- package/docs/recipes/_common-rules.md +244 -0
- package/docs/recipes/crud-detail/extension-a-edit-save.md +230 -0
- package/docs/recipes/crud-detail/extension-b-delete-restore.md +142 -0
- package/docs/recipes/crud-detail/extension-c-modal-view.md +214 -0
- package/docs/recipes/crud-detail/extension-d-control-view.md +103 -0
- package/docs/recipes/crud-detail/extension-e-auxiliary.md +87 -0
- package/docs/recipes/crud-detail/extension-f-complex-detail.md +234 -0
- package/docs/recipes/crud-detail.md +184 -706
- package/docs/recipes/crud-list/extension-a-inline-edit.md +410 -0
- package/docs/recipes/crud-list/extension-b-selection.md +226 -0
- package/docs/recipes/crud-list/extension-c-inline-delete.md +87 -0
- package/docs/recipes/crud-list/extension-d-select-modal.md +207 -0
- package/docs/recipes/crud-list/extension-e-readonly-modal.md +165 -0
- package/docs/recipes/crud-list/extension-f-modal-edit.md +177 -0
- package/docs/recipes/crud-list/extension-g-excel.md +157 -0
- package/docs/recipes/crud-list.md +196 -787
- package/docs/recipes/data-select-button.md +185 -91
- package/docs/recipes/page-modal-container.md +168 -86
- package/docs/styling/classes.md +149 -0
- package/docs/styling/mixins.md +100 -0
- package/docs/styling/themes.md +35 -0
- package/docs/styling/variables.md +147 -0
- package/docs/{type-utilities.md → type-utilities/directive-input-signals.md} +17 -35
- package/docs/ui-data/sd-list.md +37 -0
- package/docs/ui-data/sd-sheet.md +227 -0
- package/docs/ui-form/sd-additional-button.md +26 -0
- package/docs/ui-form/sd-anchor.md +31 -0
- package/docs/ui-form/sd-button.md +105 -0
- package/docs/ui-form/sd-checkbox-group.md +39 -0
- package/docs/ui-form/sd-checkbox.md +81 -0
- package/docs/ui-form/sd-date-range-picker.md +27 -0
- package/docs/ui-form/sd-form.md +89 -0
- package/docs/ui-form/sd-modal-select-button.md +54 -0
- package/docs/ui-form/sd-numpad.md +26 -0
- package/docs/ui-form/sd-range.md +26 -0
- package/docs/ui-form/sd-select.md +68 -0
- package/docs/ui-form/sd-shared-data-select.md +52 -0
- package/docs/ui-form/sd-state-preset.md +37 -0
- package/docs/ui-form/sd-switch.md +27 -0
- package/docs/ui-form/sd-textarea.md +33 -0
- package/docs/ui-form/sd-textfield.md +145 -0
- package/docs/ui-layout/sd-dock-container.md +64 -0
- package/docs/ui-layout/sd-dock.md +37 -0
- package/docs/ui-layout/sd-gap.md +26 -0
- package/docs/{ui-layout.md → ui-layout/sd-kanban-board.md} +41 -85
- package/docs/ui-layout/sd-kanban-lane.md +34 -0
- package/docs/ui-layout/sd-kanban.md +29 -0
- package/docs/ui-navigation/sd-collapse.md +35 -0
- package/docs/ui-navigation/sd-pagination.md +26 -0
- package/docs/ui-navigation/sd-sidebar-container.md +49 -0
- package/docs/ui-navigation/sd-sidebar-menu.md +22 -0
- package/docs/ui-navigation/sd-sidebar-user.md +43 -0
- package/docs/ui-navigation/sd-tab.md +51 -0
- package/docs/ui-navigation/sd-topbar-container.md +97 -0
- package/docs/ui-navigation/sd-topbar-menu.md +23 -0
- package/docs/ui-navigation/sd-topbar-user.md +38 -0
- package/docs/ui-navigation/sd-topbar.md +30 -0
- package/docs/ui-overlay/sd-busy-container.md +69 -0
- package/docs/ui-overlay/sd-confirm-modal.md +30 -0
- package/docs/ui-overlay/sd-dropdown.md +40 -0
- package/docs/ui-overlay/sd-modal.md +34 -0
- package/docs/ui-overlay/sd-prompt-modal.md +30 -0
- package/docs/ui-overlay/sd-toast.md +35 -0
- package/docs/ui-visual/sd-barcode.md +36 -0
- package/docs/ui-visual/sd-calendar.md +34 -0
- package/docs/ui-visual/sd-echarts.md +32 -0
- package/docs/ui-visual/sd-label.md +24 -0
- package/docs/ui-visual/sd-note.md +23 -0
- package/docs/ui-visual/sd-progress.md +23 -0
- package/docs/utils/inject-routing-signals.md +161 -0
- package/docs/utils/inject-sd-system-config-resource.md +35 -0
- package/docs/utils/mark.md +43 -0
- package/docs/utils/selection-managers.md +96 -0
- package/docs/utils/set-safe-style.md +19 -0
- package/docs/utils/setup-functions.md +93 -0
- package/package.json +5 -5
- package/src/controls/select/sd-select.ts +3 -3
- package/src/core/modal/sd-modal.provider.ts +1 -1
- package/src/core/modal/sd-modal.ts +1 -1
- package/src/core/routing/menu-utils.ts +1 -1
- package/src/core/shared-data/sd-shared-data.provider.ts +7 -7
- package/src/data/shared-data/sd-shared-data-select.ts +2 -2
- package/src/layout/dock/sd-dock-container.ts +1 -1
- package/docs/bootstrap.md +0 -38
- package/docs/directives.md +0 -236
- package/docs/features.md +0 -154
- package/docs/provider-types.md +0 -283
- package/docs/providers.md +0 -379
- package/docs/styling.md +0 -222
- package/docs/ui-data.md +0 -333
- package/docs/ui-form.md +0 -502
- package/docs/ui-navigation.md +0 -303
- package/docs/ui-overlay.md +0 -157
- package/docs/ui-visual.md +0 -127
- package/docs/utils.md +0 -244
package/docs/providers.md
DELETED
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
# Providers
|
|
2
|
-
|
|
3
|
-
## `SdThemeProvider`
|
|
4
|
-
|
|
5
|
-
다크모드/폰트 크기 프로바이더. `dark` signal 변경 시 body에 `sd-theme-dark` 클래스를 토글하고, `fontSize` signal 변경 시 `html` 요소의 font-size를 설정한다.
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
@Injectable({ providedIn: "root" })
|
|
9
|
-
class SdThemeProvider {
|
|
10
|
-
dark = signal<boolean>(false);
|
|
11
|
-
readonly fontSizePresets: readonly number[] = [12, 14, 16, 20, 24, 28];
|
|
12
|
-
fontSize = signal<number>(12);
|
|
13
|
-
|
|
14
|
-
increaseFontSize(): void;
|
|
15
|
-
decreaseFontSize(): void;
|
|
16
|
-
}
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
| Field | Type | Description |
|
|
20
|
-
|-------|------|-------------|
|
|
21
|
-
| `dark` | `WritableSignal<boolean>` | 다크모드 활성화 여부 |
|
|
22
|
-
| `fontSizePresets` | `readonly number[]` | 사용 가능한 폰트 크기 프리셋 배열 |
|
|
23
|
-
| `fontSize` | `WritableSignal<number>` | 현재 폰트 크기 (px). 기본값 12 |
|
|
24
|
-
|
|
25
|
-
| Method | Description |
|
|
26
|
-
|--------|-------------|
|
|
27
|
-
| `increaseFontSize()` | `fontSizePresets`에서 현재보다 큰 다음 크기로 변경 |
|
|
28
|
-
| `decreaseFontSize()` | `fontSizePresets`에서 현재보다 작은 이전 크기로 변경 |
|
|
29
|
-
|
|
30
|
-
## `SdThemeSelector`
|
|
31
|
-
|
|
32
|
-
테마 설정 드롭다운 컴포넌트. 다크모드 토글과 폰트 크기 증감 버튼을 제공한다. `SdThemeProvider`를 inject하여 사용한다.
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
@Component({
|
|
36
|
-
selector: "sd-theme-selector",
|
|
37
|
-
standalone: true,
|
|
38
|
-
})
|
|
39
|
-
class SdThemeSelector {}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
inputs 없음. `SdThemeProvider`의 `dark`, `fontSize`를 직접 조작한다.
|
|
43
|
-
|
|
44
|
-
## `SdSystemLogProvider`
|
|
45
|
-
|
|
46
|
-
시스템 로그 기록 프로바이더. console 출력 + 커스텀 `writeFn` 콜백 호출.
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
@Injectable({ providedIn: "root" })
|
|
50
|
-
class SdSystemLogProvider {
|
|
51
|
-
writeFn?: (severity: "error" | "warn" | "log", ...data: any[]) => Promise<void> | void;
|
|
52
|
-
async writeAsync(severity: "error" | "warn" | "log", ...data: any[]): Promise<void>;
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
| Field | Type | Description |
|
|
57
|
-
|-------|------|-------------|
|
|
58
|
-
| `writeFn` | `((severity, ...data) => Promise<void> \| void) \| undefined` | 커스텀 로그 기록 함수 |
|
|
59
|
-
|
|
60
|
-
| Method | Description |
|
|
61
|
-
|--------|-------------|
|
|
62
|
-
| `writeAsync(severity, ...data)` | console 출력 후 `writeFn` 호출 |
|
|
63
|
-
|
|
64
|
-
## `SdAppStructureProvider`
|
|
65
|
-
|
|
66
|
-
앱 구조(메뉴/권한) 관리 프로바이더. 서브클래스 없이 직접 사용한다.
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
@Injectable({ providedIn: "root" })
|
|
70
|
-
class SdAppStructureProvider<TModule = unknown> {
|
|
71
|
-
readonly usableModules = signal<TModule[] | undefined>(undefined);
|
|
72
|
-
readonly permRecord = signal<Record<string, boolean> | undefined>(undefined);
|
|
73
|
-
readonly items = signal<AppStructureItem<TModule>[]>([]);
|
|
74
|
-
|
|
75
|
-
usableMenus: Signal<SdMenu[]>;
|
|
76
|
-
usableFlatMenus: Signal<SdFlatMenu<TModule>[]>;
|
|
77
|
-
|
|
78
|
-
async initialize(serviceKey: string): Promise<void>;
|
|
79
|
-
getPermissionsByStructure(items, codeChain?): SdPermission<TModule>[];
|
|
80
|
-
getTitleByFullCode(fullCode: string): string;
|
|
81
|
-
getItemChainByFullCode(fullCode: string): AppStructureItem<TModule>[];
|
|
82
|
-
getPermsByFullCode<K extends string>(fullCodes: string[], permKeys: K[]): K[];
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
| WritableSignal Field | Type | Description |
|
|
87
|
-
|----------------------|------|-------------|
|
|
88
|
-
| `usableModules` | `WritableSignal<TModule[] \| undefined>` | 사용 가능한 모듈 목록. 외부에서 `set()`/`update()`로 설정 |
|
|
89
|
-
| `permRecord` | `WritableSignal<Record<string, boolean> \| undefined>` | 권한 레코드. 외부에서 `set()`/`update()`로 설정 |
|
|
90
|
-
| `items` | `WritableSignal<AppStructureItem<TModule>[]>` | 앱 구조 항목 배열 (`initialize()`로 초기화) |
|
|
91
|
-
|
|
92
|
-
| Computed | Type | Description |
|
|
93
|
-
|----------|------|-------------|
|
|
94
|
-
| `usableMenus` | `Signal<SdMenu[]>` | 사용 가능한 메뉴 트리 |
|
|
95
|
-
| `usableFlatMenus` | `Signal<SdFlatMenu<TModule>[]>` | 사용 가능한 플랫 메뉴 |
|
|
96
|
-
|
|
97
|
-
## `injectPermsSignal`
|
|
98
|
-
|
|
99
|
-
현재 뷰의 권한 목록을 signal로 반환하는 함수. 생성자에서 호출한다.
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
function injectPermsSignal<K extends string>(viewCodes: string[], keys: K[]): Signal<K[]>
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
| Parameter | Type | Description |
|
|
106
|
-
|-----------|------|-------------|
|
|
107
|
-
| `viewCodes` | `string[]` | 뷰 코드 배열 |
|
|
108
|
-
| `keys` | `K[]` | 확인할 권한 키 배열 |
|
|
109
|
-
|
|
110
|
-
반환: 활성화된 권한 키 배열의 signal
|
|
111
|
-
|
|
112
|
-
## `SdAppStructureUtils`
|
|
113
|
-
|
|
114
|
-
앱 구조 유틸리티. 정적 메서드로 메뉴/권한 조회 로직을 제공한다.
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
abstract class SdAppStructureUtils {
|
|
118
|
-
static getTitleByFullCode<TModule>(items, fullCode): string;
|
|
119
|
-
static getPermsByFullCode<TModule, K extends string>(items, fullCodes, permKeys, permRecord): K[];
|
|
120
|
-
static getItemChainByFullCode<TModule>(items, fullCode): AppStructureItem<TModule>[];
|
|
121
|
-
static getMenus<TModule>(items, codeChain, usableModules, permRecord): SdMenu[];
|
|
122
|
-
static getFlatMenus<TModule>(items, usableModules, permRecord): SdFlatMenu<TModule>[];
|
|
123
|
-
static getPermissions<TModule>(items, codeChain, usableModules): SdPermission<TModule>[];
|
|
124
|
-
static getFlatPermissions<TModule>(items, usableModules): FlatPermission<TModule>[];
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## `SdFileDialogProvider`
|
|
129
|
-
|
|
130
|
-
네이티브 파일 선택 대화상자 프로바이더.
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
@Injectable({ providedIn: "root" })
|
|
134
|
-
class SdFileDialogProvider {
|
|
135
|
-
async showAsync(multiple?: false, accept?: string): Promise<File | undefined>;
|
|
136
|
-
async showAsync(multiple: true, accept?: string): Promise<File[] | undefined>;
|
|
137
|
-
}
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
| Parameter | Type | Description |
|
|
141
|
-
|-----------|------|-------------|
|
|
142
|
-
| `multiple` | `boolean` | 다중 선택 여부 |
|
|
143
|
-
| `accept` | `string` | 허용 파일 타입 (예: `"image/*"`) |
|
|
144
|
-
|
|
145
|
-
## `SdLocalStorageProvider`
|
|
146
|
-
|
|
147
|
-
`clientName` 스코프 localStorage 래퍼. 키가 `{clientName}.{key}` 형태로 저장된다.
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
@Injectable({ providedIn: "root" })
|
|
151
|
-
class SdLocalStorageProvider<T> {
|
|
152
|
-
set<K extends keyof T & string>(key: K, value: T[K]): void;
|
|
153
|
-
get<K extends keyof T & string>(key: K): T[K] | undefined;
|
|
154
|
-
remove(key: keyof T & string): void;
|
|
155
|
-
}
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
## `SdSystemConfigProvider`
|
|
159
|
-
|
|
160
|
-
비동기 설정 저장/조회 프로바이더. `fn` 필드를 설정하면 서버 저장, 미설정 시 localStorage에 저장.
|
|
161
|
-
|
|
162
|
-
```typescript
|
|
163
|
-
@Injectable({ providedIn: "root" })
|
|
164
|
-
class SdSystemConfigProvider<T> {
|
|
165
|
-
fn?: {
|
|
166
|
-
set<K extends keyof T & string>(key: K, data: T[K]): Promise<void> | void;
|
|
167
|
-
get(key: keyof T & string): PromiseLike<any>;
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
async setAsync<K extends keyof T & string>(key: K, data: T[K]): Promise<void>;
|
|
171
|
-
async getAsync(key: keyof T & string): Promise<any>;
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
## `SdServiceClientFactoryProvider`
|
|
176
|
-
|
|
177
|
-
ServiceClient 인스턴스 팩토리/관리. key별로 연결을 관리한다.
|
|
178
|
-
|
|
179
|
-
```typescript
|
|
180
|
-
@Injectable({ providedIn: "root" })
|
|
181
|
-
class SdServiceClientFactoryProvider {
|
|
182
|
-
async connectAsync(key: string, options?: Partial<ServiceConnectionOptions>): Promise<void>;
|
|
183
|
-
async closeAsync(key: string): Promise<void>;
|
|
184
|
-
get(key: string): ServiceClient;
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
| Method | Description |
|
|
189
|
-
|--------|-------------|
|
|
190
|
-
| `connectAsync(key, options?)` | WebSocket 연결. 요청/응답 진행률을 토스트로 표시 |
|
|
191
|
-
| `closeAsync(key)` | 연결 종료 |
|
|
192
|
-
| `get(key)` | 연결된 ServiceClient 인스턴스 반환 |
|
|
193
|
-
|
|
194
|
-
## `SdSharedDataProvider`
|
|
195
|
-
|
|
196
|
-
이벤트 기반 공유 데이터 캐시 추상 프로바이더. `@Injectable()`로 제공되며, 소비 프로젝트에서 상속한다.
|
|
197
|
-
|
|
198
|
-
내부적으로 `client.getEvent()` 프록시를 사용하여 이벤트를 구독/발행한다:
|
|
199
|
-
- `client.getEvent<typeof SdSharedDataChangeEvent>("SdSharedDataChange").addListener(info, cb)`
|
|
200
|
-
- `client.getEvent<typeof SdSharedDataChangeEvent>("SdSharedDataChange").emit(selector, data)`
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
@Injectable()
|
|
204
|
-
abstract class SdSharedDataProvider<T extends Record<string, SharedDataBase<string | number>>> {
|
|
205
|
-
readonly loadingCount: WritableSignal<number>;
|
|
206
|
-
|
|
207
|
-
abstract initialize(): void;
|
|
208
|
-
register<K extends string & keyof T>(name: K, info: SharedDataInfo<T[K]>): void;
|
|
209
|
-
getHandle<K extends string & keyof T>(name: K): SharedDataHandle<T[K]>;
|
|
210
|
-
async emitAsync<K extends string & keyof T>(name: K, changeKeys?: (string | number)[]): Promise<void>;
|
|
211
|
-
async wait(): Promise<void>;
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
| Method | Description |
|
|
216
|
-
|--------|-------------|
|
|
217
|
-
| `register(name, info)` | 공유 데이터 등록 (getter, serviceKey, filter, orderBy) |
|
|
218
|
-
| `getHandle(name)` | 등록된 공유 데이터 핸들 반환 (items signal + get 메서드) |
|
|
219
|
-
| `emitAsync(name, changeKeys?)` | 변경 이벤트 발행. 내부에서 `client.getEvent<typeof SdSharedDataChangeEvent>("SdSharedDataChange").emit(...)` 호출 |
|
|
220
|
-
| `wait()` | 모든 로딩 완료까지 대기 |
|
|
221
|
-
|
|
222
|
-
### 로딩 전략 (Lazy Loading)
|
|
223
|
-
|
|
224
|
-
**`register()`는 메타정보만 등록하고 실제 데이터를 가져오지 않는다.** 타입별 데이터는 해당 타입의 `getHandle(name)`이 **처음 호출되는 시점**에 `info.getter()`를 실행하여 로딩된다. 즉 `initialize()`에서 여러 타입을 `register()` 해도 앱 시작 시 전체가 일괄 로딩되지 않으며, 실제로 사용되는 타입만 온디맨드로 로딩된다.
|
|
225
|
-
|
|
226
|
-
- 첫 `getHandle()` 호출 → `getter()` 실행 + `SdSharedDataChange` 리스너 등록
|
|
227
|
-
- 이후 같은 타입의 `getHandle()` 호출은 캐시된 `itemsSignal`을 재사용
|
|
228
|
-
- 이후 갱신은 서버에서 `emitAsync()`로 발행된 `SdSharedDataChange` 이벤트 수신 시에만 발생 (`changeKeys`가 있으면 부분 업데이트, 없으면 전체 리로드)
|
|
229
|
-
- `register()`를 동일 `name`으로 재호출하면 `generation`이 증가하고 `needsReload=true`로 표시되어, 다음 `getHandle()` 호출 시 재로딩된다
|
|
230
|
-
|
|
231
|
-
## `SdSharedDataChangeEvent`
|
|
232
|
-
|
|
233
|
-
공유 데이터 변경 이벤트 정의. `defineEvent`로 생성되며, 이벤트 이름 문자열 `"SdSharedDataChange"`를 인자로 받는다.
|
|
234
|
-
|
|
235
|
-
```typescript
|
|
236
|
-
const SdSharedDataChangeEvent = defineEvent<
|
|
237
|
-
{ name: string; filter: unknown },
|
|
238
|
-
(string | number)[] | undefined
|
|
239
|
-
>("SdSharedDataChange");
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
## `SdNavigateWindowProvider`
|
|
243
|
-
|
|
244
|
-
새 윈도우 네비게이션 + 자동 닫기 프로바이더.
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
@Injectable({ providedIn: "root" })
|
|
248
|
-
class SdNavigateWindowProvider {
|
|
249
|
-
get isWindow(): boolean;
|
|
250
|
-
open(navigate: string, params?: Record<string, string>, features?: string): void;
|
|
251
|
-
}
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
| Property/Method | Description |
|
|
255
|
-
|-----------------|-------------|
|
|
256
|
-
| `isWindow` | 현재 페이지가 팝업 윈도우인지 여부 |
|
|
257
|
-
| `open(navigate, params?, features?)` | 새 윈도우 열기. `features` 지정 시 팝업, 미지정 시 새 탭 |
|
|
258
|
-
|
|
259
|
-
## `SdActivatedModalProvider`
|
|
260
|
-
|
|
261
|
-
모달 내부에서 inject하여 모달/컨텐츠 컴포넌트 참조를 얻는 프로바이더. `@Injectable()`로 모달별 인스턴스 생성.
|
|
262
|
-
|
|
263
|
-
```typescript
|
|
264
|
-
@Injectable()
|
|
265
|
-
class SdActivatedModalProvider<T extends SdModalContentDef<any> = SdModalContentDef<any>> {
|
|
266
|
-
modalComponent = signal<any>(undefined);
|
|
267
|
-
contentComponent = signal<T | undefined>(undefined);
|
|
268
|
-
canDeactivateFn: () => boolean;
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
| Field | Type | Description |
|
|
273
|
-
|-------|------|-------------|
|
|
274
|
-
| `modalComponent` | `WritableSignal<any>` | SdModal 인스턴스 |
|
|
275
|
-
| `contentComponent` | `WritableSignal<T \| undefined>` | 컨텐츠 컴포넌트 인스턴스 |
|
|
276
|
-
| `canDeactivateFn` | `() => boolean` | 모달 닫기 가능 여부 판별 함수 (기본: `() => true`) |
|
|
277
|
-
|
|
278
|
-
## `SdToastProvider`
|
|
279
|
-
|
|
280
|
-
토스트 알림 프로바이더. 4가지 심각도(info/success/warning/danger) 메시지, 프로그래스 모드, 커스텀 토스트를 지원한다.
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
@Injectable({ providedIn: "root" })
|
|
284
|
-
class SdToastProvider {
|
|
285
|
-
alertThemes = signal<SdToastSeverity[]>([]);
|
|
286
|
-
overlap = signal(false);
|
|
287
|
-
beforeShowFn?: (theme: SdToastSeverity) => void;
|
|
288
|
-
|
|
289
|
-
info(message: string, useProgress?: true): WritableSignal<number>;
|
|
290
|
-
info(message: string, useProgress?: false): void;
|
|
291
|
-
success(message: string, useProgress?: true): WritableSignal<number>;
|
|
292
|
-
success(message: string, useProgress?: false): void;
|
|
293
|
-
warning(message: string, useProgress?: true): WritableSignal<number>;
|
|
294
|
-
warning(message: string, useProgress?: false): void;
|
|
295
|
-
danger(message: string, useProgress?: true): WritableSignal<number>;
|
|
296
|
-
danger(message: string, useProgress?: false): void;
|
|
297
|
-
|
|
298
|
-
notify<T extends SdToastContentDef<any>>(input: SdToastInput<T>): Promise<...>;
|
|
299
|
-
async try<R>(fn: () => Promise<R>, messageFn?: (err: Error) => string): Promise<R | undefined>;
|
|
300
|
-
try<R>(fn: () => R, messageFn?: (err: Error) => string): R | undefined;
|
|
301
|
-
}
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
| Field | Type | Description |
|
|
305
|
-
|-------|------|-------------|
|
|
306
|
-
| `alertThemes` | `WritableSignal<SdToastSeverity[]>` | alert()로 표시할 테마 목록 |
|
|
307
|
-
| `overlap` | `WritableSignal<boolean>` | 오버랩 모드 (새 토스트 시 기존 제거) |
|
|
308
|
-
| `beforeShowFn` | `((theme) => void) \| undefined` | 토스트 표시 전 콜백 |
|
|
309
|
-
|
|
310
|
-
| Method | Description |
|
|
311
|
-
|--------|-------------|
|
|
312
|
-
| `info/success/warning/danger(message, useProgress?)` | 토스트 표시. `useProgress=true`면 progress signal 반환 |
|
|
313
|
-
| `notify(input)` | 커스텀 토스트 컴포넌트 표시 |
|
|
314
|
-
| `try(fn, messageFn?)` | 에러 catch 시 danger 토스트 표시 후 undefined 반환 |
|
|
315
|
-
|
|
316
|
-
## `SdBusyProvider`
|
|
317
|
-
|
|
318
|
-
글로벌 busy 상태 관리 프로바이더.
|
|
319
|
-
|
|
320
|
-
```typescript
|
|
321
|
-
@Injectable({ providedIn: "root" })
|
|
322
|
-
class SdBusyProvider {
|
|
323
|
-
type = signal<SdBusyType>("bar");
|
|
324
|
-
globalBusyCount = signal(0);
|
|
325
|
-
}
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
| Field | Type | Description |
|
|
329
|
-
|-------|------|-------------|
|
|
330
|
-
| `type` | `WritableSignal<SdBusyType>` | busy 표시 유형 (`"spinner" \| "bar" \| "cube"`) |
|
|
331
|
-
| `globalBusyCount` | `WritableSignal<number>` | 글로벌 busy 카운트 (0보다 크면 busy 표시) |
|
|
332
|
-
|
|
333
|
-
## `SdPrintProvider`
|
|
334
|
-
|
|
335
|
-
인쇄 및 PDF 생성 프로바이더. jsPDF + html-to-image 사용.
|
|
336
|
-
|
|
337
|
-
```typescript
|
|
338
|
-
@Injectable({ providedIn: "root" })
|
|
339
|
-
class SdPrintProvider {
|
|
340
|
-
async printAsync<T extends SdPrint>(
|
|
341
|
-
template: SdPrintInput<T>,
|
|
342
|
-
options?: { size?: string; margin?: string },
|
|
343
|
-
): Promise<void>;
|
|
344
|
-
|
|
345
|
-
async getPdfBufferAsync<T extends SdPrint>(
|
|
346
|
-
template: SdPrintInput<T>,
|
|
347
|
-
options?: { orientation?: "portrait" | "landscape"; pageSize?: string },
|
|
348
|
-
): Promise<Uint8Array>;
|
|
349
|
-
}
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
| Method | Description |
|
|
353
|
-
|--------|-------------|
|
|
354
|
-
| `printAsync(template, options?)` | 브라우저 인쇄 대화상자 열기. `size` 기본값 `"A4 auto"`, `margin` 기본값 `"0"` |
|
|
355
|
-
| `getPdfBufferAsync(template, options?)` | PDF 바이너리 생성. `.page` 클래스 요소 단위로 페이지 분할 |
|
|
356
|
-
|
|
357
|
-
## `SdModalProvider`
|
|
358
|
-
|
|
359
|
-
프로그래밍 방식으로 모달을 생성하는 프로바이더.
|
|
360
|
-
|
|
361
|
-
```typescript
|
|
362
|
-
@Injectable({ providedIn: "root" })
|
|
363
|
-
class SdModalProvider {
|
|
364
|
-
modalCount = signal(0);
|
|
365
|
-
|
|
366
|
-
async showAsync<T extends SdModalContentDef<any>>(
|
|
367
|
-
modal: SdModalInfo<T>,
|
|
368
|
-
options?: SdModalOptions,
|
|
369
|
-
): Promise<Parameters<T["close"]["emit"]>[0] | undefined>;
|
|
370
|
-
}
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
| Field | Type | Description |
|
|
374
|
-
|-------|------|-------------|
|
|
375
|
-
| `modalCount` | `WritableSignal<number>` | 현재 열린 모달 수 |
|
|
376
|
-
|
|
377
|
-
| Method | Description |
|
|
378
|
-
|--------|-------------|
|
|
379
|
-
| `showAsync(modal, options?)` | 모달 생성 후 close 결과를 Promise로 반환 |
|
package/docs/styling.md
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
# Styling
|
|
2
|
-
|
|
3
|
-
`dist/styles.css`로 컴파일되며, `package.json`의 `style` 필드에서 참조된다. CSS Layers: `@layer base, theme-variant, utilities`.
|
|
4
|
-
|
|
5
|
-
## CSS Classes
|
|
6
|
-
|
|
7
|
-
### Flexbox
|
|
8
|
-
|
|
9
|
-
| Class | Description |
|
|
10
|
-
|-------|-------------|
|
|
11
|
-
| `.flex-row` | `display: flex; flex-direction: row; flex-wrap: nowrap` |
|
|
12
|
-
| `.flex-column` | `display: flex; flex-direction: column; flex-wrap: nowrap` |
|
|
13
|
-
| `.flex-row-inline` | `display: inline-flex; flex-direction: row` |
|
|
14
|
-
| `.flex-column-inline` | `display: inline-flex; flex-direction: column` |
|
|
15
|
-
| `.flex-fill` | `flex: 1 1 auto; overflow: auto` (가용 공간 채우기) |
|
|
16
|
-
| `.flex-auto` | `flex: 1 0 auto` (컨텐츠 크기 유지하며 확장) |
|
|
17
|
-
| `.flex-min` | `flex: 0 0 0` (최소 크기) |
|
|
18
|
-
|
|
19
|
-
### Grid
|
|
20
|
-
|
|
21
|
-
| Class | Description |
|
|
22
|
-
|-------|-------------|
|
|
23
|
-
| `.grid` | `display: grid` |
|
|
24
|
-
| `.grid-{1..12}` | `grid-template-columns: repeat(N, 1fr)` |
|
|
25
|
-
| `.grid-sm-{1..12}` | `@media (max-width: 1280px)` 반응형 |
|
|
26
|
-
| `.grid-xs-{1..12}` | `@media (max-width: 1024px)` 반응형 |
|
|
27
|
-
| `.grid-xxs-{1..12}` | `@media (max-width: 800px)` 반응형 |
|
|
28
|
-
|
|
29
|
-
### Layout
|
|
30
|
-
|
|
31
|
-
| Class | Description |
|
|
32
|
-
|-------|-------------|
|
|
33
|
-
| `.card` | 카드 스타일 (배경, 테두리, 라운드, 엘리베이션) |
|
|
34
|
-
| `.fill` | `height: 100%; width: 100%; overflow: auto` |
|
|
35
|
-
| `.sticky-top` | `position: sticky; top: 0; z-index: 1` |
|
|
36
|
-
| `.overflow-auto` | `overflow: auto` |
|
|
37
|
-
| `.position-relative` | `position: relative` |
|
|
38
|
-
| `.nowrap` | `white-space: nowrap` |
|
|
39
|
-
|
|
40
|
-
### Form Layout
|
|
41
|
-
|
|
42
|
-
| Class | Description |
|
|
43
|
-
|-------|-------------|
|
|
44
|
-
| `.form-box` | 폼 박스 레이아웃 |
|
|
45
|
-
| `.form-box-inline` | 인라인 폼 박스 |
|
|
46
|
-
| `.form-table` | 테이블 형태 폼 |
|
|
47
|
-
| `.form-control` | 기본 폼 컨트롤 스타일 (padding, border, font) |
|
|
48
|
-
| `.table` | 테이블 스타일 |
|
|
49
|
-
| `.table-inset` | 테두리 없는 테이블 |
|
|
50
|
-
| `.table-inline` | 인라인 테이블 |
|
|
51
|
-
| `.table-bd-v` | 수직 테두리만 있는 테이블 |
|
|
52
|
-
| `.table-bd-h` | 수평 테두리만 있는 테이블 |
|
|
53
|
-
|
|
54
|
-
### Spacing
|
|
55
|
-
|
|
56
|
-
키: `xxs`, `xs`, `sm`, `default`, `lg`, `xl`, `xxl`, `0`, `auto`
|
|
57
|
-
|
|
58
|
-
| Pattern | Description |
|
|
59
|
-
|---------|-------------|
|
|
60
|
-
| `.p-{key}` | 전체 padding |
|
|
61
|
-
| `.pv-{key}`, `.ph-{key}` | 수직/수평 padding |
|
|
62
|
-
| `.pt-{key}`, `.pr-{key}`, `.pb-{key}`, `.pl-{key}` | 방향별 padding |
|
|
63
|
-
| `.m-{key}` | 전체 margin |
|
|
64
|
-
| `.mv-{key}`, `.mh-{key}` | 수직/수평 margin |
|
|
65
|
-
| `.mt-{key}`, `.mr-{key}`, `.mb-{key}`, `.ml-{key}` | 방향별 margin |
|
|
66
|
-
| `.gap-{key}` | flex/grid gap |
|
|
67
|
-
| `.sw-{key}` | width 설정 |
|
|
68
|
-
| `.sh-{key}` | height 설정 |
|
|
69
|
-
| `.p-{key1}-{key2}` | `padding: {key1} {key2}` 조합 |
|
|
70
|
-
|
|
71
|
-
### Font Size
|
|
72
|
-
|
|
73
|
-
| Class | Description |
|
|
74
|
-
|-------|-------------|
|
|
75
|
-
| `.ft-size-{key}` | 폰트 크기 (h1~h6, sm, default, lg 등) |
|
|
76
|
-
|
|
77
|
-
### Text
|
|
78
|
-
|
|
79
|
-
| Class | Description |
|
|
80
|
-
|-------|-------------|
|
|
81
|
-
| `.tx-left`, `.tx-right`, `.tx-center` | 텍스트 정렬 |
|
|
82
|
-
| `.tx-line-through` | 취소선 |
|
|
83
|
-
| `.tx-underline` | 밑줄 |
|
|
84
|
-
| `.tx-trans-{key}` | 텍스트 투명도 색상 |
|
|
85
|
-
| `.tx-theme-{group}-{shade}` | 테마 텍스트 색상 |
|
|
86
|
-
|
|
87
|
-
### Background
|
|
88
|
-
|
|
89
|
-
| Class | Description |
|
|
90
|
-
|-------|-------------|
|
|
91
|
-
| `.bg-theme-{group}-{shade}` | 테마 배경 색상 |
|
|
92
|
-
| `.bg-trans-{key}` | 투명도 배경 |
|
|
93
|
-
| `.bg-default` | 기본 배경 |
|
|
94
|
-
| `.bg-control` | 컨트롤 배경 |
|
|
95
|
-
|
|
96
|
-
### Border
|
|
97
|
-
|
|
98
|
-
| Class | Description |
|
|
99
|
-
|-------|-------------|
|
|
100
|
-
| `.bd` | 전체 테두리 |
|
|
101
|
-
| `.bdt`, `.bdr`, `.bdb`, `.bdl` | 방향별 테두리 |
|
|
102
|
-
| `.bd-theme-{group}-{shade}` | 테마 테두리 색상 |
|
|
103
|
-
| `.bd-trans-{key}` | 투명도 테두리 |
|
|
104
|
-
| `.bd-none`, `.bd-transparent` | 테두리 없음/투명 |
|
|
105
|
-
| `.bd-radius-{key}` | 테두리 라운드 |
|
|
106
|
-
| `.bd-width-{key}` | 테두리 두께 |
|
|
107
|
-
|
|
108
|
-
### Alignment
|
|
109
|
-
|
|
110
|
-
| Class | Description |
|
|
111
|
-
|-------|-------------|
|
|
112
|
-
| `.main-align-start`, `.main-align-end`, `.main-align-center` | justify-content |
|
|
113
|
-
| `.cross-align-start`, `.cross-align-end`, `.cross-align-center` | align-items |
|
|
114
|
-
|
|
115
|
-
### Special
|
|
116
|
-
|
|
117
|
-
| Class | Description |
|
|
118
|
-
|-------|-------------|
|
|
119
|
-
| `.sh-topbar` | 탑바 높이 |
|
|
120
|
-
| `.sw-sidebar` | 사이드바 너비 |
|
|
121
|
-
| `.help` | 도움말 스타일 (점선 밑줄, 도움말 커서) |
|
|
122
|
-
| `.control-header` | 컨트롤 헤더 텍스트 |
|
|
123
|
-
| `.page-header` | 페이지 헤더 텍스트 |
|
|
124
|
-
|
|
125
|
-
## CSS Custom Properties
|
|
126
|
-
|
|
127
|
-
### Theme Colors
|
|
128
|
-
|
|
129
|
-
OKLCH 기반 색상 팔레트. 각 그룹에 7단계 shade가 있다.
|
|
130
|
-
|
|
131
|
-
테마 그룹: `gray`, `blue-gray`, `primary`, `secondary`, `info`, `success`, `warning`, `danger`
|
|
132
|
-
|
|
133
|
-
| Property | Description |
|
|
134
|
-
|----------|-------------|
|
|
135
|
-
| `--theme-{group}-lightest` | 가장 밝은 색조 |
|
|
136
|
-
| `--theme-{group}-lighter` | 더 밝은 색조 |
|
|
137
|
-
| `--theme-{group}-light` | 밝은 색조 |
|
|
138
|
-
| `--theme-{group}-default` | 기본 색조 |
|
|
139
|
-
| `--theme-{group}-dark` | 어두운 색조 |
|
|
140
|
-
| `--theme-{group}-darker` | 더 어두운 색조 |
|
|
141
|
-
| `--theme-{group}-darkest` | 가장 어두운 색조 |
|
|
142
|
-
|
|
143
|
-
### Layout
|
|
144
|
-
|
|
145
|
-
| Property | Description |
|
|
146
|
-
|----------|-------------|
|
|
147
|
-
| `--background-color` | body 배경 색상 |
|
|
148
|
-
| `--control-color` | 컨트롤 배경 색상 |
|
|
149
|
-
| `--font-family` | 기본 폰트 패밀리 |
|
|
150
|
-
| `--font-family-monospace` | 고정폭 폰트 패밀리 |
|
|
151
|
-
| `--font-size-default` | 기본 폰트 크기 |
|
|
152
|
-
| `--line-height` | 기본 줄 높이 |
|
|
153
|
-
| `--border-radius-default` | 기본 테두리 라운드 |
|
|
154
|
-
| `--topbar-height` | 탑바 높이 |
|
|
155
|
-
| `--sidebar-width` | 사이드바 너비 |
|
|
156
|
-
| `--elevation-size` | 그림자 기본 크기 |
|
|
157
|
-
| `--animation-duration` | 애니메이션 지속 시간 |
|
|
158
|
-
|
|
159
|
-
### Gap (Spacing)
|
|
160
|
-
|
|
161
|
-
| Property | Description |
|
|
162
|
-
|----------|-------------|
|
|
163
|
-
| `--gap-xxs` | 가장 작은 간격 |
|
|
164
|
-
| `--gap-xs` | 매우 작은 간격 |
|
|
165
|
-
| `--gap-sm` | 작은 간격 |
|
|
166
|
-
| `--gap-default` | 기본 간격 |
|
|
167
|
-
| `--gap-lg` | 큰 간격 |
|
|
168
|
-
| `--gap-xl` | 매우 큰 간격 |
|
|
169
|
-
| `--gap-xxl` | 가장 큰 간격 |
|
|
170
|
-
|
|
171
|
-
### Transparency
|
|
172
|
-
|
|
173
|
-
| Property | Description |
|
|
174
|
-
|----------|-------------|
|
|
175
|
-
| `--trans-lightest` | 가장 투명한 반투명 |
|
|
176
|
-
| `--trans-lighter` | 더 투명한 반투명 |
|
|
177
|
-
| `--trans-light` | 투명한 반투명 |
|
|
178
|
-
| `--trans-default` | 기본 반투명 |
|
|
179
|
-
| `--trans-dark` | 불투명한 반투명 |
|
|
180
|
-
| `--trans-darker` | 더 불투명한 반투명 |
|
|
181
|
-
| `--trans-darkest` | 가장 불투명한 반투명 |
|
|
182
|
-
|
|
183
|
-
### Text Transparency
|
|
184
|
-
|
|
185
|
-
| Property | Description |
|
|
186
|
-
|----------|-------------|
|
|
187
|
-
| `--text-trans-default` | 기본 텍스트 색상 |
|
|
188
|
-
| `--text-trans-light` | 밝은 텍스트 색상 |
|
|
189
|
-
| `--text-trans-lighter` | 더 밝은 텍스트 색상 |
|
|
190
|
-
| `--text-trans-dark` | 어두운 텍스트 색상 |
|
|
191
|
-
|
|
192
|
-
## Themes
|
|
193
|
-
|
|
194
|
-
### `.sd-theme-dark`
|
|
195
|
-
|
|
196
|
-
다크 모드 테마. `SdThemeProvider.dark` signal로 body에 토글된다. `themes/_variables-dark.scss`에서 색상 팔레트를 반전한다.
|
|
197
|
-
|
|
198
|
-
- 배경: 어두운 색상으로 전환
|
|
199
|
-
- 텍스트: 밝은 색상으로 전환
|
|
200
|
-
- `img:not(.no-invert)`: 이미지 자동 반전
|
|
201
|
-
|
|
202
|
-
### Responsive Breakpoints
|
|
203
|
-
|
|
204
|
-
SCSS 변수로 정의되어 media query에서 사용된다:
|
|
205
|
-
|
|
206
|
-
| Variable | Value | Description |
|
|
207
|
-
|----------|-------|-------------|
|
|
208
|
-
| `$breakpoint-mobile` | `520px` | 모바일 |
|
|
209
|
-
| `$breakpoint-xxs` | `800px` | 매우 작은 화면 |
|
|
210
|
-
| `$breakpoint-xs` | `1024px` | 작은 화면 |
|
|
211
|
-
| `$breakpoint-sm` | `1280px` | 중간 화면 |
|
|
212
|
-
|
|
213
|
-
## Mixins / Functions
|
|
214
|
-
|
|
215
|
-
| Name | Signature | Description |
|
|
216
|
-
|------|-----------|-------------|
|
|
217
|
-
| `writeVars` | `@mixin writeVars($value, $prevKey)` | 맵을 재귀 순회하여 CSS custom properties 생성 |
|
|
218
|
-
| `elevation` | `@mixin elevation($value)` | box-shadow 기반 엘리베이션 효과. 양수=외부, 음수=내부, 0/none=없음 |
|
|
219
|
-
| `form-control-base` | `@mixin form-control-base()` | 폼 컨트롤 기본 스타일 (display, padding, border, font) |
|
|
220
|
-
| `help` | `@mixin help()` | 도움말 스타일 (점선 밑줄, 커서) |
|
|
221
|
-
| `border-direction-variants` | `@mixin border-direction-variants($dir, $d)` | 방향별 테두리 유틸리티 클래스 생성 |
|
|
222
|
-
| `flex-direction` | `@mixin flex-direction($direction, $defaultGap?)` | flex-direction 설정 + Chrome 61 gap 폴백 |
|