@libs-ui/services-config-project 0.2.356-9 → 0.2.357-1

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
- # Config Project Service
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. Inject **một lần** trong `AppComponent` — áp dụng ngay cho toàn bộ ứng dụng thông qua CSS variables.
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 (load dynamic, không cần @font-face CSS)
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 active và badge
13
- - ✅ Signal reactivitythay đổi tức thì, không cần reload
14
- - ✅ Global CSS utility classes (border, shadow, disable, readonly, selection...)
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
- ## Quick Start
66
+ ## dụ sử dụng
29
67
 
30
- Inject **một lần** trong `AppComponent` set config ngay khi khởi động:
68
+ ### dụ 1 Khởi tạo 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({ standalone: true, ... })
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
- // Bước 1: Set brand/theme color
86
+ ngOnInit(): void {
87
+ // Set brand/theme color — tự động sinh 20+ CSS variables
42
88
  this.configService.ThemeColor = '#226ff5';
43
89
 
44
- // Bước 2 (tùy chọn): Set custom font
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
- ## Ví dụ
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
- ### Thay đổi Theme Color (Multi-tenant)
130
+ ### dụ 3 Thêm custom button color type
59
131
 
60
132
  ```typescript
61
- // Sau khi fetch tenant config từ API:
62
- this.configService.ThemeColor = tenantConfig.brandColor;
63
- // → 20+ CSS variables được cập nhật ngay lập tức
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 individual
171
+ ### Ví dụ 4 — Override màu cá nhân cho trạng thái đặc thù
67
172
 
68
173
  ```typescript
69
- this.configService.BorderColor = '#d1d5db';
70
- this.configService.TextErrorColor = '#dc2626';
71
- this.configService.BackgroundDisableColor = '#f3f4f6';
72
- this.configService.TextDisableColor = '#9ca3af';
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 type
199
+ ### Ví dụ 5 — Custom button status và tab colors
76
200
 
77
201
  ```typescript
78
- this.configService.FunctionGetConfigButtonIncludes = (rootColor) => ({
79
- 'button-brand': {
80
- configStepColor: {
81
- text: 'white',
82
- text_hover: 'white',
83
- text_active: 'white',
84
- text_disable: '#CDD0D6',
85
- background: 0,
86
- background_hover: 20,
87
- background_active: -20,
88
- background_disable: '#F8F9FA',
89
- border: 0,
90
- border_hover: 20,
91
- border_active: -20,
92
- border_disable: '#F8F9FA',
93
- },
94
- rootColor: '#e91e63',
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
- ### Sử dụng CSS Variables trong SCSS
241
+ ### dụ 6 — Dùng CSS variables trong SCSS của component
100
242
 
101
243
  ```scss
102
- // Dùng biến thay hardcode màu
103
- .my-button {
104
- background: var(--libs-ui-color-default);
105
- border: 1px solid var(--libs-ui-color-light-1);
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-3);
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
- &:disabled {
111
- background: var(--libs-ui-color-background-disable);
112
- color: var(--libs-ui-color-text-disable);
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
- ## APISetters
118
-
119
- | Setter | Type | Default | Mô tả |
120
- | --------------------------------- | --------------------------- | -------------------- | ------------------------------------------ |
121
- | `ThemeColor` | `string` | `'#226ff5'` | Màu chủ đạo — sinh 20+ CSS color variables |
122
- | `BorderColor` | `string` | `'#e6e7ea'` | Màu border (--libs-ui-color-border) |
123
- | `BorderErrorColor` | `string` | `'#ee2d41'` | Màu border error |
124
- | `TextErrorColor` | `string` | `'#ff5454'` | Màu text error |
125
- | `IconHoverDangerColor` | `string` | `'#f15767'` | Màu icon hover danger |
126
- | `BackgroundDisableColor` | `string` | `'#f8f9fa'` | Background disabled |
127
- | `TextDisableColor` | `string` | `'#9ca2ad'` | Text color disabled |
128
- | `TextReadonlyColor` | `string` | `'#071631'` | Text color readonly |
129
- | `BackgroundReadonlyColor` | `string` | `'#f8f9fa'` | Background readonly |
130
- | `BackgroundUserSelection` | `string` | `'#00000040'` | Text selection background |
131
- | `BackgroundList` | `string` | `'#f8f9fa'` | Dropdown/list item background |
132
- | `BackgroundListHover` | `string` | `'#f8f9fa'` | List item hover background |
133
- | `BackgroundListHoverDanger` | `string` | `'#fef5f6'` | List item hover danger background |
134
- | `ConfigFont` | `ILibsUiConfigFontFamily` | SVN-Poppins | Font family + URI files |
135
- | `ConfigFontHead` | `ILibsUiConfigFontHeading` | 7 levels × 4 weights | Heading styles (h1r→h7b) |
136
- | `ConfigButtonStatus` | `ILibsUiConfigButtonStatus` | 8 màu | Badge status colors |
137
- | `ConfigButtonTab` | `ILibsUiConfigButtonTab` | 8 màu | Tab button colors |
138
- | `FunctionGetConfigButtonIncludes` | `Function` | `() => {}` | Hàm thêm custom button types |
139
-
140
- ## API Getters
141
-
142
- | Getter | Returns | Mô tả |
143
- | -------------------- | ----------------------------------------- | --------------------------------------------- |
144
- | `ConfigButton` | `Signal<{ [key: string]: IColorButton }>` | Tất cả button color configs (computed Signal) |
145
- | `ConfigButtonStatus` | `ILibsUiConfigButtonStatus` | Current button status config |
146
-
147
- ## API — Methods
148
-
149
- | Method | Returns | Mô tả |
150
- | ------------------------------------------- | ----------------- | ------------------------------------------------------ |
151
- | `colorStepContrastFromOrigin(step, color?)` | `{ light, dark }` | Tính màu lighter/darker N steps |
152
- | `setupFontFamily(doc?)` | `void` | Load font vào document (public để dùng cho shadow DOM) |
153
-
154
- ## CSS Variables được tạo ra
155
-
156
- | Variable | tả |
157
- | ------------------------------------ | ------------------------------------------- |
158
- | `--libs-ui-color-default` | ThemeColor gốc |
159
- | `--libs-ui-color-light-1` | ThemeColor + 20 steps sáng |
160
- | `--libs-ui-color-light-2` | ThemeColor + 90 steps sáng |
161
- | `--libs-ui-color-light-3` | ThemeColor + 95 steps sáng (background nhẹ) |
162
- | `--libs-ui-color-dark` | ThemeColor - 20 steps tối |
163
- | `--libs-ui-color-border` | BorderColor |
164
- | `--libs-ui-color-border-error` | BorderErrorColor |
165
- | `--libs-ui-color-text-error` | TextErrorColor |
166
- | `--libs-ui-color-text-disable` | TextDisableColor |
167
- | `--libs-ui-color-background-disable` | BackgroundDisableColor |
168
- | `--libs-ui-font-family-name` | Font family name |
169
-
170
- ## Types
267
+ ### 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 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]: { color: string; background?: 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]: { color: string; background?: string; background_badge?: 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: { text, text_hover, text_active, text_disable, background?, ... };
191
- rootColor: string;
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
- - **Inject một lần** trong `AppComponent` service là `providedIn: 'root'`, mọi nơi đều dùng chung instance
198
- - **Signal reactivity** — thay đổi bất kỳ setter nào → Angular `effect()` tự chạy lại → CSS vars cập nhật ngay
199
- - **Font URIs** phải accessible từ browser (URL tuyệt đối hoặc tương đối từ root). Load bằng FontFace API — không cần `@font-face` trong CSS
200
- - **String.prototype** được extend global (replaceAt, occurrencesByCharacter, indexesOfCharacter) khi service khởi tạo
201
- - **`configService.ThemeColor = '#e91e63'`** (setter syntax) — không phải method call
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.