@libs-ui/icons 0.2.356-42 → 0.2.356-43

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,3 +1,357 @@
1
- # libs-ui-icons
1
+ # @libs-ui/icons
2
2
 
3
- This library was generated with [Nx](https://nx.dev).
3
+ > Bộ SVG icon components và pipe lazy-load dùng trong hệ sinh thái libs-ui.
4
+
5
+ ## Giới thiệu
6
+
7
+ `@libs-ui/icons` cung cấp tập hợp các SVG icon được đóng gói thành Angular Standalone Component, hỗ trợ tùy biến kích thước và màu sắc thông qua Signal API. Thư viện còn bao gồm pipe `LibsUiIconsGetIconComponentPipe` để lazy-load icon component theo key string, phù hợp cho các trường hợp render icon động tại runtime mà không cần import tĩnh từng component.
8
+
9
+ ## Tính năng
10
+
11
+ - ✅ 13 icon component SVG sẵn dùng (file types, AI, trạng thái rỗng, reload, v.v.)
12
+ - ✅ Tùy biến `size` và `color` thông qua Signal `input()`
13
+ - ✅ Hỗ trợ trạng thái `active` với màu riêng (`colorActive`)
14
+ - ✅ Pipe lazy-load icon theo key string — không import tĩnh toàn bộ bundle
15
+ - ✅ Mọi component đều Standalone + `ChangeDetectionStrategy.OnPush`
16
+ - ✅ Abstract base class `LibsUiIconsComponentAbstract` để mở rộng icon mới nhất quán
17
+
18
+ ## Khi nào sử dụng
19
+
20
+ - Hiển thị icon định dạng file (PDF, Word, Excel, PPTX, JSON, XML) trong danh sách tài liệu hoặc upload preview
21
+ - Hiển thị trạng thái rỗng (`no-data`, `no-result`) trong bảng dữ liệu hoặc màn hình list
22
+ - Sử dụng icon AI (`ai`, `ai-interaction`, `sparkles-ai-solid`) trong các tính năng trí tuệ nhân tạo
23
+ - Render icon động theo key từ API/config mà không biết trước loại icon khi build
24
+ - Tích hợp icon `reload`, `send-solid`, `stop-solid` vào các nút hành động
25
+
26
+ ## Cài đặt
27
+
28
+ ```bash
29
+ npm install @libs-ui/icons
30
+ ```
31
+
32
+ ## Import
33
+
34
+ ```typescript
35
+ // Import từng icon component cụ thể
36
+ import { LibsUiIconsAiComponent } from '@libs-ui/icons';
37
+ import { LibsUiIconsPdfComponent } from '@libs-ui/icons';
38
+ import { LibsUiIconsNoDataComponent } from '@libs-ui/icons';
39
+ import { LibsUiIconsReloadComponent } from '@libs-ui/icons';
40
+ import { LibsUiIconsSendSolidComponent } from '@libs-ui/icons';
41
+ import { LibsUiIconsStopSolidComponent } from '@libs-ui/icons';
42
+ import { LibsUiIconsSparklesAiSolidComponent } from '@libs-ui/icons';
43
+ import { LibsUiIconsAiInteractionComponent } from '@libs-ui/icons';
44
+ import { LibsUiIconsNoResultComponent } from '@libs-ui/icons';
45
+ import { LibsUiIconsWordComponent } from '@libs-ui/icons';
46
+ import { LibsUiIconsXlsxComponent } from '@libs-ui/icons';
47
+ import { LibsUiIconsPptxComponent } from '@libs-ui/icons';
48
+ import { LibsIconsJsonComponent } from '@libs-ui/icons';
49
+ import { LibsUiIconsXmlComponent } from '@libs-ui/icons';
50
+ import { LibsIconsImageDefaultComponent } from '@libs-ui/icons';
51
+
52
+ // Import pipe lazy-load
53
+ import { LibsUiIconsGetIconComponentPipe } from '@libs-ui/icons';
54
+
55
+ // Import abstract base class (khi tạo icon mới)
56
+ import { LibsUiIconsComponentAbstract } from '@libs-ui/icons';
57
+ ```
58
+
59
+ ## Ví dụ sử dụng
60
+
61
+ ### Ví dụ 1 — Icon cơ bản với size và color tùy chỉnh
62
+
63
+ ```typescript
64
+ import { Component } from '@angular/core';
65
+ import { ChangeDetectionStrategy } from '@angular/core';
66
+ import { LibsUiIconsPdfComponent } from '@libs-ui/icons';
67
+ import { LibsUiIconsWordComponent } from '@libs-ui/icons';
68
+ import { LibsUiIconsXlsxComponent } from '@libs-ui/icons';
69
+
70
+ @Component({
71
+ selector: 'app-file-icon-demo',
72
+ standalone: true,
73
+ changeDetection: ChangeDetectionStrategy.OnPush,
74
+ imports: [LibsUiIconsPdfComponent, LibsUiIconsWordComponent, LibsUiIconsXlsxComponent],
75
+ template: `
76
+ <!-- PDF icon — size 24, màu mặc định -->
77
+ <libs_ui-icons-pdf [size]="24" />
78
+
79
+ <!-- Word icon — size 32 (mặc định) -->
80
+ <libs_ui-icons-word />
81
+
82
+ <!-- Excel icon — size 40, màu tùy chỉnh -->
83
+ <libs_ui-icons-xlsx [size]="40" [color]="'#217346'" />
84
+ `,
85
+ })
86
+ export class FileIconDemoComponent {}
87
+ ```
88
+
89
+ ### Ví dụ 2 — Icon trạng thái rỗng
90
+
91
+ ```typescript
92
+ import { Component } from '@angular/core';
93
+ import { ChangeDetectionStrategy } from '@angular/core';
94
+ import { LibsUiIconsNoDataComponent } from '@libs-ui/icons';
95
+ import { LibsUiIconsNoResultComponent } from '@libs-ui/icons';
96
+
97
+ @Component({
98
+ selector: 'app-empty-state-demo',
99
+ standalone: true,
100
+ changeDetection: ChangeDetectionStrategy.OnPush,
101
+ imports: [LibsUiIconsNoDataComponent, LibsUiIconsNoResultComponent],
102
+ template: `
103
+ <!-- Khi không có dữ liệu nào -->
104
+ <div class="flex flex-col items-center gap-2">
105
+ <libs_ui-icons-no_data [size]="65" />
106
+ <span class="libs-ui-font-h5r">Chưa có dữ liệu</span>
107
+ </div>
108
+
109
+ <!-- Khi tìm kiếm không có kết quả -->
110
+ <div class="flex flex-col items-center gap-2">
111
+ <libs_ui-icons-no_result [size]="65" />
112
+ <span class="libs-ui-font-h5r">Không tìm thấy kết quả</span>
113
+ </div>
114
+ `,
115
+ })
116
+ export class EmptyStateDemoComponent {}
117
+ ```
118
+
119
+ ### Ví dụ 3 — Icon AI với trạng thái active
120
+
121
+ ```typescript
122
+ import { Component, signal } from '@angular/core';
123
+ import { ChangeDetectionStrategy } from '@angular/core';
124
+ import { LibsUiIconsAiComponent } from '@libs-ui/icons';
125
+ import { LibsUiIconsSparklesAiSolidComponent } from '@libs-ui/icons';
126
+ import { LibsUiIconsSendSolidComponent } from '@libs-ui/icons';
127
+ import { LibsUiIconsStopSolidComponent } from '@libs-ui/icons';
128
+
129
+ @Component({
130
+ selector: 'app-ai-icon-demo',
131
+ standalone: true,
132
+ changeDetection: ChangeDetectionStrategy.OnPush,
133
+ imports: [
134
+ LibsUiIconsAiComponent,
135
+ LibsUiIconsSparklesAiSolidComponent,
136
+ LibsUiIconsSendSolidComponent,
137
+ LibsUiIconsStopSolidComponent,
138
+ ],
139
+ template: `
140
+ <!-- AI icon gradient — size 32 (mặc định) -->
141
+ <libs_ui-icons-ai [size]="32" />
142
+
143
+ <!-- Sparkles AI solid — màu xanh mặc định #226FF5 -->
144
+ <libs_ui-icons-sparkles_ai_solid [size]="24" />
145
+
146
+ <!-- Send solid — active state đổi màu -->
147
+ <libs_ui-icons-send_solid
148
+ [size]="24"
149
+ [color]="'#226FF5'"
150
+ [colorActive]="'#0050CC'"
151
+ [active]="isActive()" />
152
+
153
+ <!-- Stop solid — dừng stream AI -->
154
+ <libs_ui-icons-stop_solid [size]="24" [color]="'#226FF5'" />
155
+ `,
156
+ })
157
+ export class AiIconDemoComponent {
158
+ protected isActive = signal(false);
159
+ }
160
+ ```
161
+
162
+ ### Ví dụ 4 — Lazy-load icon bằng pipe (render động)
163
+
164
+ ```typescript
165
+ import { Component, signal } from '@angular/core';
166
+ import { AsyncPipe, NgComponentOutlet } from '@angular/common';
167
+ import { ChangeDetectionStrategy } from '@angular/core';
168
+ import { LibsUiIconsGetIconComponentPipe } from '@libs-ui/icons';
169
+
170
+ @Component({
171
+ selector: 'app-dynamic-icon-demo',
172
+ standalone: true,
173
+ changeDetection: ChangeDetectionStrategy.OnPush,
174
+ imports: [AsyncPipe, NgComponentOutlet, LibsUiIconsGetIconComponentPipe],
175
+ template: `
176
+ <!-- Lazy-load icon theo key động -->
177
+ @for (file of files(); track file.id) {
178
+ <ng-container
179
+ *ngComponentOutlet="file.type | LibsUiIconsGetIconComponentPipe | async" />
180
+ }
181
+ `,
182
+ })
183
+ export class DynamicIconDemoComponent {
184
+ protected files = signal([
185
+ { id: '1', name: 'report.pdf', type: 'pdf' },
186
+ { id: '2', name: 'data.xlsx', type: 'xlsx' },
187
+ { id: '3', name: 'doc.docx', type: 'word' },
188
+ { id: '4', name: 'data.json', type: 'json' },
189
+ ]);
190
+ }
191
+ ```
192
+
193
+ ### Ví dụ 5 — Icon reload và ai-interaction
194
+
195
+ ```typescript
196
+ import { Component } from '@angular/core';
197
+ import { ChangeDetectionStrategy } from '@angular/core';
198
+ import { LibsUiIconsReloadComponent } from '@libs-ui/icons';
199
+ import { LibsUiIconsAiInteractionComponent } from '@libs-ui/icons';
200
+
201
+ @Component({
202
+ selector: 'app-action-icon-demo',
203
+ standalone: true,
204
+ changeDetection: ChangeDetectionStrategy.OnPush,
205
+ imports: [LibsUiIconsReloadComponent, LibsUiIconsAiInteractionComponent],
206
+ template: `
207
+ <!-- Reload icon — màu xám mặc định #6A7383 -->
208
+ <button (click)="handlerReload($event)" class="p-2 hover:bg-gray-100 rounded">
209
+ <libs_ui-icons-reload [size]="20" />
210
+ </button>
211
+
212
+ <!-- AI Interaction icon — size 32 mặc định -->
213
+ <libs_ui-icons-ai-interaction [size]="28" />
214
+ `,
215
+ })
216
+ export class ActionIconDemoComponent {
217
+ protected handlerReload(event: Event): void {
218
+ event.stopPropagation();
219
+ // xử lý reload
220
+ }
221
+ }
222
+ ```
223
+
224
+ ## @Input() — Shared (tất cả icon components)
225
+
226
+ Tất cả icon component đều kế thừa `LibsUiIconsComponentAbstract` và có chung các input sau:
227
+
228
+ | Input | Type | Default | Mô tả | Ví dụ |
229
+ |---|---|---|---|---|
230
+ | `size` | `number` | `16` (xem bảng riêng) | Kích thước icon theo px (áp dụng cho cả width và height của SVG) | `[size]="24"` |
231
+ | `color` | `string` | `'#e6e7ea'` (xem bảng riêng) | Màu fill mặc định của icon khi không active | `[color]="'#333333'"` |
232
+ | `colorActive` | `string` | `'#ffffff'` | Màu fill của icon khi `active` là `true` | `[colorActive]="'#0050CC'"` |
233
+ | `active` | `boolean` | `undefined` | Khi `true`, icon hiển thị với màu `colorActive` thay vì `color` | `[active]="isSelected()"` |
234
+
235
+ ### Default size và color theo từng component
236
+
237
+ | Component | Selector | Default size | Default color |
238
+ |---|---|---|---|
239
+ | `LibsUiIconsAiComponent` | `libs_ui-icons-ai` | `32` | `#e6e7ea` (gradient SVG) |
240
+ | `LibsUiIconsAiInteractionComponent` | `libs_ui-icons-ai-interaction` | `32` | `#e6e7ea` |
241
+ | `LibsIconsImageDefaultComponent` | `libs_ui-icons-image_default` | `64` | `#e6e7ea` |
242
+ | `LibsIconsJsonComponent` | `libs_ui-icons-json` | `32` | `#e6e7ea` |
243
+ | `LibsUiIconsNoDataComponent` | `libs_ui-icons-no_data` | `65` | `#e6e7ea` |
244
+ | `LibsUiIconsNoResultComponent` | `libs_ui-icons-no_result` | `65` | `#e6e7ea` |
245
+ | `LibsUiIconsPdfComponent` | `libs_ui-icons-pdf` | `32` | `#e6e7ea` |
246
+ | `LibsUiIconsPptxComponent` | `libs_ui-icons-pptx` | `32` | `#e6e7ea` |
247
+ | `LibsUiIconsReloadComponent` | `libs_ui-icons-reload` | `32` | `#6A7383` |
248
+ | `LibsUiIconsSendSolidComponent` | `libs_ui-icons-send_solid` | `32` | `#226FF5` |
249
+ | `LibsUiIconsSparklesAiSolidComponent` | `libs_ui-icons-sparkles_ai_solid` | `32` | `#226FF5` |
250
+ | `LibsUiIconsStopSolidComponent` | `libs_ui-icons-stop_solid` | `32` | `#226FF5` |
251
+ | `LibsUiIconsWordComponent` | `libs_ui-icons-word` | `32` | `#e6e7ea` |
252
+ | `LibsUiIconsXlsxComponent` | `libs_ui-icons-xlsx` | `32` | `#e6e7ea` |
253
+ | `LibsUiIconsXmlComponent` | `libs_ui-icons-xml` | `32` | `#e6e7ea` |
254
+
255
+ ## Pipe — LibsUiIconsGetIconComponentPipe
256
+
257
+ Pipe async lazy-load icon component theo key string. Trả về `Promise<Type<any> | null>`, dùng kết hợp với `AsyncPipe` và `NgComponentOutlet`.
258
+
259
+ | Tham số | Type | Bắt buộc | Mô tả | Ví dụ |
260
+ |---|---|---|---|---|
261
+ | `key` | `string \| undefined` | Không | Key định danh icon. Xem bảng key hợp lệ bên dưới | `'pdf'` |
262
+
263
+ ### Key hợp lệ
264
+
265
+ | Key | Component được lazy-load |
266
+ |---|---|
267
+ | `'no-data'` | `LibsUiIconsNoDataComponent` |
268
+ | `'no-result'` | `LibsUiIconsNoResultComponent` |
269
+ | `'json'` | `LibsIconsJsonComponent` |
270
+ | `'pdf'` | `LibsUiIconsPdfComponent` |
271
+ | `'pptx'` | `LibsUiIconsPptxComponent` |
272
+ | `'word'` | `LibsUiIconsWordComponent` |
273
+ | `'xlsx'` | `LibsUiIconsXlsxComponent` |
274
+ | `'xml'` | `LibsUiIconsXmlComponent` |
275
+ | `'image-default'` | `LibsIconsImageDefaultComponent` |
276
+ | `'ai'` | `LibsUiIconsAiComponent` |
277
+ | `'ai-interaction'` | `LibsUiIconsAiInteractionComponent` |
278
+ | `'reload'` | `LibsUiIconsReloadComponent` |
279
+ | `'send-solid'` | `LibsUiIconsSendSolidComponent` |
280
+ | `'sparkles-ai-solid'` | `LibsUiIconsSparklesAiSolidComponent` |
281
+ | `'stop-solid'` | `LibsUiIconsStopSolidComponent` |
282
+ | Bất kỳ key khác | `null` (không render) |
283
+
284
+ ### Sử dụng pipe trong template
285
+
286
+ ```html
287
+ <!-- Kết hợp async pipe + NgComponentOutlet -->
288
+ <ng-container
289
+ *ngComponentOutlet="'pdf' | LibsUiIconsGetIconComponentPipe | async" />
290
+ ```
291
+
292
+ ### Sử dụng pipe trong TypeScript (standalone)
293
+
294
+ ```typescript
295
+ import { LibsUiIconsGetIconComponentPipe } from '@libs-ui/icons';
296
+
297
+ const pipe = new LibsUiIconsGetIconComponentPipe();
298
+ const component = await pipe.transform('pdf');
299
+ // component = LibsUiIconsPdfComponent class (có thể dùng với dynamic component)
300
+
301
+ const nullResult = await pipe.transform('unknown-key');
302
+ // nullResult = null
303
+ ```
304
+
305
+ ## Abstract Base Class — LibsUiIconsComponentAbstract
306
+
307
+ Dùng khi tạo icon component mới trong dự án, kế thừa để có sẵn các input `size`, `color`, `colorActive`, `active` và computed `colorBind`.
308
+
309
+ ```typescript
310
+ import { ChangeDetectionStrategy, Component, input } from '@angular/core';
311
+ import { LibsUiIconsComponentAbstract } from '@libs-ui/icons';
312
+
313
+ @Component({
314
+ selector: 'app-custom-icon',
315
+ standalone: true,
316
+ changeDetection: ChangeDetectionStrategy.OnPush,
317
+ template: `
318
+ <svg [attr.width]="size()" [attr.height]="size()" viewBox="0 0 24 24" fill="none">
319
+ <circle cx="12" cy="12" r="10" [attr.fill]="colorBind()" />
320
+ </svg>
321
+ `,
322
+ })
323
+ export class CustomIconComponent extends LibsUiIconsComponentAbstract {
324
+ // Override default size nếu cần
325
+ override readonly size = input<number, number | undefined>(24, { transform: (value) => value ?? 24 });
326
+ }
327
+ ```
328
+
329
+ ### API của LibsUiIconsComponentAbstract
330
+
331
+ | Thành phần | Loại | Mô tả |
332
+ |---|---|---|
333
+ | `size` | `input<number>` (default: `16`) | Kích thước px |
334
+ | `color` | `input<string>` (default: `'#e6e7ea'`) | Màu mặc định |
335
+ | `colorActive` | `input<string>` (default: `'#ffffff'`) | Màu khi active |
336
+ | `active` | `input<boolean>` | Trạng thái active |
337
+ | `colorBind` | `computed` (protected) | Trả về `colorActive()` khi `active()` là `true`, ngược lại trả về `color()` |
338
+
339
+ ## Lưu ý quan trọng
340
+
341
+ ⚠️ **Selector dùng dấu gạch dưới (`_`) cho dấu gạch ngang trong tên folder**: Các selector như `libs_ui-icons-no_data`, `libs_ui-icons-send_solid` dùng `_` để thay thế `-` trong tên folder theo quy ước selector của libs-ui. Cần viết đúng selector khi dùng trong template.
342
+
343
+ ⚠️ **Pipe là async**: `LibsUiIconsGetIconComponentPipe` trả về `Promise`, bắt buộc kết hợp với `| async` trong template và import `AsyncPipe` vào `imports[]` của component.
344
+
345
+ ⚠️ **Icon AI (`libs_ui-icons-ai`) dùng SVG gradient**: Màu của icon AI được định nghĩa trực tiếp trong SVG path qua `linearGradient`, input `color` không ảnh hưởng đến màu gradient này.
346
+
347
+ ⚠️ **`colorActive` default là `'#ffffff'`**: Trong abstract base, giá trị mặc định của `colorActive` khi không truyền vào là `'#ffffff'` (trắng). Một số component override giá trị này (ví dụ: `reload` dùng `#6A7383`, `send-solid` dùng `#226FF5`). Kiểm tra bảng default ở trên trước khi dùng.
348
+
349
+ ⚠️ **Không có @Output()**: Tất cả icon component chỉ là SVG display thuần, không emit event. Nếu cần xử lý click, bọc bên ngoài bằng `<button>` hoặc element có `(click)` handler.
350
+
351
+ ## Demo
352
+
353
+ ```bash
354
+ npx nx serve core-ui
355
+ ```
356
+
357
+ Truy cập: http://localhost:4500/icons
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { computed, input, Directive, ChangeDetectionStrategy, Component, Pipe } from '@angular/core';
2
+ import { computed, input, Directive, Component, ChangeDetectionStrategy, Pipe } from '@angular/core';
3
3
 
4
4
  class LibsUiIconsComponentAbstract {
5
5
  colorBind = computed(() => {