@libs-ui/services-config-project 0.2.356-9 → 0.2.357-0
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
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @libs-ui/services-config-project
|
|
2
2
|
|
|
3
|
-
Service cấu hình toàn cục cho libs-ui: theme color, font family, heading styles, button colors/sizes/statuses/tabs
|
|
3
|
+
> Service cấu hình toàn cục cho hệ sinh thái libs-ui: theme color, font family, heading styles, button colors/sizes/statuses/tabs — inject một lần, áp dụng toàn bộ ứng dụng qua CSS variables và Signal reactivity.
|
|
4
|
+
|
|
5
|
+
## Giới thiệu
|
|
6
|
+
|
|
7
|
+
`LibsUiConfigProjectService` là service trung tâm quản lý design token và cấu hình giao diện cho toàn bộ ứng dụng sử dụng libs-ui. Service nhận một màu chủ đạo (ThemeColor) rồi tự động tính toán và thiết lập hơn 20 CSS custom variables tương ứng, đồng thời hỗ trợ load custom font family qua FontFace API, cấu hình heading typography (h1–h7), button color variants và button tab/status colors. Mọi thay đổi thông qua setter đều được phản ánh ngay lập tức nhờ Angular Signals + `effect()`.
|
|
4
8
|
|
|
5
9
|
## Tính năng
|
|
6
10
|
|
|
7
|
-
- ✅ Theme color — tự động tính 20+ CSS color variables từ một màu gốc
|
|
8
|
-
- ✅ Custom font family qua FontFace API (
|
|
9
|
-
- ✅ Heading styles — 7 levels × 4 weights (h1r → h7b)
|
|
10
|
-
- ✅ Button colors — 14 built-in types + extensible qua `FunctionGetConfigButtonIncludes`
|
|
11
|
-
- ✅ Button status colors — 8 màu mặc định + custom
|
|
12
|
-
- ✅ Button tab colors — 8 màu với background
|
|
13
|
-
- ✅
|
|
14
|
-
- ✅
|
|
11
|
+
- ✅ **Theme color** — tự động tính 20+ CSS color variables từ một màu gốc duy nhất
|
|
12
|
+
- ✅ **Custom font family** — load dynamic qua FontFace API (không cần `@font-face` trong CSS)
|
|
13
|
+
- ✅ **Heading styles** — 7 levels × 4 weights (h1r → h7b), áp dụng qua CSS class `libs-ui-font-*`
|
|
14
|
+
- ✅ **Button colors** — 14 built-in button types + extensible qua `FunctionGetConfigButtonIncludes`
|
|
15
|
+
- ✅ **Button status colors** — 8 màu mặc định (blue, green, red, orange, yellow, cyan, purple, brown) + custom
|
|
16
|
+
- ✅ **Button tab colors** — 8 màu với active background và badge background
|
|
17
|
+
- ✅ **Button sizes** — 4 kích thước (large, medium, small, smaller) cho icon và text
|
|
18
|
+
- ✅ **Signal reactivity** — setter nào thay đổi → `effect()` tự cập nhật CSS vars tức thì
|
|
19
|
+
- ✅ **Global CSS utility classes** — border, shadow, disable, readonly, selection highlight...
|
|
20
|
+
- ✅ **Multi-tenant support** — đổi toàn bộ brand color chỉ bằng một setter
|
|
21
|
+
|
|
22
|
+
## Khi nào sử dụng
|
|
23
|
+
|
|
24
|
+
- Khởi tạo brand color và font family khi app load (trong `AppComponent`)
|
|
25
|
+
- Multi-tenant: đổi theme color theo tenant config từ API
|
|
26
|
+
- Override màu sắc đặc thù (error, disable, readonly, border) so với giá trị mặc định
|
|
27
|
+
- Thêm custom button color type ngoài 14 types có sẵn
|
|
28
|
+
- Cấu hình button status/tab colors cho các badge và tab component
|
|
29
|
+
- Truy xuất button config hiện tại dưới dạng Signal để dùng trong component tùy chỉnh
|
|
15
30
|
|
|
16
31
|
## Cài đặt
|
|
17
32
|
|
|
@@ -23,25 +38,56 @@ npm install @libs-ui/services-config-project
|
|
|
23
38
|
|
|
24
39
|
```typescript
|
|
25
40
|
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
|
|
41
|
+
|
|
42
|
+
// Import interfaces khi cần type cụ thể
|
|
43
|
+
import {
|
|
44
|
+
ILibsUiConfigFontFamily,
|
|
45
|
+
ILibsUiConfigFontHeading,
|
|
46
|
+
ILibsUiConfigFontHeadingStyle,
|
|
47
|
+
ILibsUiConfigButtonStatus,
|
|
48
|
+
ILibsUiConfigButtonTab,
|
|
49
|
+
IColorButton,
|
|
50
|
+
ILibsUiConfigButtonSize,
|
|
51
|
+
IColorButtonTab,
|
|
52
|
+
} from '@libs-ui/services-config-project';
|
|
53
|
+
|
|
54
|
+
// Import default data/config để tham khảo hoặc override một phần
|
|
55
|
+
import {
|
|
56
|
+
fontConfig,
|
|
57
|
+
configHeading,
|
|
58
|
+
sizeButtonConfig,
|
|
59
|
+
configButtonColor,
|
|
60
|
+
configLinkButton,
|
|
61
|
+
configButtonStatus,
|
|
62
|
+
configButtonTab,
|
|
63
|
+
} from '@libs-ui/services-config-project';
|
|
26
64
|
```
|
|
27
65
|
|
|
28
|
-
##
|
|
66
|
+
## Ví dụ sử dụng
|
|
29
67
|
|
|
30
|
-
|
|
68
|
+
### Ví dụ 1 — Khởi tạo cơ bản trong AppComponent
|
|
69
|
+
|
|
70
|
+
Inject service và cấu hình brand color + font khi app khởi động:
|
|
31
71
|
|
|
32
72
|
```typescript
|
|
33
73
|
import { Component, inject, OnInit } from '@angular/core';
|
|
74
|
+
import { RouterOutlet } from '@angular/router';
|
|
34
75
|
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
|
|
35
76
|
|
|
36
|
-
@Component({
|
|
77
|
+
@Component({
|
|
78
|
+
selector: 'app-root',
|
|
79
|
+
standalone: true,
|
|
80
|
+
imports: [RouterOutlet],
|
|
81
|
+
template: '<router-outlet />',
|
|
82
|
+
})
|
|
37
83
|
export class AppComponent implements OnInit {
|
|
38
|
-
private configService = inject(LibsUiConfigProjectService);
|
|
84
|
+
private readonly configService = inject(LibsUiConfigProjectService);
|
|
39
85
|
|
|
40
|
-
ngOnInit() {
|
|
41
|
-
//
|
|
86
|
+
ngOnInit(): void {
|
|
87
|
+
// Set brand/theme color — tự động sinh 20+ CSS variables
|
|
42
88
|
this.configService.ThemeColor = '#226ff5';
|
|
43
89
|
|
|
44
|
-
//
|
|
90
|
+
// Set custom font family (tùy chọn — mặc định SVN-Poppins)
|
|
45
91
|
this.configService.ConfigFont = {
|
|
46
92
|
name: 'Inter',
|
|
47
93
|
uri_regular: '/assets/fonts/Inter-Regular.ttf',
|
|
@@ -53,149 +99,459 @@ export class AppComponent implements OnInit {
|
|
|
53
99
|
}
|
|
54
100
|
```
|
|
55
101
|
|
|
56
|
-
|
|
102
|
+
### Ví dụ 2 — Multi-tenant: đổi theme theo dữ liệu API
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { Component, inject, OnInit } from '@angular/core';
|
|
106
|
+
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
|
|
107
|
+
|
|
108
|
+
@Component({
|
|
109
|
+
selector: 'app-root',
|
|
110
|
+
standalone: true,
|
|
111
|
+
template: '<router-outlet />',
|
|
112
|
+
})
|
|
113
|
+
export class AppComponent implements OnInit {
|
|
114
|
+
private readonly configService = inject(LibsUiConfigProjectService);
|
|
115
|
+
private readonly tenantService = inject(TenantService);
|
|
116
|
+
|
|
117
|
+
ngOnInit(): void {
|
|
118
|
+
this.tenantService.getTenantConfig().subscribe((tenant) => {
|
|
119
|
+
// Toàn bộ design token cập nhật ngay sau lệnh này
|
|
120
|
+
this.configService.ThemeColor = tenant.brandColor;
|
|
121
|
+
|
|
122
|
+
// Override các màu phụ trợ nếu tenant yêu cầu
|
|
123
|
+
this.configService.BorderColor = tenant.borderColor ?? '#e6e7ea';
|
|
124
|
+
this.configService.TextErrorColor = tenant.errorColor ?? '#ff5454';
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
57
129
|
|
|
58
|
-
###
|
|
130
|
+
### Ví dụ 3 — Thêm custom button color type
|
|
59
131
|
|
|
60
132
|
```typescript
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
133
|
+
import { Component, inject, OnInit } from '@angular/core';
|
|
134
|
+
import { LibsUiConfigProjectService, IColorButton } from '@libs-ui/services-config-project';
|
|
135
|
+
|
|
136
|
+
@Component({
|
|
137
|
+
selector: 'app-root',
|
|
138
|
+
standalone: true,
|
|
139
|
+
template: '<router-outlet />',
|
|
140
|
+
})
|
|
141
|
+
export class AppComponent implements OnInit {
|
|
142
|
+
private readonly configService = inject(LibsUiConfigProjectService);
|
|
143
|
+
|
|
144
|
+
ngOnInit(): void {
|
|
145
|
+
this.configService.ThemeColor = '#226ff5';
|
|
146
|
+
|
|
147
|
+
// Thêm button type tùy chỉnh — key 'button-brand-pink' có thể dùng trong Button component
|
|
148
|
+
this.configService.FunctionGetConfigButtonIncludes = (rootColor: string): { [key: string]: IColorButton } => ({
|
|
149
|
+
'button-brand-pink': {
|
|
150
|
+
configStepColor: {
|
|
151
|
+
text: 'white',
|
|
152
|
+
text_hover: 'white',
|
|
153
|
+
text_active: 'white',
|
|
154
|
+
text_disable: '#CDD0D6',
|
|
155
|
+
background: 0,
|
|
156
|
+
background_hover: 20,
|
|
157
|
+
background_active: -20,
|
|
158
|
+
background_disable: '#F8F9FA',
|
|
159
|
+
border: 0,
|
|
160
|
+
border_hover: 20,
|
|
161
|
+
border_active: -20,
|
|
162
|
+
border_disable: '#F8F9FA',
|
|
163
|
+
},
|
|
164
|
+
rootColor: '#e91e63',
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
64
169
|
```
|
|
65
170
|
|
|
66
|
-
### Override màu
|
|
171
|
+
### Ví dụ 4 — Override màu cá nhân cho trạng thái đặc thù
|
|
67
172
|
|
|
68
173
|
```typescript
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
174
|
+
import { Component, inject, OnInit } from '@angular/core';
|
|
175
|
+
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
|
|
176
|
+
|
|
177
|
+
@Component({
|
|
178
|
+
selector: 'app-root',
|
|
179
|
+
standalone: true,
|
|
180
|
+
template: '<router-outlet />',
|
|
181
|
+
})
|
|
182
|
+
export class AppComponent implements OnInit {
|
|
183
|
+
private readonly configService = inject(LibsUiConfigProjectService);
|
|
184
|
+
|
|
185
|
+
ngOnInit(): void {
|
|
186
|
+
this.configService.ThemeColor = '#226ff5';
|
|
187
|
+
|
|
188
|
+
// Override từng màu trạng thái
|
|
189
|
+
this.configService.BackgroundDisableColor = '#f3f4f6';
|
|
190
|
+
this.configService.TextDisableColor = '#9ca3af';
|
|
191
|
+
this.configService.TextReadonlyColor = '#374151';
|
|
192
|
+
this.configService.BackgroundReadonlyColor = '#f9fafb';
|
|
193
|
+
this.configService.BorderErrorColor = '#dc2626';
|
|
194
|
+
this.configService.BackgroundListHover = '#eff6ff';
|
|
195
|
+
}
|
|
196
|
+
}
|
|
73
197
|
```
|
|
74
198
|
|
|
75
|
-
### Custom button
|
|
199
|
+
### Ví dụ 5 — Custom button status và tab colors
|
|
76
200
|
|
|
77
201
|
```typescript
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
202
|
+
import { Component, inject, OnInit } from '@angular/core';
|
|
203
|
+
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
|
|
204
|
+
|
|
205
|
+
@Component({
|
|
206
|
+
selector: 'app-root',
|
|
207
|
+
standalone: true,
|
|
208
|
+
template: '<router-outlet />',
|
|
209
|
+
})
|
|
210
|
+
export class AppComponent implements OnInit {
|
|
211
|
+
private readonly configService = inject(LibsUiConfigProjectService);
|
|
212
|
+
|
|
213
|
+
ngOnInit(): void {
|
|
214
|
+
this.configService.ThemeColor = '#226ff5';
|
|
215
|
+
|
|
216
|
+
// Custom button status colors (dùng cho badge/tag component)
|
|
217
|
+
this.configService.ConfigButtonStatus = {
|
|
218
|
+
active: { color: '#00D16D', background: '#E6FAF0' },
|
|
219
|
+
inactive: { color: '#9CA3AF', background: '#F3F4F6' },
|
|
220
|
+
pending: { color: '#F59E0B', background: '#FEF3C7' },
|
|
221
|
+
rejected: { color: '#EF4444', background: '#FEE2E2' },
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// Custom button tab colors
|
|
225
|
+
this.configService.ConfigButtonTab = {
|
|
226
|
+
primary: {
|
|
227
|
+
color: '#226FF5',
|
|
228
|
+
background: '#F4F8FF',
|
|
229
|
+
background_badge: '#E9F1FE',
|
|
230
|
+
},
|
|
231
|
+
success: {
|
|
232
|
+
color: '#00D16D',
|
|
233
|
+
background: '#F2FCF7',
|
|
234
|
+
background_badge: '#E6FAF0',
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
97
239
|
```
|
|
98
240
|
|
|
99
|
-
###
|
|
241
|
+
### Ví dụ 6 — Dùng CSS variables trong SCSS của component
|
|
100
242
|
|
|
101
243
|
```scss
|
|
102
|
-
//
|
|
103
|
-
.
|
|
104
|
-
|
|
105
|
-
|
|
244
|
+
// Sử dụng CSS variables được tạo ra bởi service — không hardcode màu
|
|
245
|
+
.custom-card {
|
|
246
|
+
border: 1px solid var(--libs-ui-color-border, #e6e7ea);
|
|
247
|
+
background: var(--libs-ui-color-light-3, #f4f8ff);
|
|
106
248
|
|
|
107
249
|
&:hover {
|
|
108
|
-
background: var(--libs-ui-color-light-
|
|
250
|
+
background: var(--libs-ui-color-light-2, #dce9fd);
|
|
251
|
+
border-color: var(--libs-ui-color-light-1, #4e8cf7);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
&.is-disabled {
|
|
255
|
+
background: var(--libs-ui-color-background-disable, #f8f9fa);
|
|
256
|
+
color: var(--libs-ui-color-text-disable, #9ca2ad);
|
|
257
|
+
cursor: not-allowed;
|
|
109
258
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
color: var(--libs-ui-color-
|
|
259
|
+
|
|
260
|
+
&.is-error {
|
|
261
|
+
border-color: var(--libs-ui-color-border-error, #ee2d41);
|
|
262
|
+
color: var(--libs-ui-color-text-error, #ff5454);
|
|
113
263
|
}
|
|
114
264
|
}
|
|
115
265
|
```
|
|
116
266
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
267
|
+
### Ví dụ 7 — Đọc ConfigButton Signal trong component tùy chỉnh
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
import { Component, inject } from '@angular/core';
|
|
271
|
+
import { LibsUiConfigProjectService } from '@libs-ui/services-config-project';
|
|
272
|
+
|
|
273
|
+
@Component({
|
|
274
|
+
selector: 'app-custom-button',
|
|
275
|
+
standalone: true,
|
|
276
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
277
|
+
template: `
|
|
278
|
+
@if (buttonConfig()['button-primary']) {
|
|
279
|
+
<button [style.background]="resolvedColor()">Click me</button>
|
|
280
|
+
}
|
|
281
|
+
`,
|
|
282
|
+
})
|
|
283
|
+
export class CustomButtonComponent {
|
|
284
|
+
private readonly configService = inject(LibsUiConfigProjectService);
|
|
285
|
+
|
|
286
|
+
// ConfigButton là Signal — reactive với mọi thay đổi ThemeColor
|
|
287
|
+
protected readonly buttonConfig = this.configService.ConfigButton;
|
|
288
|
+
|
|
289
|
+
protected readonly resolvedColor = computed(() => {
|
|
290
|
+
const config = this.buttonConfig();
|
|
291
|
+
return config['button-primary']?.rootColor ?? '#226ff5';
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Ví dụ 8 — Dùng global CSS utility classes trong template
|
|
297
|
+
|
|
298
|
+
```html
|
|
299
|
+
<!-- Border utilities -->
|
|
300
|
+
<div class="libs-ui-border-general">Viền đơn chuẩn</div>
|
|
301
|
+
<div class="libs-ui-border-bottom-general">Chỉ viền dưới</div>
|
|
302
|
+
<div class="libs-ui-border-error-general">Viền lỗi màu đỏ</div>
|
|
303
|
+
|
|
304
|
+
<!-- Background utilities -->
|
|
305
|
+
<div class="libs-ui-bg-list">Nền list item</div>
|
|
306
|
+
<div class="libs-ui-bg-list-hover">Nền hover list item</div>
|
|
307
|
+
<div class="libs-ui-bg-list-active">Nền active list item</div>
|
|
308
|
+
|
|
309
|
+
<!-- Shadow utilities -->
|
|
310
|
+
<div class="libs-ui-shadow">Shadow chuẩn</div>
|
|
311
|
+
<div class="libs-ui-shadow-md">Shadow medium</div>
|
|
312
|
+
<div class="libs-ui-shadow-large">Shadow large</div>
|
|
313
|
+
|
|
314
|
+
<!-- State utilities -->
|
|
315
|
+
<span class="libs-ui-disable">Text disabled</span>
|
|
316
|
+
<span class="libs-ui-disable-background">Background disabled</span>
|
|
317
|
+
<span class="libs-ui-readonly">Text readonly</span>
|
|
318
|
+
<span class="libs-ui-readonly-background">Background readonly</span>
|
|
319
|
+
<span class="libs-ui-text-error">Text lỗi</span>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## Methods
|
|
323
|
+
|
|
324
|
+
| Method | Signature | Mô tả |
|
|
325
|
+
|---|---|---|
|
|
326
|
+
| `colorStepContrastFromOrigin` | `(step: number, color?: string) => { light: string; dark: string } \| undefined` | Tính màu lighter (light) hoặc darker (dark) với N step từ màu gốc. Nếu bỏ qua `color`, dùng ThemeColor hiện tại |
|
|
327
|
+
| `setupFontFamily` | `(currentDoc?: Document) => void` | Load font family vào document. Public để hỗ trợ shadow DOM (iframe, Web Component). Mặc định dùng `document` global |
|
|
328
|
+
|
|
329
|
+
### Ví dụ sử dụng `colorStepContrastFromOrigin`
|
|
171
330
|
|
|
172
331
|
```typescript
|
|
332
|
+
// Trong component inject service
|
|
333
|
+
private readonly configService = inject(LibsUiConfigProjectService);
|
|
334
|
+
|
|
335
|
+
// Tính màu sáng hơn ThemeColor 20 steps
|
|
336
|
+
const lighterColor = this.configService.colorStepContrastFromOrigin(20);
|
|
337
|
+
// → { light: '#4e8cf7', dark: '#1b59c4' }
|
|
338
|
+
|
|
339
|
+
// Tính màu từ một màu tùy ý
|
|
340
|
+
const customLight = this.configService.colorStepContrastFromOrigin(50, '#e91e63');
|
|
341
|
+
// → { light: '#f06292', dark: '#c2185b' }
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Setters (API cấu hình)
|
|
345
|
+
|
|
346
|
+
| Setter | Type | Mặc định | Mô tả | Ví dụ |
|
|
347
|
+
|---|---|---|---|---|
|
|
348
|
+
| `ThemeColor` | `string` | `'#226ff5'` | Màu chủ đạo — sinh toàn bộ CSS color variables | `configService.ThemeColor = '#1a73e8'` |
|
|
349
|
+
| `BorderColor` | `string` | `'#e6e7ea'` | Màu border toàn cục (`--libs-ui-color-border`) | `configService.BorderColor = '#d1d5db'` |
|
|
350
|
+
| `BorderErrorColor` | `string` | `'#ee2d41'` | Màu border khi lỗi (`--libs-ui-color-border-error`) | `configService.BorderErrorColor = '#dc2626'` |
|
|
351
|
+
| `TextErrorColor` | `string` | `'#ff5454'` | Màu text lỗi (`--libs-ui-color-text-error`) | `configService.TextErrorColor = '#ef4444'` |
|
|
352
|
+
| `IconHoverDangerColor` | `string` | `'#f15767'` | Màu icon khi hover trạng thái danger | `configService.IconHoverDangerColor = '#f15767'` |
|
|
353
|
+
| `BackgroundDisableColor` | `string` | `'#f8f9fa'` | Background khi disabled (`--libs-ui-color-background-disable`) | `configService.BackgroundDisableColor = '#f3f4f6'` |
|
|
354
|
+
| `TextDisableColor` | `string` | `'#9ca2ad'` | Text color khi disabled (`--libs-ui-color-text-disable`) | `configService.TextDisableColor = '#9ca3af'` |
|
|
355
|
+
| `TextReadonlyColor` | `string` | `'#071631'` | Text color khi readonly (`--libs-ui-color-text-readonly`) | `configService.TextReadonlyColor = '#374151'` |
|
|
356
|
+
| `BackgroundReadonlyColor` | `string` | `'#f8f9fa'` | Background khi readonly (`--libs-ui-color-background-readonly`) | `configService.BackgroundReadonlyColor = '#f9fafb'` |
|
|
357
|
+
| `BackgroundUserSelection` | `string` | `'#00000040'` | Màu nền khi user bôi chọn text (`::selection`) | `configService.BackgroundUserSelection = '#bfdbfe'` |
|
|
358
|
+
| `BackgroundList` | `string` | `'#f8f9fa'` | Background item trong list/dropdown | `configService.BackgroundList = '#f8fafc'` |
|
|
359
|
+
| `BackgroundListHover` | `string` | `'#f8f9fa'` | Background khi hover trên list item | `configService.BackgroundListHover = '#eff6ff'` |
|
|
360
|
+
| `BackgroundListHoverDanger` | `string` | `'#fef5f6'` | Background khi hover trạng thái nguy hiểm | `configService.BackgroundListHoverDanger = '#fef2f2'` |
|
|
361
|
+
| `ConfigFont` | `ILibsUiConfigFontFamily` | SVN-Poppins | Font family + đường dẫn file font | Xem ví dụ 1 |
|
|
362
|
+
| `ConfigFontHead` | `ILibsUiConfigFontHeading` | 7 levels × 4 weights | Toàn bộ heading styles (h1r → h7b) | Xem mục Heading Styles |
|
|
363
|
+
| `ConfigButtonStatus` | `ILibsUiConfigButtonStatus` | 8 màu built-in | Màu cho badge/status button | Xem ví dụ 5 |
|
|
364
|
+
| `ConfigButtonTab` | `ILibsUiConfigButtonTab` | 8 màu built-in | Màu cho tab button active | Xem ví dụ 5 |
|
|
365
|
+
| `FunctionGetConfigButtonIncludes` | `(rootColor: string) => { [key: string]: IColorButton }` | `() => ({})` | Hàm mở rộng thêm custom button types | Xem ví dụ 3 |
|
|
366
|
+
|
|
367
|
+
## Getters (đọc config hiện tại)
|
|
368
|
+
|
|
369
|
+
| Getter | Kiểu trả về | Mô tả |
|
|
370
|
+
|---|---|---|
|
|
371
|
+
| `ConfigButton` | `Signal<{ [key: string]: IColorButton }>` | Toàn bộ button color configs dưới dạng computed Signal — reactive với ThemeColor |
|
|
372
|
+
| `ConfigButtonStatus` | `ILibsUiConfigButtonStatus` | Config màu button status hiện tại |
|
|
373
|
+
|
|
374
|
+
## Types & Interfaces
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
import {
|
|
378
|
+
ILibsUiConfigFontFamily,
|
|
379
|
+
ILibsUiConfigFontWeight,
|
|
380
|
+
ILibsUiConfigFontHeading,
|
|
381
|
+
ILibsUiConfigFontHeadingStyle,
|
|
382
|
+
ILibsUiConfigButtonStatus,
|
|
383
|
+
ILibsUiConfigButtonTab,
|
|
384
|
+
IColorButtonTab,
|
|
385
|
+
IColorButton,
|
|
386
|
+
ILibsUiConfigButtonSize,
|
|
387
|
+
} from '@libs-ui/services-config-project';
|
|
388
|
+
|
|
389
|
+
// Font family config
|
|
173
390
|
interface ILibsUiConfigFontFamily {
|
|
174
|
-
name: string;
|
|
175
|
-
uri_regular: string;
|
|
176
|
-
uri_medium: string;
|
|
177
|
-
uri_semibold: string;
|
|
178
|
-
uri_bold?: string;
|
|
391
|
+
name: string; // Tên font (dùng cho font-family CSS)
|
|
392
|
+
uri_regular: string; // Đường dẫn file font weight 400
|
|
393
|
+
uri_medium: string; // Đường dẫn file font weight 500
|
|
394
|
+
uri_semibold: string; // Đường dẫn file font weight 600
|
|
395
|
+
uri_bold?: string; // Đường dẫn file font weight 700 (tùy chọn)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Heading style cho một cấp (vd: h1r, h2m, h5s...)
|
|
399
|
+
interface ILibsUiConfigFontHeadingStyle {
|
|
400
|
+
'font-size': string; // VD: '16px'
|
|
401
|
+
'font-weight': string; // VD: '500'
|
|
402
|
+
'line-height': string; // VD: '24px'
|
|
403
|
+
'letter-spacing': string; // VD: 'calc(16px * (0.5 / 100))'
|
|
179
404
|
}
|
|
180
405
|
|
|
406
|
+
// Button status color (dùng cho badge, tag, label...)
|
|
181
407
|
interface ILibsUiConfigButtonStatus {
|
|
182
|
-
[key: string]: {
|
|
408
|
+
[key: string]: {
|
|
409
|
+
color: string; // Text/icon color
|
|
410
|
+
background?: string; // Background color
|
|
411
|
+
};
|
|
183
412
|
}
|
|
184
413
|
|
|
414
|
+
// Button tab color (dùng cho tab navigation)
|
|
185
415
|
interface ILibsUiConfigButtonTab {
|
|
186
|
-
[key: string]: {
|
|
416
|
+
[key: string]: {
|
|
417
|
+
color: string; // Text color khi active
|
|
418
|
+
background?: string; // Background khi active
|
|
419
|
+
background_badge?: string; // Background badge khi active
|
|
420
|
+
};
|
|
187
421
|
}
|
|
188
422
|
|
|
423
|
+
// Button color config (dùng để mở rộng custom button)
|
|
189
424
|
interface IColorButton {
|
|
190
|
-
configStepColor: {
|
|
191
|
-
|
|
425
|
+
configStepColor: {
|
|
426
|
+
text: string | number; // Text color (hex hoặc step number)
|
|
427
|
+
text_hover: string | number; // Text color khi hover
|
|
428
|
+
text_active: string | number; // Text color khi active/click
|
|
429
|
+
text_disable: string | number; // Text color khi disabled
|
|
430
|
+
background?: string | number; // Background (hex hoặc step)
|
|
431
|
+
background_hover?: string | number;
|
|
432
|
+
background_active?: string | number;
|
|
433
|
+
background_disable?: string | number;
|
|
434
|
+
border?: string | number;
|
|
435
|
+
border_hover?: string | number;
|
|
436
|
+
border_active?: string | number;
|
|
437
|
+
border_disable?: string | number;
|
|
438
|
+
};
|
|
439
|
+
rootColor: string; // Màu gốc để tính step
|
|
192
440
|
}
|
|
193
441
|
```
|
|
194
442
|
|
|
443
|
+
## CSS Variables được sinh ra
|
|
444
|
+
|
|
445
|
+
| Variable | Mô tả | Ví dụ giá trị |
|
|
446
|
+
|---|---|---|
|
|
447
|
+
| `--libs-ui-color-default` | ThemeColor gốc | `#226ff5` |
|
|
448
|
+
| `--libs-ui-color-light-1` | ThemeColor + 20 steps sáng | `#4e8cf7` |
|
|
449
|
+
| `--libs-ui-color-light-2` | ThemeColor + 90 steps sáng | `#dce9fd` |
|
|
450
|
+
| `--libs-ui-color-light-3` | ThemeColor + 95 steps sáng (background nhẹ) | `#f4f8ff` |
|
|
451
|
+
| `--libs-ui-color-light-4` | ThemeColor + 50 steps sáng (disabled active) | `#91b7fa` |
|
|
452
|
+
| `--libs-ui-color-light-5` | ThemeColor + 70 steps sáng | `#b8d2fb` |
|
|
453
|
+
| `--libs-ui-color-light-6` | ThemeColor + 80 steps sáng | `#cfe0fd` |
|
|
454
|
+
| `--libs-ui-color-dark` | ThemeColor - 20 steps tối | `#1b59c4` |
|
|
455
|
+
| `--libs-ui-color-border` | BorderColor | `#e6e7ea` |
|
|
456
|
+
| `--libs-ui-color-border-error` | BorderErrorColor | `#ee2d41` |
|
|
457
|
+
| `--libs-ui-color-text-error` | TextErrorColor | `#ff5454` |
|
|
458
|
+
| `--libs-ui-color-text-disable` | TextDisableColor | `#9ca2ad` |
|
|
459
|
+
| `--libs-ui-color-text-readonly` | TextReadonlyColor | `#071631` |
|
|
460
|
+
| `--libs-ui-color-background-disable` | BackgroundDisableColor | `#f8f9fa` |
|
|
461
|
+
| `--libs-ui-color-background-readonly` | BackgroundReadonlyColor | `#f8f9fa` |
|
|
462
|
+
| `--libs-ui-color-background-selection` | BackgroundUserSelection | `#00000040` |
|
|
463
|
+
| `--libs-ui-color-icon-hover-danger` | IconHoverDangerColor | `#f15767` |
|
|
464
|
+
| `--libs-ui-color-gradient-from` | Gradient start color | Tính từ ThemeColor |
|
|
465
|
+
| `--libs-ui-color-gradient-to` | Gradient end color | Tính từ ThemeColor |
|
|
466
|
+
| `--libs-ui-font-family-name` | Tên font family | `Inter, Arial, Helvetica, sans-serif` |
|
|
467
|
+
|
|
468
|
+
## Heading Typography (CSS classes)
|
|
469
|
+
|
|
470
|
+
Service tự động sinh CSS class `libs-ui-font-{level}{weight}` cho toàn bộ 28 combinations:
|
|
471
|
+
|
|
472
|
+
| Level | Regular (r) | Medium (m) | Semibold (s) | Bold (b) |
|
|
473
|
+
|---|---|---|---|---|
|
|
474
|
+
| h1 | `libs-ui-font-h1r` (30px/400) | `libs-ui-font-h1m` (30px/500) | `libs-ui-font-h1s` (30px/600) | `libs-ui-font-h1b` (30px/700) |
|
|
475
|
+
| h2 | `libs-ui-font-h2r` (20px/400) | `libs-ui-font-h2m` (20px/500) | `libs-ui-font-h2s` (20px/600) | `libs-ui-font-h2b` (20px/700) |
|
|
476
|
+
| h3 | `libs-ui-font-h3r` (16px/400) | `libs-ui-font-h3m` (16px/500) | `libs-ui-font-h3s` (16px/600) | `libs-ui-font-h3b` (16px/700) |
|
|
477
|
+
| h4 | `libs-ui-font-h4r` (13px/400) | `libs-ui-font-h4m` (13px/500) | `libs-ui-font-h4s` (13px/600) | `libs-ui-font-h4b` (13px/700) |
|
|
478
|
+
| h5 | `libs-ui-font-h5r` (12px/400) | `libs-ui-font-h5m` (12px/500) | `libs-ui-font-h5s` (12px/600) | `libs-ui-font-h5b` (12px/700) |
|
|
479
|
+
| h6 | `libs-ui-font-h6r` (11px/400) | `libs-ui-font-h6m` (11px/500) | `libs-ui-font-h6s` (11px/600) | `libs-ui-font-h6b` (11px/700) |
|
|
480
|
+
| h7 | `libs-ui-font-h7r` (10px/400) | `libs-ui-font-h7m` (10px/500) | `libs-ui-font-h7s` (10px/600) | `libs-ui-font-h7b` (10px/700) |
|
|
481
|
+
|
|
482
|
+
Thêm hậu tố `i` để in nghiêng: `libs-ui-font-h3mi`, `libs-ui-font-h5si`, ...
|
|
483
|
+
|
|
484
|
+
```html
|
|
485
|
+
<h1 class="libs-ui-font-h1b">Tiêu đề cấp 1 bold</h1>
|
|
486
|
+
<h2 class="libs-ui-font-h2s">Tiêu đề cấp 2 semibold</h2>
|
|
487
|
+
<p class="libs-ui-font-h4r">Văn bản body regular</p>
|
|
488
|
+
<small class="libs-ui-font-h6m">Caption medium</small>
|
|
489
|
+
<span class="libs-ui-font-h3si">Heading italic</span>
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
## Global CSS Utility Classes
|
|
493
|
+
|
|
494
|
+
### Border
|
|
495
|
+
|
|
496
|
+
| Class | Mô tả |
|
|
497
|
+
|---|---|
|
|
498
|
+
| `libs-ui-border-general` | Border đầy đủ 4 cạnh |
|
|
499
|
+
| `libs-ui-border-top-general` | Chỉ border-top |
|
|
500
|
+
| `libs-ui-border-right-general` | Chỉ border-right |
|
|
501
|
+
| `libs-ui-border-bottom-general` | Chỉ border-bottom |
|
|
502
|
+
| `libs-ui-border-left-general` | Chỉ border-left |
|
|
503
|
+
| `libs-ui-border-x-general` | Border trái + phải |
|
|
504
|
+
| `libs-ui-border-y-general` | Border trên + dưới |
|
|
505
|
+
| `libs-ui-border-dashed-general` | Border nét đứt đầy đủ |
|
|
506
|
+
| `libs-ui-border-error-general` | Border màu lỗi (important) |
|
|
507
|
+
| `libs-ui-border-primary-general` | Border màu ThemeColor |
|
|
508
|
+
|
|
509
|
+
### Shadow
|
|
510
|
+
|
|
511
|
+
| Class | Mô tả |
|
|
512
|
+
|---|---|
|
|
513
|
+
| `libs-ui-shadow` | Shadow chuẩn `0 2px 10px 1px rgba(51,51,51,0.1)` |
|
|
514
|
+
| `libs-ui-shadow-sm` | Shadow nhỏ |
|
|
515
|
+
| `libs-ui-shadow-md` | Shadow medium |
|
|
516
|
+
| `libs-ui-shadow-lg` | Shadow lớn |
|
|
517
|
+
| `libs-ui-shadow-small` | Shadow tối ưu (design system) |
|
|
518
|
+
| `libs-ui-shadow-medium` | Shadow medium (design system) |
|
|
519
|
+
| `libs-ui-shadow-large` | Shadow lớn (design system) |
|
|
520
|
+
| `libs-ui-shadow-extra-large` | Shadow rất lớn (design system) |
|
|
521
|
+
| `libs-ui-shadow-none` | Tắt shadow (important) |
|
|
522
|
+
|
|
523
|
+
### Background
|
|
524
|
+
|
|
525
|
+
| Class | Mô tả |
|
|
526
|
+
|---|---|
|
|
527
|
+
| `libs-ui-bg-list` | Background list item |
|
|
528
|
+
| `libs-ui-bg-list-hover` | Background hover list item |
|
|
529
|
+
| `libs-ui-bg-list-active` | Background active list item (ThemeColor-95) |
|
|
530
|
+
| `libs-ui-bg-list-hover-active` | Hover + active states kết hợp |
|
|
531
|
+
| `libs-ui-bg-list-hover-danger` | Hover với màu danger |
|
|
532
|
+
|
|
533
|
+
### State
|
|
534
|
+
|
|
535
|
+
| Class | Mô tả |
|
|
536
|
+
|---|---|
|
|
537
|
+
| `libs-ui-disable` | Cursor not-allowed + text màu disable |
|
|
538
|
+
| `libs-ui-disable-background` | Background màu disable |
|
|
539
|
+
| `libs-ui-disable-active` | Disabled active state |
|
|
540
|
+
| `libs-ui-readonly` | Cursor not-allowed + text màu readonly |
|
|
541
|
+
| `libs-ui-readonly-background` | Background màu readonly |
|
|
542
|
+
| `libs-ui-text-error` | Text màu lỗi (important) |
|
|
543
|
+
| `libs-ui-icon-hover-danger` | Icon hover danger color |
|
|
544
|
+
|
|
195
545
|
## Lưu ý quan trọng
|
|
196
546
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
547
|
+
⚠️ **Inject một lần duy nhất**: Service là `providedIn: 'root'` — chỉ inject trong `AppComponent`. Mọi component khác trong app đều tự động nhận cấu hình chung thông qua CSS variables.
|
|
548
|
+
|
|
549
|
+
⚠️ **Setter syntax — không phải method**: Dùng assignment `configService.ThemeColor = '#color'` (property setter), không phải `configService.setThemeColor('#color')`.
|
|
550
|
+
|
|
551
|
+
⚠️ **Font URIs phải accessible từ browser**: Đường dẫn font có thể là URL tuyệt đối (`https://...`) hoặc tương đối từ gốc (`/assets/fonts/...`). Font được load qua FontFace API — không cần khai báo `@font-face` trong CSS.
|
|
552
|
+
|
|
553
|
+
⚠️ **String.prototype được extend global**: Khi service khởi tạo, `String.prototype` được bổ sung các method: `replaceAt`, `replaceAll` (override), `occurrencesByCharacter`, `indexesOfCharacter`, `indexesByString`. Cần lưu ý khi dùng trong môi trường có strict prototype protection.
|
|
554
|
+
|
|
555
|
+
⚠️ **ConfigButton là Signal không phải giá trị thường**: `configService.ConfigButton` trả về `Signal<{...}>`. Để đọc giá trị cần gọi `configService.ConfigButton()` hoặc dùng trong `computed()`/`effect()`.
|
|
556
|
+
|
|
557
|
+
⚠️ **ThemeColor gradient mặc định**: Khi ThemeColor là `#226FF5` (giá trị mặc định), gradient được tính theo công thức đặc biệt kết hợp với màu `#5B2EBB`. Với màu khác, gradient được tính thuần từ ThemeColor.
|